# How OfficeCLI's Template Merge Feature Replaces Placeholders in Office Documents

> Discover how OfficeCLI's template merge feature automatically replaces {{key}} placeholders in Word, Excel, and PowerPoint documents. Streamline your document generation process with smart placeholder substitution that preserve...

- Repository: [OfficeAI/OfficeCLI](https://github.com/iofficeai/OfficeCLI)
- Tags: how-to-guide
- Published: 2026-07-17

---

**OfficeCLI's template merge feature scans the OOXML structure of Word, Excel, and PowerPoint files to locate Mustache-style `{{key}}` placeholders and substitutes them with values from a JSON payload while preserving the original document formatting.**

OfficeCLI is an open-source command-line tool that enables programmatic generation of Office documents through a unified template system. The **`merge`** command implements a universal template-merge engine that operates on the raw OOXML package structure of `.docx`, `.xlsx`, and `.pptx` files. By traversing the XML DOM and applying a consistent regex-based detection pattern, the tool allows designers to create visual templates once and enables agents to generate filled documents deterministically without re-rendering layouts.

## Format-Specific Implementation Details

The template merge engine employs specialized handlers for each Office format, ensuring that placeholder replacement works across plain-text runs, table cells, shape text boxes, chart titles, and headers or footers.

### Word Documents (docx)

In Word files, the **[`WordHandler.Helpers.FindReplace.cs`](https://github.com/iOfficeAI/OfficeCLI/blob/main/WordHandler.Helpers.FindReplace.cs)** module handles placeholder detection. The engine walks the document's DOM to locate `<w:t>` runs inside paragraphs, tables, headers, and footers, as well as content-control (`<w:sdt>`) placeholders.

The helper uses a regular expression `{{([^}]+)}}` to identify runs containing placeholder text. Upon detection, it replaces the run text with the corresponding JSON value and updates the associated run-properties (`<w:rPr>`) so that the replacement text inherits the original styling.

### Excel Spreadsheets (xlsx)

For Excel files, **[`ExcelHandler.cs`](https://github.com/iOfficeAI/OfficeCLI/blob/main/ExcelHandler.cs)** (located under `src/officecli/Handlers/Excel/`) iterates over the worksheet's `SheetData` rows. It extracts each cell's string value, performs placeholder substitution using the same regex pattern, and writes the new value back to the cell.

For rich-text cells containing styled fragments, the engine rebuilds the `<is>` inline string elements to preserve formatting while updating the text content.

### PowerPoint Presentations (pptx)

The **[`PptxBatchEmitter.Resources.cs`](https://github.com/iOfficeAI/OfficeCLI/blob/main/PptxBatchEmitter.Resources.cs)** file contains the logic for PowerPoint placeholder replacement. When the engine detects a placeholder within a shape's `<a:t>` element, it substitutes the text with the JSON data.

The emitter also handles layout preservation by creating a "sized placeholder" `<a:solidFill>` when the original content is empty, preventing the slide layout from collapsing after replacement.

## Step-by-Step Placeholder Replacement Process

The merge engine follows a deterministic seven-step workflow to process templates:

1. **Load the template** – The binary opens the OOXML package as a `ZipArchive` and parses the relevant XML parts, including [`word/document.xml`](https://github.com/iOfficeAI/OfficeCLI/blob/main/word/document.xml), `xl/worksheets/sheet*.xml`, and `ppt/slides/slide*.xml`.

2. **Parse the JSON payload** – The supplied JSON string or file is deserialized into a dictionary mapping keys to values.

3. **Traverse the XML DOM** – Format-specific handlers walk the XML tree:
   - Word → [`WordHandler.Helpers.FindReplace.cs`](https://github.com/iOfficeAI/OfficeCLI/blob/main/WordHandler.Helpers.FindReplace.cs) (runs)
   - Excel → [`ExcelHandler.cs`](https://github.com/iOfficeAI/OfficeCLI/blob/main/ExcelHandler.cs) (cells)
   - PowerPoint → [`PptxBatchEmitter.Resources.cs`](https://github.com/iOfficeAI/OfficeCLI/blob/main/PptxBatchEmitter.Resources.cs) (shape text)

4. **Detect placeholders** – A compiled regex `{{\s*([^}]+)\s*}}` matches any text node containing a placeholder. The captured group (the key) is looked up in the JSON dictionary.

5. **Replace the text** – If the key exists in the payload, the node's text content is replaced with the JSON value. Surrounding formatting nodes (`<w:rPr>`, `<a:pPr>`, etc.) remain untouched to maintain visual consistency.

6. **Handle empty placeholders** – When a placeholder constitutes the only content of a run or cell, the engine injects a non-breaking space (Unicode `0xA0`) or a minimal "sized placeholder" block to prevent layout shifts.

7. **Persist the modified package** – After processing all document parts, the updated XML files are written back into the zip archive, producing the final merged document.

## Usage Examples

### Command Line Interface

The **[`MergeCommand.cs`](https://github.com/iOfficeAI/OfficeCLI/blob/main/MergeCommand.cs)** file provides the glue code that parses CLI arguments and dispatches to the appropriate format handler.

```bash

# Merge a Word template

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

# Merge an Excel template (cell placeholders)

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

# Merge a PowerPoint template

officecli merge deck-template.pptx q4-acme.pptx '{"title":"Q4 Report","author":"AI Agent"}'

```

### Python SDK

```python
from officecli import Doc

# JSON payload for placeholders

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

# Word merge

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

# Excel merge

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

# PowerPoint merge

with Doc("deck-template.pptx") as d:
    d.merge("deck-q2.pptx", data)

```

### Node.js SDK

```javascript
import { Doc } from "@officecli/sdk";

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

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

```

## Summary

- OfficeCLI provides a **single, consistent placeholder syntax** (`{{key}}`) that works across Word, Excel, and PowerPoint formats.
- The engine operates on **raw OOXML**, ensuring that document formatting, styles, and layout remain intact after replacement.
- **Format-specific handlers** in [`WordHandler.Helpers.FindReplace.cs`](https://github.com/iOfficeAI/OfficeCLI/blob/main/WordHandler.Helpers.FindReplace.cs), [`ExcelHandler.cs`](https://github.com/iOfficeAI/OfficeCLI/blob/main/ExcelHandler.cs), and [`PptxBatchEmitter.Resources.cs`](https://github.com/iOfficeAI/OfficeCLI/blob/main/PptxBatchEmitter.Resources.cs) manage the DOM traversal for each file type.
- A **compiled regex** (`{{\s*([^}]+)\s*}}`) detects placeholders, and the engine preserves styling by leaving XML property nodes untouched.
- **Empty placeholder handling** prevents layout collapse by injecting non-breaking spaces or sized placeholder blocks when necessary.

## Frequently Asked Questions

### What regex pattern does OfficeCLI use to detect placeholders?

OfficeCLI uses the compiled regular expression `{{\s*([^}]+)\s*}}` to locate Mustache-style placeholders. This pattern captures the key name inside the double curly braces, allowing for optional whitespace between the braces and the key text. The captured group is then used to look up the replacement value in the JSON payload.

### How does OfficeCLI preserve formatting when replacing text?

The engine preserves formatting by only modifying the text content nodes (such as `<w:t>` in Word or `<a:t>` in PowerPoint) while leaving the surrounding property nodes (like `<w:rPr>` or `<a:pPr>`) untouched. For Excel rich-text cells, the engine rebuilds the `<is>` inline string fragments to maintain styling while updating the text.

### What happens if a placeholder is the only content in a cell or text run?

When a placeholder constitutes the sole content of a run or cell, the engine injects a non-breaking space (Unicode `0xA0`) or creates a minimal "sized placeholder" block (such as `<a:solidFill>` in PowerPoint). This ensures that the document layout does not shift or collapse after the replacement occurs.

### Can I use the same template across Word, Excel, and PowerPoint?

Yes, the template merge feature is **format-agnostic** regarding the placeholder syntax. You can use identical `{{key}}` placeholders in `.docx`, `.xlsx`, and `.pptx` templates. Each format-specific handler implements the same replacement logic, allowing you to maintain a single source of truth for your data keys across different document types.