Quick start
Install with npm install @agent-sheet/wasm and use Node.js 22 or newer.
Create a workbook, save it, then read it back:
const XLSX = require("@agent-sheet/wasm");
const ws = XLSX.utils.aoa_to_sheet([["Item", "Price"], ["abc", 1.23], ["def", 4.56]]);XLSX.utils.sheet_set_range_style(ws, "A1:B1", { bold: true });XLSX.utils.sheet_set_range_style(ws, "B2:B3", { z: "0.00" });
const wb = XLSX.utils.book_new();XLSX.utils.book_append_sheet(wb, ws, "Prices");XLSX.writeFile(wb, "quickstart.xlsx", { cellStyles: true });
const back = XLSX.readFile("quickstart.xlsx", { cellStyles: true });console.log(back.SheetNames, back.Sheets.Prices.A1.s.bold);[ 'Prices' ] 1Load the browser bundle with a script tag. It defines the global XLSX.
<script src="https://cdn.jsdelivr.net/npm/@agent-sheet/wasm@0.3/dist/xlsx.full.min.js"></script><script> var ws = XLSX.utils.aoa_to_sheet([["a", "b"], [1, 2]]); var wb = XLSX.utils.book_new(); XLSX.utils.book_append_sheet(wb, ws, "Sheet1"); XLSX.writeFile(wb, "out.xlsx"); // starts a download</script>Alternatively, copy dist/xlsx.full.min.js from the package to your web server. If your page uses a
Content-Security-Policy, see Browsers and CSP.
To read a file the user picks:
<input type="file" id="file"><script src="https://cdn.jsdelivr.net/npm/@agent-sheet/wasm@0.3/dist/xlsx.full.min.js"></script><script> document.getElementById("file").addEventListener("change", async function (e) { var file = e.target.files[0]; if (!file) return; var data = await file.arrayBuffer(); var wb = XLSX.read(data); console.log(wb.SheetNames); });</script>Import the package like any other module. Use the default import in ESM syntax.
import XLSX from "@agent-sheet/wasm";
export function toCsv(buffer) { const wb = XLSX.read(buffer); return XLSX.utils.sheet_to_csv(wb.Sheets[wb.SheetNames[0]]);}
const wb = XLSX.utils.book_new();XLSX.utils.book_append_sheet(wb, XLSX.utils.aoa_to_sheet([["a", "b"], [1, 2]]), "S");console.log(toCsv(XLSX.write(wb, { type: "array", bookType: "xlsx" })));a,b1,2The browser field of the package replaces fs, stream, buffer, crypto and process with empty
modules, so the bundle contains no Node-only code. esbuild bundles were tested with CommonJS, ESM,
browser and minified output.
Heavy files block the thread that parses them. Do the work in a worker:
importScripts("xlsx.full.min.js");
self.onmessage = function (e) { var wb = XLSX.read(e.data, { type: "array" }); var rows = XLSX.utils.sheet_to_json(wb.Sheets[wb.SheetNames[0]], { header: 1 }); self.postMessage(rows);};<input type="file" id="file"><script> var worker = new Worker("worker.js"); worker.onmessage = function (e) { console.log(e.data.length + " rows"); }; document.getElementById("file").addEventListener("change", async function (e) { var file = e.target.files[0]; if (!file) return; var buffer = await file.arrayBuffer(); worker.postMessage(new Uint8Array(buffer), [buffer]); });</script>See Workers for more.
The workbook model
Section titled “The workbook model”A workbook is a plain object. It has SheetNames and Sheets. A worksheet maps cell addresses
such as A1 to cell objects. Keys that start with ! hold sheet-level data such as !ref (the used range).
const XLSX = require("@agent-sheet/wasm");const wb = XLSX.read("a,b\n1,2", { type: "string" });const ws = wb.Sheets[wb.SheetNames[0]];console.log(wb.SheetNames);console.log(ws["!ref"]);console.log(ws.A1, ws.A2);[ 'Sheet1' ]A1:B2{ w: 'a', t: 's', v: 'a' } { w: '1', t: 'n', v: 1 }A cell has a type t (n number, s string, b boolean, d date, e error, z blank), a raw value v,
a formatted text w and optionally a formula f, a number format z and a style s.