Excel File Manipulation in Node.js Comparison
xlsx vs exceljs vs excel4node vs xlsx-populate
1 Year
xlsxexceljsexcel4nodexlsx-populate
What's Excel File Manipulation in Node.js?

Excel file manipulation libraries in Node.js provide developers with tools to create, read, and modify Excel files programmatically. These libraries are essential for automating tasks such as generating reports, processing data, and integrating Excel functionality into web applications. They support various Excel formats, including XLSX and CSV, and offer features like styling, formulas, and data validation. Popular libraries include excel4node, exceljs, xlsx, and xlsx-populate, each with unique capabilities and use cases.

NPM Package Downloads Trend
Github Stars Ranking
Stat Detail
Package
Downloads
Stars
Size
Issues
Publish
License
xlsx1,758,44535,2777.5 MB129-Apache-2.0
exceljs1,283,87513,93521.8 MB681a year agoMIT
excel4node117,5561341.12 MB342 years agoMIT
xlsx-populate50,643960-1575 years agoMIT
Feature Comparison: xlsx vs exceljs vs excel4node vs xlsx-populate

File Creation and Manipulation

  • xlsx:

    xlsx is a powerful library for both reading and writing Excel files. It supports a wide range of formats and allows for detailed manipulation of cell data, styles, and structures. It is particularly strong in data extraction and transformation tasks, making it suitable for both creation and manipulation of Excel files.

  • exceljs:

    exceljs excels in both creating and manipulating Excel files. It supports reading, writing, and modifying existing files, making it a versatile choice for comprehensive Excel file handling. It also supports advanced features like streaming and handling large files efficiently.

  • excel4node:

    excel4node is primarily focused on creating Excel files from scratch. It allows for basic manipulation of cell values, styles, and formatting, but it does not support reading or modifying existing Excel files.

  • xlsx-populate:

    xlsx-populate is designed for manipulating existing Excel files. It allows for easy modification of cell values, styles, and formulas, but it does not provide features for creating files from scratch. It is ideal for tasks that require updating or enhancing existing spreadsheets.

Support for Existing Files

  • xlsx:

    xlsx offers extensive support for existing files, allowing for both reading and writing operations. It can handle complex data structures, making it suitable for applications that need to manipulate or analyze data from existing Excel files.

  • exceljs:

    exceljs provides robust support for both reading and writing existing Excel files. This makes it a great choice for applications that need to process, modify, or extract data from pre-existing spreadsheets.

  • excel4node:

    excel4node does not support reading or modifying existing Excel files. It is designed solely for creating new files from scratch, which limits its functionality in scenarios where existing data needs to be accessed or altered.

  • xlsx-populate:

    xlsx-populate focuses on modifying existing Excel files. It allows for intuitive manipulation of cell values, styles, and formulas, but it does not support reading data in the same way as other libraries. It is best suited for tasks that involve updating or enhancing already created spreadsheets.

Styling and Formatting

  • xlsx:

    xlsx supports basic styling and formatting, but it is not as feature-rich as exceljs in this regard. The library focuses more on data manipulation and file handling rather than providing extensive styling capabilities.

  • exceljs:

    exceljs offers advanced styling and formatting features, including support for fonts, colors, borders, and even conditional formatting. It provides a more flexible and powerful styling API, making it suitable for creating complex and visually appealing Excel files.

  • excel4node:

    excel4node provides basic styling and formatting capabilities, including font styles, colors, and cell borders. However, its styling features are limited compared to more comprehensive libraries, making it suitable for simple formatting tasks.

  • xlsx-populate:

    xlsx-populate provides a user-friendly API for styling and formatting cells, including support for fonts, colors, borders, and more. It allows for more intuitive and flexible styling compared to some other libraries, making it easier to create visually appealing spreadsheets.

Ease of Use: Code Examples

  • xlsx:

    Reading and Writing Excel Files with xlsx

    const XLSX = require('xlsx');
    
    // Create a new workbook and worksheet
    const workbook = XLSX.utils.book_new();
    const worksheet = XLSX.utils.aoa_to_sheet([['Name', 'Age'], ['Alice', 30], ['Bob', 25]]);
    
    // Add the worksheet to the workbook
    XLSX.utils.book_append_sheet(workbook, worksheet, 'Sheet1');
    
    // Write the workbook to a file
    XLSX.writeFile(workbook, 'example.xlsx');
    
    // Read the workbook
    const readWorkbook = XLSX.readFile('example.xlsx');
    const readWorksheet = readWorkbook.Sheets['Sheet1'];
    const data = XLSX.utils.sheet_to_json(readWorksheet);
    console.log(data);
    
  • exceljs:

    Creating and Reading Excel Files with exceljs

    const ExcelJS = require('exceljs');
    
    // Create a new workbook and worksheet
    const workbook = new ExcelJS.Workbook();
    const sheet = workbook.addWorksheet('My Sheet');
    
    // Add data to the worksheet
    sheet.addRow(['Name', 'Age']);
    sheet.addRow(['Alice', 30]);
    sheet.addRow(['Bob', 25]);
    
    // Save the workbook
    await workbook.xlsx.writeFile('example.xlsx');
    
    // Read the workbook
    const readWorkbook = new ExcelJS.Workbook();
    await readWorkbook.xlsx.readFile('example.xlsx');
    const readSheet = readWorkbook.getWorksheet('My Sheet');
    readSheet.eachRow((row, rowNumber) => {
      console.log(`Row ${rowNumber}: ${row.values}`);
    });
    
  • excel4node:

    Creating a Simple Excel File with excel4node

    const excel = require('excel4node');
    
    // Create a new instance of a Workbook
    const wb = new excel.Workbook();
    
    // Add Worksheets to the Workbook
    const ws = wb.addWorksheet('Sheet 1');
    
    // Set value of a cell
    ws.cell(1, 1).string('Hello');
    ws.cell(1, 2).number(123);
    
    // Save the Workbook
    wb.write('SimpleExcel.xlsx');
    
  • xlsx-populate:

    Modifying an Existing Excel File with xlsx-populate

    const XlsxPopulate = require('xlsx-populate');
    
    // Load an existing workbook
    XlsxPopulate.fromFileAsync('example.xlsx').then(workbook => {
      const sheet = workbook.sheet(0);
    
      // Modify cell values
      sheet.cell('A1').value('Name');
      sheet.cell('B1').value('Age');
      sheet.cell('A2').value('Alice');
      sheet.cell('B2').value(30);
    
      // Save the changes
      return workbook.toFileAsync('modified-example.xlsx');
    });
    
How to Choose: xlsx vs exceljs vs excel4node vs xlsx-populate
  • xlsx:

    Opt for xlsx if you need a versatile library for reading, writing, and manipulating Excel files in various formats. It is particularly useful for data extraction and transformation tasks, and it supports a wide range of file types, including XLSX, XLS, and CSV.

  • exceljs:

    Select exceljs if you require a comprehensive solution for both reading and writing Excel files. It supports advanced features like streaming, formulas, and rich text, making it ideal for applications that need to handle complex Excel files or process large datasets efficiently.

  • excel4node:

    Choose excel4node if you need a simple and straightforward library for creating Excel files with basic styling and formatting. It is easy to use and suitable for projects that require quick Excel file generation without complex features.

  • xlsx-populate:

    Choose xlsx-populate if you want to work with Excel files in a more intuitive way, focusing on modifying existing files rather than creating them from scratch. It provides a simple API for manipulating cell values, styles, and formulas, making it great for tasks that involve updating or enhancing existing spreadsheets.

