add_notes_pptx.py 技術ドキュメント

プログラムの動作

add_notes_pptx.py は、Microsoft PowerPoint(.pptx)ファイルを操作するためのPythonスクリプトです。主な目的は、PowerPointスライドのノート情報を活用して、プレゼンテーションの表示内容を強化または自動化することです。

本プログラムは以下の2つの主要な機能モードを提供します。

  1. add モード:

    • 各スライドに添付されているノートのテキスト内容を読み込みます。

    • 読み込んだノート内容を、スライドの下部に半透明の字幕テキストボックスとして追加します。

    • 字幕ボックスのフォント、サイズ、色、背景色、透明度、位置(余白、高さ)はコマンドライン引数で細かく設定可能です。

    • これにより、発表者はスライドノートを別途参照することなく、プレゼンテーション中に重要な情報を視覚的に提示できるようになります。

  2. replace モード:

    • スライド内のテキストに含まれる {{key}} 形式のプレースホルダーを、事前に定義された値で置換します。

    • 置換する値は、コマンドラインで指定するTOML風の key=value 形式のファイルから読み込まれます。

    • さらに、各スライドに添付されているノート内容も {{supertitle}} という特別なキーの値として利用され、ファイル側の指定よりも優先されます。

    • このモードの重要な特徴は、既存のテキスト書式(フォント、色、サイズなど)やアニメーションを保持したまま、指定された部分のみを置換することです。

    • これにより、テンプレートスライドの特定の情報を動的に変更したり、プレゼンテーションのパーソナライズを効率的に行ったりすることが可能になります。

本プログラムは、PowerPointのノート機能をより柔軟に活用したいユーザーや、定型的なプレゼンテーションのテキスト更新作業を自動化したいユーザーの課題を解決します。

原理

add_notes_pptx.py は、Windows環境でMicrosoft PowerPointアプリケーションをCOM(Component Object Model)経由で操作するために、win32com.client ライブラリを利用しています。

共通処理: ノート本文の取得と整形

  1. PowerPointアプリケーションとの連携: ppt = win32com.client.Dispatch("PowerPoint.Application") このコードにより、PowerPointアプリケーションのインスタンスが取得され、スクリプトからPowerPointを制御できるようになります。

  2. プレゼンテーションのオープン: presentation = ppt.Presentations.Open(args.infile, WithWindow=False) 指定された入力PowerPointファイルを非表示モードで開きます。

  3. ノート本文の取得: get_notes_text(slide) 関数は、各スライドのノートページからテキストを抽出します。具体的には、ノートページのシェイプコレクション内の Placeholders(2)(通常はノート本文のプレースホルダー)から TextFrame.TextRange.Text を読み込みます。

  4. テキストの整形: clean_text(text) 関数は、取得したテキストから空行や空白文字のみの行を除去し、整形されたテキストを返します。これにより、ノートに記述された余分な改行などが取り除かれます。

add モード: 字幕テキストボックスの追加

  1. スライド寸法の取得: presentation.PageSetup.SlideWidth および presentation.PageSetup.SlideHeight を利用して、スライド全体の幅と高さを取得します。

  2. 字幕ボックスの位置とサイズの計算: コマンドライン引数で指定された左右余白 (box_margin) と高さ (box_height)、およびスライド全体の寸法に基づいて、字幕テキストボックスの LeftTopWidthHeight を計算します。Top の計算では、スライド下部から一定の余白を取って配置されます。

  3. テキストボックスの追加: slide.Shapes.AddTextbox(Orientation=1, Left=..., Top=..., Width=..., Height=...) スライドに新しいテキストボックスを追加します。Orientation=1 は水平方向のテキストを意味します。

  4. テキストとスタイルの設定:

    • shape.TextFrame.TextRange.Text = note_text で、整形済みのノートテキストをボックスに設定します。

    • TextRange.Font.NameTextRange.Font.SizeTextRange.Font.Color.RGB でフォント、サイズ、色を設定します。色のRGB値は、引数で受け取った16進数文字列(例: "884444")を int(args.font_color, 16) で10進数に変換して使用します。

    • shape.Fill.ForeColor.RGBshape.Fill.Transparencyshape.Fill.Visible = Trueshape.Fill.Solid() で背景色と透明度を設定し、塗りつぶしを有効にします。

