Skip to content

table

table

The Table object and related proxy classes.

_TableBorders

_TableBorders(tbl: CT_Tbl)

Bases: _Borders

The border edges of a table, table.borders.

Source code in src/docx/table.py
def __init__(self, tbl: CT_Tbl):
    # -- the edges come from the element class rather than being repeated here, so
    # -- the mapping cannot drift from the schema sequence the element declares --
    super().__init__(CT_TblBorders.edges)
    self._tbl = tbl

_CellBorders

_CellBorders(tc: CT_Tc)

Bases: _Borders

The border edges of a table cell, cell.borders.

Source code in src/docx/table.py
def __init__(self, tc: CT_Tc):
    super().__init__(CT_TcBorders.edges)
    self._tc = tc

_TableLook

_TableLook(tbl: CT_Tbl)

Which parts of the table style apply to a table, table.look.

w:tblLook is what tells Word whether the first row is a header row, whether the first or last column is emphasised, and whether row or column banding is on. Without it a styled table looks nothing like the style preview in Word.

Each flag is tri-state: None means the attribute is absent and Word applies its own default (off for every flag). The two banding flags are stored inverted in the XML, as w:noHBand and w:noVBand; that inversion lives here so the oxml layer stays faithful to the attribute names.

Word writes the six named attributes and the equivalent legacy bitmask in @w:val, and keeps them in step. Setting any flag through this proxy rewrites @w:val to match, because some older consumers read only the bitmask.

Source code in src/docx/table.py
def __init__(self, tbl: CT_Tbl):
    self._tbl = tbl

first_row property writable

first_row: bool | None

True when the table style's first-row (header) formatting applies.

last_row property writable

last_row: bool | None

True when the table style's last-row (total) formatting applies.

first_column property writable

first_column: bool | None

True when the table style's first-column formatting applies.

last_column property writable

last_column: bool | None

True when the table style's last-column formatting applies.

horizontal_banding property writable

horizontal_banding: bool | None

True when the table style's row banding applies.

Stored inverted, as w:noHBand.

vertical_banding property writable

vertical_banding: bool | None

True when the table style's column banding applies.

Stored inverted, as w:noVBand.

_TableCellMargins

_TableCellMargins(tbl: CT_Tbl)

The default cell margins of a table, table.cell_margins.

These are the padding Word applies inside every cell of the table that does not override them. An edge reads None when the table sets no value for it, in which case the table style's value applies.

The start and end edges are the logical (writing-direction) synonyms of left and right. Word writes left and right; both are exposed because documents from other producers use the newer pair.

Source code in src/docx/table.py
def __init__(self, tbl: CT_Tbl):
    self._tbl = tbl

clear

clear() -> None

Remove the w:tblCellMar element, restoring the table style's margins.

Source code in src/docx/table.py
def clear(self) -> None:
    """Remove the `w:tblCellMar` element, restoring the table style's margins."""
    self._tbl.tblPr._remove_tblCellMar()  # pyright: ignore[reportPrivateUsage]

Table

Table(tbl: CT_Tbl, parent: ProvidesStoryPart)

Bases: StoryChild

Proxy class for a WordprocessingML <w:tbl> element.

Source code in src/docx/table.py
def __init__(self, tbl: CT_Tbl, parent: t.ProvidesStoryPart):
    super(Table, self).__init__(parent)
    self._element = tbl
    self._tbl = tbl

alignment property writable

alignment: WD_TABLE_ALIGNMENT | None

Read/write.

A member of WdRowAlignment or None, specifying the positioning of this table between the page margins. None if no setting is specified, causing the effective value to be inherited from the style hierarchy.

autofit property writable

autofit: bool

True if column widths can be automatically adjusted to improve the fit of cell contents.

False if table layout is fixed. Column widths are adjusted in either case if total column width exceeds page width. Read/write boolean.

description property writable

description: str | None

Alternative-text description for this table, or None if not set.

Assigning None removes the description. This value is stored in the w:tblDescription table-property element and is used by assistive technologies.

indent property writable

indent: Length | None

Indentation of this table from the margin, or None if not set.

This is w:tblInd. Assigning None removes it.

width property writable

width: Length | Pct | None

The preferred width of this table.

A Length for an absolute width, a Pct for a percentage of the text column, and None when the width is auto — Word sizing the table to its content — or no w:tblW is present at all.

A percentage table reflows with the page margins where one built from absolute column widths does not, so table.width = Pct(100) is not the same as setting the column widths to add up:

table.width = Pct(100)
table.width = Inches(6)
table.width = None       # auto

Note this is the preferred width: Word may widen a table whose content does not fit, and a table with autofit on will do so routinely.

style property writable

style: _TableStyle | None

_TableStyle object representing the style applied to this table.

Read/write. The default table style for the document (often Normal Table) is returned if the table has no directly-applied style. Assigning None to this property removes any directly-applied table style causing it to inherit the default table style of the document.

Note that the style name of a table style differs slightly from that displayed in the user interface; a hyphen, if it appears, must be removed. For example, Light Shading - Accent 1 becomes Light Shading Accent 1.

table property

table

Provide child objects with reference to the Table object they belong to, without them having to know their direct parent is a Table object.

This is the terminus of a series of parent._table calls from an arbitrary child through its ancestors.

table_direction property writable

table_direction: WD_TABLE_DIRECTION | None

Member of WdTableDirection indicating cell-ordering direction.

For example: WD_TABLE_DIRECTION.LTR. None indicates the value is inherited from the style hierarchy.

title property writable

title: str | None

Alternative-text title for this table, or None if not set.

Assigning None removes the title. This value is stored in the w:tblCaption table-property element and is used by assistive technologies.

add_column

add_column(width: Length)

Return a _Column object of width, newly added rightmost to the table.

Source code in src/docx/table.py
def add_column(self, width: Length):
    """Return a |_Column| object of `width`, newly added rightmost to the table."""
    tblGrid = self._tbl.tblGrid
    gridCol = tblGrid.add_gridCol()
    gridCol.w = width
    for tr in self._tbl.tr_lst:
        tc = tr.add_tc()
        tc.width = width
    return _Column(gridCol, self)

add_row

add_row()

Return a _Row instance, newly added bottom-most to the table.

Source code in src/docx/table.py
def add_row(self):
    """Return a |_Row| instance, newly added bottom-most to the table."""
    tbl = self._tbl
    tr = tbl.add_tr()
    for gridCol in tbl.tblGrid.gridCol_lst:
        tc = tr.add_tc()
        if gridCol.w is not None:
            tc.width = gridCol.w
    return _Row(tr, self)

borders

borders() -> _TableBorders

The border edges of this table, as a mapping keyed by edge name:

table.borders["top"].line = WD_LINE_STYLE.SINGLE
table.borders["top"].size = Pt(1)

These are the borders applied to the table as a whole; insideH and insideV set the horizontal and vertical borders between its cells. A border set on an individual cell through cell.borders takes precedence over the table border at that edge.

Source code in src/docx/table.py
@lazyproperty
def borders(self) -> _TableBorders:
    """The border edges of this table, as a mapping keyed by edge name::

        table.borders["top"].line = WD_LINE_STYLE.SINGLE
        table.borders["top"].size = Pt(1)

    These are the borders applied to the table as a whole; `insideH` and `insideV`
    set the horizontal and vertical borders between its cells. A border set on an
    individual cell through `cell.borders` takes precedence over the table border
    at that edge.
    """
    return _TableBorders(self._tbl)

cell

cell(row_idx: int, col_idx: int) -> _Cell

_Cell at row_idx, col_idx intersection.

(0, 0) is the top, left-most cell. Negative indices count back from the end, as for a sequence.

Raises IndexError if row_idx is out of range, or if the row does not occupy layout-grid column col_idx — Word allows a row to start late or end early.

The target cell is located directly, without materializing the whole layout grid, so reading a table cell-by-cell costs time proportional to the number of cells rather than to its square.

Source code in src/docx/table.py
def cell(self, row_idx: int, col_idx: int) -> _Cell:
    """|_Cell| at `row_idx`, `col_idx` intersection.

    (0, 0) is the top, left-most cell. Negative indices count back from the end, as
    for a sequence.

    Raises |IndexError| if `row_idx` is out of range, or if the row does not occupy
    layout-grid column `col_idx` — Word allows a row to start late or end early.

    The target cell is located directly, without materializing the whole layout
    grid, so reading a table cell-by-cell costs time proportional to the number of
    cells rather than to its square.
    """
    tr = self._tbl.tr_at_idx(row_idx)

    if col_idx < 0:
        col_idx += self._column_count
    try:
        tc = tr.tc_covering_grid_offset(col_idx)
    except ValueError:
        raise IndexError("table column index [%d] is out of range" % col_idx) from None

    # -- a continuation cell of a vertical span holds no content; the cell the span
    # -- starts at does --
    return _Cell(tc.top_tc, self)

column_cells

column_cells(column_idx: int) -> list[_Cell]

Sequence of cells in the column at column_idx in this table.

A row that does not occupy column_idx, because it starts late or ends early, contributes no cell.

Source code in src/docx/table.py
def column_cells(self, column_idx: int) -> list[_Cell]:
    """Sequence of cells in the column at `column_idx` in this table.

    A row that does not occupy `column_idx`, because it starts late or ends early,
    contributes no cell.
    """

    def iter_column_cells() -> Iterator[_Cell]:
        for tr in self._tbl.tr_lst:
            try:
                tc = tr.tc_covering_grid_offset(column_idx)
            except ValueError:
                continue
            yield _Cell(tc.top_tc, self)

    return list(iter_column_cells())

cell_margins

cell_margins() -> _TableCellMargins

The default cell margins for every cell of this table:

table.cell_margins.left = Pt(6)

An edge reads None when the table sets no value for it, in which case the table style's margin applies. Assigning None removes the override.

Source code in src/docx/table.py
@lazyproperty
def cell_margins(self) -> _TableCellMargins:
    """The default cell margins for every cell of this table::

        table.cell_margins.left = Pt(6)

    An edge reads |None| when the table sets no value for it, in which case the
    table style's margin applies. Assigning |None| removes the override.
    """
    return _TableCellMargins(self._tbl)

look

look() -> _TableLook

Which parts of the table style apply to this table:

table.look.first_row = True
table.look.horizontal_banding = True

Applying a table style without setting these produces a table that looks nothing like the style preview in Word.

Source code in src/docx/table.py
@lazyproperty
def look(self) -> _TableLook:
    """Which parts of the table style apply to this table::

        table.look.first_row = True
        table.look.horizontal_banding = True

    Applying a table style without setting these produces a table that looks nothing
    like the style preview in Word.
    """
    return _TableLook(self._tbl)

copy_to

copy_to(
    container: BlockItemContainer | Document,
    *,
    before: Paragraph | Table | None = None,
    after: Paragraph | Table | None = None,
    missing_style: str = "copy",
) -> Table

Return a copy of this table, newly placed in container:

new_table = table.copy_to(document)

See Paragraph.copy_to for what is repaired on the way — relationships, drawing ids, bookmarks, and, for a copy into another document, styles and numbering.

Source code in src/docx/table.py
def copy_to(
    self,
    container: BlockItemContainer | Document,
    *,
    before: Paragraph | Table | None = None,
    after: Paragraph | Table | None = None,
    missing_style: str = "copy",
) -> Table:
    """Return a copy of this table, newly placed in `container`::

        new_table = table.copy_to(document)

    See :meth:`.Paragraph.copy_to` for what is repaired on the way — relationships,
    drawing ids, bookmarks, and, for a copy into another document, styles and
    numbering.
    """
    from docx.copy import copy_content, destination_for, place

    dest_part, dest_element = destination_for(container)
    new_tbl = copy_content(self._tbl, self.part, dest_part, missing_style=missing_style)
    place(new_tbl, dest_element, before, after)
    return Table(new_tbl, container)  # pyright: ignore[reportArgumentType]

delete

delete() -> None

Remove this table from the document.

Relationships referenced only from inside the table are dropped, and any range marker left unmatched is removed, as for Paragraph.delete().

Source code in src/docx/table.py
def delete(self) -> None:
    """Remove this table from the document.

    Relationships referenced only from inside the table are dropped, and any range
    marker left unmatched is removed, as for `Paragraph.delete()`.
    """
    delete_element(self._tbl, self.part)

columns

columns()

_Columns instance representing the sequence of columns in this table.

Source code in src/docx/table.py
@lazyproperty
def columns(self):
    """|_Columns| instance representing the sequence of columns in this table."""
    return _Columns(self._tbl, self)

row_cells

row_cells(row_idx: int) -> list[_Cell]

DEPRECATED: Use table.rows[row_idx].cells instead.

Sequence of cells in the row at row_idx in this table.

Source code in src/docx/table.py
def row_cells(self, row_idx: int) -> list[_Cell]:
    """DEPRECATED: Use `table.rows[row_idx].cells` instead.

    Sequence of cells in the row at `row_idx` in this table.
    """
    column_count = self._column_count
    start = row_idx * column_count
    end = start + column_count
    return self._cells[start:end]

rows

rows() -> _Rows

_Rows instance containing the sequence of rows in this table.

Source code in src/docx/table.py
@lazyproperty
def rows(self) -> _Rows:
    """|_Rows| instance containing the sequence of rows in this table."""
    return _Rows(self._tbl, self)

_Cell

_Cell(tc: CT_Tc, parent: TableParent)

Bases: BlockItemContainer

Table cell.

Source code in src/docx/table.py
def __init__(self, tc: CT_Tc, parent: TableParent):
    super(_Cell, self).__init__(tc, cast("t.ProvidesStoryPart", parent))
    self._parent = parent
    self._tc = self._element = tc

column_index property

column_index: int

Index of the left-most layout-grid column this cell occupies.

Together with .row_index this gives the origin of the cell, which is what tells a repeat of a merged cell apart from a cell in its own right:

for row_idx, row in enumerate(table.rows):
    for col_idx, cell in enumerate(row.cells):
        if (cell.row_index, cell.column_index) != (row_idx, col_idx):
            continue  # -- already emitted, this is part of a merged cell --
        emit(cell.text, rowspan=cell.span_height, colspan=cell.grid_span)

Note this is a layout-grid column index, so it accounts for the grid positions a row leaves unpopulated at its start; see _Row.grid_cols_before.

grid_span property

grid_span: int

Number of layout-grid cells this cell spans horizontally.

A "normal" cell has a grid-span of 1. A horizontally merged cell has a grid-span of 2 or more.

is_merged property

is_merged: bool

True when this cell spans more than one layout-grid cell.

Horizontally, vertically, or both.

paragraphs property

paragraphs

List of paragraphs in the cell.

A table cell is required to contain at least one block-level element and end with a paragraph. By default, a new cell contains a single paragraph. Read-only

row_index property

row_index: int

Index of the top-most row this cell occupies.

For a vertically merged cell this is the row the merge starts at, not the row the cell was reached through. See .column_index for how the pair is used.

span property

span: tuple[int, int]

The extent of this cell as (rows, columns).

(1, 1) for an unmerged cell.

span_height property

span_height: int

Number of rows this cell spans vertically.

An unmerged cell has a span-height of 1; a vertically merged cell has 2 or more. This is the read-side counterpart of .grid_span, and the two together describe a merge completely, including the combined case of a cell that is merged in both directions.

A merge is measured by following its continuation cells, so a document whose origin cell omits w:vMerge — legal in practice and common from generators other than Word — reports the same extent Word renders.

tables property

tables

List of tables in the cell, in the order they appear.

Read-only.

text property writable

text: str

The entire contents of this cell as a string of text.

Assigning a string to this property replaces all existing content with a single paragraph containing the assigned text in a single run.

text_direction property writable

text_direction: WD_TEXT_DIRECTION | None

Flow direction of the text in this cell, or None when inherited.

This is what a rotated header cell needs:

cell.text_direction = WD_TEXT_DIRECTION.BT_LR

Assigning None removes the setting, restoring inheritance.

vertical_alignment property writable

vertical_alignment

Member of WdCellVerticalAlignment or None.

A value of None indicates vertical alignment for this cell is inherited. Assigning None causes any explicitly defined vertical alignment to be removed, restoring inheritance.

width property writable

width

The width of this cell in EMU, or None if no explicit width is set.

add_paragraph

add_paragraph(
    text: str = "",
    style: str | ParagraphStyle | None = None,
)

Return a paragraph newly added to the end of the content in this cell.

If present, text is added to the paragraph in a single run. If specified, the paragraph style style is applied. If style is not specified or is None, the result is as though the 'Normal' style was applied. Note that the formatting of text in a cell can be influenced by the table style. text can contain tab (\t) characters, which are converted to the appropriate XML form for a tab. text can also include newline (\n) or carriage return (\r) characters, each of which is converted to a line break.

Source code in src/docx/table.py
def add_paragraph(self, text: str = "", style: str | ParagraphStyle | None = None):
    """Return a paragraph newly added to the end of the content in this cell.

    If present, `text` is added to the paragraph in a single run. If specified, the
    paragraph style `style` is applied. If `style` is not specified or is |None|,
    the result is as though the 'Normal' style was applied. Note that the formatting
    of text in a cell can be influenced by the table style. `text` can contain tab
    (``\\t``) characters, which are converted to the appropriate XML form for a tab.
    `text` can also include newline (``\\n``) or carriage return (``\\r``)
    characters, each of which is converted to a line break.
    """
    return super(_Cell, self).add_paragraph(text, style)

add_table

add_table(
    rows: int,
    cols: int,
    *,
    title: str | None = None,
    description: str | None = None,
) -> Table

Return a table newly added to this cell after any existing cell content.

The new table will have rows rows and cols columns.

An empty paragraph is added after the table because Word requires a paragraph element as the last element in every cell.

description is the table's alternative text and title the separate, caption-like field Word writes alongside it. Both are omitted from the XML when None.

Source code in src/docx/table.py
def add_table(  # pyright: ignore[reportIncompatibleMethodOverride]
    self,
    rows: int,
    cols: int,
    *,
    title: str | None = None,
    description: str | None = None,
) -> Table:
    """Return a table newly added to this cell after any existing cell content.

    The new table will have `rows` rows and `cols` columns.

    An empty paragraph is added after the table because Word requires a paragraph
    element as the last element in every cell.

    `description` is the table's alternative text and `title` the separate,
    caption-like field Word writes alongside it. Both are omitted from the XML when
    |None|.
    """
    width = self.width if self.width is not None else Inches(1)
    table = super(_Cell, self).add_table(
        rows, cols, width, title=title, description=description
    )
    self.add_paragraph()
    return table

add_caption

add_caption(
    label: str,
    text: str = "",
    *,
    style: str | None = "Caption",
    separator: str = " ",
    restart_at_heading_level: int | None = None,
    before: Paragraph | None = None,
) -> Caption

Add a numbered, cross-referenceable caption to this cell and return it.

See Document.add_caption.

Source code in src/docx/table.py
def add_caption(
    self,
    label: str,
    text: str = "",
    *,
    style: str | None = "Caption",
    separator: str = " ",
    restart_at_heading_level: int | None = None,
    before: Paragraph | None = None,
) -> Caption:
    """Add a numbered, cross-referenceable caption to this cell and return it.

    See :meth:`.Document.add_caption`.
    """
    from docx.caption import add_caption

    return add_caption(
        self,
        label,
        text,
        style=style,
        separator=separator,
        restart_at_heading_level=restart_at_heading_level,
        before=before,
    )

borders

borders() -> _CellBorders

The border edges of this cell, as a mapping keyed by edge name:

cell.borders["bottom"].line = WD_LINE_STYLE.DOUBLE

A cell adds the two diagonal edges tl2br and tr2bl to the edges a table admits. A border set here takes precedence over the table border at the same edge.

Source code in src/docx/table.py
@lazyproperty
def borders(self) -> _CellBorders:
    """The border edges of this cell, as a mapping keyed by edge name::

        cell.borders["bottom"].line = WD_LINE_STYLE.DOUBLE

    A cell adds the two diagonal edges `tl2br` and `tr2bl` to the edges a table
    admits. A border set here takes precedence over the table border at the same
    edge.
    """
    return _CellBorders(self._tc)

merge

merge(other_cell: _Cell)

Return a merged cell created by spanning the rectangular region having this cell and other_cell as diagonal corners.

Raises InvalidSpanError if the cells do not define a rectangular region.

Source code in src/docx/table.py
def merge(self, other_cell: _Cell):
    """Return a merged cell created by spanning the rectangular region having this
    cell and `other_cell` as diagonal corners.

    Raises |InvalidSpanError| if the cells do not define a rectangular region.
    """
    tc, tc_2 = self._tc, other_cell._tc
    merged_tc = tc.merge(tc_2)
    return _Cell(merged_tc, self._parent)

_Column

_Column(gridCol: CT_TblGridCol, parent: TableParent)

Bases: Parented

Table column.

Source code in src/docx/table.py
def __init__(self, gridCol: CT_TblGridCol, parent: TableParent):
    super(_Column, self).__init__(parent)
    self._parent = parent
    self._gridCol = gridCol

cells property

cells: tuple[_Cell, ...]

Sequence of _Cell instances corresponding to cells in this column.

table property

table: Table

Reference to the Table object this column belongs to.

width property writable

width: Length | None

The width of this column in EMU, or None if no explicit width is set.

delete

delete() -> None

Remove this column from its table.

Removes the w:gridCol and the cell occupying this layout-grid column in every row. A cell that spans this column and others is narrowed by one rather than removed, so the rest of its span survives.

Source code in src/docx/table.py
def delete(self) -> None:
    """Remove this column from its table.

    Removes the `w:gridCol` and the cell occupying this layout-grid column in every
    row. A cell that spans this column and others is narrowed by one rather than
    removed, so the rest of its span survives.
    """
    table = self.table
    column_idx = self._index
    for tr in table._tbl.tr_lst:  # pyright: ignore[reportPrivateUsage]
        tr.delete_grid_column(column_idx, table.part)
    delete_element(self._gridCol, table.part)

_Columns

_Columns(tbl: CT_Tbl, parent: TableParent)

Bases: Parented

Sequence of _Column instances corresponding to the columns in a table.

Supports len(), iteration and indexed access.

Source code in src/docx/table.py
def __init__(self, tbl: CT_Tbl, parent: TableParent):
    super(_Columns, self).__init__(parent)
    self._parent = parent
    self._tbl = tbl

table property

table: Table

Reference to the Table object this column collection belongs to.

_Row

_Row(tr: CT_Row, parent: TableParent)

Bases: Parented

Table row.

Source code in src/docx/table.py
def __init__(self, tr: CT_Row, parent: TableParent):
    super(_Row, self).__init__(parent)
    self._parent = parent
    self._tr = self._element = tr

cells property

cells: tuple[_Cell, ...]

Sequence of _Cell instances corresponding to cells in this row.

Note that Word allows table rows to start later than the first column and end before the last column.

  • Only cells actually present are included in the return value.
  • This implies the length of this cell sequence may differ between rows of the same table.
  • If you are reading the cells from each row to form a rectangular "matrix" data structure of the table cell values, you will need to account for empty leading and/or trailing layout-grid positions using .grid_cols_before and .grid_cols_after.

grid_cols_after property

grid_cols_after: int

Count of unpopulated grid-columns after the last cell in this row.

Word allows a row to "end early", meaning that one or more cells are not present at the end of that row.

Note these are not simply "empty" cells. The renderer reads this value and "skips" this many columns after drawing the last cell.

Note this also implies that not all rows are guaranteed to have the same number of cells, e.g. _Row.cells could have length n for one row and n - m for the next row in the same table. Visually this appears as a column (at the beginning or end, not in the middle) with one or more cells missing.

grid_cols_before property

grid_cols_before: int

Count of unpopulated grid-columns before the first cell in this row.

Word allows a row to "start late", meaning that one or more cells are not present at the beginning of that row.

Note these are not simply "empty" cells. The renderer reads this value and skips forward to the table layout-grid position of the first cell in this row; the renderer "skips" this many columns before drawing the first cell.

Note this also implies that not all rows are guaranteed to have the same number of cells, e.g. _Row.cells could have length n for one row and n - m for the next row in the same table.

height property writable

height: Length | None

Return a Length object representing the height of this cell, or None if no explicit height is set.

dont_split property writable

dont_split: bool | None

True if this row is kept on a single page rather than broken across pages.

Corresponds to unchecking "Allow row to break across pages" in Word. None indicates no explicit setting, which Word treats as allowing the break.

repeat_as_header property writable

repeat_as_header: bool | None

True when this row repeats at the top of each page the table spans.

