PPTXファイルの画像ファイルへの変換

###はじめに

PPTXから画像ファイルへの変換について調べたので、その備忘録として記載します。
Windows ApplicationをPythonで使うには、comtypesまたは、pywin32をインストールする必要があります。また、操作する（今回はPowerpoint)アプリケーションもインストールされている必要があります。
COMという言葉が出てきますが、Component Object Model (COM)のことのようです。communication port（COMポート）とは違います。


###参考
Windows ApplicationをPythonで使うには
(1)[PowerpointをPythonで使うための検討](http://students.hatenablog.com/entry/2018/11/25/213353)
(2)[Automating Windows Applications Using COM - Practical ...](https://pbpython.com/windows-com.html)
(3)[PythonでExcelを操作してみる](http://kagetsu.sblo.jp/article/186477958.html)
(4)[win32com-PyWin32（Python for Windows extensions）](http://ichitcltk.hustle.ne.jp/gudon2/index.php?pageType=file&id=python_win32com.md)

Powerpointを画像に出力するには
(5)[Automate the export of PowerPoint files to Images](https://www.free-power-point-templates.com/articles/automate-the-export-of-powerpoint-files-to-images/)
(6) [PythonでPowerPointの各ページを画像ファイルにする](https://qiita.com/natsutan/items/2487e24fe3f31569b40d)

エラー対応
comtypes
(7)[AttributeError: module 'comtypes.gen.Word' has no ... - GitHub](https://stackoverflow.com/questions/51825798/comtypes-has-no-attribute-application)
Dispatch()とDispatchEx()の違い
(8)[[b-PAC SDKをPython + pywin32(win32com)で操作してみた](https://thinkami.hatenablog.com/entry/2016/05/11/061626)

###環境と環境構築

Win10
Anaconda
Python3.7
Microsoft Office 2013 (PowerPoint含む）

####モジュールインストール
同じ機能を提供しているモジュールとして、comtypesとpywin32の2つがありますが、今のところpywin32の方を使っています。
Condaでインストールするならば

```Python
conda install -c conda-forge comtypes
conda install -c conda-forge pywin32
```
conda-forgeからインストールできます。
comtypesをインストールするとpywin32もインストールされるかもしれません。

pipでインストールするならば

```Python
pip install comtypes
pip install pywin32
```

私の環境でのインストール状況（conda listの結果）
comtypes                  1.1.7           py37hc8dfbb8_1001    conda-forge
pywin32                   227              py37hfa6e2cd_0    conda-forge



###作成コード
参考(6) の[PythonでPowerPointの各ページを画像ファイルにする](https://qiita.com/natsutan/items/2487e24fe3f31569b40d)を参考にコードを作成しました。題材として、以下のようなPowerPointファイル（Qiita_test.pptx）を作成しました。PPTXデータは添付しませんので、データはご自身で作成してください。

![pptx01.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/165987/881b96b4-58fb-c99f-43b8-2f1a32d9d4e6.jpeg)

#####ホルダー構成

dataホルダー（この中にPPTXファイルを入れます）
imageホルダー（画像になったものがこのホルダーに入ります）
test.py（コードが書かれたファイル）

#####コードと解説

```python

from pathlib import Path
import win32com.client


def export_pptx_img(file_name, output_dir, image_name='slide', fmt="png"):
    """
    pptxファイルを画像ファイルに変換する関数
    
    file_name: file name -> str or pathlib object
    output_dir: output dir -> str or pathlib object
    image_name:output slide name ->str
    fmt = "png" or "jpg" or "bmp"
    """
    
    #Pathlib objectに変換、絶対パスに変更
    f_path = Path(file_name)
    f_path_abs =f_path.resolve()
    o_path = Path(output_dir)
    o_path_abs = o_path.resolve()
    
    
    # application = comtypes.client.CreateObject("Powerpoint.Application")
    # AttributeError: module 'comtypes.gen.PowerPoint' has no attribute '_Application'
    # エラーが出るためwin32comに変更しています
    # DispatchExとDispatchの違い参照

    application = win32com.client.DispatchEx("Powerpoint.Application")
    
    # Trueにしないとうまく動かない
    application.Visible = True
    
    # file Path は絶対パスでないとエラーになる
    # pathlib objectは受け付けないので文字列に変更
    presentation = application.Presentations.open(str(f_path_abs))

    presentation.Export(str(o_path_abs), FilterName=fmt)
    presentation.close()
    application.quit()
    
    # スライドをリネームします
    # globでファイルを見つけてリストにします
    rename_list = list(o_path.glob('スライド?.{}'.format(fmt.upper())))

    for i, file in enumerate(rename_list):
        # 新しい名前
        name_format = '{}_{:02d}.{}'.format(image_name,i+1,fmt.upper())
        name_path = Path(file.parent/name_format)
        # print(name_path)
        if name_path.exists() == False:
            # # 存在しないことを確認
            # print("is_exists?:", name_path.exists())  # False
            file.replace(name_path)
        else:
            print("Rename is Failure")

if __name__ == '__main__':
    input_path = Path('./data') 
    output_path = Path('./image') 
    input_file_lists = list(input_path.glob('*'))
    # 注：リストオブジェクトが帰って来ます
    print(input_file_lists[0])

    export_pptx_img(input_file_lists[0],output_path,image_name='test1',fmt="png")
   
```

参考にしたコードでは`os.path`オブジェクトを使っていますが、`pathlib`オブジェクトに変更しています。
`application= comtypes.client.CreateObject("Powerpoint.Application")`
のインスタンスを作るところで
`AttributeError: module 'comtypes.gen.PowerPoint' has no attribute '_Application'`
のようなエラーが出るため、以下のように書き換えています(参考（7）)。
`application = win32com.client.DispatchEx("Powerpoint.Application")`
参考（8）にある`DispatchEx`と`Dispatch`の違いより`DispatchEx`にしています。

#####実行

実行すると、一度PowerPointのアプリケーションが開きます。そして処理が終わると閉じます。
最終的imageホルダー内にtest1とリネームされたファイルが作成されます。
![pptx02.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/165987/f6452785-4bc4-fb15-30b2-4c55a0fc50bf.jpeg)