Skip to content

Migration from SheetJS

The xlsx-format API is intentionally close to SheetJS. Most code migrates with three small changes -- and nothing else.

The Three Changes

1. read() and write() are async

ZIP operations use streaming internally, so both functions return a Promise. Add await to every call.

2. Named imports replace the namespace

Instead of accessing everything through XLSX.*, import each function by name.

3. Utility names are camelCase

sheet_to_json becomes sheetToJson, sheet_to_csv becomes sheetToCsv, and so on.

Side-by-Side

- import XLSX from "xlsx";
+ import { read, write, sheetToJson, sheetToCsv } from "xlsx-format";

- const wb = XLSX.read(buffer);
+ const wb = await read(buffer);

- const rows = XLSX.utils.sheet_to_json(ws);
+ const rows = sheetToJson(ws);

- const buf = XLSX.write(wb, { type: "buffer", bookType: "xlsx" });
+ const buf = await write(wb, { type: "buffer" });

- const csv = XLSX.utils.sheet_to_csv(ws);
+ const csv = sheetToCsv(ws);

Function Name Mapping

SheetJSxlsx-format
XLSX.read()read()
XLSX.readFile(path)read(await fs.readFile(path))
XLSX.write()write()
XLSX.writeFile(wb, path)await fs.writeFile(path, await write(wb))
XLSX.utils.sheet_to_json()sheetToJson()
XLSX.utils.json_to_sheet()jsonToSheet()
XLSX.utils.sheet_to_csv()sheetToCsv()
XLSX.utils.sheet_to_html()sheetToHtml()
XLSX.utils.aoa_to_sheet()arrayToSheet()
XLSX.utils.sheet_to_formulae()sheetToFormulae()
XLSX.utils.decode_cell()decodeCell()
XLSX.utils.encode_cell()encodeCell()
XLSX.utils.decode_range()decodeRange()
XLSX.utils.encode_range()encodeRange()
XLSX.utils.book_new()createWorkbook()
XLSX.utils.book_append_sheet()appendSheet()

File I/O

xlsx-format does not include readFile / writeFile -- it stays platform-agnostic by keeping node:fs out of the bundle. Use Node's fs module directly:

- import XLSX from "xlsx";
+ import { readFile, writeFile } from "node:fs/promises";
+ import { read, write } from "xlsx-format";

- const wb = XLSX.readFile("input.xlsx");
+ const wb = await read(await readFile("input.xlsx"));

- XLSX.writeFile(wb, "output.xlsx");
+ await writeFile("output.xlsx", await write(wb));

For CSV or HTML files, read as a UTF-8 string:

const wb = await read(await readFile("data.csv", "utf-8"), { type: "string" });

Cell Objects Stay the Same

Cell objects keep the same shape. { t: "n", v: 42, w: "42" } works exactly as before. No data migration needed.

What's Different Under the Hood

  • Streaming ZIP -- reads and writes are non-blocking
  • Tree-shaking -- named exports let your bundler drop unused code
  • No legacy formats -- xlsx-format focuses on XLSX, XLSM, CSV, TSV, and HTML
  • Zero dependencies -- nothing to audit, nothing that can break
  • Platform-agnostic -- no node:fs imports; the library works in Node.js, browsers, and edge runtimes without polyfills