WolfSDKWolfXLWolfPPTWolfDocxWolfRender

WolfDocx - nested tables

Can python-docx handle nested tables and complex headers?

Yes: python-docx can create a table inside a cell and tables inside section headers, so those requirements alone do not require another Python Word library. Use cell.add_table for nesting and the section header API for header content. Problems often come from traversal or replacement assumptions rather than a lack of nested-table support.

Nested tables are not top-level document tables

The python-docx cell API documents add_table and the cell's tables collection. A nested table belongs to its containing cell, not to the document's top-level table collection. Code that inspects only document.tables can therefore miss content that is present in the file. Header tables belong to a header story and need their own traversal as well.

A cell must end with a paragraph. The public add_table method adds the required paragraph after the new table, so leave it in place or populate it as this example does. There is no need to splice a w:tbl string into document.xml or remove the last paragraph to make the table fit. Layout and content structure are separate concerns.

Create a nested fee table and a two-column page header

Install python-docx==1.2.0, then run the example in a fresh directory. It creates a body table, nests a second table in one cell, and places a separate table in the default section header. The final assertions reopen the DOCX and check each structure through its actual owner.

from docx import Document
from docx.shared import Inches

# Run in a fresh directory. No template or private XML API is needed.
document = Document()
outer = document.add_table(rows=1, cols=2)
outer.cell(0, 0).text = "Matter"
container = outer.cell(0, 1)
container.text = "Fees"
nested = container.add_table(rows=2, cols=2)
nested.cell(0, 0).text = "Service"
nested.cell(0, 1).text = "Amount"
nested.cell(1, 0).text = "Review"
nested.cell(1, 1).text = "1,200"
# add_table leaves the required trailing paragraph in the cell.
container.paragraphs[-1].text = "All amounts in USD"

header = document.sections[0].header
header.paragraphs[0].text = "Engagement letter"
header_table = header.add_table(rows=1, cols=2, width=Inches(6))
header_table.cell(0, 0).text = "A & B Legal"
header_table.cell(0, 1).text = "Confidential"
document.save("nested_tables.docx")

reopened = Document("nested_tables.docx")
assert len(reopened.tables) == 1  # Only the top-level body table.
inner = reopened.tables[0].cell(0, 1).tables[0]
assert inner.cell(1, 1).text == "1,200"
assert reopened.sections[0].header.tables[0].cell(0, 0).text == "A & B Legal"

Why a nested table can disappear during an edit

Assigning cell.text after creating a nested table replaces all existing cell content with a single paragraph and run, as the same cell API reference states. That removes the nested table by design. Set the initial cell text before adding the table, or edit a specific paragraph or inner cell afterward. A convenience property that replaces a whole container is not a targeted text-edit operation.

Headers introduce another ownership boundary. The header and footer guide explains that linked sections inherit a definition. Unlink a header before making independent changes, and decide separately whether first-page or even-page variants are needed. A table in the default header does not automatically configure every header variant.

When WolfDocx adds something different

Keep python-docx when the task is constructing these structures from code. WolfDocx is relevant when the source is a reviewed template and the pipeline may change only selected values. Its Commercial reporting workflow discovers supported simple-run cells and binds edits to the source identity and expected text. Header and footer targets require the exact part name. Do not infer that support for reading or preserving a nested table makes every cell or repeating-region edit available.

What it does not do

  • The example does not lay out pages, render a PDF, or prove the table fits a particular printed page.
  • It demonstrates paragraph and table headers, not arbitrary floating objects or every possible Word header feature.
  • WolfDocx's literal-placeholder repeat workflow refuses merged or nested table selections; it is not a general nested-table templating engine.
  • Commercial reporting functions are not exports of the MIT wolfdocx 0.1.0 pip package.

Related: targeted table-cell edits, repeat a supported template row, and python-docx migration boundaries.

Get WolfDocx

WolfDocx Community is MIT-licensed and free, including commercial use. It edits existing .docx files in place in pure Python and does not render pages or convert to PDF. WolfDocx Commercial does not change those rights.

pip install wolfdocx

WolfDocx Commercial is an organization-scoped subscription. WolfDocx Community installs from public PyPI with pip install wolfdocx. WolfDocx Commercial installs from the authenticated WolfDocx package index with a per-purchase credential, issued on the checkout success page after payment and reissued through https://wolfxl.com/recover.

Review the scoped before-and-after memo files in the reporting walkthrough, or ask about your document before purchasing if compatibility is uncertain.

Related tasks