Python外部ライブラリ(python-docx)で『Word』ドキュメントに画像・表・セクションを設定する

スポンサーリンク
Python外部ライブラリ(python-docx)画像・表・ページ設定の基本 Python

前回に続きMS-Office WordをPythonで操作するライブラリとして「python-docx」の解説をしていきます。

前回の記事では、ライブラリの紹介とWordを操作するための「基本操作」と「文章を作成する」の部分を取り上げました。

前回の記事はこちらになります。

「python-docx」の基本を押さえてから以降の内容に進まれた方が理解しやすいと思われますし重複する解説は割愛しておりますのでまずはこちらを一読されることをお勧めします。

さて、後半の今回では、「画像や表をWordドキュメントに挿入する方法」とセクションの活用事例として「ヘッダーとフッターを設定する」といった内容を解説します。

文章が主体となるWordドキュメントですが、画像や表などを効果的に使うことで、視覚的が訴求力や信ぴょう性が増します。とくに論文などしっかりとした文章の場合は必須となることでしょう。

本記事の所掌範囲_part2
図1 本記事の解説範囲

それでは、次節からは具体的な各種オブジェクトの扱い方について詳しく解説していきます。

この記事を読むことでWordドキュメントの操作に関する次のようなことが「できる・わかる」ようになりますので最後までお付き合いください

➀ 画像ファイル(InlineShapeオブジェクト)を挿入することができる。

➁ 表(Tableオブジェクト)を挿入することができる。

➂ フッターやヘッダーなどページ設定(Sectionオブジェクト)に関わる各種プロパティ

本サイトでの紹介例は一例です。また、関数などの省略可能なオプション引数などについては割愛していますので、詳細や不明点などは必要に応じて公式サイトなどを参照してください。

<公式サイト>https://python-docx.readthedocs.io/en/latest/

スポンサーリンク

1. 画像(InlineShapeオブジェクト)を挿入する

画像は段落 Paragraphオブジェクト 内に配置することができます。さらに段落の中身である文章

Runオブジェクト 中にも埋め込むこともできます。

python-docxではWordドキュメント内の画像やSmatArt・グラフは Inline picture/Inline shape(Text Layer) であれば扱うことができますが、次の公式ドキュメントの記載にもあるとおりFloatingShape(Drawing Layer) はサポートされていません

Understanding pictures and other shapes

At the time of writing, python-docx only supports inline pictures. Floating pictures can be added.  If you have an active use case, submit a feature request on the issue tracker.

https://python-docx.readthedocs.io/en/latest/user/shapes.html

また、Inline shapeであっても図形(Wordメニュー->挿入タブ->図)に関してはpython-docでは扱うことはできないようです。図2にまとめましたので参考にして下さい。

InlineShapeとFloatingShapeの対応状況
図2 python-docxで対応可能な図

補足として、図形[Floating Shapes]を挿入・取得する場合は次の2つの方法があります。

それぞれ得意・不得意がありますのでpython-docxと使い分けると良いでしょう。

➀「pywin32ライブラリ」のShapeオブジェクトを使う。

➁ WordドキュメントをXMLファイルに変換して構造解析をして目的のオブジェクトを取得する。

1.1 段落(Paragraphオブジェクト)に画像を挿入する

段落に画像を挿入するにはDocumentオブジェクトの add_picture()メソッド を次の書式のように使います。

Paragraphオブジェクト

Documentオブジェクト.add_picture(image_path, width, height)


引数1:image_path:挿入する画像ファイルを指定

引数2:width:画像の横幅を指定する(オブション)

引数3:width:画像の横幅を指定する(オブション)

戻り値:InlineShapeオブジェクト

画像ファイルはjpg/pngどちらの画像形式にも対応しております、オプショナル引数として挿入画像の大きさを設定する width/height があります。mm(ミリ)やInche(インチ) などで指定します。

また、add_picture()メソッド を実行するとParagraphオブジェクトが新たに追加され、その中に戻り値であるInlineShapeオブジェクトが挿入されます。

それでは、実際のコードによる使用例を紹介します。

from docx import Document
from docx.enum.text import WD_ALIGN_PARAGRAPH # 段落位置の定義クラスをインポート
from docx.shared import Mm                    # 単位系や色が定義されているSharedクラス

doc1=Document()

# 段落"1"
p1 = doc1.add_paragraph('画像1(.png)を挿入します。')
# 段落"2" add_pictureメソッドpng画像(幅50mm)を挿入
doc1.add_picture('./picture/picture1.png', width=Mm(50))

# 段落"3" 
p3 = doc1.add_paragraph('画像2(.jpeg)を挿入します。')
# 段落"4" add_pictureメソッドjpec画像(幅50mm)を挿入
doc1.add_picture('./picture/picture2.jpg', width=Mm(50))

# 段落"5"
p5 = doc1.add_paragraph('画像3(.png)を挿入します。')
# 段落"6" add_pictureメソッドpng画像(高さ50mm)を挿入
doc1.add_picture('./picture/picture3.png', height=Mm(50))

print(len(doc1.paragraphs)) # >>6 段落の個数を調べる

for p_index in [0, 1, 4, 5]:
    
    # 画像はInlineShapeオブジェクトとして段落として認識され、alignmentプロパティ
    # で段落の開始位置を指定することで画像挿入位置を大まかに設定することができる
    doc1.paragraphs[p_index].paragraph_format.alignment = WD_ALIGN_PARAGRAPH.CENTER

doc1.save('段落に画像を挿入する.docx')

実行結果は以下のようになりました。3つの画像が挿入され、段落の数はadd_picture()メソッドによって追加されたものも含めて6つとなっています。

また段落の alignmentプロパティ で挿入位置が「左寄・中央」となっています。

add_pictureのコード例の実行結果➀
図3 List1の実行結果

1.2 文章の途中(最初・最後を含む)に画像を挿入する

文章の途中に画像を挿入する場合は、Runオブジェクトの add_picture()メソッド を次の書式のようにして使います。

Runオブジェクト

Runオブジェクト.add_picture(image_path, width, height)


引数1:image_path:挿入する画像ファイルを指定

引数2:width:画像の横幅を指定する(オブション)

引数3:height:画像の横幅を指定する(オブション)

戻り値:InlineShapeオブジェクト

使い方は段落(Paragraph)直下に挿入する場合と同じです。新たな段落は追加されませんが、InlineShapeオブジェクトは都度追加されます。

それでは、実際のコードによる使用例を紹介します。

from docx import Document
from docx.shared import Mm

doc1=Document()

# 段落 "1"
p1 = doc1.add_paragraph(style='Title')

# 段落のRunオブジェクトのadd_pictureメソッドで文章の途中に画像を挿入する
p1.add_run().add_picture('./picture/picture1.png', width=Mm(15))
p1.add_run(' Runオブジェクトの ')

p1.add_run().add_picture('./picture/picture2.jpg', width=Mm(15))
p1.add_run(' add_pictureメソッドで画像挿入 ')

p1.add_run().add_picture('./picture/picture3.png', height=Mm(15))


doc1.save('文章中に画像を挿入する.docx')

実行結果は以下のようになりました。add_run()メソッド でRunオブジェクトを追加しながら配下のadd_picture()メソッド で文章中(最初・途中・最後)に画像を挿入しています。

add_pictureのコード例の実行結果②
図4 List2の実行結果

2. 表・テーブル(Tableオブジェクト)を挿入する

Python_基本文法_内包表記

python-docxではWordドキュメントに表(テーブル)を挿入することができます。

表(テーブル)はpython-docxでは Tableオブジェクト として管理されています。TableオブジェクトはDocumentオブジェクト配下の add_table()メソッド を次の書式で取得・設定することが可能です。

Tableオブジェクト

Documentオブジェクト.add_table(rows, cols, style)


引数1:rows:rows:表の行数を指定する

引数2:cols:表の列数を指定する

引数3:style:表に設定するスタイルを指定する(オプショナル引数)

戻り値:Tableオブジェクト

引数styleに指定できるテンプレートには以下のように様々なものが用意されています。

Table styles_template
図5 Tableオブジェクトに設定できるテンプレート(抜粋)

Tableオブジェクトはさらに列( Column(s)オブジェクト )、行( Row(s)オブジェクト )で構成され、イテラブルに最小構成要素のセル( Cellオブジェクト )を取り出し・設定することができます。 (図6)

Tableオブジェクトの構成_階層構造
図6 Tableオブジェクトの階層構造

Tableオブジェクトには多くの関連したメソッド・プロパティがあります。主なものをまとめると次のようになります。

メソッド・プロパティ機能その他詳細
Tableオブジェクト.add_column(width)Comumnオブジェクトを右端に追加する引数:width:列幅を指定
Tableオブジェクト.add_row()Rowオブジェクトを下端に追加する
Tableオブジェクト.cell(row_idx, col_idx)Cellオブジェクトを取得する引数:row_idx:行のインデックス ,引数:col_idx:列の
インデックス(0,0)が表の左上を指す
・[num]を付加すると、Tableオブジェクトnum番目の

