使用 python-docx 指定表格中的边框外观

Specify border appearance in tables using python-docx

我正在阅读 python-docx 的教程和文档。

但是,我找不到任何关于如何指定和操作在 Microsoft Word 文档中创建的 table 边框外观的参考资料。

当我使用以下代码时:

from docx import Document
from docx.shared import Inches

document = Document()

################################
################################
################################

table = document.add_table(rows=1, cols=3)
hdr_cells = table.rows[0].cells
hdr_cells[0].text = 'Qty'
hdr_cells[1].text = 'Id'
hdr_cells[2].text = 'Desc'

row_cells = table.add_row().cells
row_cells[0].text = 'Str0'
row_cells[1].text = 'Str1'
row_cells[2].text = 'Str2'

row2_cells = table.add_row().cells
row2_cells[0].text = 'Str00'
row2_cells[1].text = 'Str11'
row2_cells[2].text = 'Str22'

################################
################################
################################

document.save('demo.docx')

生成的 docx 文件显示 3x3 table 和 header。当前 table 上没有黑色边框(内部或外部)。

如何指定 header 周围的上下边框、环绕 table 的下边框以及内部垂直边框?

例如:

遗憾的是,无法从 python-docx 内直接操作 table 边界。您基本上需要使用 style 来指定这些。样式必须 已经 存在于 Word 中。

为了生成您喜欢的 table 样式,您需要在 Word 中手动创建一个新的空文档,自定义其中一个现有的 table 样式(例如 Colorful Shading),并使用此修改后的样式添加 table。接下来,删除此 table 并将文件(比如 example.docx)保存到磁盘上。这是将修改后的样式保存在文档中所必需的。

然后您所要做的就是使用 python-docx 加载文件并添加一个新的 table,它将引用(修改的)table 样式:

document = Document('example.docx')
table = document.add_table(rows=1, cols=3)
table.style = 'ColorfulShading'

另请参阅文档中的 Understanding styles,了解有关 Word 样式工作原理的详细信息。

由于python-docx库目前没有直接设置单元格边框的函数方法,我从这个web(强烈推荐的讲座)中找到了这个解决方案:

from docx.table import _Cell
from docx.oxml import OxmlElement
from docx.oxml.ns import qn

def set_cell_border(cell: _Cell, **kwargs):
    """
    Set cell`s border
    Usage:
    set_cell_border(
        cell,
        top={"sz": 12, "val": "single", "color": "#FF0000", "space": "0"},
        bottom={"sz": 12, "color": "#00FF00", "val": "single"},
        start={"sz": 24, "val": "dashed", "shadow": "true"},
        end={"sz": 12, "val": "dashed"},
    )
    """
    tc = cell._tc
    tcPr = tc.get_or_add_tcPr()

    # check for tag existnace, if none found, then create one
    tcBorders = tcPr.first_child_found_in("w:tcBorders")
    if tcBorders is None:
        tcBorders = OxmlElement('w:tcBorders')
        tcPr.append(tcBorders)
 
    # list over all available tags
    for edge in ('start', 'top', 'end', 'bottom', 'insideH', 'insideV'):
        edge_data = kwargs.get(edge)
        if edge_data:
            tag = 'w:{}'.format(edge)
 
            # check for tag existnace, if none found, then create one
            element = tcBorders.find(qn(tag))
            if element is None:
                element = OxmlElement(tag)
                tcBorders.append(element)
 
            # looks like order of attributes is important
            for key in ["sz", "val", "color", "space", "shadow"]:
                if key in edge_data:
                    element.set(qn('w:{}'.format(key)), str(edge_data[key]))

列出了用于编辑单元格边框的可选关键字参数列表 here