npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

modern-xlsx

v1.0.0

Published

High-performance XLSX read/write library powered by Rust WASM. Full styling, encryption, data validation, conditional formatting — features SheetJS charges for, free and open source.

Readme


Full cell styling, data validation, conditional formatting, frozen panes, hyperlinks, comments, sheet protection, encryption, and more — features that SheetJS locks behind a paid Pro license — all free and open source.

Install

npm install modern-xlsx

Requires a runtime with WASM support (Node.js 24+, Bun, Deno, modern browsers).

Quick Start

import { initWasm, Workbook } from 'modern-xlsx';
await initWasm();

const wb = new Workbook();
wb.addSheet('Sheet1').cell('A1').value = 'Hello, Excel!';
await wb.toFile('output.xlsx');

Create a Styled Workbook

import { initWasm, Workbook, readFile } from 'modern-xlsx';
await initWasm();

const wb = new Workbook();
const ws = wb.addSheet('Sales');

ws.cell('A1').value = 'Product';
ws.cell('B1').value = 'Revenue';
ws.cell('A2').value = 'Widget';
ws.cell('B2').value = 9999.99;

// Style headers
const header = wb.createStyle()
  .font({ bold: true, size: 14, color: '1F4E79' })
  .fill({ pattern: 'solid', fgColor: 'D6E4F0' })
  .alignment({ horizontal: 'center' })
  .border({ bottom: { style: 'medium', color: '1F4E79' } })
  .build(wb.styles);

ws.cell('A1').styleIndex = header;
ws.cell('B1').styleIndex = header;

await wb.toFile('sales.xlsx');

// Read an existing file
const existing = await readFile('report.xlsx');
console.log(existing.getSheet('Sheet1')?.cell('A1').value);

Performance

Benchmarks on Node.js (single thread, v1.0.0):

| Operation | modern-xlsx | SheetJS CE | Factor | |-----------|------------:|-----------:|-------:| | Read 100K rows | 472 ms | 1,901 ms | 4.0x faster | | Read 10K rows | 69 ms | 170 ms | 2.5x faster | | Write 100K (batch aoaToSheet) | 232 ms | 1,950 ms | 8.4x faster | | Write 50K (batch aoaToSheet) | 49 ms | 80 ms | 1.6x faster | | Write 10K (cell-by-cell) | 175 ms | 125 ms | 0.7x | | sheetToCsv (10K) | 37 ms | 31 ms | ~1.0x | | sheetToJson (10K) | 36 ms | 22 ms | ~0.6x |

Summary: modern-xlsx is 4-8x faster for bulk read/write (its primary use case). SheetJS is faster for cell-by-cell writes and small utility conversions. For large workbooks, the WASM-accelerated Rust core delivers significant throughput gains.

ESM 133 KB + IIFE 60 KB + WASM 1.1 MB. Zero runtime dependencies.

Feature Comparison

| Feature | modern-xlsx | SheetJS CE | SheetJS Pro | |---------|:-----------:|:----------:|:-----------:| | Read / write XLSX | Yes | Yes | Yes | | Cell styling (fonts, fills, borders) | Free | No | Paid | | Number formats | Free | Read only | Paid | | Alignment & text wrap | Free | No | Paid | | Cell protection | Free | No | Paid | | Comments / notes | Free | Read only | Paid | | Rich text (inline formatting) | Free | No | Paid | | Data validation | Free | No | Paid | | Conditional formatting | Free | No | Paid | | Frozen panes | Free | Partial | Paid | | Hyperlinks | Free | Yes | Yes | | Auto filter | Free | Basic | Yes | | Sheet protection | Free | Read only | Paid | | Page setup & margins | Free | Margins only | Paid | | Temporal API dates | Yes | No | No | | Format cell values (SSF) | Free | Basic | Full | | Available on npm | Yes | Yes | No | | Tree-shakable ESM | Yes | No | No | | Strict TypeScript types | Yes | Partial | Partial | | WASM-accelerated I/O | Yes | No | No | | OOXML validation & repair | Yes | No | No | | Barcode & QR code generation | Yes | No | No | | Image embedding | Yes | No | Paid | | Excel Tables (ListObjects) | Yes | No | Paid | | Headers & footers | Yes | No | Paid | | Row/column grouping (outline) | Yes | No | Paid | | Print titles & areas | Yes | No | Paid | | Encryption (password protection) | Yes | No | No | | Charts (bar, line, pie, etc.) | Yes | No | Paid | | Formula engine (54 functions) | Yes | No | No | | Sparklines | Yes | No | Paid | | Pivot tables (read/write) | Yes | No | Paid | | Threaded comments | Yes | No | No | | Slicers (read/write) | Yes | No | No | | Timelines (read/write) | Yes | No | No | | Streaming writer (100K+ rows) | Yes | No | Paid | | CLI tool (info/convert) | Yes | No | No | | Feature-gated WASM | Yes | No | No |

