Skip to content

Getting Started ​

MarcusOK publishes two packages across two categories — how they relate is on the Ecosystem page. This page starts with the one decision that comes first (which package to install), then walks through a first export with the most common one.

Requirement: Node >= 22. Example commands use pnpm; npm / yarn work the same (pnpm >= 9 is only a dev requirement of this repository, not of consumers).

Which package do I need? ​

I want to…InstallStart at
Export data to a downloadable .xlsx@marcusok/excel-exporterThe exporter walkthrough below
Show an uploaded .xlsx / .xlsm / .csv, read-only@marcusok/excel-previewPreview quick start

Everything below walks through @marcusok/excel-exporter; the preview's quick start is linked in the table above. For the two tasks that used to be separate packages: the progress overlay is reachable through the exporter's /overlay subpath (Overlay guide), and there is no longer a standalone engine package — both business packages bundle the engine and re-export its loader. The full comparison — dependency graph, what is bundled at runtime, how versions relate — is in Package Relationships & Selection.

1. Install ​

bash
pnpm add @marcusok/excel-exporter

That is the entire setup — no same-scope runtime dependencies to think about. The export engine (modern-xlsx JS glue + fflate) and the progress overlay UI are bundled into the package's dist at build time, and the WASM binary ships under the package's own exports map, so there is no engine package to wire in and no engines conflict from upstream ranges.

2. First export ​

ts
import { exportExcel, StylePresets } from "@marcusok/excel-exporter";

await exportExcel({
  filename: "sales-report-2026",
  sheets: [
    {
      name: "Sales",
      freezeRows: 1,
      autoFilter: true,
      columns: [
        { prop: "orderId", label: "Order ID", width: 18 },
        { prop: "date", label: "Date", width: 12, format: { type: "date" } },
        {
          prop: "amount",
          label: "Amount",
          width: 14,
          style: StylePresets.currency,
        },
        {
          prop: "status",
          label: "Status",
          width: 10,
          format: {
            type: "enum",
            map: { paid: "Paid", pending: "Pending" },
            fallback: "Unknown",
          },
        },
      ],
      data: [
        {
          orderId: "ORD-000001",
          date: "2026-07-01",
          amount: 1299.99,
          status: "paid",
        },
      ],
    },
  ],
});

In the browser this triggers a download; .xlsx is appended when missing. Use download: false to receive the Blob only.

No main.ts wiring, no bundler plugins: the shipped assets (this package's own modern-xlsx.wasm and export.worker.js) are located automatically — bundlers emit them as hashed assets via the standard new URL(asset, import.meta.url) pattern, and Node reads the wasm from disk. Node / SSR environments need no browser assets and no initialization boilerplate (see Node/SSR). Self-hosted or CDN-hosted copies are the one case that needs configureWasm.

3. Next steps ​