README for xlsx

SheetJS

The SheetJS Community Edition offers battle-tested open-source solutions for extracting useful data from almost any complex spreadsheet and generating new spreadsheets that will work with legacy and modern software alike.

SheetJS Pro offers solutions beyond data processing: Edit complex templates with ease; let out your inner Picasso with styling; make custom sheets with images/graphs/PivotTables; evaluate formula expressions and port calculations to web apps; automate common spreadsheet tasks, and much more!

License Build Status Snyk Vulnerabilities npm Downloads Analytics

Browser Test and Support Matrix

Build Status

Supported File Formats

circo graph of format support

graph legend

Table of Contents

Expand to show Table of Contents

Getting Started

Installation

Standalone Browser Scripts

The complete browser standalone build is saved to dist/xlsx.full.min.js and can be directly added to a page with a script tag:

<script lang="javascript" src="dist/xlsx.full.min.js"></script>
CDN Availability (click to show)

| CDN | URL | |-----------:|:-------------------------------------------| | unpkg | https://unpkg.com/xlsx/ | | jsDelivr | https://jsdelivr.com/package/npm/xlsx | | CDNjs | https://cdnjs.com/libraries/xlsx |

For example, unpkg makes the latest version available at:

<script src="https://unpkg.com/xlsx/dist/xlsx.full.min.js"></script>
Browser builds (click to show)

The complete single-file version is generated at dist/xlsx.full.min.js

dist/xlsx.core.min.js omits codepage library (no support for XLS encodings)

A slimmer build is generated at dist/xlsx.mini.min.js. Compared to full build:

  • codepage library skipped (no support for XLS encodings)
  • no support for XLSB / XLS / Lotus 1-2-3 / SpreadsheetML 2003 / Numbers
  • node stream utils removed

With bower:

$ bower install js-xlsx

ECMAScript Modules

The ECMAScript Module build is saved to xlsx.mjs and can be directly added to a page with a script tag using type=module:

<script type="module">
import { read, writeFileXLSX } from "./xlsx.mjs";

/* load the codepage support library for extended support with older formats  */
import { set_cptable } from "./xlsx.mjs";
import * as cptable from './dist/cpexcel.full.mjs';
set_cptable(cptable);
</script>

The npm package also exposes the module with the module parameter, supported in Angular and other projects:

import { read, writeFileXLSX } from "xlsx";

/* load the codepage support library for extended support with older formats  */
import { set_cptable } from "xlsx";
import * as cptable from 'xlsx/dist/cpexcel.full.mjs';
set_cptable(cptable);

Deno

xlsx.mjs can be imported in Deno. It is available from unpkg:

// @deno-types="https://unpkg.com/xlsx/types/index.d.ts"
import * as XLSX from 'https://unpkg.com/xlsx/xlsx.mjs';

/* load the codepage support library for extended support with older formats  */
import * as cptable from 'https://unpkg.com/xlsx/dist/cpexcel.full.mjs';
XLSX.set_cptable(cptable);

NodeJS

With npm:

$ npm install xlsx

By default, the module supports require:

var XLSX = require("xlsx");

The module also ships with xlsx.mjs for use with import:

import * as XLSX from 'xlsx/xlsx.mjs';

/* load 'fs' for readFile and writeFile support */
import * as fs from 'fs';
XLSX.set_fs(fs);

/* load 'stream' for stream support */
import { Readable } from 'stream';
XLSX.stream.set_readable(Readable);

/* load the codepage support library for extended support with older formats  */
import * as cpexcel from 'xlsx/dist/cpexcel.full.mjs';
XLSX.set_cptable(cpexcel);

Photoshop and InDesign

dist/xlsx.extendscript.js is an ExtendScript build for Photoshop and InDesign that is included in the npm package. It can be directly referenced with a #include directive:

#include "xlsx.extendscript.js"
Internet Explorer and ECMAScript 3 Compatibility (click to show)

For broad compatibility with JavaScript engines, the library is written using ECMAScript 3 language dialect as well as some ES5 features like Array#forEach. Older browsers require shims to provide missing functions.

To use the shim, add the shim before the script tag that loads xlsx.js:

<!-- add the shim first -->
<script type="text/javascript" src="shim.min.js"></script>
<!-- after the shim is referenced, add the library -->
<script type="text/javascript" src="xlsx.full.min.js"></script>

The script also includes IE_LoadFile and IE_SaveFile for loading and saving files in Internet Explorer versions 6-9. The xlsx.extendscript.js script bundles the shim in a format suitable for Photoshop and other Adobe products.

Usage

Most scenarios involving spreadsheets and data can be broken into 5 parts:

  1. Acquire Data: Data may be stored anywhere: local or remote files, databases, HTML TABLE, or even generated programmatically in the web browser.

  2. Extract Data: For spreadsheet files, this involves parsing raw bytes to read the cell data. For general JS data, this involves reshaping the data.

  3. Process Data: From generating summary statistics to cleaning data records, this step is the heart of the problem.

  4. Package Data: This can involve making a new spreadsheet or serializing with JSON.stringify or writing XML or simply flattening data for UI tools.

  5. Release Data: Spreadsheet files can be uploaded to a server or written locally. Data can be presented to users in an HTML TABLE or data grid.

A common problem involves generating a valid spreadsheet export from data stored in an HTML table. In this example, an HTML TABLE on the page will be scraped, a row will be added to the bottom with the date of the report, and a new file will be generated and downloaded locally. XLSX.writeFile takes care of packaging the data and attempting a local download:

// Acquire Data (reference to the HTML table)
var table_elt = document.getElementById("my-table-id");

// Extract Data (create a workbook object from the table)
var workbook = XLSX.utils.table_to_book(table_elt);

// Process Data (add a new row)
var ws = workbook.Sheets["Sheet1"];
XLSX.utils.sheet_add_aoa(ws, [["Created "+new Date().toISOString()]], {origin:-1});

// Package and Release Data (`writeFile` tries to write and save an XLSB file)
XLSX.writeFile(workbook, "Report.xlsb");

This library tries to simplify steps 2 and 4 with functions to extract useful data from spreadsheet files (read / readFile) and generate new spreadsheet files from data (write / writeFile). Additional utility functions like table_to_book work with other common data sources like HTML tables.

This documentation and various demo projects cover a number of common scenarios and approaches for steps 1 and 5.

Utility functions help with step 3.

"Acquiring and Extracting Data" describes solutions for common data import scenarios.

"Packaging and Releasing Data" describes solutions for common data export scenarios.

"Processing Data" describes solutions for common workbook processing and manipulation scenarios.

"Utility Functions" details utility functions for translating JSON Arrays and other common JS structures into worksheet objects.

The Zen of SheetJS

Data processing should fit in any workflow

The library does not impose a separate lifecycle. It fits nicely in websites and apps built using any framework. The plain JS data objects play nice with Web Workers and future APIs.

JavaScript is a powerful language for data processing

The "Common Spreadsheet Format" is a simple object representation of the core concepts of a workbook. The various functions in the library provide low-level tools for working with the object.

For friendly JS processing, there are utility functions for converting parts of a worksheet to/from an Array of Arrays. The following example combines powerful JS Array methods with a network request library to download data, select the information we want and create a workbook file:

Get Data from a JSON Endpoint and Generate a Workbook (click to show)

The goal is to generate a XLSB workbook of US President names and birthdays.

Acquire Data

Raw Data

https://theunitedstates.io/congress-legislators/executive.json has the desired data. For example, John Adams:

