Compare Excel & CSV Files

Compare two spreadsheets and highlight added, removed and changed rows and cells. Match by key column or by position. Nothing is uploaded.

🌐 Español

File A (original)

No file chosen

File B (new)

No file chosen

🔒 Private by design: everything runs locally in your browser and never uploaded to any server.

Row order is what breaks a naive spreadsheet diff

Two exports of the same table are almost never in the same order. Someone sorted by a different column, a record was inserted in the middle, the database returned rows in whatever order the query planner preferred that day. Line row 1 up against row 1 in that situation and one inserted record at the top turns every record below it into a change. The result is a diff that is technically accurate and completely useless.

So key matching is the default here. You nominate the column that identifies a record (an SKU, an email address, an invoice number, an employee ID) and rows are paired on that value wherever they sit in the file. A key only File B has is genuinely new. A key only File A has was genuinely deleted. A key on both sides whose other cells disagree is a change, and the table prints the old value struck through beside the new one so you can see exactly which cells moved. Position matching still lives in the Match rows by dropdown for the cases where position is the whole point, such as confirming a bulk edit did not shuffle anything.

Columns get the same forgiving treatment. With First row is a header on, columns are aligned by name, so a re-ordered export lines up anyway. A column only one file has is listed on its own as an added or removed column and is left out of cell-by-cell comparison, which is what stops a single dropped column from painting every row yellow.

Two files in, and the table redraws as you change your mind

  1. Load the older spreadsheet under File A (original) using its Choose file button, then the newer one under File B (new). Both slots take .xlsx, .xls, .csv and .tsv, and mixing formats between the two sides is fine.
  2. Leave First row is a header ticked if your files begin with column names, then set Match rows by to Key column(s) or to Row position.
  3. In key mode, tick the column or columns that identify a record under Key column(s). Only columns present in both files are offered, and the first common column is used until you choose something else.
  4. Adjust Ignore surrounding spaces (on by default) and Ignore case (off by default), then use the four count buttons to show or hide added, removed, changed and unchanged rows. Download diff as CSV saves whatever the table is showing at that moment, under the fixed name spreadsheet-diff.csv.

There is no Compare button and no processing phase, because there is nothing to queue: the whole diff is a derivation from the two grids already sitting in memory. Every toggle re-runs it. Unchanged rows start hidden, on the assumption you came here for the differences rather than for a re-print of your data.

Every cell is compared as text, deliberately

Cell equality is string equality. A value stored as the number 1 in one system’s export and as the text “1” in another’s is treated as the same value, which is the sane behaviour when you are reconciling two systems that disagree about types. Leading and trailing spaces are trimmed off before comparing unless you turn Ignore surrounding spaces off, and comparison is case-sensitive until you turn Ignore case on. An empty cell, a cell past the end of a short row, and a column that only one file has all collapse to the same empty string, so none of them register as a phantom change.

The trade-off is on the other side of that coin. Because XLSX cells arrive as the text Excel shows rather than as raw values, formatting is part of the comparison. Two files recording the same day as 15/01/2024 and 1/15/24 are two different strings, and this tool will say so. If that is the noise in your reconciliation, normalise the number format in the source workbook before exporting.

Only the first sheet is read, and blank rows vanish first

Each side is a single sheet, not a workbook. The reader takes the first sheet name SheetJS reports and never looks at the rest, so a workbook whose first tab is a chart or a notes page will compare that instead of your table. There is no sheet picker to work around it; move the sheet or export it separately.

Entirely blank rows are dropped during parsing, on both the spreadsheet path and the CSV path. That is usually what you want, but it means the A12 / B14 row references in the table count rows in the parsed grid rather than in Excel’s own row gutter. On a sheet peppered with spacer rows those two numbers drift apart.

Duplicate keys are paired in order of appearance

Real exports repeat keys. Two order lines with the same order number, a contact listed twice, a join that fanned out. Rather than picking one row and quietly dropping the other, occurrences are matched positionally within the key: File A’s first row with key K against File B’s first row with key K, second against second, and so on. Whatever is left over on one side becomes an added or a removed row. Nothing is discarded, which is why the four counts in the summary always add up to the row list underneath them.

A composite key is just several columns joined for display, so ticking two or three columns together works when no single column is unique on its own.

What the diff CSV actually contains

The export is a flat CSV, escaped to RFC 4180 by the same routine Convert JSON to CSV uses, with a Status column, a Key column in key mode, and then one column per unified column. Removed rows carry File A’s values; everything else carries File B’s. A changed cell is written inline as old -> new, so the file is readable as a report rather than needing the page open beside it.

For related jobs, the sibling tools split up cleanly. CSV Viewer opens one CSV or TSV as a sortable, searchable table when you only want to look at a file rather than compare two. JSON Diff is the structural equivalent for JSON documents, where key order does not matter. Text Diff Checker is the right choice when the two things you are comparing are prose or code rather than tabular data. And if the reconciliation is really a prelude to loading the sheet somewhere, Convert Excel to JSON hands the same workbook to an app or a script instead. The rest of the data utilities are on the dev tools hub.

See it in action

Screenshot of the Compare Excel & CSV Files tool with two file slots waiting for the spreadsheets to compare, either .xlsx or .csv
Compare Excel & CSV Files mid-process: two file slots waiting for the spreadsheets to compare, either .xlsx or .csv.
Screenshot of the Compare Excel & CSV Files result screen showing the first sheet loaded and parsed into rows and columns, ready for the second to be compared against it
The finished result: the first sheet loaded and parsed into rows and columns, ready for the second to be compared against it. The download link is a local blob URL — the file never leaves your device.

Frequently asked questions

Which sheet does it read from a workbook with several tabs?

Only the first sheet of each workbook. The reader asks SheetJS for the first sheet name and ignores everything after it, so a cover or summary tab sitting in front of your data is what ends up being compared. Move the sheet you care about to the front of the workbook and save, or export just that sheet as CSV and drop the CSV in instead.

Does the CSV export contain the whole comparison or only what is on screen?

Only what is on screen. The export is handed the rows the table is currently showing, so any status you have switched off and anything excluded by the search field is left out of the file. Unchanged rows start hidden, which means a straight export gives you added, removed and changed rows only. Switch Unchanged back on and clear the search box first if you want every row in the CSV.

Is there a button that runs the comparison?

No, and there is no waiting for one either. The diff is derived from the two parsed grids, so ticking Ignore case or switching to Row position recomputes it and redraws the table immediately. You can try a different key column and watch the added and removed counts move without reloading either file.

What happens when the two files share no column names?

In key matching the key picker is replaced by a message saying the two files have no column in common, with a pointer to Row position matching instead. The usual cause is that one export carries a header row and the other does not, so unticking First row is a header before you give up on key matching is worth a try.

How are dates and numbers read out of an XLSX file?

As the text Excel displays for them, not as the underlying value. A date cell showing 1/15/24 is compared as the string 1/15/24, and a numeric cell showing 30 is compared as the two characters 3 and 0. The practical consequence is that two files holding the same date under different number formats are reported as changed even though the stored value is identical.

Can I put a CSV on one side and an Excel workbook on the other?

Yes. The two sides are read independently, so mixing formats is completely normal. CSV and TSV go through the same RFC 4180 parser the CSV Viewer tool uses, with the delimiter detected from a sample of the text, while XLSX and XLS go through SheetJS. Both paths end at a plain grid of strings before a single cell is compared.

Related tools