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:
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.
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
- Template workbook: template-named-ranges-sample.xlsx
- Injection payload: template-assembly-input.json
Large Workbook Planning
For large datasets, use preflight(...) and plan(...) before you render.
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
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.