{
  "id": { /* (data omitted) */ },
  "name": {
    "first": "John",          // <-- first name
    "last": "Adams"           // <-- last name
  },
  "bio": {
    "birthday": "1735-10-19", // <-- birthday
    "gender": "M"
  },
  "terms": [
    { "type": "viceprez", /* (other fields omitted) */ },
    { "type": "viceprez", /* (other fields omitted) */ },
    { "type": "prez", /* (other fields omitted) */ } // <-- look for "prez"
  ]
}

Filtering for Presidents

The dataset includes Aaron Burr, a Vice President who was never President!

Array#filter creates a new array with the desired rows. A President served at least one term with type set to "prez". To test if a particular row has at least one "prez" term, Array#some is another native JS function. The complete filter would be:

const prez = raw_data.filter(row => row.terms.some(term => term.type === "prez"));

Lining up the data

For this example, the name will be the first name combined with the last name (row.name.first + " " + row.name.last) and the birthday will be the subfield row.bio.birthday. Using Array#map, the dataset can be massaged in one call:

const rows = prez.map(row => ({
  name: row.name.first + " " + row.name.last,
  birthday: row.bio.birthday
}));

The result is an array of "simple" objects with no nesting:

[
  { name: "George Washington", birthday: "1732-02-22" },
  { name: "John Adams", birthday: "1735-10-19" },
  // ... one row per President
]

Extract Data

With the cleaned dataset, XLSX.utils.json_to_sheet generates a worksheet:

const worksheet = XLSX.utils.json_to_sheet(rows);

XLSX.utils.book_new creates a new workbook and XLSX.utils.book_append_sheet appends a worksheet to the workbook. The new worksheet will be called "Dates":

const workbook = XLSX.utils.book_new();
XLSX.utils.book_append_sheet(workbook, worksheet, "Dates");

Process Data

Fixing headers

By default, json_to_sheet creates a worksheet with a header row. In this case, the headers come from the JS object keys: "name" and "birthday".

The headers are in cells A1 and B1. XLSX.utils.sheet_add_aoa can write text values to the existing worksheet starting at cell A1:

XLSX.utils.sheet_add_aoa(worksheet, [["Name", "Birthday"]], { origin: "A1" });

Fixing Column Widths

Some of the names are longer than the default column width. Column widths are set by setting the "!cols" worksheet property.

The following line sets the width of column A to approximately 10 characters:

worksheet["!cols"] = [ { wch: 10 } ]; // set column A width to 10 characters

One Array#reduce call over rows can calculate the maximum width:

const max_width = rows.reduce((w, r) => Math.max(w, r.name.length), 10);
worksheet["!cols"] = [ { wch: max_width } ];

Note: If the starting point was a file or HTML table, XLSX.utils.sheet_to_json will generate an array of JS objects.

Package and Release Data

XLSX.writeFile creates a spreadsheet file and tries to write it to the system. In the browser, it will try to prompt the user to download the file. In NodeJS, it will write to the local directory.

XLSX.writeFile(workbook, "Presidents.xlsx");

Complete Example

// Uncomment the next line for use in NodeJS:
// const XLSX = require("xlsx"), axios = require("axios");

(async() => {
  /* fetch JSON data and parse */
  const url = "https://theunitedstates.io/congress-legislators/executive.json";
  const raw_data = (await axios(url, {responseType: "json"})).data;

  /* filter for the Presidents */
  const prez = raw_data.filter(row => row.terms.some(term => term.type === "prez"));

  /* flatten objects */
  const rows = prez.map(row => ({
    name: row.name.first + " " + row.name.last,
    birthday: row.bio.birthday
  }));

  /* generate worksheet and workbook */
  const worksheet = XLSX.utils.json_to_sheet(rows);
  const workbook = XLSX.utils.book_new();
  XLSX.utils.book_append_sheet(workbook, worksheet, "Dates");

  /* fix headers */
  XLSX.utils.sheet_add_aoa(worksheet, [["Name", "Birthday"]], { origin: "A1" });

  /* calculate column width */
  const max_width = rows.reduce((w, r) => Math.max(w, r.name.length), 10);
  worksheet["!cols"] = [ { wch: max_width } ];

  /* create an XLSX file and try to save to Presidents.xlsx */
  XLSX.writeFile(workbook, "Presidents.xlsx");
})();

For use in the web browser, assuming the snippet is saved to snippet.js, script tags should be used to include the axios and xlsx standalone builds:

<script src="https://unpkg.com/xlsx/dist/xlsx.full.min.js"></script>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<script src="snippet.js"></script>

File formats are implementation details

The parser covers a wide gamut of common spreadsheet file formats to ensure that "HTML-saved-as-XLS" files work as well as actual XLS or XLSX files.

The writer supports a number of common output formats for broad compatibility with the data ecosystem.

To the greatest extent possible, data processing code should not have to worry about the specific file formats involved.

JS Ecosystem Demos

The demos directory includes sample projects for:

Frameworks and APIs

Bundlers and Tooling

Platforms and Integrations

Other examples are included in the showcase.

https://sheetjs.com/demos/modify.html shows a complete example of reading, modifying, and writing files.

https://github.com/SheetJS/sheetjs/blob/HEAD/bin/xlsx.njs is the command-line tool included with node installations, reading spreadsheet files and exporting the contents in various formats.

Acquiring and Extracting Data

Parsing Workbooks

API

Extract data from spreadsheet bytes

var workbook = XLSX.read(data, opts);

The read method can extract data from spreadsheet bytes stored in a JS string, "binary string", NodeJS buffer or typed array (Uint8Array or ArrayBuffer).

Read spreadsheet bytes from a local file and extract data

var workbook = XLSX.readFile(filename, opts);

The readFile method attempts to read a spreadsheet file at the supplied path. Browsers generally do not allow reading files in this way (it is deemed a security risk), and attempts to read files in this way will throw an error.

The second opts argument is optional. "Parsing Options" covers the supported properties and behaviors.

Examples

Here are a few common scenarios (click on each subtitle to see the code):

Local file in a NodeJS server (click to show)

readFile uses fs.readFileSync under the hood:

var XLSX = require("xlsx");

var workbook = XLSX.readFile("test.xlsx");

For Node ESM, the readFile helper is not enabled. Instead, fs.readFileSync should be used to read the file data as a Buffer for use with XLSX.read:

import { readFileSync } from "fs";
import { read } from "xlsx/xlsx.mjs";

const buf = readFileSync("test.xlsx");
/* buf is a Buffer */
const workbook = read(buf);
Local file in a Deno application (click to show)

readFile uses Deno.readFileSync under the hood:

// @deno-types="https://deno.land/x/sheetjs/types/index.d.ts"
import * as XLSX from 'https://deno.land/x/sheetjs/xlsx.mjs'

const workbook = XLSX.readFile("test.xlsx");

Applications reading files must be invoked with the --allow-read flag. The deno demo has more examples

User-submitted file in a web page ("Drag-and-Drop") (click to show)

For modern websites targeting Chrome 76+, File#arrayBuffer is recommended:

// XLSX is a global from the standalone script

async function handleDropAsync(e) {
  e.stopPropagation(); e.preventDefault();
  const f = e.dataTransfer.files[0];
  /* f is a File */
  const data = await f.arrayBuffer();
  /* data is an ArrayBuffer */
  const workbook = XLSX.read(data);

  /* DO SOMETHING WITH workbook HERE */
}
drop_dom_element.addEventListener("drop", handleDropAsync, false);

For maximal compatibility, the FileReader API should be used:

