Skip to content

Excel / Excelize

@alneas/data-engine/excel defines ExcelWorkbookData and the common ExcelAdapter interface. It exports HTTP, custom Go WASM, CSV and mock adapters. The mock output is not a usable XLSX file. CSV exports one sheet without Excel formatting. HttpServerExcelAdapter needs a separately operated backend; WasmExcelAdapter expects a custom generateExcel(JSON) Go WASM runtime.

For genuine XLSX generation without operating that backend or compiling Go, use ExcelizeExcelAdapter from the separate @alneas/data-engine/excel/excelize entry. Install the optional peer explicitly:

Terminal window
npm install @alneas/data-engine excelize-wasm@0.1.3

The peer uses BSD-3-Clause; retain its notices when redistributing its assets. Engine’s root and ordinary /excel entry neither import nor require it. The Excelize entry loads the peer only when load() or generate() is called. Its TypeScript declarations require the peer to be installed.

import { createRequire } from 'node:module';
import { writeFile } from 'node:fs/promises';
import { ExcelizeExcelAdapter } from '@alneas/data-engine/excel/excelize';
const require = createRequire(import.meta.url);
const adapter = new ExcelizeExcelAdapter({
wasmPath: require.resolve('excelize-wasm/excelize.wasm.gz'),
});
const workbook = {
metadata: { title: 'Sales' },
sheets: [{
name: 'Sales',
columns: [
{ header: 'Item', key: 'item', width: 25 },
{ header: 'Amount', key: 'amount', format: '#,##0.00' },
],
rows: [{ item: 'Apple', amount: 150 }],
cells: [{ cell: 'B4', formula: '=SUM(B2:B3)' }],
startRow: 1,
}],
};
await writeFile('sales.xlsx', await adapter.generate(workbook));

CommonJS consumers can use require('@alneas/data-engine/excel/excelize'). Use generate() to obtain bytes on the server. As with the existing adapters, download() triggers a download only when a browser document is available.

Copy node_modules/excelize-wasm/excelize.wasm.gz to your application’s public assets as part of its build. Preserve the gzip archive bytes; do not serve it with Content-Encoding: gzip, which would make the browser decompress the asset before the upstream loader receives it. No separate wasm_exec.js script is required. Do not rely on a relative node_modules URL being available in production.

import { ExcelizeExcelAdapter } from '@alneas/data-engine/excel/excelize';
const adapter = new ExcelizeExcelAdapter({
wasmPath: '/assets/excelize.wasm.gz',
});
// Optional warm-up; generate/download also initialize lazily.
await adapter.load();
await adapter.download(workbook, 'sales.xlsx');

Include your application’s deployment base path in the asset URL. For a cross-origin asset, configure CORS. Ensure the response is the WASM archive, not an HTML fallback. Your bundler must resolve the peer’s browser module (main.js); the package’s Node entry is CommonJS. Package verification checks browser bundling, and quality CI also tests actual WASM loading, XLSX generation/readback and download in Chromium. Verify your application’s production asset delivery and CSP setup separately. CSP must permit WebAssembly compilation and the upstream loader’s JavaScript implementation. Do not weaken an application’s CSP automatically to enable this adapter. Edge/Workers execution is not covered by this adapter’s runtime tests.

All adapter instances and both module formats share one initialized runtime in a JavaScript realm. Use the same exact wasmPath string throughout the application. A different path is rejected after initialization, and a failed initialization can be retried. Do not separately call excelize-wasm.init() in that realm: it replaces the global Go runtime used by existing workbooks. The loader does not load assets merely because a module is imported.

  • At least one worksheet is required. Names must be unique ignoring case and satisfy Excelize’s sheet-name rules. No extra default sheet is retained.
  • Table headers start at startRow. Without it, headers follow the largest row referenced by cells, or start at row 1 when there are no direct cells. Table data follows the header. Direct cells are applied after table data and can override it. null/undefined leave a cell blank and do not clear an already written table cell.
  • Cell values support strings, finite numbers, booleans and Date objects. Unsupported objects, arrays, bigint and non-finite numbers are rejected. A string beginning with = stays text; use formula explicitly for formulas.
  • A column with type: 'date' accepts Date, YYYY-MM-DD, or ISO timestamps with an explicit timezone. Values become Excel 1900-system date serials using UTC, including time fractions. Supported dates are 1900–9999. Date columns and direct Date cells default to yyyy-mm-dd; an explicit format overrides it. Other type hints do not coerce values; supply actual numbers and booleans.
  • Column style formats the header. Column format formats its data cells. Cell styles support font, colors, alignment, wrapping, borders and number format. Colors use RGB with or without #. Styles are reused within a workbook.
  • Merges, column widths, row heights, grid-line visibility and document metadata map to Excelize. Explicit colWidths override table-column widths. Omitted widths use Excel’s defaults; this adapter does not auto-fit columns.
  • Formulas are written and the workbook requests recalculation when opened. Generation does not evaluate formulas or populate cached results. Spreadsheet applications differ in formula support; the adapter is not an Excel calculation engine. Charts, images and existing workbook editing are outside this data model.
  • The adapter supports XLSX only. Use CsvExcelAdapter for CSV. timeoutMs and HTTP headers are rejected: WASM generation runs synchronously after loading and cannot be cancelled with a JavaScript timeout. Large workbooks need memory for the WASM runtime and the workbook/output buffers. Use a Worker or a backend at the application level if UI responsiveness requires it.

loadExcelize(wasmPath) returns the shared upstream runtime for advanced uses, including OpenReader(bytes). Check upstream error results yourself for those operations. The adapter converts returned upstream errors into rejected promises. The existing adapters and invoice templates remain compatible. Japanese invoice presets stay in @alneas/business-jp/excel; pass their workbook definitions to this adapter. React consumers can pass it to an existing useExcelExport that accepts ExcelAdapter, without changing the hook interface.

bun run test:excelize tests the actual packed package with the installed peer in an isolated consumer. It creates XLSX, reopens it with Excelize, checks Japanese text, numbers/booleans, dates, formulas, styles, merges, dimensions, metadata, multiple sheets, initialization sharing/retry and invalid inputs. It runs ESM/CJS on Node and Bun, checks strict NodeNext declarations without Node types, and builds the Excelize entry for browsers. bun run test:excelize:browser additionally checks actual WASM/readback/download with Playwright Chromium and runs in quality CI. It installs matching Playwright 1.63.0 browser binaries into the isolated fixture and removes them afterwards. Select additional browsers with EXCELIZE_BROWSERS=chromium,firefox,webkit. test:consumer also verifies peer-free engine/Excel imports and the missing-peer error. Both are included in verify and the existing Node 24/26 quality workflow. No service or npm publication is required for this adapter’s tests.