Convert Excel to JSON

Drop an Excel file here

.xlsx, .xls, .xlsm, .xlsb or .ods

Output options

Drop a spreadsheet in and get a JSON array of objects, one per row, keyed by the header row. Most converters hand you dates as serial numbers such as 45366, use a report's title line as the header, and let a repeated column name overwrite the first one. This one writes dates as 2024-03-15, finds the real header row, renames duplicate headers, and reports what it did. Nothing is uploaded.

How to convert Excel to JSON

  1. Drop an .xlsx, .xls, .xlsm, .xlsb or .ods file into the box above. It is read in your browser and never uploaded.
  2. Pick the sheet, or All sheets to get one array per sheet name.
  3. Check the report's header line. If the detected header row is wrong, choose the right one from the list, which shows the start of each row.
  4. Copy the JSON or download it as a .json file.

What you get

An array of objects, one per data row, with the header row supplying the keys. That is the shape almost every API, seed script and chart library expects:

[
  { "region": "North", "q1": 10, "q2": 12, "updated": "2024-03-15" },
  { "region": "South", "q1": 7, "q2": 9, "updated": "2024-03-16" }
]

Values keep their spreadsheet types. Numbers become JSON numbers, TRUE and FALSE become booleans, and text stays a string, including text that looks like a number. A code stored as the text 00721 is not quietly turned into 721. Choosing All sheets gives an object keyed by sheet name, with each sheet's rows as an array.

Three things most Excel to JSON converters get wrong

Dates arrive as serial numbers

Excel stores 15 March 2024 as 45366, the number of days since the end of 1899, and only the cell's format marks it as a date. A converter that reads stored values gives you 45366. Your code then has to convert it, which means knowing that Excel counts a 29 February 1900 that never existed, and that files from old Mac versions of Excel count from 1904 instead. Here every date-formatted cell becomes an ISO 8601 string such as "2024-03-15", which JavaScript's Date, Python's datetime.fromisoformat and every database read the same way. Cells with a time become "2024-03-15 12:00:00", time-only cells become "18:00:00", and 1904-system workbooks are corrected.

The first row is not always the header

Spreadsheets made for people often start with a title, a date line and a blank row before the table. Converters that always take row 1 give you a key called "Quarterly report", a column of column_2 keys, and the real header row as your first object. The header is detected here instead. It is the first row that contains only text and is filled across most of the table's width, looking at the first twenty rows with content. Rows above it are skipped and counted. The report shows which row was chosen and the keys it produced, and the header list lets you pick another row. Each row in that list shows its first few values, not just a number.

Duplicate headings overwrite each other

Two columns called name cannot both be keys in one JSON object. Most converters write both and the second silently replaces the first, so half a column disappears without a message. The second one is renamed to name_2 here and every rename appears in the report. Blank headings become column_4 and so on by position.

Empty cells, merges and formulas

In the sheetIn the JSON
Empty cellKey left out, null or "", as you choose
Completely empty rowSkipped and counted
Merged areaValue in the first cell, or repeated across the merge
FormulaThe result saved with the file
Formula never calculatednull, with the cell named in the report
Error such as #N/Anull, with the cell named in the report
Number shown rounded, 3.14159 as 3.143.14159, the stored value
Zero-padded number, 721 as 00721"00721"

Leaving empty keys out keeps the file small and is what most APIs expect. Writing null gives every object the same set of keys, which some typed languages and database loaders need. The formula row matters for files produced by scripts. They often contain formulas that were never calculated, and the library underneath this page reports those as 0. We measured it. Reporting a missing total as zero is worse than reporting nothing, so those cells become null and are named.

Numbers are kept at full precision

Excel keeps 15 significant digits, and the JSON uses the same limit. A value that JavaScript would print as 0.30000000000000004 is written as 0.3, as Excel displays it. Formatting such as currency symbols, percent signs and thousands separators is not part of the value. A cell showing 12.5% holds 0.125, and that is what you get.

Next steps

Excel to CSV exports the same sheets as CSV files with the same date and precision rules. JSON to CSV and JSON to XML take the result further, and CSV to Excel builds a workbook from a CSV without losing leading zeros. All of them are on the data tools page.

Frequently asked questions

Why do Excel dates turn into numbers like 45366 in JSON?

Excel stores a date as a count of days since 1900 and relies on the cell's format to show it as a date. A converter that reads only the stored value gives you 45366 instead of 2024-03-15, and your code then has to know Excel's epoch - including its deliberate 1900 leap-year bug. Here every date-formatted cell becomes an ISO 8601 string. Date and time cells become 2024-03-15 12:00:00, time-only cells become 18:00:00, and workbooks using the 1904 date system are corrected.

My sheet has a title above the table. Which row becomes the keys?

Reports often start with a title such as Quarterly report and a blank line. Taking the first row as the header would give keys like "Quarterly report" and "column_2". The header is detected instead: the first row that contains only text and spans most of the table's width. The report says which row was used, and you can set the row number yourself.

What happens when two columns have the same heading?

A JSON object cannot hold the same key twice, so the second value would silently replace the first. The second column is renamed, so name and name become name and name_2, and every rename is listed. Blank headings become column_4 and so on, by position, so their values are still reachable.

Are numbers, text and TRUE/FALSE kept as their types?

Yes. Numbers become JSON numbers, TRUE and FALSE become true and false, and text stays a string. A cell stored as text in Excel stays a string even if it looks like a number, so a code such as 00721 is not turned into 721. Numbers formatted with zero padding, such as 721 shown as 00721, come out as the padded string, because that is the real value.

How are empty cells handled?

You choose. By default an empty cell is left out of that row's object, which keeps the output small. You can have it written as null instead, so every object has the same keys, or as an empty string. Completely empty rows are skipped and counted.

Can I convert every sheet in the workbook?

Yes. Convert one sheet to get a plain array, or all of them to get an object with one array per sheet name. Each sheet gets its own header row detection, since sheets in the same workbook rarely share a layout.

What about formulas and error cells?

Formulas come out as the result Excel saved with the file. Error cells such as #N/A become null, and the report lists where they were. If a formula has no saved result, which happens with files written by scripts, it becomes null rather than a fake 0, and the report names the cell.

Is my file uploaded?

No. The workbook is read inside your browser tab; only the spreadsheet reader is downloaded, the first time you drop a file in. Your data does not leave the device.