function handleDrop(e) {
  e.stopPropagation(); e.preventDefault();
  var f = e.dataTransfer.files[0];
  /* f is a File */
  var reader = new FileReader();
  reader.onload = function(e) {
    var data = e.target.result;
    /* reader.readAsArrayBuffer(file) -> data will be an ArrayBuffer */
    var workbook = XLSX.read(data);

    /* DO SOMETHING WITH workbook HERE */
  };
  reader.readAsArrayBuffer(f);
}
drop_dom_element.addEventListener("drop", handleDrop, false);

https://oss.sheetjs.com/sheetjs/ demonstrates the FileReader technique.

User-submitted file with an HTML INPUT element (click to show)

Starting with an HTML INPUT element with type="file":

<input type="file" id="input_dom_element">

For modern websites targeting Chrome 76+, Blob#arrayBuffer is recommended:

// XLSX is a global from the standalone script

async function handleFileAsync(e) {
  const file = e.target.files[0];
  const data = await file.arrayBuffer();
  /* data is an ArrayBuffer */
  const workbook = XLSX.read(data);

  /* DO SOMETHING WITH workbook HERE */
}
input_dom_element.addEventListener("change", handleFileAsync, false);

For broader support (including IE10+), the FileReader approach is recommended:

function handleFile(e) {
  var file = e.target.files[0];
  var reader = new FileReader();
  reader.onload = function(e) {
    var data = e.target.result;
    /* reader.readAsArrayBuffer(file) -> data will be an ArrayBuffer */
    var workbook = XLSX.read(e.target.result);

    /* DO SOMETHING WITH workbook HERE */
  };
  reader.readAsArrayBuffer(file);
}
input_dom_element.addEventListener("change", handleFile, false);

The oldie demo shows an IE-compatible fallback scenario.

Fetching a file in the web browser ("Ajax") (click to show)

For modern websites targeting Chrome 42+, fetch is recommended:

// XLSX is a global from the standalone script

(async() => {
  const url = "http://oss.sheetjs.com/test_files/formula_stress_test.xlsx";
  const data = await (await fetch(url)).arrayBuffer();
  /* data is an ArrayBuffer */
  const workbook = XLSX.read(data);

  /* DO SOMETHING WITH workbook HERE */
})();

For broader support, the XMLHttpRequest approach is recommended:

var url = "http://oss.sheetjs.com/test_files/formula_stress_test.xlsx";

/* set up async GET request */
var req = new XMLHttpRequest();
req.open("GET", url, true);
req.responseType = "arraybuffer";

req.onload = function(e) {
  var workbook = XLSX.read(req.response);

  /* DO SOMETHING WITH workbook HERE */
};

req.send();

The xhr demo includes a longer discussion and more examples.

http://oss.sheetjs.com/sheetjs/ajax.html shows fallback approaches for IE6+.

Local file in a PhotoShop or InDesign plugin (click to show)

readFile wraps the File logic in Photoshop and other ExtendScript targets. The specified path should be an absolute path:

#include "xlsx.extendscript.js"

/* Read test.xlsx from the Documents folder */
var workbook = XLSX.readFile(Folder.myDocuments + "/test.xlsx");

The extendscript demo includes a more complex example.

Local file in an Electron app (click to show)

readFile can be used in the renderer process:

/* From the renderer process */
var XLSX = require("xlsx");

var workbook = XLSX.readFile(path);

Electron APIs have changed over time. The electron demo shows a complete example and details the required version-specific settings.

Local file in a mobile app with React Native (click to show)

The react demo includes a sample React Native app.

Since React Native does not provide a way to read files from the filesystem, a third-party library must be used. The following libraries have been tested:

The base64 encoding returns strings compatible with the base64 type:

import XLSX from "xlsx";
import { FileSystem } from "react-native-file-access";

const b64 = await FileSystem.readFile(path, "base64");
/* b64 is a base64 string */
const workbook = XLSX.read(b64, {type: "base64"});

The ascii encoding returns binary strings compatible with the binary type:

import XLSX from "xlsx";
import { readFile } from "react-native-fs";

const bstr = await readFile(path, "ascii");
/* bstr is a binary string */
const workbook = XLSX.read(bstr, {type: "binary"});
NodeJS Server File Uploads (click to show)

read can accept a NodeJS buffer. readFile can read files generated by a HTTP POST request body parser like formidable:

const XLSX = require("xlsx");
const http = require("http");
const formidable = require("formidable");

const server = http.createServer((req, res) => {
  const form = new formidable.IncomingForm();
  form.parse(req, (err, fields, files) => {
    /* grab the first file */
    const f = Object.entries(files)[0][1];
    const path = f.filepath;
    const workbook = XLSX.readFile(path);

    /* DO SOMETHING WITH workbook HERE */
  });
}).listen(process.env.PORT || 7262);

The server demo has more advanced examples.

Download files in a NodeJS process (click to show)

Node 17.5 and 18.0 have native support for fetch:

const XLSX = require("xlsx");

const data = await (await fetch(url)).arrayBuffer();
/* data is an ArrayBuffer */
const workbook = XLSX.read(data);

For broader compatibility, third-party modules are recommended.

request requires a null encoding to yield Buffers:

var XLSX = require("xlsx");
var request = require("request");

request({url: url, encoding: null}, function(err, resp, body) {
  var workbook = XLSX.read(body);

  /* DO SOMETHING WITH workbook HERE */
});

axios works the same way in browser and in NodeJS:

const XLSX = require("xlsx");
const axios = require("axios");

(async() => {
  const res = await axios.get(url, {responseType: "arraybuffer"});
  /* res.data is a Buffer */
  const workbook = XLSX.read(res.data);

  /* DO SOMETHING WITH workbook HERE */
})();
Download files in an Electron app (click to show)

The net module in the main process can make HTTP/HTTPS requests to external resources. Responses should be manually concatenated using Buffer.concat:

const XLSX = require("xlsx");
const { net } = require("electron");

const req = net.request(url);
req.on("response", (res) => {
  const bufs = []; // this array will collect all of the buffers
  res.on("data", (chunk) => { bufs.push(chunk); });
  res.on("end", () => {
    const workbook = XLSX.read(Buffer.concat(bufs));

    /* DO SOMETHING WITH workbook HERE */
  });
});
req.end();
Readable Streams in NodeJS (click to show)

When dealing with Readable Streams, the easiest approach is to buffer the stream and process the whole thing at the end:

var fs = require("fs");
var XLSX = require("xlsx");

function process_RS(stream, cb) {
  var buffers = [];
  stream.on("data", function(data) { buffers.push(data); });
  stream.on("end", function() {
    var buffer = Buffer.concat(buffers);
    var workbook = XLSX.read(buffer, {type:"buffer"});

    /* DO SOMETHING WITH workbook IN THE CALLBACK */
    cb(workbook);
  });
}
ReadableStream in the browser (click to show)

When dealing with ReadableStream, the easiest approach is to buffer the stream and process the whole thing at the end:

// XLSX is a global from the standalone script

async function process_RS(stream) {
  /* collect data */
  const buffers = [];
  const reader = stream.getReader();
  for(;;) {
    const res = await reader.read();
    if(res.value) buffers.push(res.value);
    if(res.done) break;
  }

  /* concat */
  const out = new Uint8Array(buffers.reduce((acc, v) => acc + v.length, 0));

  let off = 0;
  for(const u8 of arr) {
    out.set(u8, off);
    off += u8.length;
  }

  return out;
}

const data = await process_RS(stream);
/* data is Uint8Array */
const workbook = XLSX.read(data);

More detailed examples are covered in the included demos

Processing JSON and JS Data

JSON and JS data tend to represent single worksheets. This section will use a few utility functions to generate workbooks.

Create a new Workbook

var workbook = XLSX.utils.book_new();

The book_new utility function creates an empty workbook with no worksheets.

Spreadsheet software generally require at least one worksheet and enforce the requirement in the user interface. This library enforces the requirement at write time, throwing errors if an empty workbook is passed to write functions.

API

Create a worksheet from an array of arrays of JS values

var worksheet = XLSX.utils.aoa_to_sheet(aoa, opts);

The aoa_to_sheet utility function walks an "array of arrays" in row-major order, generating a worksheet object. The following snippet generates a sheet with cell A1 set to the string A1, cell B1 set to B1, etc:

var worksheet = XLSX.utils.aoa_to_sheet([
  ["A1", "B1", "C1"],
  ["A2", "B2", "C2"],
  ["A3", "B3", "C3"]
]);

"Array of Arrays Input" describes the function and the optional opts argument in more detail.

Create a worksheet from an array of JS objects

var worksheet = XLSX.utils.json_to_sheet(jsa, opts);

The json_to_sheet utility function walks an array of JS objects in order, generating a worksheet object. By default, it will generate a header row and one row per object in the array. The optional opts argument has settings to control the column order and header output.

"Array of Objects Input" describes the function and the optional opts argument in more detail.

Examples

"Zen of SheetJS" contains a detailed example "Get Data from a JSON Endpoint and Generate a Workbook"

x-spreadsheet is an interactive data grid for previewing and modifying structured data in the web browser. The xspreadsheet demo includes a sample script with the xtos function for converting from x-spreadsheet data object to a workbook. https://oss.sheetjs.com/sheetjs/x-spreadsheet is a live demo.

Records from a database query (SQL or no-SQL) (click to show)

The database demo includes examples of working with databases and query results.

Numerical Computations with TensorFlow.js (click to show)

@tensorflow/tfjs and other libraries expect data in simple arrays, well-suited for worksheets where each column is a data vector. That is the transpose of how most people use spreadsheets, where each row is a vector.

When recovering data from tfjs, the returned data points are stored in a typed array. An array of arrays can be constructed with loops. Array#unshift can prepend a title row before the conversion:

const XLSX = require("xlsx");
const tf = require('@tensorflow/tfjs');

/* suppose xs and ys are vectors (1D tensors) -> tfarr will be a typed array */
const tfdata = tf.stack([xs, ys]).transpose();
const shape = tfdata.shape;
const tfarr = tfdata.dataSync();

/* construct the array of arrays */
const aoa = [];
for(let j = 0; j < shape[0]; ++j) {
  aoa[j] = [];
  for(let i = 0; i < shape[1]; ++i) aoa[j][i] = tfarr[j * shape[1] + i];
}
/* add headers to the top */
aoa.unshift(["x", "y"]);

/* generate worksheet */
const worksheet = XLSX.utils.aoa_to_sheet(aoa);

The array demo shows a complete example.

Processing HTML Tables

API

Create a worksheet by scraping an HTML TABLE in the page

var worksheet = XLSX.utils.table_to_sheet(dom_element, opts);

The table_to_sheet utility function takes a DOM TABLE element and iterates through the rows to generate a worksheet. The opts argument is optional. "HTML Table Input" describes the function in more detail.

Create a workbook by scraping an HTML TABLE in the page

var workbook = XLSX.utils.table_to_book(dom_element, opts);

The table_to_book utility function follows the same logic as table_to_sheet. After generating a worksheet, it creates a blank workbook and appends the spreadsheet.

The options argument supports the same options as table_to_sheet, with the addition of a sheet property to control the worksheet name. If the property is missing or no options are specified, the default name Sheet1 is used.

Examples

Here are a few common scenarios (click on each subtitle to see the code):

HTML TABLE element in a webpage (click to show)
<!-- include the standalone script and shim.  this uses the UNPKG CDN -->
<script src="https://unpkg.com/xlsx/dist/shim.min.js"></script>
<script src="https://unpkg.com/xlsx/dist/xlsx.full.min.js"></script>

<!-- example table with id attribute -->
<table id="tableau">
  <tr><td>Sheet</td><td>JS</td></tr>
  <tr><td>12345</td><td>67</td></tr>
</table>

<!-- this block should appear after the table HTML and the standalone script -->
<script type="text/javascript">
  var workbook = XLSX.utils.table_to_book(document.getElementById("tableau"));

  /* DO SOMETHING WITH workbook HERE */
</script>

Multiple tables on a web page can be converted to individual worksheets:

/* create new workbook */
var workbook = XLSX.utils.book_new();

/* convert table "table1" to worksheet named "Sheet1" */
var sheet1 = XLSX.utils.table_to_sheet(document.getElementById("table1"));
XLSX.utils.book_append_sheet(workbook, sheet1, "Sheet1");

/* convert table "table2" to worksheet named "Sheet2" */
var sheet2 = XLSX.utils.table_to_sheet(document.getElementById("table2"));
XLSX.utils.book_append_sheet(workbook, sheet2, "Sheet2");

/* workbook now has 2 worksheets */

Alternatively, the HTML code can be extracted and parsed:

var htmlstr = document.getElementById("tableau").outerHTML;
var workbook = XLSX.read(htmlstr, {type:"string"});
Chrome/Chromium Extension (click to show)

The chrome demo shows a complete example and details the required permissions and other settings.

In an extension, it is recommended to generate the workbook in a content script and pass the object back to the extension:

/* in the worker script */
chrome.runtime.onMessage.addListener(function(msg, sender, cb) {
  /* pass a message like { sheetjs: true } from the extension to scrape */
  if(!msg || !msg.sheetjs) return;
  /* create a new workbook */
  var workbook = XLSX.utils.book_new();
  /* loop through each table element */
  var tables = document.getElementsByTagName("table")
  for(var i = 0; i < tables.length; ++i) {
    var worksheet = XLSX.utils.table_to_sheet(tables[i]);
    XLSX.utils.book_append_sheet(workbook, worksheet, "Table" + i);
  }
  /* pass back to the extension */
  return cb(workbook);
});
Server-Side HTML Tables with Headless Chrome (click to show)

The headless demo includes a complete demo to convert HTML files to XLSB workbooks. The core idea is to add the script to the page, parse the table in the page context, generate a base64 workbook and send it back for further processing:

const XLSX = require("xlsx");
const { readFileSync } = require("fs"), puppeteer = require("puppeteer");

const url = `https://sheetjs.com/demos/table`;

/* get the standalone build source (node_modules/xlsx/dist/xlsx.full.min.js) */
const lib = readFileSync(require.resolve("xlsx/dist/xlsx.full.min.js"), "utf8");

(async() => {
  /* start browser and go to web page */
  const browser = await puppeteer.launch();
  const page = await browser.newPage();
  await page.goto(url, {waitUntil: "networkidle2"});

  /* inject library */
  await page.addScriptTag({content: lib});

  /* this function `s5s` will be called by the script below, receiving the Base64-encoded file */
  await page.exposeFunction("s5s", async(b64) => {
    const workbook = XLSX.read(b64, {type: "base64" });

    /* DO SOMETHING WITH workbook HERE */
  });

  /* generate XLSB file in webpage context and send back result */
  await page.addScriptTag({content: `
    /* call table_to_book on first table */
    var workbook = XLSX.utils.table_to_book(document.querySelector("TABLE"));

    /* generate XLSX file */
    var b64 = XLSX.write(workbook, {type: "base64", bookType: "xlsb"});

    /* call "s5s" hook exposed from the node process */
    window.s5s(b64);
  `});

  /* cleanup */
  await browser.close();
})();
Server-Side HTML Tables with Headless WebKit (click to show)

