📃

python-docxでテーブルの罫線を細かく設定する

2023/08/17に公開

イントロダクション

PythonでWordを扱えるpython-docxライブラリですが、テーブル全体のスタイルを変更するのは容易な一方で、テーブルの罫線を柔軟にカスタマイズするのは意外と難しいです。ありがたいことに便利な関数を公開してくださっている方がいらっしゃるのですが、日本語で紹介している記事が見当たらなかったので、簡単な利用例を掲載したいと思います。

動作環境

  • Windows 11
  • Python 3.11.2
  • python-docx 0.8.11

コードと実行結果

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

# テーブルの罫線を設定する関数
# https://programmersought.com/article/74085524416/
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]))

# 4x4のテーブルを作成
document = Document()
table = document.add_table(rows=4, cols=4)

# Table Gridのテンプレートスタイルを使用
table.style = 'Table Grid'

# セルの指定を見やすくするためテキストを追加
for i, row in enumerate(table.rows):
    for j, cell in enumerate(row.cells):
        cell.text = f'{i}, {j}'

# テーブルの罫線を設定
# 中央の2x2のセルの周りの線を太くする
for i in range(1, 3):
    set_cell_border(table.cell(1, i), top={"sz": 18, "val": "thick"})
    set_cell_border(table.cell(2, i), bottom={"sz": 18, "val": "thick"})
    set_cell_border(table.cell(i, 1), start={"sz": 18, "val": "thick"})
    set_cell_border(table.cell(i, 2), end={"sz": 18, "val": "thick"})

# 名前をつけて保存
document.save('sample.docx')

コードの説明

set_cell_border()関数では、任意のcellオブジェクトの上下左右(top, bottom, start, end)の線に対してパラメータを渡すことで、それぞれの線のスタイルを変更できます。線を太くする以外にも、波線や波線にしたり、線の色を変えたりすることもできます。元の記事に詳しい説明があるのでご参照ください。
なお、セルはtable.cell(行, 列)で指定できます。行・列ともに0から始まるので少しややこしいですが、図を見ていただくとイメージしやすいかと思います。

出典

https://programmersought.com/article/74085524416/

Discussion