How Template Merge with {{key}} Placeholders Works in OfficeCLI for docx, xlsx, and pptx Files

OfficeCLI's merge command uses a universal Mustache-style {{key}} replacement engine that operates directly on OOXML structures to fill Word, Excel, and PowerPoint templates with JSON data.

The OfficeCLI tool provides a deterministic, token-free approach to document generation. By scanning the raw OOXML of .docx, .xlsx, and .pptx files, it detects {{key}} placeholders and substitutes them with JSON values while preserving all original formatting. This single syntax works identically across all three Microsoft Office formats.

How the Template Merge Engine Works

The merge process follows a consistent seven-step pipeline regardless of target format:

  1. Load the OOXML package — Opens the document as a ZipArchive and parses the relevant XML parts
  2. Deserialize the JSON payload — Converts the supplied data into a key → value dictionary
  3. Traverse the XML DOM — Format-specific handlers walk the document tree
  4. Detect placeholders — Compiled regex {{\s*([^}]+)\s*}} matches {{key}} patterns
  5. Substitute values — Replaces text content with JSON values, preserving surrounding formatting tags
  6. Handle empty placeholders — Injects non-breaking spaces or minimal blocks to prevent layout collapse
  7. Persist the modified package — Writes updated XML back to the zip archive

Because the engine operates on raw OOXML rather than rendered documents, it achieves format-agnostic performance with identical {{key}} syntax across Word, Excel, and PowerPoint.

Word Document (docx) Template Merge

In Word documents, the template merge engine targets text runs, content controls, and structured document tags.

Implementation location: src/officecli/Handlers/Word/WordHandler.Helpers.FindReplace.cs

The WordHandler.Helpers.FindReplace.cs file implements the core logic:

  • Scans <w:t> runs inside paragraphs, tables, and headers/footers
  • Detects content-control placeholders (<w:sdt> elements)
  • Preserves run properties (<w:rPr>) such as font, color, and style after replacement

# CLI usage for Word template merge

officecli merge template.docx report-001.docx \
    '{"client":"Acme Corp","total":"$5,200","date":"2026-07-15"}'

# Python SDK

from officecli import Doc

data = {"client": "Acme Corp", "total": "$5,200"}

with Doc("invoice-template.docx") as d:
    d.merge("invoice-001.docx", data)

Excel Spreadsheet (xlsx) Template Merge

Excel template merge operates on cell values, including rich-text formatting and chart metadata.

Implementation location: src/officecli/Handlers/Excel/ExcelHandler.cs

The ExcelHandler.cs processes:

  • Standard cell values in SheetData rows
  • Rich-text cells by rebuilding <is> inline string fragments
  • Table headers/footers and chart titles/axis labels

For rich-text cells, the engine reconstructs the entire <is> element to ensure styling (bold, color, font) remains intact after placeholder substitution.


# CLI usage for Excel template merge

officecli merge budget-template.xlsx budget-q2.xlsx data.json

# Python SDK

with Doc("budget-template.xlsx") as d:
    d.merge("budget-q2.xlsx", data)

PowerPoint Presentation (pptx) Template Merge

PowerPoint template merge handles shape text, slide masters, and visual layout preservation.

Implementation location: src/officecli/Handlers/Pptx/PptxBatchEmitter.Resources.cs

The PptxBatchEmitter.Resources.cs manages:

  • Shape text boxes and auto-shape placeholders (<a:t> elements)
  • Table cells and chart titles
  • Slide-master placeholders for consistent branding

When a placeholder is the only content of a shape, the emitter creates a "sized placeholder" using <a:solidFill> to prevent layout collapse after replacement.


# CLI usage for PowerPoint template merge

officecli merge deck-template.pptx q4-acme.pptx '{"title":"Q4 Report","author":"AI Agent"}'
// Node.js SDK
import { Doc } from "@officecli/sdk";

const data = { title: "Q4 Report", author: "AI Agent" };

await using d = await Doc.open("deck-template.pptx");
await d.merge("deck-q4.pptx", data);

Key Source Files and Their Roles

File Function
src/officecli/Handlers/Word/WordHandler.Helpers.FindReplace.cs Scans Word runs, detects {{key}} patterns, preserves run properties
src/officecli/Handlers/Excel/ExcelHandler.cs Walks worksheet XML, handles standard and rich-text cell replacement
src/officecli/Handlers/Pptx/PptxBatchEmitter.Resources.cs Replaces placeholders in PowerPoint shapes, tables, and chart titles
src/officecli/Commands/MergeCommand.cs Parses CLI arguments and dispatches to format-specific handlers

Supported Placeholder Locations by Format

Format Placeholder Locations
Word (docx) Paragraph text, tables, headers/footers, content controls (<w:sdt>), page numbers, dates
Excel (xlsx) Cell values, rich-text cells, table headers/footers, chart titles, axis labels
PowerPoint (pptx) Shape text boxes, table cells, chart titles, data labels, slide-master placeholders

Summary

  • Single syntax: {{key}} placeholders work identically across Word, Excel, and PowerPoint
  • OOXML-native: Direct XML manipulation preserves all original formatting and styling
  • Format-specific handlers: WordHandler.Helpers.FindReplace.cs, ExcelHandler.cs, and PptxBatchEmitter.Resources.cs implement the core logic
  • Layout protection: Empty placeholder handling prevents document collapse
  • Multi-platform: CLI, Python SDK, and Node.js SDK all support template merge operations

Frequently Asked Questions

What happens if a {{key}} in my template has no matching value in the JSON payload?

The placeholder text remains unchanged in the output document. The engine only substitutes when it finds an exact key match in the JSON dictionary, leaving unmatched {{key}} patterns untouched for manual review.

Does OfficeCLI preserve formatting like fonts, colors, and styles after replacement?

Yes. The engine specifically preserves surrounding XML formatting tags—<w:rPr> for Word, <a:pPr> for PowerPoint, and reconstructed <is> fragments for Excel—so the replaced text inherits all visual styling from the original template.

Can I use nested objects or arrays in my JSON payload for complex template data?

The current implementation uses a flat key → value dictionary. For nested data, flatten your JSON using dot notation (e.g., {"client.name": "Acme", "client.id": "12345"}) and reference keys directly as {{client.name}} in your templates.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →