
【python-docx】PythonでWordを操作してハイパーリンクを追加する
PythonでWordを操作する機会があったので備忘録。
python-docxのインストール
PythonでWordを操作するためには、「python-docx」というライブラリが必要です。
記事投稿時点の最新バージョンは0.8.11 (2021-05-15)です。
pip install python-docx
実装方法
記事投稿時点でライブラリにはハイパーリンクを追加する処理は実装されていないようなので、ドキュメントを構成するOffice Open XML (OOXML)(※)ファイルを編集する処理を書く必要があります。
※Microsoftが策定した、XMLベースで書かれているファイル形式。Wordファイルの拡張子をzipに変えて展開すると見えるアレ
処理内容をざっくり書きます。
まず、ドキュメント本体以外との関連付けが書かれるファイル「\word\_rels\document.xml.rels」にリレーションシップIDを新規作成し、リンクを紐付けます。
次に、リンクに表示されるテキストと新規作成したリレーションシップIDを用いて、以下形式の要素を作成した後、ドキュメントの内容が書かれたファイル「\word\document.xml」の指定した段落に追加します。
<w:hyperlink r:id="リレーションシップID">
<w:r>
<w:t>リンクに表示されるテキスト</w:t>
</w:r>
</w:hyperlink>
この時点でハイパーリンクは設定できていますが、文字装飾が何もされていない状態です。
必要があれば文字色と下線を設定します。
コード
以下の関数を使用することで、ドキュメントにハイパーリンクを追加することができます。
import docx
from docx.enum.dml import MSO_THEME_COLOR_INDEX
def add_hyperlink(paragraph, text, link):
# 段落のpart属性取得
part = paragraph.part
# 構成ファイル(\word\_rels\document.xml.rels)にリレーションシップIDを作成してリンクを紐付け
r_id = part.relate_to(link, docx.opc.constants.RELATIONSHIP_TYPE.HYPERLINK, is_external=True)
# ハイパーリンク作成
# w:hyperlink要素を作成
hyperlink = docx.oxml.shared.OxmlElement("w:hyperlink")
# w:hyperlink要素にリレーションシップIDを設定
hyperlink.set(docx.oxml.shared.qn("r:id"), r_id)
# w:r要素を作成
new_run = docx.oxml.shared.OxmlElement("w:r")
# w:r要素にテキストを設定
new_run.text = text
# w:hyperlink要素にw:r要素を追加
hyperlink.append(new_run)
# 段落にRunオブジェクト追加
r = paragraph.add_run()
# Runオブジェクトにハイパーリンクを追加
r._r.append(hyperlink)
# ハイパーリンクの文字色を標準色に変更
r.font.color.theme_color = MSO_THEME_COLOR_INDEX.HYPERLINK
# ハイパーリンクに下線追加
r.font.underline = True
return hyperlink
使用例
# 新しいWordドキュメントを作成
doc = Document()
# 段落追加
paragraph = doc.add_paragraph()
# ハイパーリンクを段落に追加
add_hyperlink(paragraph, "Google", "https://www.google.com/")
# 保存
doc.save("google_link.docx")
参考URL
いいなと思ったら応援しよう!
