Skip to content
ABCrimson edited this page Mar 7, 2026 · 8 revisions

FAQ

General

What runtimes are supported?

modern-xlsx works in any environment with WASM support:

  • Node.js 24+ (uses node:fs for file operations)
  • Bun (full support)
  • Deno (full support)
  • Browsers (Chrome, Firefox, Safari, Edge — all modern versions)

Why Node.js 24+?

The TypeScript source uses modern features available in Node.js 24+. If you need older Node.js support, you can try building from source with appropriate transpilation, but this is not officially supported.

Does it support .xls files?

No. modern-xlsx only supports the OOXML .xlsx format (Office 2007+). The legacy .xls binary format is not supported.

Is it production-ready?

Yes. v1.0.0 is the first stable release with 1,711 tests (424 Rust + 1,287 TypeScript) covering reading, writing, styling, encryption, charts, pivot tables, formula evaluation, and round-trip fidelity. The API is frozen and production-ready.

Reading Files

How do I read a file in the browser?

const input = document.querySelector('input[type="file"]');
input.addEventListener('change', async (e) => {
  const file = e.target.files[0];
  const buffer = new Uint8Array(await file.arrayBuffer());
  const wb = await readBuffer(buffer);
  console.log(wb.sheetNames);
});

How do I access shared strings?

The reader resolves shared strings automatically. Cell values are returned as their actual text content — you don't need to look up SST indices manually.

Can modern-xlsx read password-protected Excel files?

Yes! As of v0.6.0, modern-xlsx supports both reading and writing encrypted XLSX files:

// Read encrypted file
const wb = await readFile('protected.xlsx', { password: 'mypassword' });

// Write encrypted file
await wb.toFile('output.xlsx', { password: 'newpassword' });

Supports Agile Encryption (Excel 2010+) and Standard Encryption (Excel 2007). Key material is automatically zeroized from memory.

Writing Files

How do I download a file in the browser?

import { writeBlob } from 'modern-xlsx';

const blob = writeBlob(wb);
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = 'output.xlsx';
a.click();
URL.revokeObjectURL(url);

Can I write formulas?

Yes! Set the formula property on a cell:

ws.cell('C1').formula = 'SUM(A1:B1)';

The formula will be preserved in the file. Excel will calculate the result when the file is opened.

Can I set date values?

Use dateToSerial to convert a Date to an Excel serial number, then apply a date number format:

import { dateToSerial } from 'modern-xlsx';

ws.cell('A1').value = dateToSerial(new Date(2024, 0, 15));

const dateStyle = wb.createStyle()
  .numberFormat('yyyy-mm-dd')
  .build(wb.styles);
ws.cell('A1').styleIndex = dateStyle;

Styling

Why do I need wb.styles?

Styles in XLSX are shared across the workbook, not stored per-cell. The build(wb.styles) call adds the style definition to the workbook's shared style table and returns an index. Assigning that index to a cell is very efficient — it's just setting a number.

Can I apply a style to a range?

There's no built-in range styling, but you can loop:

const bold = wb.createStyle().font({ bold: true }).build(wb.styles);
for (let col = 0; col < 10; col++) {
  ws.cell(encodeCellRef(0, col)).styleIndex = bold;
}

Troubleshooting

"WASM not initialized" error

You forgot to call initWasm() before using the library:

import { initWasm } from 'modern-xlsx';
await initWasm(); // must be called first

File opens but looks wrong in Excel

Check that you're using the correct number format for dates. Raw serial numbers display as plain numbers unless you apply a date format style.

Large files are slow to write

Writing performance scales with cell count. For very large files (500K+ cells), consider:

  • Using aoaToSheet for batch cell creation
  • Splitting data across multiple sheets
  • Reducing the number of unique styles (each unique combination creates a new style entry)

Browser & CDN

How do I use modern-xlsx in the browser without a bundler?

Use the IIFE bundle from jsDelivr or unpkg:

<script src="https://cdn.jsdelivr.net/npm/modern-xlsx@1.0.0/dist/modern-xlsx.min.js"></script>

The full API is available on window.ModernXlsx. The WASM binary is auto-fetched from the same CDN.

Can I specify a custom WASM URL?

Yes — pass a URL to initWasm():

await ModernXlsx.initWasm('https://my-cdn.com/modern-xlsx.wasm');

How do Web Workers help with performance?

Web Workers run XLSX parsing/writing in a separate thread, keeping the main thread responsive for UI interactions. Use createXlsxWorker() to set this up:

const worker = createXlsxWorker({ workerUrl: '/modern-xlsx.worker.js' });
const data = await worker.readBuffer(xlsxBytes);
worker.terminate();

Does modern-xlsx work in Cloudflare Workers / Deno Deploy?

Yes. See the examples in examples/cloudflare-worker/ and examples/deno-deploy/. Both support WASM modules natively.

What's the browser bundle size?

The IIFE bundle is 29 KB (10 KB gzipped) plus the 939 KB WASM binary. The WASM binary is fetched lazily on initWasm().

Clone this wiki locally