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.

pythondocxWorddocument-generationautomation

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.