Keep and reorder chosen columns, with the list built from the widest row so a field beyond the header is not dropped
Initializing in your browser…
Filter rows with each condition stating its rule: a cell that is not a number does not match a comparison, and an empty cell is not a zero
Rename columns under a stated convention, with two that would end up with the same name numbered rather than left to collide
Sort by any number of columns, with the comparison stated: numbers by value, dates by day, text by a collation you choose
A file whose header names three columns and whose second data row has five fields. Two of those fields have no column name, and a tool that builds its list from the header cannot see them at all.
contacts.csv
id,name,email 1,Alice,alice@x.com 2,Bob,bob@x.com,extra-1,extra-2 3,Carol
The column list, and keeping columns 1, 4 and 5
id · name · email · Column 4 (beyond the header) · Column 5 (beyond the header) 2 columns exist only because some rows have more fields than the header names: columns 4, 5. RFC 4180 section 2.4 asks for one width, and this file has 3. id,, 1,, 2,extra-1,extra-2 3,, 6 cells carried, 6 written as empty because the row was too short, 7 dropped, 13 in
The previous version built its column list from the width of the header row, so this file had three columns as far as it was concerned and extra-1 and extra-2 could not be selected, previewed or exported. The width is the width of the widest row now. The counts underneath are the other half of the answer: six cells came from the file, six are empty because those rows have no such field (which is a different fact from the file holding an empty value), and six plus seven dropped is the thirteen cells that went in.
Choose which columns to keep and what order they come out in. Every cell is carried across as the string it was, and the column list is built from the widest row in the file rather than from the header, so a field that only some rows have is a column you can select rather than one that disappears.
This is a pure column operation: it changes which columns appear and in what order, and never rewrites a value. No number, date or currency is parsed, so leading zeros, currency symbols and date formats come out as they went in. Measured on 2026-09-02 by reading the download back with Python's csv module and comparing it cell by cell against the selected columns of the input: 81 browser checks and 118 module assertions pass, and every cell in every fixture is identical.
The fault the pass found was in the column list rather than in the copying. The list was built from `data[0].length`, the width of the HEADER ROW. RFC 4180 section 2.4 says every line should have the same number of fields and real files depart from that constantly, so on a file whose header names three columns and whose third row has five fields, the tool offered three columns, dropped the other two, and gave no way to reach them. The same fault turned up in the file comparator in the previous batch. The width is the width of the widest row now, columns that exist only in the data are listed and marked "beyond the header", and the page says how many row widths the file has.
Two columns can share a header name, which is legal CSV and impossible to act on from a list of names. The picker showed two entries both reading "name" with nothing to tell them apart. Each column now carries its position, so they read "name (column 2)" and "name (column 3)", and the page says why.
A row narrower than your selection has no cell for the missing column. Writing an empty string there is reasonable and it is not the same fact as the file holding an empty value, so those cells are counted separately and reported. The counts below the preview add up: cells carried plus cells dropped is every cell that went in.
One premise this pass started from did not survive measurement, and it is recorded because the measurement wins. The projection was written `row[index] || ''`, which looks like a falsy test that would turn a cell holding `0` into an empty string. It does not: every non-empty string is truthy in JavaScript, so `0`, `false` and a single space all survived it, and on a 16 cell fixture built to catch exactly that, 16 of 16 cells were identical. The expression only ever differed from `?? ''` where the cell was absent, which is the padding case above.
A single-column CSV was refused outright, because papaparse reports UndetectableDelimiter for a file with no delimiter in it to detect and every Delimiter-type error was treated as fatal. It loads now. And the download is written by RFC 4180: CRLF records per section 2.1, quoting as a minimum, and a UTF-8 byte order mark so a spreadsheet reads accented and non-Latin headers correctly.
Remove sensitive columns before passing data to an external team. Invert the selection when you want everything except a few fields.
Trim a CSV down to the exact columns a target system expects, in the exact order it expects them.
A file whose rows are wider than its header has columns nothing has named. They are listed here and can be selected like any other, which is how you get at data another tool would drop.
Strip unnecessary columns from a large export before sharing it.
Because some rows in your file have more fields than the header names them. RFC 4180 section 2.4 asks for one width and files often have several. Those extra columns are real data and are listed as "beyond the header" so you can select them. The previous version built its list from the header alone and dropped them without saying so.
Yes. Drag them into the order you want, or use the up and down arrows, and the export follows that order. Reset restores the original order while leaving your checkbox choices alone.
The missing cell is written as empty, and the count of those cells is reported separately from cells that really hold an empty value, because they are different facts about your file.
No. Nothing is trimmed, nothing is parsed as a number or a date, and no value is converted. A cell holding 007, $50, 2024-13-45 or a single space comes out as exactly that string. This was checked by reading the download back with a separate CSV implementation and comparing every cell.
They are listed with their positions, as "name (column 2)" and "name (column 3)", and a note says why. Two columns sharing a header is legal CSV, and a list of bare names cannot tell them apart.
Rows and columns are parsed and transformed in memory in your browser. No record ever reaches a server.