How OfficeCLI Template Merge Works with {{key}} Placeholders Across DOCX, XLSX, and PPTX Files
The OfficeCLI merge command replaces {{key}} placeholders in Word, Excel, and PowerPoint documents using a single-pass regex substitution that preserves formatting and reports unresolved placeholders.
OfficeCLI's template merge functionality lets you populate Office documents with JSON data by replacing {{key}} markers. This deep dive examines the implementation in the iOfficeAI/OfficeCLI repository, showing exactly how the tool handles DOCX, XLSX, and PPTX files differently while maintaining consistent placeholder syntax.
Command Entry Point and Data Parsing
The merge operation begins in CommandBuilder.Import.cs, which defines the CLI interface and delegates to Core/TemplateMerger.cs.
Argument Handling
Lines 284-313 of CommandBuilder.Import.cs parse the template path, output path, JSON data (--data), and optional --force flag:
var data = Core.TemplateMerger.ParseMergeData(dataArg);
var mergeResult = Core.TemplateMerger.Merge(template, output, data, force);
JSON Flattening Strategy
TemplateMerger.ParseMergeData (lines 39-89) accepts either inline JSON or a file path, then builds a flat Dictionary<string,string> through two passes:
- Pass 1: Stores literal top-level keys directly—
"a.b"takes precedence over nested{ "a": { "b": … } } - Pass 2: Flattens nested objects into dot-notation (
a.b) and arrays into bracket-notation (items[0])
This flattening enables natural template syntax like {{user.name}} and {{items[0].price}} regardless of JSON structure.
Placeholder Detection Regex
The core pattern matching uses a compiled regex defined at line 28 of TemplateMerger.cs:
private static readonly Regex PlaceholderPattern =
new(@"\{\{\s*(\w[\w.\-\[\] ]*?)\s*\}\}", RegexOptions.Compiled);
This pattern tolerates:
- Outer whitespace:
{{ key }} - Hyphens and spaces:
{{customer-name}},{{order date}} - Dot-paths:
{{invoice.total}} - Array indexes:
{{line_items[3]}}
Format-Specific Merge Implementation
TemplateMerger.Merge (lines 57-89) copies the template and dispatches to format-specific handlers based on file extension.
DOCX: Word Document Handling
The MergeDocx method processes the full document structure:
- Opens
WordprocessingDocumentand enumerates main document, headers, footers, footnotes, endnotes, and comments - For every
<w:t>(text) element containing{{, callsSinglePassReplace SinglePassReplaceruns the regex once, substitutes matches, records used keys, and does not re-scan output—preventing nested placeholder expansionScanUnresolvedDocx(second pass) collects any remaining placeholders
Source: lines 91-126, 130-166, 168-210
XLSX: Excel Spreadsheet Handling
The MergeXlsx method focuses on cell-level operations:
- Opens
SpreadsheetDocument, iterates all worksheets - Extracts cell text handling inline strings, shared strings, and plain strings
- Applies
SinglePassReplaceto each cell's text - Writes results back via
SetCellTextas inline strings - Post-merge scan collects unresolved placeholders
Source: lines 28-68, 70-108
PPTX: PowerPoint Presentation Handling
The MergePptx method handles rich text runs carefully:
- Opens
PresentationDocument, iterates slides and notes - For each
<p:sp>(shape) withTextBody:- Concatenates all run texts
- Runs
SinglePassReplace - Re-writes runs: first run receives new text, subsequent runs removed—preserving original formatting of first run
- Post-merge scan gathers unresolved placeholders
Source: lines 29-73, 75-87, 89-115
Result Reporting and Metrics
The Merge method returns a MergeResult containing:
| Property | Description |
|---|---|
ReplacedCount |
Total substitutions across document |
UnresolvedPlaceholders |
Sorted list of placeholders not found in JSON data |
UsedKeys |
Keys that actually appeared in template |
The CLI prints a summary and writes warnings to stderr for unresolved placeholders.
Practical Usage Examples
Command-Line Merge
# Basic inline JSON
officecli merge template.docx merged.docx --data '{"name":"Alice","date":"2026-07-29"}'
# JSON file with force overwrite
officecli merge report.xlsx report-out.xlsx --data data.json --force
Template Document Example
Dear {{ name }},
Your appointment is scheduled for {{ date }}.
Best regards,
{{ sender.department }}
JSON Data File
{
"name": "Alice Chen",
"date": "2026-07-29",
"sender": {
"name": "Dr. Smith",
"department": "Research Division"
}
}
Programmatic C# Usage
var data = OfficeCli.Core.TemplateMerger.ParseMergeData(
"{\"title\":\"Q1 Report\",\"year\":2024}");
var result = OfficeCli.Core.TemplateMerger.Merge(
"presentation.pptx",
"presentation-merged.pptx",
data,
force: true);
Console.WriteLine($"Replacements: {result.ReplacedCount}");
if (result.UnresolvedPlaceholders.Any())
{
Console.WriteLine("Unresolved: " +
string.Join(", ", result.UnresolvedPlaceholders));
}
Key Implementation Files
src/officecli/CommandBuilder.Import.cs— CLI command definition and argument parsingsrc/officecli/Core/TemplateMerger.cs— Core merge engine, JSON flattening, format handlers- Line 28 — Placeholder regex pattern
- Lines 130-166 — DOCX replacement logic
- Lines 71-108 — XLSX replacement logic
- Lines 89-115 — PPTX replacement logic
Summary
- Single-pass substitution:
SinglePassReplaceprevents recursive expansion by not re-scanning output text - Format-aware handling: DOCX preserves document parts, XLSX manages cell string types, PPTX collapses runs while keeping first-run formatting
- Flat key dictionary: Nested JSON flattens to dot-notation, enabling intuitive template keys
- Comprehensive reporting:
MergeResulttracks replacements, used keys, and unresolved placeholders - CLI and programmatic APIs: Both command-line and C# library usage supported
Frequently Asked Questions
What placeholder syntax does OfficeCLI support?
OfficeCLI accepts {{key}} syntax with flexible spacing. Keys can include letters, numbers, dots for nesting, brackets for arrays, hyphens, and spaces: {{ user.name }}, {{items[0]}}, {{order-date}}, and {{customer name}} are all valid.
How does OfficeCLI handle nested JSON objects in templates?
The ParseMergeData method flattens nested objects into dot-notation keys automatically. A JSON object like {"user": {"name": "Alice"}} becomes accessible as {{user.name}} without manual flattening.
Why does PowerPoint merging preserve only the first run's formatting?
The PPTX handler concatenates all text runs in a shape, performs substitution, then assigns the result to the first run and removes subsequent runs. This maintains the formatting of the first run while ensuring clean text replacement—a necessary trade-off since PowerPoint's run-based structure would create fragmented styling if individual runs were modified.
What happens to unresolved placeholders after merging?
Unresolved placeholders remain as literal text in the output document. The MergeResult includes a sorted list of these placeholders, and the CLI writes a warning to stderr. You can use this list to debug missing JSON keys or intentional optional placeholders.
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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →