Drop a spreadsheet here
.xlsx, .xlsm, .xls or .ods
Convert an Excel workbook into JSON. Drop the file
in, pick a sheet, and get an array of objects with the header row as
keys. Date cells come out as ISO 8601 strings such as
2026-01-14 instead of the serial numbers Excel stores.
Drop a spreadsheet here
.xlsx, .xlsm, .xls or .ods
[
{
"id": 1,
"name": "Alex Morgan",
"signed_up": "2026-01-14",
"spent": 240000
},
{
"id": 2,
"name": "Sam Patel",
"signed_up": "2026-02-03",
"spent": 99500.5
}
]
Excel stores a date as the number of days since 1 January
1900, plus a cell format that says to display it as a date. A
naive conversion ignores the format, so 14 January 2026 arrives
as 46036. This is the most common mistake when
moving data out of a spreadsheet.
Keep Dates as ISO 8601 on unless you need the serial.
With it on, any cell Excel formatted as a date comes out as
2026-01-14. Turn it off to get the raw serial
number, which helps when you are reproducing a spreadsheet
calculation. The 1900 epoch also counts a 29 February 1900
that never existed. Lotus 1-2-3 had the bug first, and Excel
kept it for file compatibility.
You get the last value Excel calculated, not the formula. A file written by a library that does not compute formulas can contain stale or empty cells.
A merged range keeps its value in the top-left cell and leaves the rest empty, so the JSON has gaps where the sheet looked full. Unmerge the cells before you convert.
A blank cell in the header row has no name, so the column comes out as __EMPTY. Give every column a header, and delete any title rows that sit above the real one.
The file is read with FileReader and parsed by SheetJS in this tab, so a spreadsheet of customer data never leaves your machine. That matters when company policy rules out uploading to online converters.
// npm i xlsx
const XLSX = require("xlsx");
// cellDates gives you Date objects instead of serial numbers
const wb = XLSX.readFile("customers.xlsx", { cellDates: true });
const sheet = wb.Sheets[wb.SheetNames[0]];
// raw: true keeps numbers as numbers. With raw: false you get the
// *displayed* text, so ids become strings and dates become "1/14/26".
const rows = XLSX.utils.sheet_to_json(sheet, { raw: true, defval: null });
console.log(rows[0]); Watch the raw flag. It looks like a formatting option, but it changes the type of every value in the output without any warning.
# pip install pandas openpyxl
import pandas as pd
df = pd.read_excel("customers.xlsx", sheet_name="Customers")
# dtype=str on the read if leading zeros matter:
# pd.read_excel("f.xlsx", dtype={"zip": str})
df["signed_up"] = pd.to_datetime(df["signed_up"]).dt.strftime("%Y-%m-%d")
print(df.to_json(orient="records", indent=2))
# Every sheet at once
sheets = pd.read_excel("customers.xlsx", sheet_name=None)
print(list(sheets)) <?php
// composer require phpoffice/phpspreadsheet
use PhpOffice\PhpSpreadsheet\IOFactory;
use PhpOffice\PhpSpreadsheet\Shared\Date;
$sheet = IOFactory::load('customers.xlsx')->getActiveSheet();
$rows = $sheet->toArray(null, true, true, false);
$headers = array_shift($rows);
$out = array_map(fn($r) => array_combine($headers, $r), $rows);
// A date cell is a float until you convert it
// $date = Date::excelToDateTimeObject($value)->format('Y-m-d');
echo json_encode($out, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE); The 1900 epoch contains a leap day that never existed: Excel treats 29 February 1900 as a real date. Lotus 1-2-3 had the bug, and Excel copied it for file compatibility. It only affects dates before March 1900, so it rarely shows up in practice. However, Excel for Mac historically defaulted to a 1904 epoch, and a workbook that mixes the two systems shows dates shifted by 1,462 days (about four years).
This tool follows the specifications below. Read them when you need the exact normative wording, for example to settle an edge case between two implementations.
.xlsx and .xlsm from Excel 2007 onwards, the older .xls binary format, and .ods from LibreOffice. SheetJS parses the file in your browser tab, so a spreadsheet of customer data never leaves your machine.
The Sheet dropdown lists every sheet, and you pick the one to convert. The output contains only the selected sheet.
Excel stores a date as a number of days since 1900, so a raw conversion gives you 45292 instead of 2024-01-01. With Dates as ISO 8601 on, the tool converts date-formatted cells to ISO 8601 strings. This is the most common mistake when exporting from Excel.
You get the last calculated value, not the formula. That value dates from Excel's last recalculation, so a workbook saved by a library that does not compute formulas can contain stale or empty cells.
They can be. A merged range holds its value in the top-left cell and leaves the rest empty, so the JSON has gaps where the spreadsheet looked full. Unmerge the cells before converting if the layout matters.
The first row had blank cells, so those columns had no name. Give every column a header, or delete any title rows that sit above the real header row.
JSON to Excel builds a workbook from JSON. If the data is already a CSV export, CSV to JSON skips the spreadsheet step, and CSV to SQL turns it into INSERT statements.