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

json-as-xlsx

v2.6.4

Published

Create excel xlsx file from json

Readme

json-as-xlsx

npm version npm downloads Test suites license

Build an Excel (.xlsx) file straight from JSON. It is a thin, typed wrapper around the SheetJS-compatible @e965/xlsx library, so it works both in the browser (downloads the file) and in Node.js (can return a buffer when configured).

You can see a live demo on any of these sites (there are several, just in case):

Features

  • 📊 Turn an array of JSON sheets into a multi-sheet workbook.
  • 🧱 Render several tables in the same sheet (opt-in, vertical or horizontal layout).
  • 🧭 Read deeply nested values ("more.phone") or compute them with a function.
  • 🎨 Per-column number, date, currency and hyperlink formatting.
  • 🖌️ Opt-in cell styling for fonts, fills, borders, alignment and number formats.
  • ⬜ Opt-in true blank cells for empty, null or missing values.
  • 📐 Automatic column widths (tunable with extraLength).
  • ↔️ Right-to-left (RTL) sheet support.
  • 🌐 Works in the browser (file download) and in Node.js (file or buffer output).
  • 🟦 Written in TypeScript — ships with type definitions.

Installation

npm install json-as-xlsx
# or
yarn add json-as-xlsx
# or
pnpm add json-as-xlsx

Usage

import xlsx from "json-as-xlsx"
// Alternative import styles:
// import { xlsx } from "json-as-xlsx"
// const xlsx = require("json-as-xlsx")

let data = [
  {
    sheet: "Employees",
    columns: [
      { label: "Name", value: "name" }, // Top level data
      { label: "Salary", value: (row) => row.salary + " USD" }, // Custom format
      { label: "Email", value: (row) => (row.contact ? row.contact.email || "" : "") }, // Run functions
    ],
    content: [
      { name: "Ada Lovelace", salary: 5000, contact: { email: "[email protected]" } },
      { name: "Grace Hopper", salary: 6200, contact: { email: "[email protected]" } },
    ],
  },
  {
    sheet: "Products",
    columns: [
      { label: "Product", value: "product" }, // Top level data
      { label: "Price", value: "price", format: "$#,##0.00" }, // Column format
      { label: "Stock", value: "inventory.stock", format: "#,##0" }, // Deep props and column format
    ],
    content: [
      { product: "Keyboard", price: 29.99, inventory: { stock: 1200 } },
      { product: "Monitor", price: 199.5, inventory: { stock: 340 } },
    ],
  },
]

let settings = {
  fileName: "MySpreadsheet", // Name of the resulting spreadsheet
  enableStyles: false, // Set to true to write cell styles (`s`) into the .xlsx file
  extraLength: 3, // A bigger number means that columns will be wider
  writeMode: "writeFile", // The available parameters are 'writeFile' and 'write'. This setting is optional. Useful in such cases https://docs.sheetjs.com/docs/solutions/output#example-remote-file
  writeOptions: {}, // Style options from https://docs.sheetjs.com/docs/api/write-options
  RTL: true, // Display the columns from right-to-left (the default value is false)
  writeEmptyValuesAsBlankCells: false, // Set to true so Excel treats empty, null and missing values as blank cells
}

xlsx(data, settings) // Will download the excel file

Settings

| Option | Type | Default | Description | | ------------------------------ | ----------------------- | --------------- | --------------------------------------------------------------------------------------------------- | | enableStyles | boolean | false | Write cell style objects into the .xlsx file. Only supported with bookType: "xlsx". | | fileName | string | "Spreadsheet" | Name of the resulting file (the .xlsx extension is added automatically). | | extraLength | number | 1 | Extra characters added to every auto-calculated column width. | | writeMode | "writeFile"/"write" | "writeFile" | "writeFile" downloads/writes the file; "write" returns the raw data (e.g. a Node buffer). | | writeOptions | object | {} | Passed straight to SheetJS — see write options. | | RTL | boolean | false | Render every sheet right-to-left. | | writeEmptyValuesAsBlankCells | boolean | false | Omit empty-string, null, undefined and missing-path values so Excel treats them as blank cells. |

True blank cells

For backward compatibility, empty values are written as empty strings by default. Excel can count those cells as text values even when they look blank. Set writeEmptyValuesAsBlankCells: true to omit empty-string, null, undefined and missing-path values from the worksheet XML:

let data = [
  {
    sheet: "Sparse data",
    columns: [
      { label: "ID", value: "id" },
      { label: "Email", value: (row) => row.contact?.email ?? "" },
      { label: "Score", value: "score", format: "0.00" },
    ],
    content: [{ id: "ID-101", contact: { email: "[email protected]" }, score: 98.5 }, { id: "ID-102", contact: { email: "" } }, { id: "ID-103", score: null }, { id: "ID-104" }],
  },
]

xlsx(data, {
  fileName: "BlankCellSpreadsheet",
  writeEmptyValuesAsBlankCells: true,
})

Values like 0 and false are still written normally.

This option applies to both string-path columns (value: "email") and function columns (value: (row) => row.email ?? ""). Formats, hyperlinks and cell styles are applied only to cells that still have a value; blank cells remain truly blank. Sheets or multi-table entries with no content still render their headers.

Callback

If you want to inspect or post-process the workbook, pass a callback as the third argument. It receives the generated WorkBook right before it is written, so you can read or mutate it:

let callback = function (workbook) {
  console.log("Workbook ready:", workbook.SheetNames)
}

xlsx(data, settings, callback) // Will download the excel file

Use in Node.js (server-side)

Set writeOptions.type to "buffer" (or writeMode: "write") to get the file contents back instead of writing them to disk. This is handy for sending the spreadsheet over HTTP:

import xlsx from "json-as-xlsx"

const settings = {
  writeOptions: {
    type: "buffer",
    bookType: "xlsx",
  },
}

app.get("/download", (_, res) => {
  const buffer = xlsx(data, settings)
  res.writeHead(200, {
    "Content-Type": "application/octet-stream",
    "Content-Disposition": "attachment; filename=MySheet.xlsx",
  })
  res.end(buffer)
})

Column formatting

Note: Cell formatting is type based, i.e. the format type and value type must match.

If you want to use a Date format, the value must be of type Date; if you want a number format, the value must be a Number.

Column formatting can be provided in the column object, i.e.

columns: [{ label: "Income", value: "income", format: "€#,##0.00" }]

Examples

// Number formats
"$0.00" // Basic
"\£#,##0.00" // Pound
"0%" // Percentage
'#.# "ft"' // Number and text

// Date formats
"d-mmm-yy" // 12-Mar-22
"ddd" // (eg. Sat)
"dddd" // (eg. Saturday)
"h:mm AM/PM" // 1:10 PM

Hyperlinks

Use the special "hyperlink" format to turn a column's text values into clickable links:

columns: [{ label: "Website", value: "url", format: "hyperlink" }]

Cell Styling

Cell styling is disabled by default to keep the regular export path unchanged. Set enableStyles: true to write style objects into the generated .xlsx file. Styled exports only support XLSX output; if you set writeOptions.bookType, keep it as "xlsx".

You can style headers, full columns, or individual cell values:

let data = [
  {
    sheet: "Styled employees",
    columns: [
      {
        label: "Name",
        value: "name",
        headerStyle: {
          fill: { fgColor: { rgb: "21A366" } },
          font: { bold: true, color: { rgb: "FFFFFF" } },
        },
        cellStyle: {
          alignment: { wrapText: true },
        },
      },
      {
        label: "Salary",
        value: "salary",
        format: "$#,##0.00",
        cellStyle: {
          font: { italic: true },
        },
      },
    ],
    content: [
      {
        name: {
          v: "Ada\nLovelace",
          t: "s",
          s: { font: { bold: true, color: { rgb: "FF0000" } } },
        },
        salary: 5000,
      },
    ],
  },
]

xlsx(data, {
  fileName: "StyledSpreadsheet",
  enableStyles: true,
})

Supported style groups are alignment, border, fill, font, and numFmt. Column format values are also preserved as number formats when styles are enabled.

Multiple tables per sheet

By default a sheet renders a single table from its columns and content. To place several independent tables in the same sheet, provide a tables array instead — each entry has its own columns and content (with the same formatting and styling options). This is fully opt-in: sheets that don't set tables keep working exactly as before.

let data = [
  {
    sheet: "Quarter summary",
    tablesLayout: "vertical", // "vertical" (default) stacks tables; "horizontal" places them side by side
    tablesGap: 1, // blank rows (vertical) or columns (horizontal) between tables — defaults to 1
    tables: [
      {
        columns: [
          { label: "Product", value: "product" },
          { label: "Revenue", value: "revenue", format: "$#,##0.00" },
        ],
        content: [
          { product: "Keyboard", revenue: 35988 },
          { product: "Monitor", revenue: 67830 },
        ],
      },
      {
        columns: [
          { label: "Team", value: "team" },
          { label: "Expenses", value: "expenses", format: "$#,##0.00" },
        ],
        content: [
          { team: "Engineering", expenses: 42000 },
          { team: "Marketing", expenses: 18500 },
        ],
      },
    ],
  },
]

xlsx(data, { fileName: "MultiTableSpreadsheet" })

When tables is present and non-empty it takes precedence over the sheet's top-level columns/content.

| Sheet option | Type | Default | Description | | -------------- | --------------------------- | ------------ | ------------------------------------------------------------------------- | | tables | { columns, content }[] | — | Render multiple tables in the sheet. Each table keeps its own formatting. | | tablesLayout | "vertical"/"horizontal" | "vertical" | Stack tables top-to-bottom or place them left-to-right. | | tablesGap | number | 1 | Blank rows (vertical) or columns (horizontal) left between tables. |

TypeScript

The package is written in TypeScript and ships its own type definitions. The public interfaces are exported for your convenience. The xlsx function is available as both the default export and a named export:

import xlsx, { IJsonSheet, ISettings, IColumn, IContent, ICellStyle } from "json-as-xlsx"
// or:
// import { xlsx, IJsonSheet, ISettings, IColumn, IContent, ICellStyle } from "json-as-xlsx"

const data: IJsonSheet[] = [/* ... */]
const settings: ISettings = {/* ... */}

xlsx(data, settings)

Examples

These examples are part of the Yarn workspace and are intended to be installed and run from the repository root.

Contributing

Contributions are welcome! Please read the contributing guide and the code of conduct before opening a pull request. To report a security issue, see the security policy.

License

MIT © LuisEnMarroquin