replace モード: プレースホルダーの置換

  1. TOML風ファイルのパース: parse_toml_style(filepath) 関数は、key=value 形式のテキストファイルを読み込み、辞書として解析します。

    • 正規表現 r'^\s*([a-zA-Z0-9_]+)\s*=\s*(.*?)\s*(?:#.*)?$' を使用して、行頭・行末の空白、コメント行(#で始まる)、キーと値の間の = を柔軟に処理します。

    • 値がシングルクォート ' またはダブルクォート " で囲まれている場合は、それらを除去します。

  2. 置換マップの構築: replace_placeholders_on_slide 関数内で、読み込んだ基本マップ(base_map)に、現在のスライドのノート内容を supertitle キーとして追加します。この supertitlebase_map 内の同じキーよりも優先されます。

  3. スライド内のシェイプの再帰的走査: _replace_in_shapes および _replace_in_shape_deep 関数は、スライド内のすべてのシェイプを走査します。

    • グループ化されたシェイプ: shp.Type == 6 (msoGroup) の場合、shp.GroupItems を再帰的に走査します。

    • 表 (Table): shp.HasTable の場合、表の各セル tbl.Cell(r, c).Shape を取得し、そのシェイプに対して置換処理を行います。

    • 通常のテキストフレーム: 上記以外のテキストフレームを持つシェイプに対しては、_replace_in_textframe を呼び出します。

  4. プレースホルダーの部分置換: _replace_in_textframe(shp, kv) 関数が置換処理の中核を担います。

    • shp.TextFrame.TextRange オブジェクトを取得し、その Find メソッドを利用して、{{key}} 形式のプレースホルダーを検索します。Find(FindWhat=placeholder, After=after_pos, ...) をループで繰り返し呼び出すことで、テキスト全体からすべてのプレースホルダーを見つけ出します。

    • プレースホルダーが見つかると、tr_hit.Text = value のように、win32com が提供する TextRange オブジェクトの Text プロパティを直接書き換えます。この操作により、テキストの書式設定(フォント、色、サイズ、太字、斜体など)や、そのテキストに適用されているアニメーション、ハイパーリンクなどの属性を維持したまま、テキスト内容だけを更新することが可能です。これは、PowerPoint COM API の強力な機能の一つです。

全体の終了処理

処理完了後、presentation.SaveAs(args.outfile) で変更を新しいファイルに保存し、presentation.Close() でプレゼンテーションを閉じ、ppt.Quit() でPowerPointアプリケーションを終了します。最後に terminate() 関数がユーザーにEnterキーの入力を促し、プログラムを終了します。

必要な非標準ライブラリとインストール方法

このプログラムは、Microsoft PowerPointのCOMオブジェクトを操作するために pywin32 ライブラリに依存しています。

  • ライブラリ名: pywin32

  • インストール方法: 以下の pip コマンドでインストールできます。

    pip install pywin32
    

必要な入力ファイル

  1. 入力PowerPointファイル (.pptx)

    • 形式: Microsoft PowerPoint 2007以降の .pptx 形式のファイル。

    • 目的:

      • add モードの場合: ノートを字幕として追加する元のプレゼンテーションファイル。

      • replace モードの場合: {{key}} プレースホルダーを含むプレゼンテーションファイル。

    • データ構造: 各スライドのノートページにテキストデータが含まれていることが想定されます。replace モードでは、スライド内のテキストボックスや表のセルに {{key}} 形式のプレースホルダーが含まれていることが期待されます。

  2. 置換用のTOML風 key=value ファイル (任意)

    • 形式: 任意の拡張子(例: .txt, .toml, .conf)を持つプレーンテキストファイル。

    • 目的: replace モードで使用され、{{key}} プレースホルダーを置換するためのキーと値のペアを提供します。

    • データ構造:

      • 各行に key = value の形式で記述します。

      • 行頭/行末の空白は無視されます。

      • # で始まる行はコメントとして無視されます。

      • 値はクォート (" または ') で囲むこともでき、その場合はクォートが剥がされます。

      • 例:

        title = "プロジェクト概要"
        date = '2023-10-27'
        version = 1.0
        # これはコメント行です
        author = John Doe
        
    • 注意: このファイルが指定されない場合、replace モードでは各スライドのノート内容({{supertitle}})のみが置換対象となります。

生成される出力ファイル

本プログラムは、常に新しいPowerPointファイルを出力します。入力ファイルは変更されません。

  • ファイル形式: .pptx

  • ファイル名:

    • コマンドラインで -o または --outfile オプションを使って出力ファイル名を明示的に指定した場合、そのファイル名が使用されます。

    • 出力ファイル名が指定されなかった場合、入力ファイル名に基づいて以下の規則で自動生成されます。

      • add モード: 入力ファイル名の末尾に -note-added.pptx が付加されます。

        • 例: MyPresentation.pptxMyPresentation-note-added.pptx

      • replace モード: 入力ファイル名の末尾に -replaced.pptx が付加されます。

        • 例: MyPresentation.pptxMyPresentation-replaced.pptx

  • 内容:

    • add モード: 入力PowerPointファイルに、各スライドのノート内容が半透明の字幕テキストボックスとして追加されたプレゼンテーション。

    • replace モード: 入力PowerPointファイルのスライド内の {{key}} プレースホルダーが、指定された置換マップ(TOML風ファイルおよびスライドノート)に従って置換されたプレゼンテーション。既存の書式やアニメーションは保持されます。

コマンドラインでの使用例 (Usage)

add_notes_pptx.py スクリプトの基本的な使用方法は以下の通りです。

python add_notes_pptx.py [-h] [-o OUTFILE] [--mode {add,replace}] [--replace REPLACE]
                         [--box_margin BOX_MARGIN] [--box_height BOX_HEIGHT]
                         [--font_name FONT_NAME] [--font_size FONT_SIZE]
                         [--font_color FONT_COLOR] [--bgcolor BGCOLOR]
                         [--bgalpha BGALPHA]
                         infile
  • infile: 必須。処理する入力PowerPointファイル(.pptx)のパス。

  • -o OUTFILE, --outfile OUTFILE: オプション。生成される出力PowerPointファイルのパス。省略した場合、入力ファイル名に基づき自動生成されます。

  • --mode {add,replace}: オプション。スクリプトの動作モードを指定します。

    • add: ノートを字幕テキストボックスとして追加します。(デフォルト)

    • replace: {{key}} プレースホルダーを置換します。

  • -R REPLACE, --replace REPLACE: replace モードの場合に必須。置換用の key=value 形式のファイルパス。


add モード固有のオプション:

  • --box_margin BOX_MARGIN: 字幕ボックスの左右余白(pt)。デフォルトは 50

  • --box_height BOX_HEIGHT: 字幕ボックスの高さ(pt)。デフォルトは 60

  • --font_name FONT_NAME: フォント名。デフォルトは メイリオ

  • --font_size FONT_SIZE: フォントサイズ(pt)。デフォルトは 12

  • --font_color FONT_COLOR: 文字色(16進RGB形式)。デフォルトは 884444

  • --bgcolor BGCOLOR: 背景色(16進RGB形式)。デフォルトは 00dddd

  • --bgalpha BGALPHA: 背景の透明度(0.0〜1.0)。デフォルトは 0.6

コマンドラインでの具体的な使用例

1. add モードでの字幕追加

入力ファイル presentation.pptx のノートを読み込み、緑の背景に白文字で半透明の字幕を追加し、presentation-note-added.pptx として出力します。

python add_notes_pptx.py presentation.pptx --mode add --font_name "Yu Gothic UI" --font_size 14 --font_color FFFFFF --bgcolor 008800 --bgalpha 0.7

実行結果の説明: presentation.pptx の各スライドのノート内容が、スライド下部に新しいテキストボックスとして追加されます。このテキストボックスは「Yu Gothic UI」フォント、サイズ14pt、白色の文字、濃い緑色(008800)の背景、透明度70%(0.7)で表示されます。出力ファイルは presentation-note-added.pptx という名前で保存されます。

2. replace モードでのプレースホルダー置換

入力ファイル template.pptx 内の {{key}} プレースホルダーを、replace_data.txt の内容と各スライドのノート内容で置換し、template-replaced.pptx として出力します。

replace_data.txt の内容例:

project_name = "新製品ローンチ計画"
client_name = "XYZ株式会社"

template.pptx の1枚目のスライドに「{{project_name}}へようこそ」というテキストがあり、そのスライドのノートに「今後の計画」と書かれていると仮定します。

python add_notes_pptx.py template.pptx --mode replace --replace replace_data.txt -o output_final.pptx

実行結果の説明: replace_data.txt に定義された project_nameclient_name の値が読み込まれます。 template.pptx のスライドを走査し、例えば「{{project_name}}へようこそ」というテキストは「新製品ローンチ計画へようこそ」に置換されます。 また、各スライドのノート内容が {{supertitle}} キーに対応するため、スライド内に {{supertitle}} があれば、そのスライドのノート内容(例:「今後の計画」)で置換されます。 元のテキストのフォント、サイズ、色などの書式設定は維持されたまま置換が行われます。出力ファイルは -o オプションで指定された output_final.pptx として保存されます。 実行後のコンソールには、置換された箇所の総数が表示され、「注:ノートを置換する場合は {{supertitle}} を使ってください」というメッセージも表示されます。