Skip to content

Commit 7508051

Browse files
committed
feat(table): add CT_Tc.grid_offset
This property was formerly known as `._grid_col` but that didn't account for `.grid_before` in the computation.
1 parent 382d43e commit 7508051

File tree

2 files changed

+32
-12
lines changed

2 files changed

+32
-12
lines changed

src/docx/oxml/table.py

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -450,6 +450,18 @@ def clear_content(self):
450450
for e in self.xpath("./*[not(self::w:tcPr)]"):
451451
self.remove(e)
452452

453+
@property
454+
def grid_offset(self) -> int:
455+
"""Starting offset of `tc` in the layout-grid columns of its table.
456+
457+
A cell in the leftmost grid-column has offset 0.
458+
"""
459+
grid_before = self._tr.grid_before
460+
preceding_tc_grid_spans = sum(
461+
tc.grid_span for tc in self.xpath("./preceding-sibling::w:tc")
462+
)
463+
return grid_before + preceding_tc_grid_spans
464+
453465
@property
454466
def grid_span(self) -> int:
455467
"""The integer number of columns this cell spans.
@@ -484,7 +496,7 @@ def iter_block_items(self):
484496
@property
485497
def left(self) -> int:
486498
"""The grid column index at which this ``<w:tc>`` element appears."""
487-
return self._grid_col
499+
return self.grid_offset
488500

489501
def merge(self, other_tc: CT_Tc) -> CT_Tc:
490502
"""Return top-left `w:tc` element of a new span.
@@ -510,7 +522,7 @@ def right(self) -> int:
510522
This is one greater than the index of the right-most column of the span, similar
511523
to how a slice of the cell's columns would be specified.
512524
"""
513-
return self._grid_col + self.grid_span
525+
return self.grid_offset + self.grid_span
514526

515527
@property
516528
def top(self) -> int:
@@ -553,14 +565,6 @@ def _add_width_of(self, other_tc: CT_Tc):
553565
if self.width and other_tc.width:
554566
self.width = Length(self.width + other_tc.width)
555567

556-
@property
557-
def _grid_col(self) -> int:
558-
"""The grid column at which this cell begins."""
559-
tr = self._tr
560-
idx = tr.tc_lst.index(self)
561-
preceding_tcs = tr.tc_lst[:idx]
562-
return sum(tc.grid_span for tc in preceding_tcs)
563-
564568
def _grow_to(self, width: int, height: int, top_tc: CT_Tc | None = None):
565569
"""Grow this cell to `width` grid columns and `height` rows.
566570
@@ -727,15 +731,15 @@ def _tbl(self) -> CT_Tbl:
727731
@property
728732
def _tc_above(self) -> CT_Tc:
729733
"""The `w:tc` element immediately above this one in its grid column."""
730-
return self._tr_above.tc_at_grid_col(self._grid_col)
734+
return self._tr_above.tc_at_grid_col(self.grid_offset)
731735

732736
@property
733737
def _tc_below(self) -> CT_Tc | None:
734738
"""The tc element immediately below this one in its grid column."""
735739
tr_below = self._tr_below
736740
if tr_below is None:
737741
return None
738-
return tr_below.tc_at_grid_col(self._grid_col)
742+
return tr_below.tc_at_grid_col(self.grid_offset)
739743

740744
@property
741745
def _tr(self) -> CT_Row:

tests/oxml/test_table.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,22 @@ def it_raises_on_tc_at_grid_col(
5252
class DescribeCT_Tc:
5353
"""Unit-test suite for `docx.oxml.table.CT_Tc` objects."""
5454

55+
@pytest.mark.parametrize(
56+
("tr_cxml", "tc_idx", "expected_value"),
57+
[
58+
("w:tr/(w:tc/w:p,w:tc/w:p)", 0, 0),
59+
("w:tr/(w:tc/w:p,w:tc/w:p)", 1, 1),
60+
("w:tr/(w:trPr/w:gridBefore{w:val=2},w:tc/w:p,w:tc/w:p)", 0, 2),
61+
("w:tr/(w:trPr/w:gridBefore{w:val=2},w:tc/w:p,w:tc/w:p)", 1, 3),
62+
("w:tr/(w:trPr/w:gridBefore{w:val=4},w:tc/w:p,w:tc/w:p,w:tc/w:p,w:tc/w:p)", 2, 6),
63+
],
64+
)
65+
def it_knows_its_grid_offset(self, tr_cxml: str, tc_idx: int, expected_value: int):
66+
tr = cast(CT_Row, element(tr_cxml))
67+
tc = tr.tc_lst[tc_idx]
68+
69+
assert tc.grid_offset == expected_value
70+
5571
def it_can_merge_to_another_tc(
5672
self, tr_: Mock, _span_dimensions_: Mock, _tbl_: Mock, _grow_to_: Mock, top_tc_: Mock
5773
):

0 commit comments

Comments
 (0)