The headless demo includes a complete demo to convert HTML files to XLSB workbooks using PhantomJS. The core idea is to add the script to the page, parse the table in the page context, generate a binary workbook and send it back for further processing:

var XLSX = require('xlsx');
var page = require('webpage').create();

/* this code will be run in the page */
var code = [ "function(){",
  /* call table_to_book on first table */
  "var wb = XLSX.utils.table_to_book(document.body.getElementsByTagName('table')[0]);",

  /* generate XLSB file and return binary string */
  "return XLSX.write(wb, {type: 'binary', bookType: 'xlsb'});",
"}" ].join("");

page.open('https://sheetjs.com/demos/table', function() {
  /* Load the browser script from the UNPKG CDN */
  page.includeJs("https://unpkg.com/xlsx/dist/xlsx.full.min.js", function() {
    /* The code will return an XLSB file encoded as binary string */
    var bin = page.evaluateJavaScript(code);

    var workbook = XLSX.read(bin, {type: "binary"});
    /* DO SOMETHING WITH workbook HERE */

    phantom.exit();
  });
});
NodeJS HTML Tables without a browser (click to show)

NodeJS does not include a DOM implementation and Puppeteer requires a hefty Chromium build. jsdom is a lightweight alternative:

const XLSX = require("xlsx");
const { readFileSync } = require("fs");
const { JSDOM } = require("jsdom");

/* obtain HTML string.  This example reads from test.html */
const html_str = fs.readFileSync("test.html", "utf8");
/* get first TABLE element */
const doc = new JSDOM(html_str).window.document.querySelector("table");
/* generate workbook */
const workbook = XLSX.utils.table_to_book(doc);

Processing Data

The "Common Spreadsheet Format" is a simple object representation of the core concepts of a workbook. The utility functions work with the object representation and are intended to handle common use cases.

Modifying Workbook Structure

API

Append a Worksheet to a Workbook

XLSX.utils.book_append_sheet(workbook, worksheet, sheet_name);

The book_append_sheet utility function appends a worksheet to the workbook. The third argument specifies the desired worksheet name. Multiple worksheets can be added to a workbook by calling the function multiple times. If the worksheet name is already used in the workbook, it will throw an error.

Append a Worksheet to a Workbook and find a unique name

var new_name = XLSX.utils.book_append_sheet(workbook, worksheet, name, true);

If the fourth argument is true, the function will start with the specified worksheet name. If the sheet name exists in the workbook, a new worksheet name will be chosen by finding the name stem and incrementing the counter:

XLSX.utils.book_append_sheet(workbook, sheetA, "Sheet2", true); // Sheet2
XLSX.utils.book_append_sheet(workbook, sheetB, "Sheet2", true); // Sheet3
XLSX.utils.book_append_sheet(workbook, sheetC, "Sheet2", true); // Sheet4
XLSX.utils.book_append_sheet(workbook, sheetD, "Sheet2", true); // Sheet5

List the Worksheet names in tab order

var wsnames = workbook.SheetNames;

The SheetNames property of the workbook object is a list of the worksheet names in "tab order". API functions will look at this array.

Replace a Worksheet in place

workbook.Sheets[sheet_name] = new_worksheet;

The Sheets property of the workbook object is an object whose keys are names and whose values are worksheet objects. By reassigning to a property of the Sheets object, the worksheet object can be changed without disrupting the rest of the worksheet structure.

Examples

Add a new worksheet to a workbook (click to show)

This example uses XLSX.utils.aoa_to_sheet.

var ws_name = "SheetJS";

/* Create worksheet */
var ws_data = [
  [ "S", "h", "e", "e", "t", "J", "S" ],
  [  1 ,  2 ,  3 ,  4 ,  5 ]
];
var ws = XLSX.utils.aoa_to_sheet(ws_data);

/* Add the worksheet to the workbook */
XLSX.utils.book_append_sheet(wb, ws, ws_name);

Modifying Cell Values

API

Modify a single cell value in a worksheet

XLSX.utils.sheet_add_aoa(worksheet, [[new_value]], { origin: address });

Modify multiple cell values in a worksheet

XLSX.utils.sheet_add_aoa(worksheet, aoa, opts);

The sheet_add_aoa utility function modifies cell values in a worksheet. The first argument is the worksheet object. The second argument is an array of arrays of values. The origin key of the third argument controls where cells will be written. The following snippet sets B3=1 and E5="abc":

XLSX.utils.sheet_add_aoa(worksheet, [
  [1],                             // <-- Write 1 to cell B3
  ,                                // <-- Do nothing in row 4
  [/*B5*/, /*C5*/, /*D5*/, "abc"]  // <-- Write "abc" to cell E5
], { origin: "B3" });

"Array of Arrays Input" describes the function and the optional opts argument in more detail.

Examples

Appending rows to a worksheet (click to show)

The special origin value -1 instructs sheet_add_aoa to start in column A of the row after the last row in the range, appending the data:

XLSX.utils.sheet_add_aoa(worksheet, [
  ["first row after data", 1],
  ["second row after data", 2]
], { origin: -1 });

Modifying Other Worksheet / Workbook / Cell Properties

The "Common Spreadsheet Format" section describes the object structures in greater detail.

Packaging and Releasing Data

Writing Workbooks

API

Generate spreadsheet bytes (file) from data

var data = XLSX.write(workbook, opts);

The write method attempts to package data from the workbook into a file in memory. By default, XLSX files are generated, but that can be controlled with the bookType property of the opts argument. Based on the type option, the data can be stored as a "binary string", JS string, Uint8Array or Buffer.

The second opts argument is required. "Writing Options" covers the supported properties and behaviors.

Generate and attempt to save file

XLSX.writeFile(workbook, filename, opts);

The writeFile method packages the data and attempts to save the new file. The export file format is determined by the extension of filename (SheetJS.xlsx signals XLSX export, SheetJS.xlsb signals XLSB export, etc).

The writeFile method uses platform-specific APIs to initiate the file save. In NodeJS, fs.readFileSync can create a file. In the web browser, a download is attempted using the HTML5 download attribute, with fallbacks for IE.

Generate and attempt to save an XLSX file

XLSX.writeFileXLSX(workbook, filename, opts);

The writeFile method embeds a number of different export functions. This is great for developer experience but not amenable to tree shaking using the current developer tools. When only XLSX exports are needed, this method avoids referencing the other export functions.

The second opts argument is optional. "Writing Options" covers the supported properties and behaviors.

Examples

Local file in a NodeJS server (click to show)

writeFile uses fs.writeFileSync in server environments:

var XLSX = require("xlsx");

/* output format determined by filename */
XLSX.writeFile(workbook, "out.xlsb");

For Node ESM, the writeFile helper is not enabled. Instead, fs.writeFileSync should be used to write the file data to a Buffer for use with XLSX.write:

import { writeFileSync } from "fs";
import { write } from "xlsx/xlsx.mjs";

const buf = write(workbook, {type: "buffer", bookType: "xlsb"});
/* buf is a Buffer */
const workbook = writeFileSync("out.xlsb", buf);
Local file in a Deno application (click to show)

writeFile uses Deno.writeFileSync under the hood:

// @deno-types="https://deno.land/x/sheetjs/types/index.d.ts"
import * as XLSX from 'https://deno.land/x/sheetjs/xlsx.mjs'

