添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接

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)