Excel’s own Save As CSV writes each cell as it is displayed, not as it is stored. In Excel for Mac, a 13-digit barcode in a General column came out as 4.00638E+12, seven digits gone; 1234.5 formatted as #,##0.00 came out as "1,234.50", with a comma in it; 0.1 formatted as a percentage came out as 10%; and the plain CSV format wrote é in the Mac Roman encoding. This converter reads the .xlsx itself and writes what is stored: numbers to the 15 significant digits Excel keeps, with a dot for the decimal point and no grouping, TRUE and FALSE for booleans, the error text for cells such as #N/A, and for a formula the result Excel last saved. Dates need a choice, because a date is stored only as a day count: ISO 8601 — 2026-09-29, or 2026-09-29 13:45:00 with a space, which databases and spreadsheets both read — the text Excel displays, or the serial number itself.
The output follows RFC 4180. Fields are separated by the delimiter you choose, records end with CRLF, as RFC 4180 specifies, with LF as an option, and a field is quoted only when it holds the delimiter, a quote or a line break — or every field, if you prefer. A cell containing a line break stays one quoted field, which the RFC allows but tools that read a line at a time do not expect, so such cells are counted. The table is the sheet’s used range, from the first cell with a value to the last, and short rows are padded so every line has the same number of fields. A CSV holds one sheet, so the sheet picker decides which, and hidden sheets are marked. Merged cells can be filled with their value, as in Excel to JSON.
Two things decide whether the CSV opens safely in a spreadsheet later. The first is encoding: the text is UTF-8, and Excel reads a CSV that has no byte order mark in a legacy code page, so café arrives as café. Add BOM puts the three bytes EF BB BF at the start of the downloaded file, as Excel’s own CSV UTF-8 format does, and never into the text you copy; leave it off for programs that would read the mark as part of the first header. The second is formulas. In the workbook a text cell beginning with =, +, - or @ is inert, because its type says it is text, but a CSV has no types, so a spreadsheet opening the CSV runs it as a formula. Every such cell is counted, and Escape formulas prefixes it with an apostrophe or a tab inside quotes, the two forms OWASP describes — the same option JSON to CSV has.