XLSX Templates & Large Workbooks

The highest-value spreadsheet workflows usually fall into one of two buckets:

  • you need to fill a customer-owned template
  • you need to render a workbook large enough that planning matters

CmdCal XLSX supports both, but the right mental model is important.

Template Workflow

Start by parsing the existing workbook template:

TYPESCRIPT
import fs from "node:fs/promises";
import { SpreadsheetEngine } from "@paperjsx/json-to-xlsx";

const templateBuffer = await fs.readFile("ops-template.xlsx");
const template = await SpreadsheetEngine.parseTemplate(templateBuffer);
const inspection = SpreadsheetEngine.inspectTemplate(template);

console.log(inspection.sheetInventory);
console.log(inspection.namedRangeInventory);
console.log(inspection.sanitizationActions);

That gives you:

  • sheet inventory
  • named ranges
  • tables
  • relationship inventory
  • sanitization actions
  • preserved opaque parts

Assemble From A Clean Template

Once you know the available anchors, inject data through named ranges or direct cell targets.

TYPESCRIPT
const output = await SpreadsheetEngine.assembleFromTemplate(template, {
  namedRanges: {
    KPIValue: 420000,
    DetailRow: [
      ["North", 120000, 0.24],
      ["EMEA", 98000, 0.19],
      ["LATAM", 43000, 0.14],
    ],
  },
});

Current template assembly support includes:

  • named-range injection
  • direct-cell injection
  • single-row anchor expansion
  • multiple distinct row-expansion anchors on one sheet
  • formula-bearing template rows
  • merge, validation, and table-ref shifting for the supported expansion path

Download A Template Sample

Large Workbook Planning

For large datasets, use preflight(...) and plan(...) before you render.

TYPESCRIPT
const quality = SpreadsheetEngine.preflight(workbook, {
  stringStrategy: "auto",
});

const plan = SpreadsheetEngine.plan(workbook, {
  rowChunkSize: 5000,
  stringStrategy: "auto",
});

console.log(quality.renderModeRecommendation);
console.log(quality.estimatedWorkbookSizeBytes);
console.log(plan.sheetPlans);

This helps you answer:

  • how large the workbook is likely to be
  • whether inline strings are a better fit than shared strings
  • how row chunking is likely to break down per sheet
  • which parts will dominate size

What This Does Not Pretend To Do

Phase 4 laid the groundwork for streaming and chunk-aware planning, but the true public renderStream(...) surface is still an active follow-up item.

That means the current large-workbook story is:

  • preflight honestly
  • plan honestly
  • render deterministically through the current buffered path
  • use the metrics surface to understand cost

Render With Metrics

TYPESCRIPT
const result = await SpreadsheetEngine.renderWithMetrics(workbook, {
  rowChunkSize: 5000,
});

console.log(result.metrics.totalGenerationTimeMs);
console.log(result.metrics.outputSizeBytes);
console.log(result.metrics.sheetMetrics);

This is the right tool when you want:

  • benchmark evidence
  • regression tracking
  • output-size budgeting
  • part-level and chunk-level visibility

When To Reach For Templates

Use template-backed assembly when:

  • the workbook layout is customer-owned
  • sheet tabs, print setup, or formulas already exist
  • non-engineers need to keep editing the source template

Use fully declarative generation when:

  • the workbook is application-owned
  • you want reproducibility over template flexibility
  • you want the cleanest JSON-first path for agents or backend jobs

If you want more ready-to-open examples, use XLSX Examples & Downloads.