You signed in with another tab or window.
Reload
to refresh your session.
You signed out in another tab or window.
Reload
to refresh your session.
You switched accounts on another tab or window.
Reload
to refresh your session.
By clicking “Sign up for GitHub”, you agree to our
terms of service
and
privacy statement
. We’ll occasionally send you account related emails.
Already on GitHub?
Sign in
to your account
How do you add a row to an existing table that you've opened via Document('filename.docx'), for example, and match the table formatting?
I've tried things like:
last_row = table.rows[-1]
for item in data:
try:
row_cells = table.add_row()
row_cells.cells[0].text = item['label']
row_cells.cells[1].text = item['description']
row_cells.cells[0].paragraphs[0].style = 'MediumGrid1-Accent21'
# and
row_cells.cells[0].paragraphs[0].style = last_row.cells[0].paragraphs[0].style
I can add the row without problems, but I can't match the formatting of the row above.
Ideally, would love something like:
last_row = table.rows[-1]
for item in data:
try:
table.rows.push(last_row)
row_cells = table.rows[-1]
row_cells.cells[0].text = item['label']
row_cells.cells[1].text = item['description']
So, have the ability to append the prior row to the end, then change the internal text. Is that feasible?
doc= Document('......path of your document................')
--------->
loads the document
table=doc.tables[0]
--------->
gets you the first table in the document
row=table.add_row().cells
--------------->
adds row at the end of the table with same format
row[0].text = item['label']
--------->
adds data to the last added row and the 0th column, the first column
Unfortunately for me it's also not using the same format, font size and shading are different. I tried using the above method as well as adding a run to the cell's first paragraph.
According to
https://python-docx.readthedocs.io/en/latest/dev/analysis/features/table/table-cell.html
there are some hidden properties like shading and text fitting, maybe it's because of these?
There seem to be a few properties that python-docx doesn't expose or handle. This is what one of the already existing table rows looks like:
<w:tr w:rsidR="007B0145" w:rsidRPr="007611D4" w14:paraId="02B34162" w14:textId="77777777" w:rsidTr="00B818C1">
<w:tcPr>
<w:tcW w:w="2727" w:type="dxa"/>
<w:shd w:val="pct5" w:color="000000" w:fill="FFFFFF"/>
</w:tcPr>
<w:p w14:paraId="4F51D0BC" w14:textId="77777777" w:rsidR="007B0145" w:rsidRPr="007611D4" w:rsidRDefault="007B0145" w:rsidP="00B818C1">
<w:pPr>
<w:rPr>
<w:sz w:val="18"/>
<w:szCs w:val="18"/>
<w:lang w:val="en-US"/>
</w:rPr>
</w:pPr>
<w:r w:rsidRPr="007611D4">
<w:rPr>
<w:sz w:val="18"/>
<w:szCs w:val="18"/>
<w:lang w:val="en-US"/>
</w:rPr>
<w:t>Total</w:t>
</w:tc>
</w:tr>
And this is what a newly added table row looks like:
<w:tcPr>
<w:tcW w:type="dxa" w:w="2727"/>
</w:tcPr>
<w:t>Kat1+2+6</w:t>
</w:tc>
</w:tr>
I think many of the attributes are not important, but some like <w:shd>
definitely are. I also have no clue where the font size is coming from - all existing table rows have font size 9, but the style has font size 12 🤨 maybe because of adjusting text to cell sizes?
For reference, here is also the table header:
<w:tbl>
<w:tblPr>
<w:tblW w:w="9531" w:type="dxa"/>
<w:tblInd w:w="108" w:type="dxa"/>
<w:tblBorders>
<w:insideH w:val="single" w:sz="18" w:space="0" w:color="FFFFFF"/>
<w:insideV w:val="single" w:sz="18" w:space="0" w:color="FFFFFF"/>
</w:tblBorders>
<w:tblLayout w:type="fixed"/>
<w:tblLook w:val="01E0" w:firstRow="1" w:lastRow="1" w:firstColumn="1" w:lastColumn="1" w:noHBand="0" w:noVBand="0"/>
</w:tblPr>
<w:tblGrid>
<w:gridCol w:w="2727"/>
<w:gridCol w:w="1134"/>
<w:gridCol w:w="1276"/>
<w:gridCol w:w="992"/>
<w:gridCol w:w="1276"/>
<w:gridCol w:w="992"/>
<w:gridCol w:w="1134"/>
</w:tblGrid>
I've written the following function to copy formatting from a source cell to a destination cell. It can easily be applied to add rows with formatting from the old row by looping through the old and new cells. Here is the function:
import copy
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)
Hope that helps!
@Gabriel-Kissin Thanks for that function! Works like a charm! Just had to import copy for other people reading
My pleasure :-) glad to hear it helped! Thanks for the shout about importing copy, have edited above.
I've written the following function to copy formatting from a source cell to a destination cell. It can easily be applied to add rows with formatting from the old row by looping through the old and new cells. Here is the function:
import copy
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)
Hope that helps!
Thank you very much for the code, because only the cell format cannot meet my requirements, so I added the format copy of paragraphs and runs.
# 定义一个函数 copy_cell_properties,用于复制一个单元格的属性到另一个单元格
def copy_cell_properties(source_cell:_Cell, dest_cell:_Cell):
从源单元格复制属性到目标单元格。
这个函数在 python-docx 文档中复制单元格的背景着色、边框等属性。
source_cell (docx.table._Cell): 具有所需格式的源单元格
dest_cell (docx.table._Cell): 应用格式的目标单元格
# 从源单元格获取属性
# (tcPr = 表格单元格属性)
# 使用 get_or_add_tcPr() 方法确保源单元格有一个 tcPr 元素,如果没有则添加一个
cell_properties = source_cell._tc.get_or_add_tcPr()
# 从目标单元格中移除任何表格单元格属性
# (否则,我们最终会得到两个 <w:tcPr> ... </w:tcPr> 块)
# 使用 remove() 方法移除目标单元格的 tcPr 元素,确保不会重复添加
dest_cell._tc.remove(dest_cell._tc.get_or_add_tcPr())
# 对源单元格属性进行浅拷贝
# (否则,属性会从源单元格“移动”到目标单元格,而不是复制)
# 使用 copy.copy() 进行浅拷贝,确保源单元格的属性不会被意外修改
cell_properties = copy.copy(cell_properties)
# 将源单元格属性的副本追加到目标单元格
# 使用 append() 方法将复制的属性添加到目标单元格的 XML 元素中
dest_cell._tc.append(cell_properties)
# 复制段落格式
source_paragraph = source_cell.paragraphs[0]
for dest_paragraph in dest_cell.paragraphs:
copy_paragraph_properties(source_paragraph, dest_paragraph)
def copy_paragraph_properties(source_paragraph:Paragraph, dest_paragraph:Paragraph):
复制一个段落的属性到另一个段落
source_paragraph (docx.text.paragraph.Paragraph): 具有所需格式的源段落
dest_paragraph (docx.text.paragraph.Paragraph): 应用格式的目标段落
# 复制段落的 pPr 属性(段落属性)
pPr = source_paragraph._element.get_or_add_pPr()
new_pPr = copy.copy(pPr)
dest_paragraph._element.remove(dest_paragraph._element.get_or_add_pPr())
dest_paragraph._element.append(new_pPr)
# 复制段落中的所有run
source_run = source_paragraph.runs[0]
for dest_run in dest_paragraph.runs:
copy_run_properties(source_run, dest_run)
def copy_run_properties(source_run:Run, dest_run:Run):
复制一个run的属性到另一个run
source_run (docx.text.run.Run): 具有所需格式的源run
dest_run (docx.text.run.Run): 应用格式的目标run
# 复制 run 的 rPr 属性(run 属性)
rPr = source_run._element.get_or_add_rPr()
new_rPr = copy.copy(rPr)
dest_run._element.remove(dest_run._element.get_or_add_rPr())
dest_run._element.append(new_rPr)