How It Works

                    ┌────────────────────────────┐
  TypeScript API    │  Workbook / Worksheet / Cell │
                    └─────────────┬──────────────┘
                                  │ JSON
                    ┌─────────────▼──────────────┐
  WASM boundary     │  wasm-bindgen bridge        │
                    └─────────────┬──────────────┘
                                  │
                    ┌─────────────▼──────────────┐
  Rust core         │  OOXML parser & writer      │
                    │  (quick-xml + zip)          │
                    └────────────────────────────┘

Data crosses the WASM boundary as a JSON string — 8-13x faster than serde_wasm_bindgen for large workbooks. The Rust core (Rust 1.95, Edition 2024) handles all ZIP compression, XML parsing, shared string tables, and style resolution. Error paths use cold_path() hints for optimal branch layout, and hot-path helpers are #[inline]-annotated for maximum throughput.


API Reference

Initialization

import { initWasm } from 'modern-xlsx';
await initWasm(); // call once before any operation

Reading

import { readFile, readBuffer } from 'modern-xlsx';

const wb = await readFile('data.xlsx');        // Node.js / Bun / Deno
const wb = await readBuffer(uint8Array);       // any environment

Writing

await wb.toFile('output.xlsx');                // Node.js / Bun / Deno
const buffer = await wb.toBuffer();            // Uint8Array

import { writeBlob } from 'modern-xlsx';
const blob = writeBlob(wb);                    // browser Blob

Workbook

const wb = new Workbook();

wb.sheetNames;                     // string[]
wb.sheetCount;                     // number
wb.dateSystem;                     // 'date1900' | 'date1904'
wb.styles;                         // StylesData

wb.addSheet('Name');               // Worksheet
wb.getSheet('Name');               // Worksheet | undefined
wb.getSheetByIndex(0);             // Worksheet | undefined
wb.removeSheet('Name');            // boolean
wb.removeSheet(0);                 // boolean

// Named ranges
wb.addNamedRange('MyRange', 'Sheet1!$A$1:$D$10');
wb.getNamedRange('MyRange');
wb.removeNamedRange('MyRange');

// Document properties
wb.docProperties = { title: 'Report', creator: 'App' };

// Workbook views
wb.workbookViews = [{
  activeTab: 0,
  firstSheet: 0,
  showHorizontalScroll: true,
  showVerticalScroll: true,
  showSheetTabs: true,
}];

Worksheet

const ws = wb.addSheet('Sheet1');

// Cell access
ws.cell('A1').value = 'Hello';
ws.cell('B1').value = 42;
ws.cell('C1').value = true;
ws.cell('D1').formula = 'SUM(B1:B100)';

// Columns & rows
ws.setColumnWidth(1, 20);
ws.setRowHeight(1, 30);
ws.setRowHidden(2, true);

// Merge cells
ws.addMergeCell('A1:D1');
ws.removeMergeCell('A1:D1');

// Frozen panes
ws.frozenPane = { rows: 1, cols: 0 };

// Auto filter
ws.autoFilter = 'A1:D100';
ws.autoFilter = {
  range: 'A1:D100',
  filterColumns: [{ colId: 0, filters: ['Yes'] }],
};

// Hyperlinks
ws.addHyperlink('A1', '#Sheet2!A1', {
  display: 'Go to Sheet2',
  tooltip: 'Click',
});
ws.removeHyperlink('A1');

