WolfDocx documentation - Commercial

# Fill Word templates and run DOCX mail merge in Python

Use Community find_replace for a supported literal text substitution, not as an implicit Word mail-merge engine. For real MERGEFIELD templates and one output per recipient, use WolfDocx Commercial and its source-bound mail-merge request. The Commercial example below is not available from the public pip install wolfdocx package.

## Choose the template operation

A visible placeholder, a Word merge field, and a repeated table row are different structures. Replacing ordinary text does not evaluate a Word field or repeat a row. Identify the structure in the template first, then choose the corresponding operation instead of treating every placeholder as the same syntax.

Community's `Document.find_replace` can substitute ordinary placeholder text through a regular expression. Use the [Community editing example](https://wolfdocx.com/docs/editing-text-and-tables) for that path. Do not use it to rewrite protected field instructions. Commercial provides `merge_documents` for recipient records and `author_template` for explicitly selected repeated template structures.

## Commercial installation and inputs

This page's Python sample targets the commercially licensed `wolfdocx` installation from the authenticated index. Install it in a separate environment from Community, using the authenticated index and the credential from the checkout success page. Both editions install under the name `wolfdocx` from different indexes; an environment holds one or the other, and installing Community alone does not supply this workflow.

The command below is for bash or zsh after pip authentication has been configured. It deliberately contains no credential. Never put a purchase token into source code or a committed installation command.

```
python -m pip install wolfdocx --index-url https://packages.wolfxl.com/wolfdocx/simple/
```

Prepare `template.docx` with the Word field `MERGEFIELD Client`. Use a new `recipients` output directory and an absent `records-new.json` file. The template is an existing reviewed Word document, not a plain-text file renamed to DOCX.

## Publish one recipient document

```
import hashlib
import json
from pathlib import Path

from wolfdocx.mail_merge import merge_documents, parse_mail_merge_request

source = Path("template.docx")
data_path = Path("records-new.json")
with data_path.open("x", encoding="utf-8") as stream:
    json.dump({"records": [
        {"id": "acme", "values": {"Client": "Acme Ltd"}}
    ]}, stream)

report = merge_documents(parse_mail_merge_request({
    "source": str(source),
    "source_sha256": hashlib.sha256(source.read_bytes()).hexdigest(),
    "output_dir": "recipients",
    "data": {
        "path": str(data_path),
        "sha256": hashlib.sha256(data_path.read_bytes()).hexdigest(),
    },
}))
if not report.passed:
    raise SystemExit(report.code)
print(json.dumps(report.to_dict(), indent=2))
```

The records document has a `records` array. Each record has an `id` and `values` map keyed by the template's merge-field names. For this input, the successful batch publishes `recipients/acme.docx`. Additional records produce separate recipient files rather than concatenating every letter into one document.

The request binds both source and data to their SHA-256 digests. This connects the operation to the actual files reviewed by your application. Changing the template or the records after building those bindings is not an invitation to merge the new bytes under the old request.

| Request member | Meaning |
| --- | --- |
| `source`, `source_sha256` | Reviewed template path and its exact-byte digest. |
| `output_dir` | New directory for the recipient batch. |
| `data.path`, `data.sha256` | Records JSON and its exact-byte digest. |

## Inspect before building a batch

The Commercial `discover_mail_merge_targets` function inventories reachable merge fields without publishing a document. Use that inventory to check names and structure before assembling recipient data. Inventory success means discovery succeeded; it does not guarantee that a later merge will pass every validation or publication check.

The engine stages the batch before publication. An occupied destination or unsupported merge structure is a refusal, not permission to emit an incomplete recipient set. Read the report and correct the actual input or target rather than deleting output directories automatically.

## What it does not do

- This example does not render recipients or convert them to PDF.
- It does not demonstrate every conditional field, nested region, or repeated-row operation.
- Community does not gain Commercial APIs through this shared import name.
- A published recipient is not proof of identical Word pagination.

## Related tasks

See [the mail-merge task guide](https://wolfdocx.com/mail-merge-docx-python), [repeating template rows and blocks](https://wolfdocx.com/fill-word-template-python), and [reports and command-line use](https://wolfdocx.com/docs/reports-and-cli).

## Get WolfDocx

WolfDocx Community is MIT-licensed and free, including commercial use. It edits existing .docx files in place in pure Python and does not render pages or convert to PDF. WolfDocx Commercial does not change those rights.

```
pip install wolfdocx
```

WolfDocx Commercial is an organization-scoped subscription. WolfDocx Community installs from public PyPI with pip install wolfdocx. WolfDocx Commercial installs from the authenticated WolfDocx package index with a per-purchase credential, issued on the checkout success page after payment and reissued through https://wolfxl.com/recover.

Review the scoped before-and-after memo files in the [reporting walkthrough](https://wolfsdk.com/blog/updating-existing-office-reporting-files), or [ask about your document](mailto:trial@wolfxl.com?subject=WolfDocx%20workflow%20fit) before purchasing if compatibility is uncertain.

[See WolfDocx Commercial](https://wolfdocx.com/)

### Related tasks

- [Update table cells in an existing Word document with Python](https://wolfdocx.com/update-docx-table-python)
- [Replace text in an existing Word document with Python](https://wolfdocx.com/replace-text-docx-python)
- [Fill a Word template table with rows from Python](https://wolfdocx.com/fill-word-template-python)
- [Word mail merge in Python: fill MERGEFIELD templates and repeating table rows](https://wolfdocx.com/mail-merge-docx-python)
- [Merge Word documents in Python without breaking numbering, headers, or styles](https://wolfdocx.com/merge-docx-python)
- [Update a Word table of contents in Python without opening Word](https://wolfdocx.com/update-toc-docx-python)
- [Convert DOCX to PDF in Python without Word or LibreOffice](https://wolfdocx.com/convert-docx-to-pdf-python)
- [A python-docx alternative for editing existing Word documents](https://wolfdocx.com/python-docx-alternative)
- [How can Python generate many legal contracts from one Word template?](https://wolfdocx.com/generate-contracts-docx-python)
- [Which Python workflow assembles one Word document from clauses and sections?](https://wolfdocx.com/document-assembly-python)
- [How do you prevent Word's unreadable content warning after a python-docx save?](https://wolfdocx.com/python-docx-unreadable-content)
- [Why does python-docx change Link to Previous on headers and footers?](https://wolfdocx.com/python-docx-header-footer-link-to-previous)
- [Can python-docx handle nested tables and complex headers?](https://wolfdocx.com/nested-tables-docx-python)
