ProvenPin Install

Excel .xlsx export and import with ExcelJS: working versions (tested 2026-10-15)

Generate styled .xlsx reports (header row, number formats, formulas, frozen panes) and read uploaded workbooks back into typed rows with ExcelJS, all in memory.

passed2 passed · 0 failed2026-10-15 11:52 UTC
Status
passed
Last passed
2026-10-15 11:52 UTC
Tests
2 / 2
Language
TypeScript
Runtime
node v22.23.3
pinned versions3
exceljs@4.4.0tsx@4.23.15@types/node@24.19.2
run it
npm install --no-audit --no-fund --ignore-scripts=false
npm test
test environment
node v22.23.3
linux 6.17.0-1022-azure
x64
runner: github-actions 38730348195

The code

Exactly the files that passed. Your agent can pull them with get_recipe("exceljs-read-write") (install), or see them on GitHub.

package.json
{
  "name": "exceljs-read-write",
  "private": true,
  "type": "module",
  "scripts": {
    "test": "node --import tsx --test test/*.test.ts"
  },
  "dependencies": {
    "exceljs": "4.4.0"
  },
  "devDependencies": {
    "tsx": "4.23.15",
    "@types/node": "24.19.2"
  }
}
src/xlsx.ts
import ExcelJS from "exceljs";

export type Sale = { region: string; units: number; price: number; date: Date };

export async function buildReport(sales: Sale[]) {
  const wb = new ExcelJS.Workbook();
  const ws = wb.addWorksheet("Sales", { views: [{ state: "frozen", ySplit: 1 }] });
  ws.columns = [
    { header: "Region", key: "region", width: 14 },
    { header: "Units", key: "units", width: 8 },
    { header: "Price", key: "price", width: 10, style: { numFmt: "$#,##0.00" } },
    { header: "Date", key: "date", width: 12, style: { numFmt: "yyyy-mm-dd" } },
    { header: "Total", key: "total", width: 12, style: { numFmt: "$#,##0.00" } },
  ];
  ws.getRow(1).font = { bold: true };
  sales.forEach((s, i) => {
    const r = i + 2;
    ws.addRow({ ...s, total: { formula: `B${r}*C${r}`, result: s.units * s.price } });
  });
  const last = sales.length + 1;
  ws.addRow({ region: "TOTAL", total: { formula: `SUM(E2:E${last})`, result: sales.reduce((n, s) => n + s.units * s.price, 0) } });
  return Buffer.from(await wb.xlsx.writeBuffer());
}

export async function readSales(buf: Buffer): Promise<Sale[]> {
  const wb = new ExcelJS.Workbook();
  await wb.xlsx.load(buf as any);
  const ws = wb.getWorksheet("Sales") ?? wb.worksheets[0];
  const out: Sale[] = [];
  ws.eachRow((row, n) => {
    if (n === 1 || row.getCell(1).value === "TOTAL") return;
    out.push({ region: String(row.getCell(1).value), units: Number(row.getCell(2).value), price: Number(row.getCell(3).value), date: row.getCell(4).value as Date });
  });
  return out;
}
test/xlsx.test.ts
import { test } from "node:test";
import assert from "node:assert/strict";
import ExcelJS from "exceljs";
import { buildReport, readSales } from "../src/xlsx.ts";

const sales = [
  { region: "North", units: 3, price: 9.5, date: new Date(Date.UTC(2026, 9, 1)) },
  { region: "South", units: 2, price: 20, date: new Date(Date.UTC(2026, 9, 2)) },
];

test("round-trips rows", async () => {
  const back = await readSales(await buildReport(sales));
  assert.deepEqual(back.map((s) => [s.region, s.units, s.price, s.date.toISOString().slice(0, 10)]), [["North", 3, 9.5, "2026-10-01"], ["South", 2, 20, "2026-10-02"]]);
});

test("formulas, formats and frozen header are written", async () => {
  const wb = new ExcelJS.Workbook();
  await wb.xlsx.load((await buildReport(sales)) as any);
  const ws = wb.getWorksheet("Sales")!;
  assert.deepEqual(ws.getCell("E2").value, { formula: "B2*C2", result: 28.5 });
  assert.equal((ws.getCell("E4").value as any).formula, "SUM(E2:E3)");
  assert.equal(ws.getCell("C2").numFmt, "$#,##0.00");
  assert.equal(ws.getRow(1).font?.bold, true);
  assert.equal((ws.views[0] as any).state, "frozen");
});

Connect to ProvenPin

Add the free MCP server so your agent can pull this recipe and others like it. Same setup as the docs.

terminal
claude mcp add --transport http provenpin https://mcp.provenpin.com/mcp

Any other MCP client: Streamable HTTP at https://mcp.provenpin.com/mcp. No API key, no signup.