【Pythonで自動化&作業効率UP】覚えておきたい!PowerPointのスライドを分割して保存する方法


はじめに

PowerPoint(以下、PPT)には、各スライドを分割して画像ファイルとして保存する機能がついています。
参考サイト【パワーポイントのスライドを画像で保存する方法】
しかし画像ファイルのままだと、後から編集する事ができないですよね。
そこでPPTファイルのまま自動で分割できないか、Pythonを使ってやってみようと考えました!
(もしPPTファイルが100ページあった時に、1枚ずつ切り取って新規保存する事を考えると、多くの時間がかかりそうです。)

やりたいこと

やりたいことを。以下の図に示しています。
1つのPPTファイルから各スライドごとに分割を行い、1つのPPTファイルで保存をします。
保存する際は、スライドのタイトルに記載されている名前で保存します。

実現に必要な事と工夫点

①スライドの分割

各スライドごとに分割する良い方法は無いかと考え、「指定したスライド以外のスライドを削除」する事ができれば、その処理を各スライドごとに実行すれば良いのではと考えました。

例えば2ページ目のスライドが欲しい場合は、1ページ目と3ページ目以降を削除する事で2ページ目のみ残ります。

PPTファイルのスライドを削除する方法が分かれば実現できそうです。PythonでPPTの指定した〇ページ目を削除する関数を公開しているサイトがありました。
python,The Python PPTX module can remove slides that specify the page number

このサイトで紹介している関数は、PPTファイルの(index)ページ目を削除するものです。

※ここで覚えておきたい注意点があります。
例えば、PPTファイルの3ページ目と4ページ目を削除したいと考えます。
その際、初めに3ページ目を指定して削除します。次に4ページ目を削除しようと考え、4ページ目を指定し削除すると、元のPPTファイルの5ページ目を削除する事になります。
以下の図に4ページ目だったものが3ページ目になる理由を示しています。

②PPTファイルからタイトルを取得する方法

PPTスライドからタイトルを抜き出す方法は、python-pptxの機能を利用します。
PythonでPPTファイルを操作するPython-pptxに興味がある方は、以下のサイト等を参考にしていただければと思います。
python-pptxまとめ

全てのPPTスライドにタイトルが設定されている場合は以下の処理は必要ありませんが、
①PPTスライド内のタイトルを入力する項目が削除されている場合
②タイトルが空白になっている場合
③タイトルに重複があった場合
に対応する為に、以下の図のようにスライドのページ番号でファイル保存する事にしました。


3ページ目は2ページ目とタイトルが重複している為、別名で保存。
5ページ目はタイトルを入力する項目を消している為、タイトル名を付与して保存しています。

コーディング内容

では、順を追ってプログラムの内容を解説したいと思います。

はじめにモジュールを読み込みます。
pythonでPPTファイルを操作する為、python-pptxを使用します。

split_ppt_slide.py
from pptx import Presentation
import os
import sys

次に、分割したい対象のPPTファイルを指定します。
そのPPTファイルは、prs変数として扱う事とします。
titile_listは、PPTファイルのタイトルに重複があるか判断する際に利用します。

split_ppt_slide.py
path = os.path.dirname(os.path.abspath(__file__))
ppt_filename = "./sample.pptx" # 分割したいPPTファイル名
ppt_path = os.path.join(path, ppt_filename)

if not os.path.isfile(ppt_path): #ファイルが無い場合は終了
    print("ファイルが見つかりません")
    sys.exit()

prs = Presentation(ppt_path)
title_list = []

PPTファイルの指定したページを削除する関数になります。
例えば、indexに0を指定すると1ページ目のスライドを削除します。

split_ppt_slide.py
# PPTファイルの(index)枚目のスライドを削除
def delete_slides(presentation, index): 
    xml_slides = presentation.slides._sldIdLst  
    slides = list(xml_slides)
    xml_slides.remove(slides[index]) 

最後に指定したスライド以外を削除し保存する事で、各スライドごとに保存する処理になります。
この繰り返し処理で行っている事は、
①保存するタイトルの決定。
②指定したスライド以外の削除。
の2つの処理になります。

split_ppt_slide.py
for page in range(len(prs.slides)): # スライドのページ分繰り返し処理

    prs = Presentation(ppt_path) # 2回目以降の繰り返しの際に必要。削除されていない元のPPTファイルで初期化

    if prs.slides[page].shapes.title: #スライドにタイトルのshapeが無い場合にエラーを防ぐ
        ppt_title = prs.slides[page].shapes.title.text # (page)枚目のスライドのタイトル名を変数に格納
    else:
        ppt_title = ""

    if ((ppt_title in title_list) or ppt_title == ""): # タイトルに重複がある場合、タイトルが空白の場合はスライドのページをタイトルにする
        ppt_title = "Slide number " + str(page+1)

    title_list.append(ppt_title) #決定したタイトルをリストに格納

    save_path = "./tmp/" + ppt_title + ".pptx" # (page)枚目のスライドを、タイトル名で保存をする

    for idx in range(len(prs.slides)): #(page)枚目をの除くスライドを削除する繰り返し処理
        if(idx < page): #(page)枚目の1つ前のスライドまで全て削除
            delete_slides(prs,0)
        else: #(page)枚目以前のスライドの削除が終わった後の処理
            if(len(prs.slides) == 1): #(page)枚目のみになったところで、PPTファイルを保存する
                prs.save(save_path)
                break   
            delete_slides(prs,1) #PPTファイルの2枚目の削除を行う事で、(page)枚目のスライドを残す

この繰り返し処理の内容を図にしてみました。
PPTスライドを削除する際に、
①指定したスライドまでの削除
②指定したスライド移行の削除
の2つに分かれます。

例えば、3ページ目を残す場合を想定します。
元ファイルの2ページ目まで(指定したスライドが1ページ目になるまで)はPPTファイルの1ページ目を削除します。
3ページ目(指定したスライド)が1ページ目になってからは、PPTファイルの2ページ目を削除します。
最後に、指定したスライドのみになった時点で保存を行います。
この処理を、はじめのスライドから順に実行していく事によって、1つのPPTファイルから各スライドごとに分割が可能となります。

さいごに

PPTファイルを各スライドごとに分割していますが、中身の処理としては指定したスライド以外を削除して保存しているだけです。
なぜ、この内容をQiitaに投稿をしたか。
それは、PowerPointファイルをPowerPointファイルのまま、各スライドごとに分割する方法が他に無いかを知りたかった為です。
もしあるのであれば、コメント等でご教授いただければ幸いです。
最後まで、読んでいただき、ありがとうございました。