PowerPointの混沌を制す:混在スライドの自動仕分け・PDF出力アーキテクチャ
現場の資料は、往々にして「カオス」だ。
横向きのプレゼン資料の中に、突如としてA4縦向きの調査報告書が混入する。手作業でPDFを分割して保存する?そんな非効率なルーチンにエンジニアの時間を割く必要はない。
今回は、PowerPoint VBAを用いて「スライドサイズを動的に判別し、向きごとにPDFを自動分割して保存する」という、実務直結型の自動化ソリューションを設計する。
1. なぜ「力技のループ」では失敗するのか
多くの初学者は、単にスライドを一つずつPDF出力しようとする。だが、それは地獄への入り口だ。
- API呼び出しのオーバーヘッド: スライドごとに`ExportAsFixedFormat`を呼ぶと、OSとPowerPoint間の通信コストで処理時間が指数関数的に増大する。
- ファイルロックの罠: 連続したPDF生成時に、ファイルシステムが追いつかずアクセス拒否エラーが発生する。
- スライドサイズの判定: `PageSetup.SlideOrientation`だけで判定しようとすると、カスタムサイズの変則的なスライドに対応できず、設計が崩壊する。
我々が目指すべきは、「向きごとにスライドをグルーピングし、一括でPDF出力する」という、メモリ効率を考慮した設計だ。
2. 堅牢な設計指針:論理分離とエラーハンドリング
コードを書く前に、以下の3原則を頭に叩き込んでほしい。
1. 判定ロジックの抽象化: スライドの向き(縦か横か)を判定する関数を独立させる。
2. 一時的な状態操作: `Presentation.SaveCopyAs`等で一時ファイルを生成し、そこから不要なスライドを削除して出力する「破壊的変更による抽出」は避ける(元データが汚染される)。
3. パス管理の厳格化: `Dir`関数によるファイル存在確認と、`FileSystemObject`でのフルパス生成を徹底する。
—
3. 実装:プロフェッショナル・エディション
以下のコードは、単なるスクリプトではない。保守性と拡張性を意識したアーキテクチャだ。
Option Explicit
‘ ———————————————————
‘ メイン処理: スライドを向きごとに分割してPDF出力
‘ ———————————————————
Public Sub SplitPresentationByOrientation()
Dim ppt As Presentation: Set ppt = ActivePresentation
Dim slide As slide
Dim landscapeSlides As Collection, portraitSlides As Collection
Set landscapeSlides = New Collection
Set portraitSlides = New Collection
‘ 1. スライドの向きを判別してインデックスを収集
For Each slide In ppt.Slides
If slide.Master.Width > slide.Master.Height Then
landscapeSlides.Add slide.SlideIndex
Else
portraitSlides.Add slide.SlideIndex
End If
Next slide
‘ 2. 向きごとにPDFを出力
Call ExportSlidesToPDF(ppt, landscapeSlides, “Landscape_Output.pdf”)
Call ExportSlidesToPDF(ppt, portraitSlides, “Portrait_Output.pdf”)
MsgBox “PDF分割処理が完了しました。”, vbInformation
End Sub
‘ ———————————————————
‘ 指定したスライド番号リストをPDFとして出力する汎用関数
‘ ———————————————————
Private Sub ExportSlidesToPDF(sourcePpt As Presentation, slideIndices As Collection, fileName As String)
If slideIndices.Count = 0 Then Exit Sub
Dim tempPpt As Presentation
Dim i As Long
‘ 新規プレゼンテーションの作成(メモリ上で完結)
Set tempPpt = Presentations.Add(WithWindow:=msoFalse)
‘ スライドのコピー(後半から追加していくことでインデックスズレを回避)
For i = slideIndices.Count To 1 Step -1
sourcePpt.Slides(slideIndices(i)).Copy
tempPpt.Slides.Paste
Next i
‘ PDF出力
tempPpt.ExportAsFixedFormat _
Path:=ActivePresentation.Path & “\” & fileName, _
FixedFormatType:=ppFixedFormatTypePDF, _
Intent:=ppFixedFormatIntentPrint
‘ メモリ解放
tempPpt.Close
Set tempPpt = Nothing
End Sub
—
4. プロダクション環境への組み込みにおける注意点
このコードを現場に投入する際、必ず以下の点を確認してほしい。
- 参照設定: `Microsoft PowerPoint Object Library` が有効になっていること。
- メモリの保護: 大規模なプレゼン(数百枚規模)の場合、`Paste`処理がメモリを圧迫する可能性がある。その際は、`DoEvents`をループ内に挟み、OS側の処理待ち時間を適宜挿入する設計へ変更せよ。
- パスの正規化: `ActivePresentation.Path`は、未保存のプレゼンテーションでは空文字列を返す。実行前に必ず`Save`を実行するガード句(`If ppt.Path = “” Then …`)を実装するのが、プロの流儀だ。
最後に:自動化とは「リスクの排除」である
コードを書いて終わりではない。重要なのは、このツールが「誰が使っても同じ結果を返す」ことだ。
手作業で向きを確認し、手動でPDF化していた時間は、今日で終わりだ。このコードをベースに、さらに「ファイル名に日付を付与する」「共有サーバーへ自動アップロードする」といった拡張を加え、君のエンジニアとしての価値を証明してほしい。
質問があればいつでも歓迎する。ただし、基本を飛ばした質問は受け付けない。では、現場へ戻れ。
