xlsx-writer-lite
v0.3.0
Published
A lightweight XLSX writing library
Readme
xlsx-writer
A lightweight TypeScript library for writing XLSX files. Supports plain arrays and object-with-columns modes, multi-sheet workbooks, CSS-like cell styling, and minimal dependencies (~9KB gzipped).
Installation
bun add xlsx-writer-lite
# or
npm install xlsx-writer-liteUsage
import { writeWorkbook } from 'xlsx-writer-lite';
// Plain 2D array
const blob = await writeWorkbook([
['Name', 'Age', 'Active'],
['Alice', 30, true],
['Bob', 25, false],
]);
// Object mode with columns and header
const blob = await writeWorkbook(
[
{ name: 'Alice', age: 30, joined: new Date('2024-01-15') },
{ name: 'Bob', age: 25, joined: new Date('2024-06-01') },
],
[
{ id: 'name', label: 'Name', width: 20 },
{ id: 'age', label: 'Age', style: { textAlign: 'right' } },
{ id: 'joined', label: 'Joined', width: 14 },
],
{ header: true },
);
// Multiple sheets in one workbook
const blob = await writeWorkbook([
{
name: 'People',
data: [{ name: 'Alice', age: 30 }],
columns: [{ id: 'name' }, { id: 'age' }],
header: true,
},
{
name: 'Raw Data',
data: [
['x', 'y'],
[1, 2],
],
},
]);API
writeWorkbook(data, settings?)
Creates an XLSX file from a plain 2D array.
| Parameter | Type | Description |
| ---------- | ---------------- | ------------------------------- |
| data | CellValue[][] | Row-major 2D array of values |
| settings | WriteSettings | Optional settings |
Returns: Promise<Blob> — XLSX file blob
writeWorkbook(data, columns, settings?)
Creates an XLSX file from an array of objects with column descriptors.
| Parameter | Type | Description |
| ---------- | ------------------------ | ------------------------------ |
| data | Record<string, unknown>[] | Array of data objects |
| columns | ColumnConfig[] | Column definitions |
| settings | WriteSettings | Optional settings |
Returns: Promise<Blob> — XLSX file blob
ColumnConfig:
| Field | Type | Required | Description |
| ------------- | ----------- | -------- | ---------------------------------------- |
| id | string | yes | Property key to read from each object |
| label | string | no | Header label (defaults to id) |
| width | number | no | Column width in Excel character units |
| style | CellStyle | no | Style applied to every data cell |
| headerStyle | CellStyle | no | Style applied to the header cell |
| dateFormat | string | no | Excel format code for Date values in this column; overrides the sheet default |
WriteSettings:
| Field | Type | Default | Description |
| ------------ | --------- | ---------- | ------------------------------------- |
| header | boolean | — | Prepend a header row from labels/ids |
| sheetName | string | "Sheet1" | Name of the worksheet tab |
| dateFormat | string | m/d/yyyy | Default Excel format code for Date values (e.g. "dd/mm/yyyy hh:mm") |
| dateUTC | boolean | false | Write Date values using their UTC reading instead of the local wall clock |
writeWorkbook(sheet, settings?) / writeWorkbook(sheets, settings?)
Creates an XLSX file from one worksheet configuration or an array of them — one Excel tab per config. Each sheet independently uses either 2D-array or object-with-columns data.
| Parameter | Type | Description |
| ---------- | ------------------------------------- | --------------------------------- |
| sheet(s) | WorksheetConfig \| WorksheetConfig[] | Worksheet definitions |
| settings | WorkbookSettings | Optional workbook-level settings |
Returns: Promise<Blob> — XLSX file blob
WorksheetConfig:
| Field | Type | Required | Description |
| ------------ | ------------------------------------------- | -------- | -------------------------------------------- |
| data | CellValue[][] \| Record<string, unknown>[] | yes | Sheet data: 2D array, or objects (needs columns) |
| name | string | no | Tab name (defaults to "Sheet1", "Sheet2", …) |
| columns | ColumnConfig[] | no | Column definitions; required for object data |
| header | boolean | no | Prepend a header row from labels/ids |
| dateFormat | string | no | Default Excel format code for Date values in this sheet |
| dateUTC | boolean | no | Write Date values using their UTC reading |
WorkbookSettings:
| Field | Type | Description |
| ---------------------- | -------------------------- | ------------------------------------------------- |
| defaultSheetSettings | Partial<WorksheetConfig> | Defaults merged into every sheet config; per-sheet values win |
// Shared defaults across sheets
const blob = await writeWorkbook(
[
{ name: 'Q1', data: q1Rows, columns },
{ name: 'Q2', data: q2Rows, columns },
],
{ defaultSheetSettings: { header: true, dateFormat: 'dd/mm/yyyy' } },
);Dates and Timezones
Excel serial dates are timezone-naive wall-clock values. By default, Date
values are written as the local wall clock — the same date and time the
user's browser displays. Set dateUTC: true (per call or per sheet) to write
the UTC reading instead, which is useful for server timestamps that should
render identically for every user.
Helper Functions
columnLetter(index)
Converts a 0-based column index to an Excel column letter.
import { columnLetter } from 'xlsx-writer-lite';
columnLetter(0); // → "A"
columnLetter(25); // → "Z"
columnLetter(26); // → "AA"jsDateToExcelDate(date, utc?)
Converts a JavaScript Date to an Excel serial date number. Uses the date's
local wall clock by default; pass true as the second argument for its UTC
reading.
import { jsDateToExcelDate } from 'xlsx-writer-lite';
jsDateToExcelDate(new Date(2025, 0, 15)); // → 45672
jsDateToExcelDate(new Date('2025-01-15T00:00:00Z'), true); // → 45672Cell Types
| JavaScript Type | Excel Cell Type | Notes |
| --------------- | --------------- | ------------------------------------- |
| string | Shared string | Deduplicated in shared string table |
| number | Number | Written as-is |
| boolean | Boolean | true → 1, false → 0 |
| Date | Number + format | Serial date with m/d/yyyy format |
| null | Empty | Cell omitted (unless styled) |
Cell Styles
Styles use a rigid CSS subset — the same CellStyle shape as xlsx-reader-lite
interface CellStyle {
fontWeight?: 'bold';
fontStyle?: 'italic';
textDecoration?: string; // "underline", "line-through", "underline line-through"
fontSize?: string; // "11pt"
fontFamily?: string; // "Calibri"
color?: string; // "#FF0000"
backgroundColor?: string; // "#FFFF00"
borderTop?: string; // "1px solid #000000"
borderRight?: string;
borderBottom?: string;
borderLeft?: string;
textAlign?: 'left' | 'center' | 'right' | 'justify';
verticalAlign?: 'top' | 'middle' | 'bottom';
whiteSpace?: 'normal' | 'nowrap' | 'pre-wrap';
}Border Shorthand
Borders use CSS shorthand "<width> <style> <color>":
| CSS Value | Excel Style |
| ------------------ | ------------------ |
| 1px solid #000 | thin |
| 2px solid #000 | medium |
| 3px solid #000 | thick |
| 1px dashed #000 | dashed |
| 1px dotted #000 | dotted |
| 3px double #000 | double |
| 2px dashed #000 | mediumDashed |
| 2px dotted #000 | mediumDashDotDot |
Style Example
const blob = await writeWorkbook(
[{ product: 'Widget', total: 1500 }],
[
{
id: 'product',
label: 'Product',
width: 25,
headerStyle: {
fontWeight: 'bold',
backgroundColor: '#4472C4',
color: '#FFFFFF',
borderBottom: '2px solid #000000',
},
},
{
id: 'total',
label: 'Total',
style: { textAlign: 'right' },
headerStyle: {
fontWeight: 'bold',
backgroundColor: '#4472C4',
color: '#FFFFFF',
borderBottom: '2px solid #000000',
},
},
],
{ header: true },
);Browser Usage
For CDN/browser usage, use the bundled version:
<script type="module">
import { writeWorkbook, downloadBlob } from './index.bundle.js';
const blob = await writeWorkbook([
['Name', 'Score'],
['Alice', 95],
]);
downloadBlob(blob, 'report.xlsx');
</script>Bundle Size
| Build | Size | | ------------------ | ------ | | Library (ESM) | ~17 KB | | Bundled (all deps) | ~21 KB | | Bundled + gzipped | ~9 KB |
License
MIT
