For editing .docx
files in python, python-docx
exposes some properties but not others. Text properties like bold, italics etc can easily be set, but cell properties like background shading and borders can't AFAIK.
What you can do in python-docx
is to view the xml of the cell using the .xml
attribute. So cell._tc.xml
reveals that cell properties are held in a <w:tcPr> ... </w:tcPr>
block. This can be a nested structure, for example
<w:tcPr>
<w:tcW w:w="1139" w:type="dxa"/>
<w:tcBorders>
<w:left w:val="single" w:sz="4" w:space="0" w:color="000000"/>
<w:bottom w:val="single" w:sz="4" w:space="0" w:color="000000"/>
</w:tcBorders>
<w:shd w:fill="FFDBB6" w:val="clear"/>
</w:tcPr>
I would like to copy the exact cell properties from one cell to another cell. I've tried:
<w:tcPr>
block from one cell to the other. However, the .xml
attribute is read only - python-docx
doesn't allow setting xml directly.for child in source_cell._tc.get_or_add_tcPr().iterchildren():
dest_cell._tc.get_or_add_tcPr().insert(child)
but that is raising TypeError: Argument must be bytes or unicode, got 'CT_TcPr'
.
How can I achieve this?
Here is a function which copies the properties from one cell to another:
def copy_cell_properties(source_cell, dest_cell):
'''Copies cell properties from source cell to destination cell.
Copies cell background shading, borders etc. in a python-docx Document.
Args:
source_cell (docx.table._Cell): the source cell with desired formatting
dest_cell (docx.table._Cell): the destination cell to which to apply formatting
'''
# get properties from source cell
# (tcPr = table cell properties)
cell_properties = source_cell._tc.get_or_add_tcPr()
# remove any table cell properties from destination cell
# (otherwise, we end up with two <w:tcPr> ... </w:tcPr> blocks)
dest_cell._tc.remove(dest_cell._tc.get_or_add_tcPr())
# make a shallow copy of the source cell properties
# (otherwise, properties get *moved* from source to destination)
cell_properties = copy.copy(cell_properties)
# append the copy of properties from the source cell, to the destination cell
dest_cell._tc.append(cell_properties)
There is a related discussion here - https://github.com/python-openxml/python-docx/issues/205