XLSX.writeFile(workbook, "test.xlsx");

Applications writing files must be invoked with the --allow-write flag. The deno demo has more examples

Local file in a PhotoShop or InDesign plugin (click to show)

writeFile wraps the File logic in Photoshop and other ExtendScript targets. The specified path should be an absolute path:

#include "xlsx.extendscript.js"

/* output format determined by filename */
XLSX.writeFile(workbook, "out.xlsx");
/* at this point, out.xlsx is a file that you can distribute */

The extendscript demo includes a more complex example.

Download a file in the browser to the user machine (click to show)

XLSX.writeFile wraps a few techniques for triggering a file save:

  • URL browser API creates an object URL for the file, which the library uses by creating a link and forcing a click. It is supported in modern browsers.
  • msSaveBlob is an IE10+ API for triggering a file save.
  • IE_FileSave uses VBScript and ActiveX to write a file in IE6+ for Windows XP and Windows 7. The shim must be included in the containing HTML page.

There is no standard way to determine if the actual file has been downloaded.

/* output format determined by filename */
XLSX.writeFile(workbook, "out.xlsb");
/* at this point, out.xlsb will have been downloaded */
Download a file in legacy browsers (click to show)

XLSX.writeFile techniques work for most modern browsers as well as older IE. For much older browsers, there are workarounds implemented by wrapper libraries.

FileSaver.js implements saveAs. Note: XLSX.writeFile will automatically call saveAs if available.

/* bookType can be any supported output type */
var wopts = { bookType:"xlsx", bookSST:false, type:"array" };

var wbout = XLSX.write(workbook,wopts);

/* the saveAs call downloads a file on the local machine */
saveAs(new Blob([wbout],{type:"application/octet-stream"}), "test.xlsx");

Downloadify uses a Flash SWF button to generate local files, suitable for environments where ActiveX is unavailable:

Downloadify.create(id,{
  /* other options are required! read the downloadify docs for more info */
  filename: "test.xlsx",
  data: function() { return XLSX.write(wb, {bookType:"xlsx", type:"base64"}); },
  append: false,
  dataType: "base64"
});

The oldie demo shows an IE-compatible fallback scenario.

Browser upload file (ajax) (click to show)

A complete example using XHR is included in the XHR demo, along with examples for fetch and wrapper libraries. This example assumes the server can handle Base64-encoded files (see the demo for a basic nodejs server):

/* in this example, send a base64 string to the server */
var wopts = { bookType:"xlsx", bookSST:false, type:"base64" };

var wbout = XLSX.write(workbook,wopts);

var req = new XMLHttpRequest();
req.open("POST", "/upload", true);
var formdata = new FormData();
formdata.append("file", "test.xlsx"); // <-- server expects `file` to hold name
formdata.append("data", wbout); // <-- `data` holds the base64-encoded data
req.send(formdata);
PhantomJS (Headless Webkit) File Generation (click to show)

The headless demo includes a complete demo to convert HTML files to XLSB workbooks using PhantomJS. PhantomJS fs.write supports writing files from the main process but has a different interface from the NodeJS fs module:

var XLSX = require('xlsx');
var fs = require('fs');

/* generate a binary string */
var bin = XLSX.write(workbook, { type:"binary", bookType: "xlsx" });
/* write to file */
fs.write("test.xlsx", bin, "wb");

Note: The section "Processing HTML Tables" shows how to generate a workbook from HTML tables in a page in "Headless WebKit".

The included demos cover mobile apps and other special deployments.

Writing Examples

Streaming Write

The streaming write functions are available in the XLSX.stream object. They take the same arguments as the normal write functions but return a NodeJS Readable Stream.

  • XLSX.stream.to_csv is the streaming version of XLSX.utils.sheet_to_csv.
  • XLSX.stream.to_html is the streaming version of XLSX.utils.sheet_to_html.
  • XLSX.stream.to_json is the streaming version of XLSX.utils.sheet_to_json.
nodejs convert to CSV and write file (click to show)
var output_file_name = "out.csv";
var stream = XLSX.stream.to_csv(worksheet);
stream.pipe(fs.createWriteStream(output_file_name));
nodejs write JSON stream to screen (click to show)
/* to_json returns an object-mode stream */
var stream = XLSX.stream.to_json(worksheet, {raw:true});

/* the following stream converts JS objects to text via JSON.stringify */
var conv = new Transform({writableObjectMode:true});
conv._transform = function(obj, e, cb){ cb(null, JSON.stringify(obj) + "\n"); };

stream.pipe(conv); conv.pipe(process.stdout);
Exporting NUMBERS files (click to show)

The NUMBERS writer requires a fairly large base. The supplementary xlsx.zahl scripts provide support. xlsx.zahl.js is designed for standalone and NodeJS use, while xlsx.zahl.mjs is suitable for ESM.

Browser

<meta charset="utf8">
<script src="xlsx.full.min.js"></script>
<script src="xlsx.zahl.js"></script>
<script>
var wb = XLSX.utils.book_new(); var ws = XLSX.utils.aoa_to_sheet([
  ["SheetJS", "<3","விரிதாள்"],
  [72,,"Arbeitsblätter"],
  [,62,"数据"],
  [true,false,],
]); XLSX.utils.book_append_sheet(wb, ws, "Sheet1");
XLSX.writeFile(wb, "textport.numbers", {numbers: XLSX_ZAHL, compression: true});
</script>

Node

var XLSX = require("./xlsx.flow");
var XLSX_ZAHL = require("./dist/xlsx.zahl");
var wb = XLSX.utils.book_new(); var ws = XLSX.utils.aoa_to_sheet([
  ["SheetJS", "<3","விரிதாள்"],
  [72,,"Arbeitsblätter"],
  [,62,"数据"],
  [true,false,],
]); XLSX.utils.book_append_sheet(wb, ws, "Sheet1");
XLSX.writeFile(wb, "textport.numbers", {numbers: XLSX_ZAHL, compression: true});

Deno

import * as XLSX from './xlsx.mjs';
import XLSX_ZAHL from './dist/xlsx.zahl.mjs';

var wb = XLSX.utils.book_new(); var ws = XLSX.utils.aoa_to_sheet([
  ["SheetJS", "<3","விரிதாள்"],
  [72,,"Arbeitsblätter"],
  [,62,"数据"],
  [true,false,],
]); XLSX.utils.book_append_sheet(wb, ws, "Sheet1");
XLSX.writeFile(wb, "textports.numbers", {numbers: XLSX_ZAHL, compression: true});

https://github.com/sheetjs/sheetaki pipes write streams to nodejs response.

Generating JSON and JS Data

JSON and JS data tend to represent single worksheets. The utility functions in this section work with single worksheets.

The "Common Spreadsheet Format" section describes the object structure in more detail. workbook.SheetNames is an ordered list of the worksheet names. workbook.Sheets is an object whose keys are sheet names and whose values are worksheet objects.

The "first worksheet" is stored at workbook.Sheets[workbook.SheetNames[0]].

API

Create an array of JS objects from a worksheet

var jsa = XLSX.utils.sheet_to_json(worksheet, opts);

Create an array of arrays of JS values from a worksheet

var aoa = XLSX.utils.sheet_to_json(worksheet, {...opts, header: 1});

The sheet_to_json utility function walks a workbook in row-major order, generating an array of objects. The second opts argument controls a number of export decisions including the type of values (JS values or formatted text). The "JSON" section describes the argument in more detail.

By default, sheet_to_json scans the first row and uses the values as headers. With the header: 1 option, the function exports an array of arrays of values.

