From 532c125e1a3c9e565461c4340d5cfdc0cd0a5069 Mon Sep 17 00:00:00 2001
From: Yann GASCUEL <34003959+lnv42@users.noreply.github.com>
Date: Tue, 20 Nov 2018 18:07:50 +0100
Subject: [PATCH 1/4] Table: add looking arguemnts to Table creation (headers,
band, ...)
---
docx/blkcntnr.py | 4 ++--
docx/document.py | 4 ++--
2 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/docx/blkcntnr.py b/docx/blkcntnr.py
index d57a0cd0f..bd549658f 100644
--- a/docx/blkcntnr.py
+++ b/docx/blkcntnr.py
@@ -38,14 +38,14 @@ def add_paragraph(self, text='', style=None):
paragraph.style = style
return paragraph
- def add_table(self, rows, cols, width):
+ def add_table(self, rows, cols, width, firstCol=1, firstRow=1, lastCol=0, lastRow=0, hBand=1, vBand=0):
"""
Return a table of *width* having *rows* rows and *cols* columns,
newly appended to the content in this container. *width* is evenly
distributed between the table columns.
"""
from .table import Table
- tbl = CT_Tbl.new_tbl(rows, cols, width)
+ tbl = CT_Tbl.new_tbl(rows, cols, width, firstCol, firstRow, lastCol, lastRow, hBand, vBand)
self._element._insert_tbl(tbl)
return Table(tbl, self)
diff --git a/docx/document.py b/docx/document.py
index ba94a7990..a1098101b 100644
--- a/docx/document.py
+++ b/docx/document.py
@@ -89,14 +89,14 @@ def add_section(self, start_type=WD_SECTION.NEW_PAGE):
new_sectPr.start_type = start_type
return Section(new_sectPr)
- def add_table(self, rows, cols, style=None):
+ def add_table(self, rows, cols, style=None, firstCol=1, firstRow=1, lastCol=0, lastRow=0, hBand=1, vBand=0):
"""
Add a table having row and column counts of *rows* and *cols*
respectively and table style of *style*. *style* may be a paragraph
style object or a paragraph style name. If *style* is |None|, the
table inherits the default table style of the document.
"""
- table = self._body.add_table(rows, cols, self._block_width)
+ table = self._body.add_table(rows, cols, self._block_width, firstCol, firstRow, lastCol, lastRow, hBand, vBand)
table.style = style
return table
From 5673d757b3914ac16e68c673c751b4019f855bbb Mon Sep 17 00:00:00 2001
From: Yann GASCUEL <34003959+lnv42@users.noreply.github.com>
Date: Tue, 20 Nov 2018 18:13:19 +0100
Subject: [PATCH 2/4] Table: add looking (headers, band, ...) modification
feature
---
docx/oxml/__init__.py | 3 ++-
docx/oxml/table.py | 36 +++++++++++++++++++++++++-------
docx/table.py | 48 +++++++++++++++++++++++++++++++++++++++++++
3 files changed, 79 insertions(+), 8 deletions(-)
diff --git a/docx/oxml/__init__.py b/docx/oxml/__init__.py
index 2731302e2..8905aea59 100644
--- a/docx/oxml/__init__.py
+++ b/docx/oxml/__init__.py
@@ -129,7 +129,7 @@ def OxmlElement(nsptag_str, attrs=None, nsdecls=None):
from .table import (
CT_Height, CT_Row, CT_Tbl, CT_TblGrid, CT_TblGridCol, CT_TblLayoutType,
- CT_TblPr, CT_TblWidth, CT_Tc, CT_TcPr, CT_TrPr, CT_VerticalJc, CT_VMerge
+ CT_TblPr, CT_TblWidth, CT_TblLook, CT_Tc, CT_TcPr, CT_TrPr, CT_VerticalJc, CT_VMerge
)
register_element_cls('w:bidiVisual', CT_OnOff)
register_element_cls('w:gridCol', CT_TblGridCol)
@@ -139,6 +139,7 @@ def OxmlElement(nsptag_str, attrs=None, nsdecls=None):
register_element_cls('w:tblLayout', CT_TblLayoutType)
register_element_cls('w:tblPr', CT_TblPr)
register_element_cls('w:tblStyle', CT_String)
+register_element_cls('w:tblLook', CT_TblLook)
register_element_cls('w:tc', CT_Tc)
register_element_cls('w:tcPr', CT_TcPr)
register_element_cls('w:tcW', CT_TblWidth)
diff --git a/docx/oxml/table.py b/docx/oxml/table.py
index 95f9c6243..df09ed14b 100644
--- a/docx/oxml/table.py
+++ b/docx/oxml/table.py
@@ -12,7 +12,7 @@
from .ns import nsdecls, qn
from ..shared import Emu, Twips
from .simpletypes import (
- ST_Merge, ST_TblLayoutType, ST_TblWidth, ST_TwipsMeasure, XsdInt
+ ST_Merge, ST_TblLayoutType, ST_TblWidth, ST_TwipsMeasure, XsdInt, XsdBoolean
)
from .xmlchemy import (
BaseOxmlElement, OneAndOnlyOne, OneOrMore, OptionalAttribute,
@@ -150,12 +150,12 @@ def iter_tcs(self):
yield tc
@classmethod
- def new_tbl(cls, rows, cols, width):
+ def new_tbl(cls, rows, cols, width, firstCol=1, firstRow=1, lastCol=0, lastRow=0, hBand=1, vBand=0):
"""
Return a new `w:tbl` element having *rows* rows and *cols* columns
with *width* distributed evenly between the columns.
"""
- return parse_xml(cls._tbl_xml(rows, cols, width))
+ return parse_xml(cls._tbl_xml(rows, cols, width, firstCol, firstRow, lastCol, lastRow, hBand, vBand))
@property
def tblStyle_val(self):
@@ -181,21 +181,27 @@ def tblStyle_val(self, styleId):
tblPr._add_tblStyle().val = styleId
@classmethod
- def _tbl_xml(cls, rows, cols, width):
+ def _tbl_xml(cls, rows, cols, width, firstCol, firstRow, lastCol, lastRow, hBand, vBand):
col_width = Emu(width/cols) if cols > 0 else Emu(0)
return (
'\n'
' \n'
' \n'
- ' \n'
+ ' \n'
' \n'
'%s' # tblGrid
'%s' # trs
'\n'
) % (
nsdecls('w'),
+ firstCol,
+ firstRow,
+ lastCol,
+ lastRow,
+ 0 if hBand else 1,
+ 0 if vBand else 1,
cls._tblGrid_xml(cols, col_width),
cls._trs_xml(rows, cols, col_width)
)
@@ -282,6 +288,7 @@ class CT_TblPr(BaseOxmlElement):
bidiVisual = ZeroOrOne('w:bidiVisual', successors=_tag_seq[4:])
jc = ZeroOrOne('w:jc', successors=_tag_seq[8:])
tblLayout = ZeroOrOne('w:tblLayout', successors=_tag_seq[13:])
+ tblLook = ZeroOrOne('w:tblLook', successors=_tag_seq[15:])
del _tag_seq
@property
@@ -365,6 +372,21 @@ def width(self, value):
self.type = 'dxa'
self.w = Emu(value).twips
+class CT_TblLook(BaseOxmlElement):
+ """
+ Used for ```` elements and many others, to
+ specify table-related looks.
+ """
+ # the type for `w` attr is actually ST_MeasurementOrPercent, but using
+ # XsdInt for now because only dxa (twips) values are being used. It's not
+ # entirely clear what the semantics are for other values like -01.4mm
+ firstCol = RequiredAttribute('w:firstColumn', XsdBoolean)
+ firstRow = RequiredAttribute('w:firstRow', XsdBoolean)
+ lastCol = RequiredAttribute('w:lastColumn', XsdBoolean)
+ lastRow = RequiredAttribute('w:lastRow', XsdBoolean)
+ noHBand = RequiredAttribute('w:noHBand', XsdBoolean)
+ noVBand = RequiredAttribute('w:noVBand', XsdBoolean)
+
class CT_Tc(BaseOxmlElement):
"""
diff --git a/docx/table.py b/docx/table.py
index b3bc090fb..d2957b8aa 100644
--- a/docx/table.py
+++ b/docx/table.py
@@ -158,6 +158,54 @@ def table_direction(self):
def table_direction(self, value):
self._element.bidiVisual_val = value
+ @property
+ def first_col(self):
+ return self._tbl.tblPr.tblLook.firstCol
+
+ @first_col.setter
+ def first_col(self, value):
+ self._tbl.tblPr.tblLook.firstCol = value
+
+ @property
+ def first_row(self):
+ return self._tbl.tblPr.tblLook.firstRow
+
+ @first_row.setter
+ def first_row(self, value):
+ self._tbl.tblPr.tblLook.firstRow = value
+
+ @property
+ def last_col(self):
+ return self._tbl.tblPr.tblLook.lastCol
+
+ @last_col.setter
+ def last_col(self, value):
+ self._tbl.tblPr.tblLook.lastCol = value
+
+ @property
+ def last_row(self):
+ return self._tbl.tblPr.tblLook.lastRow
+
+ @last_row.setter
+ def last_row(self, value):
+ self._tbl.tblPr.tblLook.lastRow = value
+
+ @property
+ def h_band(self):
+ return self._tbl.tblPr.tblLook.hBand
+
+ @h_band.setter
+ def h_band(self, value):
+ self._tbl.tblPr.tblLook.hBand = (0 if value else 1)
+
+ @property
+ def v_band(self):
+ return self._tbl.tblPr.tblLook.vBand
+
+ @v_band.setter
+ def v_band(self, value):
+ self._tbl.tblPr.tblLook.vBand = (0 if value else 1)
+
@property
def _cells(self):
"""
From 0464f789ba09f0fc45fc1bef1e2be0e5857cd5d2 Mon Sep 17 00:00:00 2001
From: Yann GASCUEL <34003959+lnv42@users.noreply.github.com>
Date: Tue, 20 Nov 2018 18:50:21 +0100
Subject: [PATCH 3/4] test: fix/add test for the new table looking modification
feature
---
tests/test_document.py | 9 +++++----
1 file changed, 5 insertions(+), 4 deletions(-)
diff --git a/tests/test_document.py b/tests/test_document.py
index c1cb060ec..2c7aaeb08 100644
--- a/tests/test_document.py
+++ b/tests/test_document.py
@@ -77,9 +77,9 @@ def it_can_add_a_section(self, add_section_fixture):
assert section is section_
def it_can_add_a_table(self, add_table_fixture):
- document, rows, cols, style, width, table_ = add_table_fixture
- table = document.add_table(rows, cols, style)
- document._body.add_table.assert_called_once_with(rows, cols, width)
+ document, rows, cols, style, width, firstCol, firstRow, lastCol, lastRow, hBand, vBand, table_ = add_table_fixture
+ table = document.add_table(rows, cols, style, firstCol, firstRow, lastCol, lastRow, hBand, vBand)
+ document._body.add_table.assert_called_once_with(rows, cols, width, firstCol, firstRow, lastCol, lastRow, hBand, vBand)
assert table == table_
assert table.style == style
@@ -201,9 +201,10 @@ def add_section_fixture(self, request, Section_):
def add_table_fixture(self, _block_width_prop_, body_prop_, table_):
document = Document(None, None)
rows, cols, style = 4, 2, 'Light Shading Accent 1'
+ firstCol, firstRow, lastCol, lastRow, hBand, vBand = 1,0,1,0,1,0
body_prop_.return_value.add_table.return_value = table_
_block_width_prop_.return_value = width = 42
- return document, rows, cols, style, width, table_
+ return document, rows, cols, style, width, firstCol, firstRow, lastCol, lastRow, hBand, vBand, table_
@pytest.fixture
def block_width_fixture(self, sections_prop_, section_):
From c03249a0210b09ef86fca55560e31afffe1a5e9d Mon Sep 17 00:00:00 2001
From: Yann GASCUEL <34003959+lnv42@users.noreply.github.com>
Date: Thu, 22 Nov 2018 10:28:44 +0100
Subject: [PATCH 4/4] Table: fix: (no)HBand (no)VBand reversing
---
docx/oxml/table.py | 12 ++++++++++++
docx/table.py | 4 ++--
2 files changed, 14 insertions(+), 2 deletions(-)
diff --git a/docx/oxml/table.py b/docx/oxml/table.py
index df09ed14b..b18ed47c1 100644
--- a/docx/oxml/table.py
+++ b/docx/oxml/table.py
@@ -387,6 +387,18 @@ class CT_TblLook(BaseOxmlElement):
noHBand = RequiredAttribute('w:noHBand', XsdBoolean)
noVBand = RequiredAttribute('w:noVBand', XsdBoolean)
+ def hBand(self):
+ return 0 if self.noHBand else 1
+
+ def hBand(self, value):
+ self.noHBand = 0 if value else 1
+
+ def vBand(self):
+ return 0 if self.noVBand else 1
+
+ def vBand(self, value):
+ self.noVBand = 0 if value else 1
+
class CT_Tc(BaseOxmlElement):
"""
diff --git a/docx/table.py b/docx/table.py
index d2957b8aa..687fb1da4 100644
--- a/docx/table.py
+++ b/docx/table.py
@@ -196,7 +196,7 @@ def h_band(self):
@h_band.setter
def h_band(self, value):
- self._tbl.tblPr.tblLook.hBand = (0 if value else 1)
+ self._tbl.tblPr.tblLook.hBand(value)
@property
def v_band(self):
@@ -204,7 +204,7 @@ def v_band(self):
@v_band.setter
def v_band(self, value):
- self._tbl.tblPr.tblLook.vBand = (0 if value else 1)
+ self._tbl.tblPr.tblLook.vBand(value)
@property
def _cells(self):