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

@entree_pos/xlsx

v0.5.0

Published

A zero-dependency modern JavaScript API for lossless XLSX/XLSM editing, charts, pivot tables, and Office password encryption.

Readme

@entree_pos/xlsx

Create polished Excel workbooks with a JavaScript API that stays close to how developers think about spreadsheets: workbooks, sheets, cells, ranges, styles, charts, and pivots.

@entree_pos/xlsx is a modern ESM library for Node.js 18+. It can create new .xlsx files or safely update existing .xlsx and .xlsm templates while preserving workbook parts it does not modify. There are no runtime dependencies. It also imports UTF-8 CSV files into a worksheet, preserving values as text.

npm version

[!WARNING] This package is under active development. APIs may change at any time without prior notice. Do not use it in a production environment yet. If you choose to use it in production, pin the exact package version in your lockfile and review all changes before upgrading.

npm install @entree_pos/xlsx

New to the library? Follow the visual tutorial from a basic data export through styling, formulas, templates, charts, PivotTables, and password encryption.

import { createWorkbook } from "@entree_pos/xlsx";

const workbook = createWorkbook("Orders");
const sheet = workbook.sheet("Orders");

sheet.setData([
  { order: 1001, customer: "Ada", total: 18.5 },
  { order: 1002, customer: "Linus", total: 24 },
  { order: 1003, customer: "Grace", total: 31.25 }
]);

sheet.range("A1:C1").style({
  bold: true,
  color: "#FFFFFF",
  fill: "#17324D",
  horizontal: "center"
});

sheet.range("C2:C100").style({ numberFormat: "$#,##0.00" });
sheet.autoFilter().autoFit({ max: 40 });

await workbook.save("orders.xlsx");

That is a complete workbook: structured data, a styled header, currency formatting, sensible column widths, and an Excel filter.

Why use it?

| Capability | What you can do | | --- | --- | | Direct worksheet helpers | Select ranges, rows, or columns and search, update, style, and size them with chainable helpers | | Rich styling | Fonts, colors, fills, gradients, borders, alignment, number formats, and cell protection | | Reusable design system | Define named styles once, inherit from base styles, and compose them across a workbook | | Template editing | Open an existing workbook, change only what you need, and preserve unknown OOXML parts | | CSV input and output | Read CSV through the workbook APIs and export a worksheet with toCsv() | | Charts | Create, inspect, update, and remove column, bar, line, pie, and scatter charts | | PivotTables | Build and update native PivotTables with row, column, filter, and value fields | | Password encryption | Save and open files using Excel-compatible AES-256 Agile encryption | | Simple deployment | JavaScript-only ESM, Node.js 18+, and zero runtime dependencies |

For the complete method-by-method documentation, see the API reference.

Styling is a first-class API

Spreadsheet styling quickly becomes repetitive when every cell carries its own large configuration object. This library lets you define a small workbook design system and reuse it by name.

workbook.styles
  .define("base", {
    fontName: "Aptos",
    fontSize: 11,
    vertical: "center"
  })
  .define("header", {
    bold: true,
    color: "#FFFFFF",
    fill: "#17324D",
    horizontal: "center",
    wrapText: true
  }, { extends: "base" })
  .define("money", {
    numberFormat: "$#,##0.00;[Red]-$#,##0.00"
  });

sheet.range("A1:D1").style("header");
sheet.range("D2:D100").style("money");

// Named styles and one-off adjustments can be composed left to right.
sheet.cell("D2").style(["money", { bold: true }]);

Named styles are written as real Excel cell styles and survive save/reopen cycles. Direct styles can use friendly shortcuts or detailed nested objects:

sheet.cell("B3").style({
  font: {
    name: "Aptos Display",
    size: 14,
    italic: true,
    color: { theme: 4, tint: -0.2 }
  },
  fill: {
    type: "gradient",
    degree: 90,
    stops: [
      { position: 0, color: "#FFF2CC" },
      { position: 1, color: "#D6A85F" }
    ]
  },
  horizontal: "center",
  vertical: "center",
  rotation: -30,
  shrinkToFit: true,
  protection: { locked: false }
});

