A focused playbook for generating professional Word documents (
.docx) from raw data withpython-docx, with the pitfalls called out so you don't hit them in production.
This is the methodology that backs the DOCX deliverables in the
poseidon-weather
analysis reports (5 reports: pre-show cross-validation, weather
performance FINAL, weather performance VERIFICATION, the original
report, and the FINAL REPORT consolidated version).
- The 3 mandatory
python-docxpitfalls that bite every time you reach for the library - The standard audit/comparison report structure (10-section template)
- Color coding convention for status tags
- The verification-first workflow (parse → verify every number → calculate deltas → build → cross-check third-party claims → save and verify)
- Telegram document delivery — the silent-drop trap and how to
actually deliver
.docxfiles to the user
Read the full playbook in SKILL.md.
| # | Pitfall | Fix |
|---|---|---|
| 1 | add_table() requires rows and cols — you cannot create an empty table and add rows later |
Pre-calculate 1 (header) + len(data_rows) and pass to add_table() |
| 2 | add_run() does not accept a style parameter |
The paragraph IS already that style — set the paragraph's style, not the run's |
| 3 | For inline emphasis use .bold = True on the run, not paragraph styles |
run = p.add_run('text'); run.bold = True |
Full examples, plus the standard report structure and the color-coding
convention, are in SKILL.md.
- ✅ Building audit reports that compare metrics across time periods (Phase 1 vs Phase 2)
- ✅ Data-driven reports requiring explicit source verification sections
- ✅ Any task where you need a formatted DOCX with tables from structured data
- ❌ NOT for one-off memos or prose — use Markdown for those
- ❌ NOT for spreadsheets — use
openpyxldirectly for.xlsx
pip install python-docxfrom docx import Document
from docx.shared import RGBColor
doc = Document()
doc.add_heading("Audit Report", level=1)
# Pitfall #1: pre-calculate dimensions
table = doc.add_table(rows=1 + len(data_rows), cols=4)
hdr = table.rows[0].cells
hdr[0].text = "Metric"
hdr[1].text = "Phase 1"
hdr[2].text = "Phase 2"
hdr[3].text = "Delta"
# Pitfall #2: set paragraph style, not run style
for i, row in enumerate(data_rows, start=1):
cells = table.rows[i].cells
cells[0].text = row.metric
# ...
# Pitfall #3: inline bold on a run, not the paragraph
p = doc.add_paragraph()
run = p.add_run("Bold inline emphasis")
run.bold = True
doc.save("report.docx")docx-report-generation/
├── README.md # this file
├── SKILL.md # the full playbook (pitfalls + structure + workflow + delivery)
├── LICENSE # MIT
└── .gitignore
Pouyasharp/poseidon-weather— the analysis that uses this report-generation playbook (5 DOCX reports ship in that project'soutput/)Pouyasharp/meta-price-test-analysis— the price-test pipeline; the deliverable is PNG viz (not DOCX), but the same report-structure philosophy applies
MIT. See LICENSE.