Fill DOCX template forms programmatically while preserving 100% of original structure - logos, footers, styles, metadata. Zero-artifact insertion for forms, applications, and standardized documents. Output indistinguishable from manual filling.
Fill template forms programmatically with zero detectable artifacts. The filled document must be indistinguishable from manual typing in the original template.
Invoke when:
Critical requirement: Template integrity must be 100% preserved (logos, footers, headers, styles, metadata, element structure).
WRONG approach: Extract content from template, generate new document
RIGHT approach: Load template, insert content at anchor points using XML API
# This SEEMS correct but ONLY copies styles, NOT structure
pandoc content.md -o output.docx --reference-doc=template.docx
What happens:
Why it fails: --reference-doc means "copy the style definitions," NOT "preserve the document structure"
# This destroys template structure
template = Document('template.docx')
# Remove content after markers
# ... (deletion logic)
# Append all new content at end
for para in new_content:
template.add_paragraph(para.text) # WRONG!
What happens:
# DON'T copy table structure and rebuild
new_table = template.add_table(rows=3, cols=2)
# Even if copying all properties, it's not the original!
What happens:
Always inspect before modifying. Never assume structure.
Use the provided inspection script:
python scripts/inspect_template.py template.docx
This prints:
Why critical: Prevents modifying wrong tables, missing anchors, breaking structure.
Modify cells in place. Never recreate tables.
from docx import Document
template = Document('template.docx')
# Fill specific cells in existing table
info_table = template.tables[0]
info_table.rows[0].cells[1].text = "Jane Smith"
info_table.rows[1].cells[1].text = "S12345"
# Table structure, styles, borders all preserved
Principle: Modify existing cells. Never remove and recreate.
Insert content at specific positions using XML API.
# Find anchor paragraphs
anchor_positions = []
for i, para in enumerate(template.paragraphs):
if para.text.strip() == "Answer:":
anchor_positions.append(i)
# Insert content after anchor using XML API
def insert_after(doc, anchor_idx, content_paras):
anchor_elem = doc.paragraphs[anchor_idx]._element
parent = anchor_elem.getparent()
for offset, para in enumerate(content_paras):
parent.insert(
parent.index(anchor_elem) + 1 + offset,
para._element
)
# Load content to insert
content_doc = Document('my_content.docx')
section_paragraphs = content_doc.paragraphs[5:64]
# Insert at anchor
insert_after(template, anchor_positions[0], section_paragraphs)
# Save
template.save('completed.docx')
Why XML API:
doc.add_paragraph() appends at end → wrong positionpara.insert_paragraph_before() has stale reference issuesWhen inserting at multiple positions, insert from bottom to top to preserve earlier indices.
# Template has anchors at paragraphs 18, 27, 37
# Insert in REVERSE order
insert_after(template, 37, section3_content) # Last anchor first
insert_after(template, 27, section2_content) # Middle still at 27
insert_after(template, 18, section1_content) # First still at 18
Why reverse: Inserting content shifts later paragraph indices but not earlier ones.
For detailed implementations, see references/patterns.md:
template = Document('form_template.docx')
# Fill info table
info_table = template.tables[0]
info_table.rows[0].cells[1].text = "Applicant Name"
# Find "Answer:" anchors
anchors = [i for i, p in enumerate(template.paragraphs)
if p.text.strip() == "Answer:"]
# Insert responses
responses = Document('my_responses.docx')
response_content = responses.paragraphs[5:30]
insert_after(template, anchors[0], response_content)
template.save('form_completed.docx')
template = Document('report_template.docx')
# Fill team table
team_table = template.tables[0]
team_table.rows[0].cells[1].text = "Team 5"
# Insert section content at anchors
# ... (insertion code)
# Move summary table to correct position
summary_heading_idx = next(i for i, p in enumerate(template.paragraphs)
if "Summary Table:" in p.text)
# Move table from end to after summary heading
# See references/patterns.md for move_table_to_position()
template.save('report_completed.docx')
scripts/inspect_template.py - Inspect template structure before modification
python scripts/inspect_template.py <template.docx>references/patterns.md - Detailed technical patterns
Load patterns.md when implementing specific operations beyond basic workflow.
Template filling is successful if:
This skill documents patterns where:
Use cases: Forms, questionnaires, standardized documents, applications, reports.
Core principle: Preservation over recreation. Never rebuild - always modify in place.
Edit PDFs with natural-language instructions using the nano-pdf CLI.