【実務・中級編】【中級者】横向き(16:9)と縦向き(A4)のスライドが混在するプレゼンテーションを検知し、向きごとに別々のPDFへ分割・保存する制御マクロ – PowerPoint VBA解析バイブル

スポンサーリンク

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化していた時間は、今日で終わりだ。このコードをベースに、さらに「ファイル名に日付を付与する」「共有サーバーへ自動アップロードする」といった拡張を加え、君のエンジニアとしての価値を証明してほしい。

質問があればいつでも歓迎する。ただし、基本を飛ばした質問は受け付けない。では、現場へ戻れ。

タイトルとURLをコピーしました