Corresponds to "Repeat Header Rows" in Word. None indicates no explicit setting, which Word treats as off.

Word only honours this on a contiguous run of rows starting at the first row of the table. Setting it on row 3 alone is legal XML that has no visible effect.

hidden property writable

hidden: bool | None

True when this row is not displayed.

None indicates no explicit setting, which Word treats as visible.

alignment property writable

alignment: WD_TABLE_ALIGNMENT | None

Horizontal alignment of this row within the table, or None if not set.

This overrides the table's own alignment for this row alone.

cell_spacing property writable

cell_spacing: Length | None

Spacing between the cells of this row, or None if not set.

width_before property writable

width_before: Length | None

Width of the grid positions this row leaves unpopulated at its start.

Pairs with .grid_cols_before, which counts them. None if not set.

width_after property writable

width_after: Length | None

Width of the grid positions this row leaves unpopulated at its end.

Pairs with .grid_cols_after, which counts them. None if not set.

height_rule property writable

height_rule: WD_ROW_HEIGHT_RULE | None

Return the height rule of this cell as a member of the WdRowHeightRule.

This value is None if no explicit height_rule is set.

table property

table: Table

Reference to the Table object this row belongs to.

copy_to

copy_to(
    table: Table,
    *,
    before: _Row | None = None,
    after: _Row | None = None,
    missing_style: str = "copy",
) -> _Row

Return a copy of this row, newly placed in table.

"Duplicate this table row N times" is the other most-written-by-hand operation:

for _ in range(9):
    template_row.copy_to(table)

before and after place the copy relative to an existing row; with neither it is appended.

The copy keeps this row's own cell widths and spans. It is not adjusted to table's grid, so copying a row into a table of a different column count produces a row that does not line up — which is what the XML says and what Word will render.

See Paragraph.copy_to for what is repaired on the way — relationships, drawing ids, bookmarks, and, for a copy into another document, styles and numbering.

Source code in src/docx/table.py
def copy_to(
    self,
    table: Table,
    *,
    before: _Row | None = None,
    after: _Row | None = None,
    missing_style: str = "copy",
) -> _Row:
    """Return a copy of this row, newly placed in `table`.

    "Duplicate this table row N times" is the other most-written-by-hand operation::

        for _ in range(9):
            template_row.copy_to(table)

    `before` and `after` place the copy relative to an existing row; with neither it
    is appended.

    The copy keeps this row's own cell widths and spans. It is not adjusted to
    `table`'s grid, so copying a row into a table of a different column count
    produces a row that does not line up — which is what the XML says and what Word
    will render.

    See :meth:`.Paragraph.copy_to` for what is repaired on the way — relationships,
    drawing ids, bookmarks, and, for a copy into another document, styles and
    numbering.
    """
    from docx.copy import copy_content

    dest_part = table.part
    new_tr = copy_content(self._tr, self.part, dest_part, missing_style=missing_style)

    if before is not None and after is not None:
        raise ValueError("pass at most one of `before` and `after`")
    if before is not None:
        before._tr.addprevious(new_tr)
    elif after is not None:
        after._tr.addnext(new_tr)
    else:
        table._tbl.append(new_tr)
    return _Row(new_tr, table)  # pyright: ignore[reportArgumentType]

delete

delete() -> None

Remove this row from its table.

A vertically merged cell whose span started in this row is not dropped: the row below inherits it, so the merge continues to render, which is what Word does when a row is deleted.

Source code in src/docx/table.py
def delete(self) -> None:
    """Remove this row from its table.

    A vertically merged cell whose span started in this row is not dropped: the row
    below inherits it, so the merge continues to render, which is what Word does
    when a row is deleted.
    """
    self._tr.transfer_vertical_spans_to_row_below()
    delete_element(self._tr, self.table.part)

_Rows

_Rows(tbl: CT_Tbl, parent: TableParent)

Bases: Parented

Sequence of _Row objects corresponding to the rows in a table.

Supports len(), iteration, indexed access, and slicing.

Source code in src/docx/table.py
def __init__(self, tbl: CT_Tbl, parent: TableParent):
    super(_Rows, self).__init__(parent)
    self._parent = parent
    self._tbl = tbl

table property

table: Table

Reference to the Table object this row collection belongs to.