// Data validation
ws.addValidation('B2:B100', {
  validationType: 'list',
  operator: null,
  formula1: '"Yes,No,Maybe"',
  formula2: null,
  allowBlank: true,
  showErrorMessage: true,
  errorTitle: 'Invalid',
  errorMessage: 'Pick from list',
});

// Comments
ws.addComment('A1', 'Author', 'This is a comment');
ws.removeComment('A1');

// Threaded comments (modern Excel)
const commentId = ws.addThreadedComment('A1', 'Discussion point', 'Alice');
ws.replyToComment(commentId, 'I agree', 'Bob');
ws.threadedComments;              // readonly ThreadedCommentData[]

// Pivot tables (read/write)
ws.pivotTables;                   // readonly PivotTableData[]
ws.addPivotTable({ name: 'Sales', cacheId: 0, location: { ref: 'A3:D20' }, pivotFields: [], rowFields: [], colFields: [], dataFields: [], pageFields: [] });
ws.removePivotTable(0);           // boolean

// Slicers & timelines (read/write)
ws.slicers;                       // readonly SlicerData[]
ws.addSlicer({ name: 'Slicer_Region', cacheName: 'Slicer_Region' });
ws.removeSlicer(0);               // boolean
ws.timelines;                     // readonly TimelineData[]
ws.addTimeline({ name: 'Timeline_Date', cacheName: 'NativeTimeline_Date' });
ws.removeTimeline(0);             // boolean

// Page setup & margins
ws.pageSetup = { orientation: 'landscape', paperSize: 9 };
ws.pageMargins = {
  top: 0.75, bottom: 0.75,
  left: 0.7, right: 0.7,
  header: 0.3, footer: 0.3,
};

// Sheet protection
ws.sheetProtection = {
  sheet: true, objects: false, scenarios: false,
  formatCells: false, formatColumns: false, formatRows: false,
  insertColumns: false, insertRows: false,
  deleteColumns: false, deleteRows: false,
  sort: false, autoFilter: false,
};

// Excel Tables (ListObjects)
ws.addTable({
  name: 'SalesData', ref: 'A1:B3',
  columns: [{ name: 'Product' }, { name: 'Revenue' }],
  style: { name: 'TableStyleMedium9', showRowStripes: true },
});
ws.tables;                         // TableDefinitionData[]
ws.getTable('SalesData');          // TableDefinitionData | undefined
ws.removeTable('SalesData');       // boolean

// Headers & Footers
import { HeaderFooterBuilder } from 'modern-xlsx';
ws.headerFooter = {
  oddHeader: new HeaderFooterBuilder()
    .left(HeaderFooterBuilder.date())
    .center(HeaderFooterBuilder.bold('Report'))
    .right(`Page ${HeaderFooterBuilder.pageNumber()}`)
    .build(),
};

// Row & Column Grouping
ws.groupRows(2, 10);              // outline level 1
ws.groupRows(3, 5, 2);            // nested level 2
ws.collapseRows(2, 10);
ws.expandRows(2, 10);
ws.groupColumns(1, 3);            // columns A-C
ws.outlineProperties = { summaryBelow: true, summaryRight: true };

// Print Titles & Areas
wb.setPrintTitles('Sheet1', { rows: { start: 1, end: 1 } });
wb.setPrintArea('Sheet1', 'A1:G50');

Charts

Create Excel charts with the fluent ChartBuilder API:

import { ChartBuilder } from 'modern-xlsx';

const ws = wb.addSheet('Sales');
ws.cell('A1').value = 'Q1'; ws.cell('A2').value = 'Q2';
ws.cell('B1').value = 100;  ws.cell('B2').value = 200;

// Create a bar chart
const chart = new ChartBuilder('bar')
  .title('Quarterly Sales')
  .addSeries({ name: 'Revenue', values: 'Sales!$B$1:$B$4' })
  .categoryAxis({ title: 'Quarter' })
  .valueAxis({ title: 'Amount ($)' })
  .size(800, 400)
  .build();

ws.addChart(chart);

// Supported types: bar, column, line, pie, area, scatter, radar, doughnut, bubble, stock

Formula Engine

Evaluate 54 built-in Excel functions in-memory:

import { evaluateFormula, createDefaultFunctions } from 'modern-xlsx';

