この記事は何
python経由でpptx(パワーポイント)ファイルを操作するライブラリであるpython-pptxについて、普段パワポ触ることがほとんどないのでパワーポイントの基本的な使い方も調べつつメモした記事。
pptx
Microsoft PowerPoint - Wikipedia
テンプレート・デザイン
www.slideshare.net
互換性
keynote・google drive・libreofficeなどを利用している人もいるが、python-pptxで操作できる基本的な図形はどのソフトでも対応していると思われます(詳細は未確認)。
- Keynote - Macでの互換性 - Apple(日本)
- Microsoft PowerPoint から Google スライドへの移行 - ドキュメント エディタ ヘルプ
- 『LibreOffice』と『Microsoft Office』の互換性を評価してみた|厳選6ファイルを比較 | IT trip
phton-pptx
まず初めにpython-pptxのドキュメントのGetting Startedにていくつか事例が紹介されているのでこちらを参照しつつスライドをいくつか生成して見る。
プレゼンテーションにスライドを追加する
ドキュメント参照ページ:Slides — python-pptx 0.6.18 documentation
prs = Presentation()
としてパワーポイントを作成後、slides.add_slide
でパワポのレイアウトを指定してスライドを追加する。
from pptx import Presentation def set_title_text(slide, text): shapes = slide.shapes shapes.title.text = text def get_title_text(slide): return slide.shapes.title.text prs = Presentation() slide1 = prs.slides.add_slide(prs.slide_layouts[0]) set_title_text(slide1, "test") slide2 = prs.slides.add_slide(prs.slide_layouts[1]) set_title_text(slide2, "test2") prs.save("temp.pptx")
の出力結果は下のようになる。
テキストの箇条書きのスライドを作る
ドキュメント参照ページ: Getting Started — python-pptx 0.6.18 documentation
from pptx import Presentation def set_title_text(slide, text): shapes = slide.shapes shapes.title.text = text def get_title_text(slide): return slide.shapes.title.text def set_paragraphs(slide, paragraphs): shapes = slide.shapes body_shape = shapes.placeholders[1] text_frame = body_shape.text_frame for level, text in paragraphs: p = text_frame.add_paragraph() p.level = level p.text = text return slide prs = Presentation() slide = prs.slides.add_slide(prs.slide_layouts[1]) # タイトル追加 set_title_text(slide, 'スライドのタイトル') # テキスト追加 paragraphs = [ (0, "テキストフレームのトップ"), (1, "テキストフレームの1段落目"), (2, "テキストフレームの2段落目"), (0, "テキストフレームの0段落目-2"), (2, "テキストフレームの2段落目-2"), ] set_paragraphs(slide, paragraphs) prs.save("temp.pptx")
テキストと画像が並んだスライドを作る
参照元ドキュメント:Source code for pptx.shapes.shapetree
add_picture
関数が存在し、
def add_picture(self, image_file, left, top, width=None, height=None): """Add picture shape displaying image in *image_file*. *image_file* can be either a path to a file (a string) or a file-like object. The picture is positioned with its top-left corner at (*top*, *left*). If *width* and *height* are both |None|, the native size of the image is used. If only one of *width* or *height* is used, the unspecified dimension is calculated to preserve the aspect ratio of the image. If both are specified, the picture is stretched to fit, without regard to its native aspect ratio. """
- 画像ファイルパス、左からの位置、上からの位置を指定して画像を出力
- height/widthで画像のサイズを指定
- height/widthが指定なしの場合は画像の元サイズを使用
すれば良いとあるので試して見る。位置を指定するために新たに Inches
をインポートする。
from pptx import Presentation from pptx.util import Inches import numpy as np import matplotlib.pyplot as plt def creage_sample_fig(filepath): xs = [np.random.rand()**2 for _ in range(1000)] ys = [np.random.rand()**2 for _ in range(1000)] plt.scatter(xs, ys) plt.savefig(filepath) def set_title_text(slide, text): shapes = slide.shapes shapes.title.text = text def get_title_text(slide): return slide.shapes.title.text def set_paragraphs(slide, paragraphs): shapes = slide.shapes body_shape = shapes.placeholders[1] text_frame = body_shape.text_frame for level, text in paragraphs: p = text_frame.add_paragraph() p.level = level p.text = text return slide def add_picture(slide, img_filepath, position, imgsize): left, top = position width, height = imgsize pic = slide.shapes.add_picture(img_filepath, left, top, height=height, width=width) return slide prs = Presentation() slide = prs.slides.add_slide(prs.slide_layouts[3]) # タイトル追加 set_title_text(slide, 'スライドのタイトル') # テキスト追加 paragraphs = [ (0, "テキストフレームのトップ"), (1, "テキストフレームの1段落目"), (2, "テキストフレームの2段落目"), ] set_paragraphs(slide, paragraphs) # 画像の追加 img_filepath = "sample.png" creage_sample_fig(img_filepath) add_picture(slide, img_filepath, (Inches(5), Inches(2)), (Inches(5), Inches(4))) prs.save("temp.pptx")
テーブルを含んだスライドを作る
ドキュメント参照ページ: Getting Started — python-pptx 0.6.18 documentation
table.cell(i+is_column_exists, j+is_index_exists).text = str(rij)
の箇所でデータを文字列に変換しているのは .text
属性に指定できるデータが文字列であるため。add_table(slide, tabledata, position, tablesize, columns=None, indices=None)
で指定したスライドにテーブルデータをプロットする。カラム・インデックスが渡されているときはそれをテーブルのはじめの行・列に表示するようにする。
from pptx import Presentation from pptx.util import Inches import numpy as np import matplotlib.pyplot as plt def creage_sample_fig(filepath): xs = [np.random.rand()**2 for _ in range(1000)] ys = [np.random.rand()**2 for _ in range(1000)] plt.scatter(xs, ys) plt.savefig(filepath) def set_title_text(slide, text): shapes = slide.shapes shapes.title.text = text def get_title_text(slide): return slide.shapes.title.text def set_paragraphs(slide, paragraphs): shapes = slide.shapes body_shape = shapes.placeholders[1] text_frame = body_shape.text_frame for level, text in paragraphs: p = text_frame.add_paragraph() p.level = level p.text = text return slide def add_picture(slide, img_filepath, position, imgsize): left, top = position width, height = imgsize pic = slide.shapes.add_picture(img_filepath, left, top, height=height, width=width) return slide def add_table(slide, tabledata, position, tablesize, columns=None, indices=None): tabledata = np.array(tabledata) left, top = position width, height = tablesize is_index_exists = 1 if indices is not None else 0 is_column_exists = 1 if columns is not None else 0 shapes = slide.shapes colnum = tabledata.shape[1]+1 if is_index_exists else tabledata.shape[1] rownum = tabledata.shape[0]+1 if is_column_exists else tabledata.shape[0] table = shapes.add_table(rownum, colnum, left, top, width, height).table # 列幅を等間隔にする for i in range(colnum): table.columns[i].width = Inches(width.inches/colnum) # カラム名を指定する if is_column_exists: for i, ci in enumerate(columns): table.cell(0, i+is_index_exists).text = str(ci) # インデックス名を指定する if is_index_exists: for i, ii in enumerate(indices): table.cell(i+is_column_exists, 0).text = str(ii) # インデックスを指定する for i, ri in enumerate(tabledata): for j, rij in enumerate(ri): table.cell(i+is_column_exists, j+is_index_exists).text = str(rij) prs = Presentation() slide = prs.slides.add_slide(prs.slide_layouts[3]) # タイトル追加 set_title_text(slide, 'スライドのタイトル') # テキスト追加 paragraphs = [ (0, "テキストフレームのトップ"), (1, "テキストフレームの1段落目"), (2, "テキストフレームの2段落目"), ] set_paragraphs(slide, paragraphs) # 画像の追加 img_filepath = "sample.png" creage_sample_fig(img_filepath) add_picture(slide, img_filepath, (Inches(5), Inches(2)), (Inches(5), Inches(4))) # テーブルの追加 columns = ["カラム1", "カラム2", "カラム3"] indices = ["1行目", "2行目", "3行目"] tab_position = (Inches(1), Inches(5)) tab_size = (Inches(8), Inches(1)) table = [ [1, 2, 3], [4, 5, 6], [7, 8, 9], ] add_table(slide, table, tab_position, tab_size, columns=columns, indices=indices) prs.save("temp.pptx")
グラフを含んだスライドを作る
ドキュメント参照ページ: - Working with charts — python-pptx 0.6.18 documentation - Charts — python-pptx 0.6.18 documentation
上記ページにて棒グラフ・円グラフなどの例がある。 ただ詳細なグラフを作るたびに上記APIを見るのが大変そうだったので、 複雑なグラフは画像で出力+生データをcsvなどで出力する方針にしたので割愛。
他の方の使用例
python-pptxで検索していた際に見たサイト一覧です。