cellオブジェクトを取得する
Tableオブジェクト.columnsテーブル全体を構成するColumnオブジェクト
のコレクションを取得する
[num]を付加すると、Tableオブジェクトのnum番目の
Columnオブジェクトを取得する。
Tableオブジェクト.rowsテーブル全体を構成するRowオブジェクト
のコレクションを取得する
・[num]を付加すると、Tableオブジェクトのnum番目の
Rowオブジェクトを取得する。
Columnオブジェクト.widthプロパティ列の幅を設定する
Rowオブジェクト.heightプロパティ行の高さを設定する
Cellオブジェクト.textプロパティCellオブジェクトに値/テキスト
を設定・取得する

Tableオブジェクトを使ったテーブル作成のコード例を紹介します。

from docx import Document
from docx.enum.table import WD_ALIGN_VERTICAL # セル内のは配置位置の定義
from docx.shared import Mm  # 単位系や色が定義されているSharedクラス

# 列のラベルの定義
col_names = ['氏名', '所属', '給与']

# データ内容の定義
data = [['芥川 龍之介', '総務部', '245000'],
       ['夏目 漱石', '経理部', '350000'],
       ['石川 啄木', '営業部', '298000']]

doc1 = Document()

#(A)---------------------------------------------------------------------------------------------------------------
# add_table()メソッドにより1行,3列のTableオブジェクトオブジェクトを取得する
tb1 = doc1.add_table(rows=1, cols=len(col_names), style='Colorful Shading Accent 1')

#(B)---------------------------------------------------------------------------------------------------------------
# 列名を1行目のセルに設定
for i, cell in enumerate(tb1.rows[0].cells): # CellsプロパティでCellオブジェクトのコレクションを取得
    cell.text = col_names[i]                  # Cellオブジェクトのtextプロパティで値を設定

#(C)---------------------------------------------------------------------------------------------------------------
# 行(Rowオブジェクト)を追加しなあら、セルに値を設定
for d in data:
    row = tb1.add_row()   # Rowオブジェクトの追加
    row.height = Mm(8.0)  # heightプロパティで行の高さを8mmに指定
    
    for i, cell in enumerate(row.cells): # Cellオブジェクトの取得
        cell.text = d[i]                  # Cellオブジェクトのtextプロパティで値を設定
        cell.vertical_alignment = WD_ALIGN_VERTICAL.BOTTOM  # vertical_alignmentプロパティにてセル内の配置位置を設定

#(C)---------------------------------------------------------------------------------------------------------------
# 列(Columnオブジェクト)の追加 
tb1.add_column(Mm(15.0))       # 幅15㎜の列を追加
print(tb1.columns[3].width.mm) # >>14.993

tb1.cell(0, 3).text = '備考'   # 追加列のタイトルを設定


doc1.save('テーブルを挿入する.docx')

ポイントを解説します。

・19行目の add_table()メソッド でTableオブジェクトを取得し、23行目のfor文句で列の見出しをtextプロパティで設定しています。

・28行目からのfor文句で add_row()メソッド で行(Rowオブジェクト)を追加heightプロパティで行の高さを設定します。さらにCellオブジェクトを取得しtexプロパティ、vertical_alignmentプロパティ で各セルの値と配置位置を設定します。

・38行目で、add_colum()メソッド で列(Columnオブジェクト)を幅15mmで追加しています。

実行結果は以下のようになりました。

スタイルやサイズや幅・高さなどのディメンジョンが指定したものとなり綺麗なテーブルを挿入することができました。

Tableオブジェクトのサンプルコード実行結果
図7 List3の実行結果

3. セクション(区切り)を導入する

本節ではpython-docによるセクションの設定方法について解説していきます。

3.1 セクションとは

Wordにおける「セクション」とはページサイズや余白の設定、方向、ヘッター/フッターなどをページ毎または、ページ範囲毎に設定しまとめて管理する単位のことです。

例えば、図8ではWordファイル全7ページに3つのセクションに分類してページ設定を管理している例です。

セクションの概要
図8 Wordにおけるセクション

python-docxではセクションをSectionオブジェクトとして管理しています。

3.2 セクション(Sectionオブジェクト)を取得・設定する

