ai.add_notes_pptx_com のソースコード

"""
PowerPoint COM APIを使用して、指定されたPowerPointプレゼンテーションのノートにテキストを挿入するスクリプト。

このスクリプトは、特定の書式で記述されたテキストファイル(ナレーションファイル)を解析し、
`#Slide n` で指定されたスライド番号に対応するノートページにテキストを挿入します。
PowerPointアプリケーションをCOM経由で操作するため、Windows環境でのみ動作します。

関連リンク: :doc:`add_notes_pptx_com_usage`
"""
import win32com.client
import re
import sys
import os

[ドキュメント] def insert_notes_com(pptx_path, narration_path, output_path=None): """ PowerPoint COM APIを使って、#Slide n で指定されたスライドのノート欄にテキストを追加する。 指定されたPowerPointファイルに対し、ナレーションファイルから読み込んだテキストを各スライドのノートページに挿入します。 ナレーションファイルは `#Slide n` というマーカーで各スライドのテキストを区切る必要があります。 スクリプトはPowerPointアプリケーションを起動し、指定されたプレゼンテーションを開き、 対応するスライドのノートテキストボックスにテキストを設定します。 処理後、プレゼンテーションを保存し、PowerPointアプリケーションを終了します。 :param pptx_path: str: ノートを挿入するPowerPointプレゼンテーションファイルのパス。 :param narration_path: str: 各スライドのノートとして挿入するテキストを含むナレーションファイルのパス。 各スライドのテキストは `#Slide n` (nはスライド番号) で区切られている必要があります。 :param output_path: str, optional: ノートが挿入されたプレゼンテーションの出力パス。 指定しない場合、元のPowerPointファイルを上書きします。 :returns: None: 処理が成功した場合、指定されたパスにノートが挿入されたプレゼンテーションを保存します。 エラーが発生した場合は例外が発生する可能性があります。 """ # --- 1. 読み上げテキストを解析 --- slide_texts = {} current_slide = None current_lines = [] with open(narration_path, "r", encoding="utf-8") as f: for line in f: line = line.rstrip("\n") m = re.match(r"#Slide\s+(\d+)", line, re.IGNORECASE) if m: if current_slide is not None: slide_texts[current_slide] = "\n".join(current_lines).strip() current_slide = int(m.group(1)) current_lines = [] else: current_lines.append(line) if current_slide is not None: slide_texts[current_slide] = "\n".join(current_lines).strip() # --- 2. PowerPoint起動 --- ppt = win32com.client.Dispatch("PowerPoint.Application") ppt.Visible = True pres = ppt.Presentations.Open(os.path.abspath(pptx_path)) # --- 3. ノート挿入 --- for idx, slide in enumerate(pres.Slides, start=1): if idx in slide_texts: text = slide_texts[idx] # ノートページにアクセス notes_page = slide.NotesPage # NotesPage.Shapesのうち、Placeholders(プレースホルダ)の種類2がノートテキストボックス for shp in notes_page.Shapes: if shp.Type == 14 and shp.PlaceholderFormat.Type == 2: # ppPlaceholderBody shp.TextFrame.TextRange.Text = text break print(f"スライド {idx}: ノートを挿入しました。") else: print(f"スライド {idx}: ノートなし。") # --- 4. 保存 --- if output_path is None: output_path = pptx_path pres.SaveAs(os.path.abspath(output_path)) pres.Close() ppt.Quit() print(f"\n✅ ノート挿入完了: {output_path}")
if __name__ == "__main__": if len(sys.argv) < 3: print("使い方: python insert_notes_com.py slides.pptx narration.txt [output.pptx]") sys.exit(1) pptx_file = sys.argv[1] narration_file = sys.argv[2] output_file = sys.argv[3] if len(sys.argv) > 3 else None insert_notes_com(pptx_file, narration_file, output_file)