cd /news/developer-tools/decompiling-an-excel-template-into-a… · home topics developer-tools article
[ARTICLE · art-115761] src=kookerella.com ↗ pub= topic=developer-tools verified=true sentiment=· neutral

Decompiling an Excel template into a script - #4 JSON

Kookerella Ltd's open-source tool Kookerella.FsOpenXmlDsl.Mcp version 1.0.0 enables decompiling Excel templates into JSON and rebuilding them into .xlsx files, as demonstrated in a four-part series where a PowerShell script reads orders.json and generates an invoice workbook with formulas and styling. The tool, installed via `dotnet tool install -g Kookerella.FsOpenXmlDsl.Mcp`, converts templates with `fsopenxmldsl-mcp convert` and builds with `fsopenxmldsl-mcp build`, preserving data, formulas, and styles in plain JSON.

read4 min views1 publishedAug 29, 2026

This is the JSON counterpart to the XSLT walkthrough, the last of this four-part series, but the story is slightly different. XML pairs naturally with a declarative transform language (XSLT). JSON doesn’t really have an equivalent standard — there’s no dotnet-tool-shaped “jq for .NET” to lean on. So instead of a transform engine applied to a data file, this demo is just what a JSON pipeline naturally looks like in practice: a plain script that already emits JSON, wired straight into fsopenxmldsl-mcp build

. The full project is on GitHub: Kookerella.Demo.DecompileToSource.

What we’re starting from #

The same plain Excel file used in the other three demos: a bold, 16pt “INVOICE” title, a white-on-navy header row with a bottom border, and two sample line-item rows with an Amount

column computed as Qty * Unit Price

.

Step 1: Install the tool #

dotnet tool install -g Kookerella.FsOpenXmlDsl.Mcp

Step 2: Reverse-engineer the template #

fsopenxmldsl-mcp convert templates/InvoiceTemplate.xlsx --lang json -o decompiled/InvoiceTemplate.json

This prints out plain JSON — not source code, just the workbook’s own data and styling, validated against the tool’s own Json.schema.json

schema. A trimmed excerpt, the “Widgets” row:

{ "ref": "A4", "text": "Widgets" },
{ "ref": "B4", "number": 3 },
{ "ref": "C4", "number": 9.99, "style": { "numberFormat": "currency" } },
{
  "ref": "D4",
  "formula": { "expression": "B4*C4", "cachedValue": 29.97 },
  "style": { "numberFormat": "currency" }
}

Text, numbers, a formula with its cached value, and styling — all as plain JSON, no code to read.

Step 3: Turning the decompiled snippet into a generation script #

The decompiled JSON is disposable — it’s the starting point, not the deliverable. The maintained version is split across two files: orders.json

(the data that varies invoice to invoice) and build.ps1

(reads orders.json

, builds the workbook JSON — the styling objects copied verbatim from the decompiled file, as PowerShell [ordered]

hashtables — and writes it out).

The diff from the decompiled file is deliberately small — the title cell and the four header cells are the exact same shape as the decompiled JSON, just written as PowerShell hashtables instead of raw JSON. Only the two hardcoded “Widgets”/“Gadgets” objects became this loop:

for ($i = 0; $i -lt $orders.Count; $i++) {
    $order = $orders[$i]
    $row = 4 + $i
    $amount = [double]$order.quantity * [double]$order.unitPrice

    $cells += [ordered]@{ ref = "A$row"; text = $order.item }
    $cells += [ordered]@{ ref = "B$row"; number = $order.quantity }
    $cells += [ordered]@{ ref = "C$row"; number = $order.unitPrice; style = $currencyStyle }
    $cells += [ordered]@{
        ref     = "D$row"
        formula = [ordered]@{ expression = "B$row*C$row"; cachedValue = $amount }
        style   = $currencyStyle
    }
}

This is the plain-script mirror of the C# demo’s collection-expression spread, the F# demo’s yield!

, and the XSLT demo’s xsl:for-each

— same idea (build one row per order), a fourth different way to express it, this time with no special language feature at all, just an array and a loop.

[ordered]@{...}

(rather than plain @{...}

) matters here: PowerShell’s built-in hashtable doesn’t preserve key order, and an unordered one would still work (fsopenxmldsl-mcp build

doesn’t care about JSON key order) but would make the generated file harder to read and diff against the decompiled reference.

Step 4: Building the Excel file #

.\build.ps1

Internally, this serializes the hashtables above with ConvertTo-Json -Depth 10

, writes the result to invoice.workbook.json

, and then runs:

fsopenxmldsl-mcp build invoice.workbook.json invoice.xlsx

build

is the inverse of convert --lang json

: it reads JSON matching the tool’s Json.schema.json

schema and writes a real .xlsx

. No C#, F#, or XSLT was involved anywhere in this pipeline. The only “code” is a short, ordinary script — which is also the point: most real JSON pipelines (a report generator, an API response, a CI job) are already exactly this shape.

Step 5: Prove it stays correct #

This pipeline is tested the same way the other three demos are — by running the actual build.ps1

script and inspecting the result, rather than trusting that the script “looks right”:

Schema validity— runs a realOpenXmlValidator

over the output.Correctness— feeds in 0, 1, and 3 orders and checks the row count and theAmount

formula for each one.Styling preservation— pins the exact colors, bold, font size, and border style that came from the original template.

Recap #

Step Command Output
Install the tool dotnet tool install -g Kookerella.FsOpenXmlDsl.Mcp fsopenxmldsl-mcp on your PATH
Reverse-engineer fsopenxmldsl-mcp convert InvoiceTemplate.xlsx --lang json -o InvoiceTemplate.json Plain JSON that reproduces the original .xlsx exactly
Make it data-driven Replace hardcoded JSON objects with a loop over your own data build.ps1
Build fsopenxmldsl-mcp build invoice.workbook.json invoice.xlsx A real, schema-valid .xlsx
Verify dotnet test Schema validity, formula correctness, and styling all pinned by real tests

Four languages, one template, one idea: decompile it once, then keep only the two lines that actually change. See the FsOpenXmlDsl and MCP server product pages for the libraries behind all four.

── more in #developer-tools 4 stories · sorted by recency
── more on @kookerella ltd 3 stories trending now
sponsored brought to you by zahid.host 4,200+ EU-deployed projects
reading about agents? ship yours in a single git push.

Run your AI side-project on zahid.host

EU-based hosting, git-push deploys, automatic HTTPS, no cold starts. Free tier with a custom domain — perfect for shipping the agent you just read about.

$git push zahid main
Live at https://your-agent.zahid.host
Get free account → Pricing
from €0/mo · no card required
LIVE [news/decompiling-an-excel…] indexed:0 read:4min 2026-08-29 ·