Sectionオブジェクトを新規追加および既存のオブジェクトを取得するにはDocumentオブジェクト配下の add_section()メソッド sectionsプロパティ をそれぞれ使用します。

Sectionオブジェクト

Documentオブジェクト.add_section(start_type)


引数1:start_type:追加するセクションの種類を「WD_SECTION_STARTクラス」から指定する

戻り値:Sectionオブジェクト


Documentオブジェクト.sectionsプロパティ

戻り値:Sectionオブジェクトのコレクション

引数start_typeには以下の WD_SECTION_STARTクラス の定義からいずれかを指定します。

WD_SECTION_STARTの種類
図9 セクション区切り指定の種類

Sectionオブジェクト配下の関連プロパティ各種を用いることで各セクションごとに「ページ設定の詳細」を設定することが可能ができます。Wordの「ページ設定ダイアログ」の各種設定がどのプロパティに対応するかは以下の図を参照してください。

Sectionオブジェクトのプロパティ②
図10 <余白の設定>
Sectionオブジェクトのプロパティ➂
図11 <ページサイズの設定>
Sectionオブジェクトのプロパティ➀
図12 <セクションの設定>

3.3 ヘッダー、フッターを取得・設定する

Sectionオブジェクトの headerプロパティfooterプロパティ を使うことでセクション毎のヘッダー(Headerオブジェクト)とフッター(Footerオブジェクト)を取得することができます。

Sectionオブジェクト

Sectionオブジェクト.headerプロパティ

戻り値:Headerオブジェクト


Sectionオブジェクト.footerプロパティ

戻り値:Footerオブジェクト

Headerオブジェクト/Footerオブジェクトには以下のようなプロパティやメソッドがあります。本文作成の時と同じようにParagraphオブジェクトやTableオブジェクトを追加することでコンテンツを作ります。(Paragraphオブジェクトはこちらを参照してください)

メソッド・プロパティ機能
Headerオブジェクト.add_paragraph(text, style)段落(Paragraphオブジェクト)を追加する
Headerオブジェクト.add_table(rows, cols, width)テーブル(Tableオブジェクト)を追加する
Headerオブジェクト.is_linked_to_previousプロパティ直前のセクションのヘッターの内容を引用の可否を設定
True(規定値):引用する / False:引用しない

Sectionオブジェクトを使ったコード例を紹介します。

ページの書式設定(用紙サイズ・余白・印刷の向き)とヘッター、フッターをセクション毎に確認・設定しています。

from docx import Document
from docx.enum.section import WD_SECTION

from docx.shared import Mm  # 単位系や色が定義されているSharedクラス
from docx.enum.section import WD_ORIENT # ページの向きが定義されているenumrationsクラス

from docx.enum.text import WD_ALIGN_PARAGRAPH


# ドキュメントを新規作成する
doc1 = Document()

# 現在のセクションを取得するにはsectionsプロパティに[-1]を付加する
sec1 = doc1.sections[-1]

# start_typeプロパティで現在のセクションタイプを調べる
# 新規作成されたドキュメントにはデフォルトで1つセクション(NEW_PAGE)を持っている
print(sec1.start_type) # >>NEW_PAGE (2)

#-------------------------------------------------------------------------------------
# セクション1のページの書式を調べる

# セクション1のページ設定(ページの向き、ページの幅、ページの高さ)を取得する
print(sec1.orientation, sec1.page_width.mm, sec1.page_height.mm) # >>PORTRAIT (0) 215.9 279.4

# セクション1のページ設定(ページの余白(左),ページの余白(右))
print(sec1.left_margin.mm, sec1.left_margin.mm) # >> 31.75 31.75

# セクション1のページ設定(ページの余白(上),ページの余白(下))
print(sec1.top_margin.mm, sec1.bottom_margin.mm) # >> 25.4 25.4

#-------------------------------------------------------------------------------------
# セクション1のヘッター・フッターを設定する

# headerプロパティでHeaderオブジェクトを取得する
hd1 = sec1.header

# Headerオブジェクトのadd_paragraph()メソッドで段落を追加する
hd1_pg = hd1.add_paragraph('CONFIDENTIAL_マル秘')

# footerプロパティでFooterオブジェクトを取得する
ft1 = sec1.footer

# Headerオブジェクトのadd_paragraph()メソッドで段落を追加する
ft1_pg = ft1.add_paragraph('株式会社 Pythonでもっと自由を')

# 段落の位置を右端に設定する
ft1_pg.paragraph_format.alignment = WD_ALIGN_PARAGRAPH.RIGHT


