Define the contract in Excel
Use __config__, source_table, and XTL expressions to describe how raw workbooks become reports.
AI-authored templates · deterministic runtime
An LLM (Claude, GPT, Gemini, Cursor, Codex, …) writes the template.xlsx once; xl3 turns (template.xlsx + raw.xlsx) into result.xlsx as a pure function — same inputs, same bytes, every time.
Workflow model
Developers build the converter once. The recurring business rules, source table mapping, layout, and output shape stay inside the workbook template that teams can archive and hand over.
Use __config__, source_table, and XTL expressions to describe how raw workbooks become reports.
Non-developers choose a raw Excel file and the approved template, then run the converter.
The output keeps sheet structure, number formats, styles, and merged cells while values are rendered from data.
The template becomes the handover artifact: a portable file that captures how the recurring Excel job works.
| A | B | C | |
|---|---|---|---|
| 1 | key | value | notes |
| 2 | source_sheet | Raw | worksheet to read |
| 3 | source_table | 1 | column names and data rows |
source_table tells the engine where the raw table starts and which columns belong to it.
Why developers use it
Python scripts, VBA macros, and service-specific workflows can automate Excel, but the business rules often end up scattered across code, accounts, and tribal knowledge.
xl3 separates the reusable engine from the workbook-specific contract. Developers maintain the TypeScript integration, while each recurring Excel job can travel as a template workbook.
Operational fit
The people running the workflow should not need to read code. They need a stable converter, an approved template, and a predictable result workbook.
Report rules live in a workbook file that can be reviewed, versioned, archived, and passed to the next operator.
template.xlsxThe runtime can be exposed as a browser page: upload raw data, select the template, download the workbook.
raw.xlsx → result.xlsxKeep deployment, validation, and integration in code while template-specific workflow rules stay in Excel.
convert(template, raw)XTL 0.1 ships with 70 ADRs, 154 conformance fixtures, all green at Stage 2. The TypeScript reference implementation is published at @jinyoung4478/xl3 — the Porter's Guide documents the contract so a second-language port can match it.
How it compares
| Approach | Best at | Tradeoff |
|---|---|---|
| xl3 | The execution half of an LLM-authored Excel pipeline. Model writes the template once; xl3 renders deterministically every run. | Alpha; one maintainer; XTL surface is intentionally small and still evolving until 1.0. |
| Direct LLM → xlsx (spreadsheet SDK function call) | Quick exploratory drafting, one-off charts. | Each render is non-deterministic; styles, number formats, and totals drift between runs even with temperature 0. |
| Spreadsheet SDKs (SheetJS, ExcelJS, openpyxl) | Low-level workbook generation. | The model must learn the entire SDK surface and re-emit it each render; the "template" is application code, not a portable file. |
| Power Query / Office Scripts | Microsoft 365 workflows and data shaping inside the Excel ecosystem. | Tenant-bound; the workflow rules do not travel with the workbook. |
| Template engines (JXLS, xltpl, jsreport xlsx) | Server-side report generation from spreadsheet-like templates. | Predate the LLM-as-author model; their template DSLs are larger and not designed to be model-emittable. |
| Doc-gen SaaS (Plumsail, Conga, Formstack) | Managed document workflows, integrations, approvals, and delivery. | Rules live in a vendor service, not a portable workbook you can hand an LLM to edit. |
| Python / VBA scripts | Fast one-off automation close to existing spreadsheets. | Rules live in code or one maintainer's memory; not a model-emittable artifact. |
Developer API
Use the package when the demo flow needs to become an internal portal, a CLI, or a service endpoint. The operator experience can stay file-based while your app owns deployment and validation.
$npm install @jinyoung4478/xl3import { convert } from '@jinyoung4478/xl3';
const outputs = await convert(templateBuffer, dataBuffer);
// OutputFile[] → formatted .xlsx workbook(s)Cookbook 01 — Getting started in 5 minutes · Read the spec · Porter's Guide