const ctx = {
  getCell: (sheet, col, row) => wb.getSheet(sheet)?.cell(encodeCellRef(row - 1, letterToColumn(col)))?.value ?? null,
  currentSheet: 'Sheet1',
  functions: createDefaultFunctions(),
};

const result = evaluateFormula('SUM(A1:A10)', ctx);
// Supports: SUM, AVERAGE, COUNT, IF, VLOOKUP, INDEX/MATCH, CONCATENATE, and 46 more

Encryption

Read and write password-protected XLSX files (ECMA-376 Standard Encryption):

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

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

Styles

Fluent builder that produces a style index for any cell:

const idx = wb.createStyle()
  .font({ name: 'Arial', size: 12, bold: true, color: 'FF0000' })
  .fill({ pattern: 'solid', fgColor: 'FFFF00' })
  .border({
    top:    { style: 'thin',   color: '000000' },
    bottom: { style: 'double', color: '000000' },
    left:   { style: 'thin',   color: '000000' },
    right:  { style: 'thin',   color: '000000' },
  })
  .alignment({ horizontal: 'center', vertical: 'top', wrapText: true, textRotation: 45 })
  .protection({ locked: true, hidden: false })
  .numberFormat('#,##0.00')
  .build(wb.styles);

ws.cell('A1').styleIndex = idx;

Utilities

import {
  aoaToSheet, jsonToSheet, sheetToJson, sheetToCsv, sheetToHtml,
  sheetAddAoa, sheetAddJson,
  dateToSerial, serialToDate, isDateFormatId, isDateFormatCode,
  formatCell,
  encodeCellRef, decodeCellRef, encodeRange, decodeRange,
  columnToLetter, letterToColumn,
} from 'modern-xlsx';

// Array-of-arrays -> sheet
const ws = aoaToSheet([
  ['Name', 'Age'],
  ['Alice', 30],
  ['Bob', 25],
]);

// JSON -> sheet
const ws2 = jsonToSheet([
  { name: 'Alice', age: 30 },
  { name: 'Bob', age: 25 },
]);

// Sheet -> JSON / CSV / HTML
const data = sheetToJson(ws);     // [{ Name: 'Alice', Age: 30 }, ...]
const csv  = sheetToCsv(ws);      // "Name,Age\nAlice,30\nBob,25"
const html = sheetToHtml(ws);     // "<table>..."

// Append to existing sheet
sheetAddAoa(ws, [['Charlie', 35]], { origin: 'A4' });
sheetAddJson(ws, [{ name: 'Diana', age: 28 }]);

// Limit rows
const first5 = sheetToJson(ws, { sheetRows: 5 });

// Date conversion (Date and Temporal API)
const serial = dateToSerial(new Date(2024, 0, 1));
const serial2 = dateToSerial({ year: 2024, month: 1, day: 1 }); // Temporal-like
const date = serialToDate(45292);

// Format cell value using Excel format code
formatCell(45292, 'yyyy-mm-dd'); // "2024-01-01"

// Cell references
decodeCellRef('B3');  // { row: 2, col: 1 }
encodeCellRef(2, 1);  // "B3"

Validation & Repair

WASM-accelerated OOXML compliance checking and auto-repair:

const wb = new Workbook();
const ws = wb.addSheet('Sheet1');
ws.cell('A1').value = 'Hello';
ws.cell('A1').styleIndex = 999; // dangling!

// Validate — returns a structured report
const report = wb.validate();
console.log(report.isValid);       // false
console.log(report.errorCount);    // 1
console.log(report.issues[0]);
// {
//   severity: 'error',
//   category: 'styleIndex',
//   message: 'Cell A1 styleIndex=999 exceeds cellXfs count (1)',
//   location: 'Sheet1!A1',
//   suggestion: 'Clamp styleIndex to 0',
//   autoFixable: true
// }

// Repair — auto-fixes all repairable issues
const { workbook, report: postReport, repairCount } = wb.repair();
console.log(repairCount);          // 2 (style index + missing theme)
console.log(postReport.isValid);   // true

Detects: dangling style/font/fill/border indices, overlapping merges, invalid cell refs, duplicate sheet names, bad metadata dates, missing required styles, missing theme colors, unsorted rows, SharedString cells without values.