#-------------------------------------------------------------------------------------
# セクション2を追加してページの書式を設定する

# add_section()メソッドで新規セクション(NEW_PAGE)を追加する
sec2= doc1.add_section(WD_SECTION.NEW_PAGE)

print(sec2.start_type) # >>NEW_PAGE (2)

# orientationプロパティで印刷の向きを横向きに変更する
sec2.orientation = WD_ORIENT.LANDSCAPE

# セクション2の横幅を設定する
sec2.page_width = Mm(279.4)

#  セクション2の縦幅を設定する
sec2.page_height = Mm(215.9)


#-------------------------------------------------------------------------------------
# セクション2のヘッター・フッターを設定する

hd2 = section_new.header
ft2 = section_new.footer

# is_linked_to_previousプロパティで前のセクションのヘッター・フッター
# を引用するかを選択することができる

hd2.is_linked_to_previous = False # セクション1のヘッターを引用しない

ft2.is_linked_to_previous = True # セクション1のフッターを引用する

doc1.save('ヘッター・フッター.docx')

ポイントを解説します。

・14行目の sectionsプロパティ でドキュメント内にある全ての Sectionオブジェクト を取得しています。インデックス指定が可能で[-1]とすることで現在のページのSectionオブジェクトを個別に取得できます。(新規作成の場合は、予め1つセクション(NEW_PAGE)が用意されています。)

・23~30行目で、セクションのページ書式設定の各種(印刷向き、ページサイズ、余白サイズ)を確認・取得しています。

・35~48行目で、セクションのヘッターとフッターの取得・設定をしています。

オブジェクトの取得にはそれぞれ headerプロパティfooterプロパティ を使います。各オブジェクトは、本文と同様に段落(Paragraphオブジェクト)で管理されており、使い方も同じです。

・55~66行目でセクションをもう一つ追加しています。印刷の向きを orientationプロパティ で設定し、ページの幅と高さを任意のサイズ(単位はmm)に変更しています。

・72~80行目で追加したセクションのヘッター・フッターの設定をしています。

is_linked_to_previousプロパティ で、一つ前のセクションのヘッター・フッターを引用するかを選択することができます。ヘッターはFalseとし引用させない、フッターはTrueとし引用するように設定しました。

実行結果は以下のようになりました。

ページの書式設定(用紙サイズ・余白・印刷の向き)とヘッター、フッターがセクション毎に設定できています。

セッションの使い方コードの実行結果
図13 List4の実行結果

4. まとめ

いかがでしたでしょうか?

今回はMS-OfficeのWordを操作するライブラリとして「python-docx」による画像・表の挿入、それからページ設定をする方法について解説してきました。

Wordを使った文章作成をしたことがある方でしたら、オブジェクト名やメソッド・プロパティ名から直感的にコーディングすることができることを実感して頂けたのではないでしょうか。

新規コンテンツのWordドキュメントを作成するといった用途ではわざわざPythonを使う必要はありませんが、「ある程度デフォルトスタイルがある」「一度に大量のドキュメントの編集が必要」といった場合は効果的です。

今回の記事を是非、貴方の作業効率改善にお役立てください。

最後にポイントをまとめておきましょう。

➀. python-docxで画像を挿入することができる。Word自体は画像は2つのレイヤーに挿入可能であるが、このライブラリで挿入できるのは行内(Inline Layer)のみである。Drawing Layerの画像に対応するには別のライブラリや方法を試行する必要がある。

➁. 表(Tableオブジェクト)を作成しドキュメント内に追加することができます。スタイルや各種プロパティが充実しており綺麗な見栄えの良い表を表現することができる。

➂. ページの書式設定やフッター・ヘッターはSectionオブジェクトで取得・設定することができる。


さて次回は、ドキュメントにスタイルを適用する方法について解説します。

Wordで文章を作成する目的は様々です。「公的なフォーマルな文章」であったり「論文口調なかっちちとした文章」または「内々の親しげな口語口調」・・・さまざまです。

このように目的に応じた文章を書く場合、ある程度文章のスタイル(フォント、見出し、ヘッター)が決まっているのが普通です。

このように「文章の型」をスタイルとしてWordに登録して、繰り返し使ったりすることができます。

次回は、このスタイル機能をライブラリを使って活用してみます。お楽しみに!

リンク先はこちらになります。↓

最後までお読みいただきありがとうございました。

タイトルとURLをコピーしました