---
name: docx
description: Create, read, and edit Word (.docx) documents — build structured reports with headings/paragraphs/tables/images, extract text and tables from existing .docx files, and append content to a document. Use when the task involves producing a Word report (research methodology, factor write-up, committee memo) or reading/parsing data out of a .docx file.
---

# Word (.docx) skill

Toolkit for working with Word documents via **python-docx** (1.2.0). It reads and writes the modern `.docx` format (NOT the old `.doc` binary format).

## Quick decision guide

| Task | Tool / script |
|------|---------------|
| Read all text + tables from a .docx | `scripts/docx_extract.py` |
| Build a structured report (headings/tables/image) | `scripts/build_docx.py` (JSON spec) or snippet below |
| Append to an existing doc | `Document(path)`, add content, `.save(path)` |
| Tables from a DataFrame | `df_to_table()` snippet below |

## Helper scripts

- **`scripts/docx_extract.py`** — Dump every paragraph and table (as CSV) from a .docx, or just the text.
- **`scripts/build_docx.py`** — Build a .docx from a small JSON spec describing a sequence of blocks (`heading`, `para`, `table` (CSV path), `image`, `pagebreak`). Good for templated reports.

## Build a document (python-docx)

```python
from docx import Document
from docx.shared import Pt, Cm, RGBColor
from docx.enum.text import WD_ALIGN_PARAGRAPH

doc = Document()
doc.add_heading("因子研究报告: Momentum_20d", level=0)
doc.add_heading("方法论", level=1)
p = doc.add_paragraph("本因子基于过去 20 个交易日的累计收益率构建，")
p.add_run("横截面标准化后").bold = True
p.add_paragraph("IC 均值 0.043，IR 0.51。", style="List Bullet")
doc.add_picture("cum_return.png", width=Cm(15))   # embed a chart
doc.save("factor_report.docx")
```

## DataFrame -> Word table

```python
def df_to_table(doc, df, style="Light Grid Accent 1"):
    t = doc.add_table(rows=1, cols=len(df.columns))
    t.style = style
    for i, col in enumerate(df.columns):
        t.rows[0].cells[i].text = str(col)
    for _, row in df.iterrows():
        cells = t.add_row().cells
        for i, val in enumerate(row):
            cells[i].text = str(val)
    return t
```

## Read / extract

```python
from docx import Document
doc = Document("report.docx")
text = "\n".join(p.text for p in doc.paragraphs)
for ti, table in enumerate(doc.tables):
    rows = [[c.text for c in r.cells] for r in table.rows]   # -> pandas if needed
```

## Gotchas

- Only `.docx` — the legacy `.doc` format is unsupported; convert first.
- python-docx cannot render/track-changes-accept programmatically beyond reading them; complex revision workflows are limited.
- Built-in table styles (e.g. "Light Grid Accent 1") must exist in the template; a brand-new `Document()` includes the common ones. If a style name errors, omit `t.style`.
- Chinese text renders fine, but to force a CJK-friendly font set the run's `font.name` and the east-asian font:
  `run.font.name = "SimSun"; run._element.rPr.rFonts.set(qn("w:eastAsia"), "SimSun")` (import `from docx.oxml.ns import qn`).
- Set column widths on EACH cell (Word quirk): `for cell in col.cells: cell.width = Cm(4)`.
