Python DOCX Generation — Core Concepts
python-docx is the standard library for creating and modifying Word .docx files in Python. It handles paragraphs, tables, styles, images, headers, footers, and sections — without requiring Microsoft Word.
Installation
pip install python-docx
Creating a Document
from docx import Document
from docx.shared import Inches, Pt
from docx.enum.text import WD_ALIGN_PARAGRAPH
doc = Document()
# Title
doc.add_heading("Monthly Performance Report", level=0)
# Paragraph with formatting
para = doc.add_paragraph()
run = para.add_run("Revenue exceeded targets by 15%.")
run.bold = True
run.font.size = Pt(14)
# Regular paragraph
doc.add_paragraph(
"This quarter saw sustained growth across all regions, "
"with particular strength in the Asia-Pacific market."
)
# Bullet list
doc.add_paragraph("North America: +12%", style="List Bullet")
doc.add_paragraph("Europe: +18%", style="List Bullet")
doc.add_paragraph("Asia-Pacific: +23%", style="List Bullet")
doc.save("report.docx")
Tables
table = doc.add_table(rows=1, cols=4, style="Light Grid Accent 1")
# Header row
headers = ["Product", "Q1", "Q2", "Q3"]
for i, header in enumerate(headers):
table.rows[0].cells[i].text = header
# Data rows
data = [
("Widget A", "$12,000", "$15,400", "$18,200"),
("Widget B", "$8,500", "$9,100", "$11,800"),
("Widget C", "$22,000", "$19,600", "$24,500"),
]
for product, q1, q2, q3 in data:
row = table.add_row()
row.cells[0].text = product
row.cells[1].text = q1
row.cells[2].text = q2
row.cells[3].text = q3
Images
doc.add_picture("chart.png", width=Inches(5.5))
# Centered image
last_paragraph = doc.paragraphs[-1]
last_paragraph.alignment = WD_ALIGN_PARAGRAPH.CENTER
Headings and Sections
doc.add_heading("Executive Summary", level=1)
doc.add_paragraph("Overview text...")
doc.add_heading("Regional Breakdown", level=1)
doc.add_heading("North America", level=2)
doc.add_paragraph("Details for NA...")
doc.add_heading("Europe", level=2)
doc.add_paragraph("Details for Europe...")
# Page break
doc.add_page_break()
doc.add_heading("Appendix", level=1)
Headers and Footers
section = doc.sections[0]
header = section.header
header_para = header.paragraphs[0]
header_para.text = "Acme Corp — Confidential"
header_para.alignment = WD_ALIGN_PARAGRAPH.RIGHT
footer = section.footer
footer_para = footer.paragraphs[0]
footer_para.text = "Generated automatically via Python"
Template-Based Generation
The most powerful pattern: open an existing template and fill in content.
from docx import Document
def fill_template(template_path, replacements, output_path):
"""Replace {{placeholders}} in a Word template."""
doc = Document(template_path)
for para in doc.paragraphs:
for key, value in replacements.items():
if key in para.text:
for run in para.runs:
if key in run.text:
run.text = run.text.replace(key, value)
# Also check tables
for table in doc.tables:
for row in table.rows:
for cell in row.cells:
for key, value in replacements.items():
if key in cell.text:
for para in cell.paragraphs:
for run in para.runs:
if key in run.text:
run.text = run.text.replace(key, value)
doc.save(output_path)
# Usage
fill_template("contract_template.docx", {
"{{CLIENT_NAME}}": "Acme Industries",
"{{DATE}}": "March 28, 2026",
"{{AMOUNT}}": "$50,000",
"{{TERMS}}": "Net 30",
}, "contract_acme.docx")
Reading Existing Documents
doc = Document("existing.docx")
for para in doc.paragraphs:
print(f"[{para.style.name}] {para.text}")
for table in doc.tables:
for row in table.rows:
print([cell.text for cell in row.cells])
Common Misconception
“python-docx can do everything Word can.” It covers the most common features — paragraphs, tables, images, styles, headers — but doesn’t support some advanced features like tracked changes, macros, footnotes (limited), or form fields. For those, you may need to work with the underlying XML directly or use a different approach.
The one thing to remember: python-docx is best used with templates — design your document in Word, save it as a template, then use Python to fill in the dynamic parts while preserving all the formatting.
See Also
- Python Excel Openpyxl openpyxl lets Python read and write real Excel files — no Excel needed on the computer.
- Python Pdf Generation Reportlab ReportLab lets Python draw professional PDFs from scratch — invoices, reports, certificates — without needing Word or a designer.
- Ci Cd Why big apps can ship updates every day without turning your phone into a glitchy mess — CI/CD is the behind-the-scenes quality gate and delivery truck.
- Containerization Why does software that works on your computer break on everyone else's? Containers fix that — and they're why Netflix can deploy 100 updates a day without the site going down.
- Python 310 New Features Python 3.10 gave programmers a shape-sorting machine, friendlier error messages, and cleaner ways to say 'this or that' in type hints.