"""
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)