How CSV to XLSX Conversion Runs in Your Browser
An XLSX file is not a single document but a ZIP archive of XML parts: a [Content_Types].xml manifest, a workbook part listing sheets, per-sheet XML holding cell values and references, plus relationship files wiring them together. Hand-writing that package is exactly what the SheetJS library (the xlsx.full.min build) automates. The pipeline starts with File.text(), then XLSX.read(text, { type: 'string' }) parses the CSV dialect — honoring quoted fields and commas inside quotes — and builds an in-memory worksheet object whose keys are cell addresses like A1.
That worksheet is wrapped in a minimal workbook structure: { Sheets: { Sheet1: ws }, SheetNames: ['Sheet1'] }. Then XLSX.write(workbook, { bookType: 'xlsx', type: 'array' }) serializes the whole package — compressing the XML parts into a ZIP container and returning a Uint8Array of the finished file. The bytes are wrapped in a Blob with the Excel MIME type (application/vnd.openxmlformats-officedocument.spreadsheetml.sheet) and offered for download through an object URL. Excel, Google Sheets, and LibreOffice all open the result natively because it is the real OOXML format, not a renamed text file.
Two honest caveats. First, since a CSV carries no type information, every cell is stored as text; Excel may show numbers or dates as text until you reformat the column — the data itself is intact. Second, the transform is fully in-memory: parse, worksheet, and ZIP all live in RAM, which is what allows multi-megabyte files while still guaranteeing that none of the data travels anywhere. The only download that ever happens is the SheetJS script itself, fetched once from a CDN and cached for every later conversion.