はじめに
弊社で使用している業務アプリにて、機器の計測値や分析結果をダッシュボード形式で表示する機能があるのですが、ある測定範囲での結果をまとめてほしいとの要望が来ました。
しかし貼り付ける画像の量が膨大で(数百枚ある)、手作業でひとつひとつ位置やサイズを揃えようにもめっちゃ大変だったので自動化することにしました。
完成予想図
こんな感じ。
python-pptxライブラリ
pythonでPowerPointファイルを操作できるライブラリでpptx
というものがあるらしく、さっそくインストール
pip install python-pptx
pip install pptx
ではありませんのでご注意を。
基本的な使い方
公式リファレンスの"Getting Started"のページを見ながら、サンプルコードを改造する形でコーディングしていきます。
記載のあるサンプルは以下の通り。
-
Hello World! example
- 最もシンプルで基本的なpptxの使い方
-
Bullet slide example
- 箇条書きの入れ子になっているサンプル。テキストのみ
-
add_textbox() example
- テキストボックスを追加したい時のサンプル
-
add_picture() example
- 画像を追加したい時のサンプル
- 今回は主にこのサンプルを参考にしました
-
add_shape() example
- 基本図形を追加したい時のサンプル
-
add_table() example
- 表を追加したい時のサンプル
-
Extract all text from slides in presentation
- スライド内のテキストを全て抽出する
使ってみる
公式のサンプルコードを参考に、以下のようなコードを記述
makeSlide.py
from pptx import Presentation
from pptx.util import Inches
prs = Presentation()
# スライドサイズをA4に指定
prs.slide_height = Inches(11.69)
prs.slide_width = Inches(8.27)
# 白紙スライドを追加
blank_slide_layout = prs.slide_layouts[6]
slide = prs.slides.add_slide(blank_slide_layout)
# 見出し
text_width = Inches(4)
text_height = Inches(0.5)
txBox = slide.shapes.add_textbox(
left=Inches(0.5),
top=Inches(0.3),
width=text_width, height=text_height
)
txFrame = txBox.text_frame
txFrame.text = "見出し"
# ヘッダ画像
header_path = "./images/header.png"
slide.shapes.add_picture(
header_path,
left=Inches(3.5), top=Inches(1),
width=Inches(3.5), height=Inches(2.5)
)
# 画像1-6
image_width = Inches(3.3)
image_height = Inches(2.3)
images_top = Inches(4) # 画像群,上部の座標
for index in range(6):
image_path = f"images/image_{str(index+1).zfill(2)}.png"
# 中央寄せで描画
slide.shapes.add_picture(
image_path,
left=(prs.slide_width/2)-image_width+(index%2)*image_width,
top=images_top+int(index/2)*image_height,
width=image_width, height=image_height
)
prs.save('output.pptx')
ディレクトリ構成はこんな感じ
│ makeSlide.py
└─images
header.png
image_01.png
image_02.png
image_03.png
image_04.png
image_05.png
image_06.png
実行結果
ちゃんとPowerPointスライドが生成されました。
1枚できれば、残りの作業はほぼ同じなので簡単に実装できそうです。
また、このPowerPointファイルを開いた状態で書き込み(プログラム実行)しようとすると、Permission Error
となるのでご注意ください。