Range borders understand position, so an outline is not repeatedly applied to every cell:

sheet.range("A1:D20").style({
  border: {
    outline: { style: "medium", color: "#17324D" },
    inside: { style: "thin", color: "#B7C9D6" }
  }
});

You can also copy or selectively remove formatting without touching a cell's value:

sheet.cell("D2").copyStyleFrom("C2");
sheet.cell("D2").clearStyle(["fill", "font.bold"]);
sheet.range("A2:D20").clearStyle("border");

Import a CSV file

import { openWorkbook } from "@entree_pos/xlsx";

const workbook = await openWorkbook("shipments.csv");
const shipments = workbook.sheet().toRecords({ defaultValue: "" });

The input APIs detect CSV and Excel workbook bytes automatically. CSV fields remain strings, so identifiers such as 0559 keep their leading zeros. Convert quantities or dates explicitly when your application needs typed values. Quoted commas, doubled quotes, embedded newlines, and UTF-8 BOMs are supported. Use { format: "csv" } to force CSV, or { format: "xlsx" } to accept only Excel workbooks. See the input format options.

Edit an existing workbook

Use an existing spreadsheet as a template instead of rebuilding its layout in code.

import { openWorkbook } from "@entree_pos/xlsx";

const workbook = await openWorkbook("invoice-template.xlsx");
const invoice = workbook.sheet("Invoice");

invoice.cell("B3").set("Entree POS").style({ bold: true });
invoice.cell("F18").formula("SUM(F5:F17)").numberFormat("$#,##0.00");
invoice.range("A20:F20").merge().style({ fill: "#EFE8D8" });

await workbook.save("invoice-ready.xlsx");

openWorkbook() accepts a local path, HTTP(S) URL, Buffer, Uint8Array, or ArrayBuffer. openWorkbookSync(path) is available for synchronous file access, and parseWorkbook(bytes) reads in-memory XLSX data.

When an existing .xlsx or .xlsm file is opened, the original OOXML package is retained and only changed parts are patched. Unknown extensions, VBA, images, form controls, and embedded parts are preserved.

Work with cells, ranges, and sheets

The everyday API is intentionally small and chainable:

const sheet = workbook.sheet("Orders");

sheet.set("A1", "Order Number");
sheet.cell("A2").set(1001);
sheet.cell("B2").formula("SUM(B3:B20)", 125.5);
sheet.cell("C2").hyperlink("https://example.com/orders/1001", "Open order");

sheet.range("A1:C3").setValues([
  ["Item", "Qty", "Price"],
  ["Burger", 2, 12.5],
  ["Fries", 1, 4]
]);

sheet.appendRows([["Drink", 2, 3.5]]);
sheet.appendData([{ item: "Shake", qty: 1, price: 5.25 }]);
sheet.insertRows(4, 2);
sheet.copyRow(2, 4);
sheet.deleteRows(10, 1);

sheet.column("B").width(24);
sheet.row(1).height(28);
sheet.autoFit({ min: 8, max: 48, padding: 2 });

Select exactly the worksheet area you need. Every selection supports find(), findAll(), and forEach():

const table = sheet.range("A1:C20");
const header = sheet.row(1);
const body = sheet.rows("2:20");
const prices = sheet.column("C");
const reportColumns = sheet.columns("A:C");

const burger = table.find("Classic Burger");
console.log(burger?.address); // A2

header.style({ bold: true }).height(24);
body.style({ vertical: "center" });
prices.style({ numberFormat: "$#,##0.00" }).width(14);
reportColumns.forEach((cell) => console.log(cell.address, cell.value));

Rows use one-based Excel row numbers. Numeric column references remain zero-based; column letters are usually easier to read.

Read worksheet data in the form your application needs:

const rows = sheet.toRows();
const records = sheet.toRecords();
const csv = sheet.toCsv();
const html = sheet.toHtml();

Manage workbook sheets with similarly direct methods:

workbook.addSheet("Summary", [["Status", "Total"]]);
workbook.renameSheet("Summary", "Dashboard");
workbook.removeSheet("Dashboard");

console.log(workbook.sheetNames);
console.log(workbook.sheetCount);

Use setData() when the new dataset should replace the current cell values. Use appendData() for object records that should follow the sheet's existing headers, and appendRows() for positional array rows.

Add a chart

Charts use worksheet ranges as their data source and cell addresses for placement.

const chart = workbook.charts.add({
  sheet: "Orders",
  name: "RevenueChart",
  type: "column", // column, bar, line, pie, or scatter
  title: "Monthly revenue",
  range: "A1:B13",
  position: { from: "D2", to: "L18" }
});

workbook.charts.update(chart.id, {
  type: "line",
  title: "Revenue trend",
  range: "A1:B13"
});

console.log(workbook.charts.list("Orders"));
// workbook.charts.remove(chart.id);

Build a PivotTable

PivotTables are native Excel objects, not a static table made to look like a pivot.

workbook.addSheet("Summary");

const pivot = workbook.pivotTables.add({
  name: "SalesPivot",
  source: { sheet: "Orders", range: "A1:D500" },
  target: { sheet: "Summary", cell: "A3" },
  rows: ["Region"],
  columns: ["Month"],
  filters: ["Store"],
  values: [
    { field: "Sales", summarize: "sum", name: "Total Sales" }
  ]
});

workbook.pivotTables.update(pivot.id, {
  rows: ["Store"],
  columns: ["Region"]
});

Supported summaries are sum, count, average, min, and max. The library writes the PivotTable definition, cache definition, cache records, and a cached worksheet rendering.

Protect or encrypt a workbook

Password encryption protects the entire file:

await workbook.save("private.xlsx", {
  password: process.env.REPORT_PASSWORD
});

const opened = await openWorkbook("private.xlsx", {
  password: process.env.REPORT_PASSWORD
});

Encrypted files use Excel-compatible AES-256 Agile Office encryption.

Workbook and worksheet protection control editing and structure. They are separate from file encryption:

workbook.protectStructure({
  password: process.env.STRUCTURE_PASSWORD,
  structure: true
});

workbook.sheet("Orders").protectSheet({
  password: process.env.SHEET_PASSWORD
});

Save or export

workbook.properties = {
  title: "Daily orders",
  author: "Entree POS"
};

await workbook.save("daily-orders.xlsx");

const bytes = workbook.toBuffer();
const base64 = workbook.toBase64();

Command line

The package also includes a small command-line utility for inspection and data conversion:

entree-xlsx inspect orders.xlsx
entree-xlsx convert orders.xlsx orders.json --sheet Orders
entree-xlsx convert orders.xlsx orders.csv --sheet Orders
entree-xlsx convert shipments.csv shipments.xlsx

Important behavior

  • The library reads and writes .xlsx and .xlsm, not legacy .xls or .xlsb files.
  • CSV input uses UTF-8 and preserves fields as strings. CSV export is available through sheet.toCsv() or the command-line converter.
  • Formulas are stored but not calculated by the library. Excel recalculates them when the workbook opens.
  • The optional second argument to formula() is a cached value that spreadsheet applications can display before recalculation.
  • Workbook and sheet protection discourage editing; use file encryption when the workbook contents must remain confidential.

Requirements

  • Node.js 18 or newer
  • Native ECMAScript modules (import / export)
  • No runtime dependencies

[!NOTE] This package is designed specifically for use by Entree POS software. Its API evolves to support Entree POS coding conventions and product needs; it is not intended to provide a stable public API. Breaking changes may occur at any time without prior notice. Use this package at your own risk and pin the exact version if you depend on it.

License

MIT