Barcode & QR Code Generation

Generate barcodes and embed them as images — pure TypeScript, zero dependencies:

import { Workbook, generateBarcode, encodeQR, renderBarcodePNG } from 'modern-xlsx';

const wb = new Workbook();
wb.addSheet('Labels');

// High-level: generate + embed in one call
wb.addBarcode('Labels',
  { fromCol: 0, fromRow: 0, toCol: 4, toRow: 4 },
  'https://example.com',
  { type: 'qr', ecLevel: 'M' },
);

// Or use the low-level pipeline:
const matrix = encodeQR('Hello', { ecLevel: 'H' });
const png = renderBarcodePNG(matrix, { moduleSize: 6, showText: true, textValue: 'Hello' });
wb.addImage('Labels', { fromCol: 5, fromRow: 0, toCol: 9, toRow: 4 }, png);

Supported formats: QR Code, Code 128, EAN-13, UPC-A, Code 39, PDF417, Data Matrix, ITF-14, GS1-128.

See the Barcode Guide for format comparison and usage details.

CLI Tool

# Show sheet info
npx modern-xlsx info report.xlsx

# Convert to JSON
npx modern-xlsx convert report.xlsx output.json

# Export single sheet as CSV
npx modern-xlsx convert report.xlsx sheet1.csv --sheet 0 --format csv

Error Handling

import { ModernXlsxError } from 'modern-xlsx';

try {
  ws.replyToComment('nonexistent-id', 'text', 'author');
} catch (e) {
  if (e instanceof ModernXlsxError) {
    console.log(e.code);    // 'COMMENT_NOT_FOUND'
    console.log(e.message); // 'Comment nonexistent-id not found'
  }
}

Rich Text

import { RichTextBuilder } from 'modern-xlsx';

const runs = new RichTextBuilder()
  .text('Normal ')
  .bold('Bold ')
  .italic('Italic ')
  .styled('Custom', { color: 'FF0000', fontSize: 14 })
  .build();

Browser Usage (ESM)

<script type="module">
  import { initWasm, Workbook, writeBlob } from 'modern-xlsx';

  await initWasm();

  const wb = new Workbook();
  wb.addSheet('Sheet1').cell('A1').value = 'Hello from browser!';

  const blob = writeBlob(wb);
  const a = document.createElement('a');
  a.href = URL.createObjectURL(blob);
  a.download = 'output.xlsx';
  a.click();
</script>

Browser Usage (CDN / IIFE)

Single <script> tag — no bundler required:

<script src="https://cdn.jsdelivr.net/npm/modern-xlsx@latest/dist/modern-xlsx.min.js"></script>
<script>
  (async () => {
    await ModernXlsx.initWasm();
    const wb = new ModernXlsx.Workbook();
    wb.addSheet('Sheet1').cell('A1').value = 'Hello!';
    const blob = ModernXlsx.writeBlob(wb);
    // trigger download...
  })();
</script>

Also available via unpkg: https://unpkg.com/modern-xlsx@latest/dist/modern-xlsx.min.js

Web Worker (Off-Thread)

Keep the main thread responsive by running XLSX operations in a Web Worker:

import { createXlsxWorker } from 'modern-xlsx';

const worker = createXlsxWorker({
  workerUrl: '/modern-xlsx.worker.js',
  wasmUrl: '/modern-xlsx.wasm',  // optional
});

const data = await worker.readBuffer(xlsxBytes);
const output = await worker.writeBuffer(data);
worker.terminate();

Lazy Initialization

Auto-initialize WASM on first use:

import { ensureReady, Workbook } from 'modern-xlsx';

await ensureReady();  // no-op if already initialized
const wb = new Workbook();

Custom WASM URL

For environments where auto-detection doesn't work:

import { initWasm } from 'modern-xlsx';

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

// From fetch Response
const res = await fetch('/wasm/modern-xlsx.wasm');
await initWasm(res);

Types

All types are exported and include full TypeScript definitions:

import type {
  WorkbookData, WorksheetData, SheetData, CellData, RowData,
  StylesData, FontData, FillData, BorderData, AlignmentData, ProtectionData,
  CellXfData, NumFmt, ColumnInfo, FrozenPane,
  AutoFilterData, FilterColumnData, HyperlinkData,
  DataValidationData, ConditionalFormattingData,
  PageSetupData, SheetProtectionData,
  DocPropertiesData, ThemeColorsData, WorkbookViewData,
  RichTextRun, DefinedNameData, CalcChainEntryData,
  // Validation & compliance
  ValidationReport, ValidationIssue, Severity, IssueCategory, RepairResult,
  // Barcode & image embedding
  BarcodeMatrix, DrawBarcodeOptions, RenderOptions, ImageAnchor,
  // Tables & print layout
  TableDefinitionData, TableColumnData, TableStyleInfoData,
  HeaderFooterData, OutlinePropertiesData,
  // Charts
  ChartDataModel, ChartSeriesData, ChartAxisData, ChartType,
  ChartAnchorData, ChartGrouping, ChartLegendData,
  // Formula engine
  ASTNode, CellValue, EvalContext, FormulaFunction,
  // Pivot tables & caches
  PivotTableData, PivotFieldData, PivotDataFieldData, PivotAxis, SubtotalFunction,
  PivotCacheDefinitionData, PivotCacheRecordsData, CacheFieldData, CacheSource, CacheValue,
  // Threaded comments
  ThreadedCommentData, PersonData,
  // Slicers & timelines
  SlicerData, SlicerCacheData, TimelineData, TimelineCacheData,
  // Streaming writer
  StreamingXlsxWriter, StreamingCellInput,
} from 'modern-xlsx';

Pivot Tables

const wb = await readAsync(buffer);
const ws = wb.getSheet('PivotReport');

// Read pivot table metadata
for (const pt of ws.pivotTables) {
  console.log(pt.name, pt.location);
}

// Add a pivot table
ws.addPivotTable({
  name: 'SalesPivot', cacheId: 0,
  location: { ref: 'A3:D20' },
  pivotFields: [{ items: [], name: 'Region', axis: 'axisRow' }],
  rowFields: [{ x: 0 }], colFields: [], dataFields: [], pageFields: [],
});

// Workbook-level pivot caches
wb.addPivotCache({ source: { ref: 'A1:D100', sheet: 'Data' } });

Threaded Comments

const ws = wb.getSheet('Sheet1');

// Add a threaded comment
ws.addThreadedComment('A1', 'Review this value', 'Alice');
ws.replyToComment('A1', 'Looks correct to me', 'Bob');

// Read threaded comments
for (const tc of ws.threadedComments) {
  console.log(tc.ref, tc.text, tc.author);
}

Slicers & Timelines

const ws = wb.getSheet('Dashboard');

// Read slicers & timelines
for (const slicer of ws.slicers) console.log(slicer.name, slicer.caption);
for (const tl of ws.timelines) console.log(tl.name, tl.caption);

// Add a slicer
ws.addSlicer({ name: 'Slicer_Region', cacheName: 'Slicer_Region', caption: 'Region' });
wb.addSlicerCache({ name: 'Slicer_Region', sourceName: 'Region', items: [{ n: 'East', s: true }, { n: 'West', s: false }] });

// Add a timeline
ws.addTimeline({ name: 'Timeline_Date', cacheName: 'NativeTimeline_Date', caption: 'Date', level: 'months' });
wb.addTimelineCache({ name: 'NativeTimeline_Date', sourceName: 'Date', selectionStart: '2024-01-01', selectionEnd: '2024-12-31' });

Streaming Writer (Large Files)

import { initWasm, StreamingXlsxWriter } from 'modern-xlsx';

await initWasm();
const writer = StreamingXlsxWriter.create();
writer.startSheet('Data');
for (let i = 0; i < 100_000; i++) {
  writer.writeRow([
    { value: String(i), cellType: 'number' },
    { value: `row_${i}`, cellType: 'sharedString' },
  ]);
}
const xlsx: Uint8Array = writer.finish();

CLI Tool

# Get workbook info
modern-xlsx info report.xlsx

# Convert to JSON
modern-xlsx convert report.xlsx output.json

# Convert to CSV
modern-xlsx convert report.xlsx output.csv

License

MIT