Examples

x-spreadsheet is an interactive data grid for previewing and modifying structured data in the web browser. The xspreadsheet demo includes a sample script with the stox function for converting from a workbook to x-spreadsheet data object. https://oss.sheetjs.com/sheetjs/x-spreadsheet is a live demo.

Previewing data in a React data grid (click to show)

react-data-grid is a data grid tailored for react. It expects two properties: rows of data objects and columns which describe the columns. For the purposes of massaging the data to fit the react data grid API it is easiest to start from an array of arrays.

This demo starts by fetching a remote file and using XLSX.read to extract:

import { useEffect, useState } from "react";
import DataGrid from "react-data-grid";
import { read, utils } from "xlsx";

const url = "https://oss.sheetjs.com/test_files/RkNumber.xls";

export default function App() {
  const [columns, setColumns] = useState([]);
  const [rows, setRows] = useState([]);
  useEffect(() => {(async () => {
    const wb = read(await (await fetch(url)).arrayBuffer(), { WTF: 1 });

    /* use sheet_to_json with header: 1 to generate an array of arrays */
    const data = utils.sheet_to_json(wb.Sheets[wb.SheetNames[0]], { header: 1 });

    /* see react-data-grid docs to understand the shape of the expected data */
    setColumns(data[0].map((r) => ({ key: r, name: r })));
    setRows(data.slice(1).map((r) => r.reduce((acc, x, i) => {
      acc[data[0][i]] = x;
      return acc;
    }, {})));
  })(); });

  return <DataGrid columns={columns} rows={rows} />;
}
Previewing data in a VueJS data grid (click to show)

vue3-table-lite is a simple VueJS 3 data table. It is featured in the VueJS demo.

Populating a database (SQL or no-SQL) (click to show)

The database demo includes examples of working with databases and query results.

Numerical Computations with TensorFlow.js (click to show)

@tensorflow/tfjs and other libraries expect data in simple arrays, well-suited for worksheets where each column is a data vector. That is the transpose of how most people use spreadsheets, where each row is a vector.

A single Array#map can pull individual named rows from sheet_to_json export:

const XLSX = require("xlsx");
const tf = require('@tensorflow/tfjs');

const key = "age"; // this is the field we want to pull
const ages = XLSX.utils.sheet_to_json(worksheet).map(r => r[key]);
const tf_data = tf.tensor1d(ages);

All fields can be processed at once using a transpose of the 2D tensor generated with the sheet_to_json export with header: 1. The first row, if it contains header labels, should be removed with a slice:

const XLSX = require("xlsx");
const tf = require('@tensorflow/tfjs');

/* array of arrays of the data starting on the second row */
const aoa = XLSX.utils.sheet_to_json(worksheet, {header: 1}).slice(1);
/* dataset in the "correct orientation" */
const tf_dataset = tf.tensor2d(aoa).transpose();
/* pull out each dataset with a slice */
const tf_field0 = tf_dataset.slice([0,0], [1,tensor.shape[1]]).flatten();
const tf_field1 = tf_dataset.slice([1,0], [1,tensor.shape[1]]).flatten();

The array demo shows a complete example.

Generating HTML Tables

API

Generate HTML Table from Worksheet

var html = XLSX.utils.sheet_to_html(worksheet);

The sheet_to_html utility function generates HTML code based on the worksheet data. Each cell in the worksheet is mapped to a <TD> element. Merged cells in the worksheet are serialized by setting colspan and rowspan attributes.

Examples

The sheet_to_html utility function generates HTML code that can be added to any DOM element by setting the innerHTML:

var container = document.getElementById("tavolo");
container.innerHTML = XLSX.utils.sheet_to_html(worksheet);

Combining with fetch, constructing a site from a workbook is straightforward:

Vanilla JS + HTML fetch workbook and generate table previews (click to show)
<body>
  <style>TABLE { border-collapse: collapse; } TD { border: 1px solid; }</style>
  <div id="tavolo"></div>
  <script src="https://unpkg.com/xlsx/dist/xlsx.full.min.js"></script>
  <script type="text/javascript">
(async() => {
  /* fetch and parse workbook -- see the fetch example for details */
  const workbook = XLSX.read(await (await fetch("sheetjs.xlsx")).arrayBuffer());

  let output = [];
  /* loop through the worksheet names in order */
  workbook.SheetNames.forEach(name => {

    /* generate HTML from the corresponding worksheets */
    const worksheet = workbook.Sheets[name];
    const html = XLSX.utils.sheet_to_html(worksheet);

    /* add a header with the title name followed by the table */
    output.push(`<H3>${name}</H3>${html}`);
  });
  /* write to the DOM at the end */
  tavolo.innerHTML = output.join("\n");
})();
  </script>
</body>
React fetch workbook and generate HTML table previews (click to show)

It is generally recommended to use a React-friendly workflow, but it is possible to generate HTML and use it in React with dangerouslySetInnerHTML:

function Tabeller(props) {
  /* the workbook object is the state */
  const [workbook, setWorkbook] = React.useState(XLSX.utils.book_new());

  /* fetch and update the workbook with an effect */
  React.useEffect(() => { (async() => {
    /* fetch and parse workbook -- see the fetch example for details */
    const wb = XLSX.read(await (await fetch("sheetjs.xlsx")).arrayBuffer());
    setWorkbook(wb);
  })(); });

  return workbook.SheetNames.map(name => (<>
    <h3>name</h3>
    <div dangerouslySetInnerHTML={{
      /* this __html mantra is needed to set the inner HTML */
      __html: XLSX.utils.sheet_to_html(workbook.Sheets[name])
    }} />
  </>));
}

The react demo includes more React examples.

VueJS fetch workbook and generate HTML table previews (click to show)

It is generally recommended to use a VueJS-friendly workflow, but it is possible to generate HTML and use it in VueJS with the v-html directive:

import { read, utils } from 'xlsx';
import { reactive } from 'vue';

const S5SComponent = {
  mounted() { (async() => {
    /* fetch and parse workbook -- see the fetch example for details */
    const workbook = read(await (await fetch("sheetjs.xlsx")).arrayBuffer());
    /* loop through the worksheet names in order */
    workbook.SheetNames.forEach(name => {
      /* generate HTML from the corresponding worksheets */
      const html = utils.sheet_to_html(workbook.Sheets[name]);
      /* add to state */
      this.wb.wb.push({ name, html });
    });
  })(); },
  /* this state mantra is required for array updates to work */
  setup() { return { wb: reactive({ wb: [] }) }; },
  template: `
  <div v-for="ws in wb.wb" :key="ws.name">
    <h3>{{ ws.name }}</h3>
    <div v-html="ws.html"></div>
  </div>`
};

The vuejs demo includes more React examples.

Generating Single-Worksheet Snapshots

The sheet_to_* functions accept a worksheet object.

API

Generate a CSV from a single worksheet

var csv = XLSX.utils.sheet_to_csv(worksheet, opts);

This snapshot is designed to replicate the "CSV UTF8 (.csv)" output type. "Delimiter-Separated Output" describes the function and the optional opts argument in more detail.

Generate "Text" from a single worksheet

var txt = XLSX.utils.sheet_to_txt(worksheet, opts);

This snapshot is designed to replicate the "UTF16 Text (.txt)" output type. "Delimiter-Separated Output" describes the function and the optional opts argument in more detail.

Generate a list of formulae from a single worksheet

var fmla = XLSX.utils.sheet_to_formulae(worksheet);

This snapshot generates an array of entries representing the embedded formulae. Array formulae are rendered in the form