カオスなスライドを秩序へ。横向き・縦向き混在プレゼンを自動判別してPDF分割保存する「極限の制御術」
こんにちは。自動化の深淵へようこそ。
「マクロの記録」ボタンを押して、記録されたコードを眺めては「これ、どういう意味なんだろう?」と首を傾げたことはありませんか? もしそうなら、あなたは今、プログラミングの「書き手」から「設計者(アーキテクト)」へと進化する境界線に立っています。
今日扱うテーマは、実務で直面する非常に「泥臭く、かつ厄介な問題」です。
「スライドの中に、横向き(16:9)のグラフ資料と、縦向き(A4)の報告書が混ざっている。これをバラバラのPDFとして一瞬で出力したい」
PowerPointの標準機能では、PDF出力は「プレゼンテーション全体」か「選択したスライド」のどちらかです。混在している場合、手作業で分割して保存するのは、エンジニアとしてのプライドが許さない……そんな状況を、VBAの力でエレガントに解決していきましょう。
1. アーキテクチャの設計図:どうやって「判別」し「仕分ける」か
いきなりコードを書き始めるのは、設計図なしでビルを建てるようなものです。まずは、頭の中に「ロジックの設計図」を描きましょう。
今回のミッションを達成するための戦略は、以下の3ステップです。
1. 検知(Detection): 各スライドの `Width`(幅)と `Height`(高さ)を比較し、どちらが大きいかを判定する。
2. 隔離(Isolation): 判別した向きごとに、新しい「空のプレゼンテーション」をメモリ上に用意する。
3. 複製と出力(Cloning & Export): 元のスライドを新しいプレゼンテーションへコピーし、最後にそれぞれをPDFとして書き出す。
ここで重要なのは、「元のファイルをいじらない」という設計思想です。元のファイルを直接操作してスライドを削除したりすると、万が一エラーが起きた時にデータが壊れるリスクがあります。新しいプレゼンテーションを「器」として用意する。これが、プロの仕事です。
2. 実装:向きを判別し、別々のPDFへ導くマスターコード
それでは、魂を込めたコードを公開します。このコードは、単に動くだけでなく、エラーに強く、メンテナンスしやすい構造を意識しています。
Option Explicit
''' <summary>
''' スライドの向きを自動判別し、横向き用と縦向き用のPDFに分割保存するメインルーチン
''' </summary>
Sub SplitPresentationByOrientation()
Dim sourcePres As Presentation
Dim landscapePres As Presentation
Dim portraitPres As Presentation
Dim sld As Slide
Dim slideCount As Integer
Dim folderPath As String
Dim baseFileName As String
' 1. 環境のセットアップ
Set sourcePres = ActivePresentation
folderPath = sourcePres.Path & "\"
' ファイル名から拡張子を除いたものを取得
baseFileName = Left(sourcePres.Name, InStrRev(sourcePres.Name, ".") - 1)
' 2. 新しいプレゼンテーション(器)の準備
' 横向き用と縦向き用の2つの「空のプレゼン」をメモリ上に作成します
Set landscapePres = Presentations.Add(WithWindow:=msoFalse)
Set portraitPres = Presentations.Add(WithWindow:=msoFalse)
On Error GoTo ErrorHandler
' 画面更新を止めてパフォーマンスを向上させる(お作法)
' ※PowerPoint VBAにはExcelのような ScreenUpdating がないため、
' 手動でウィンドウ操作を制御するのがコツです。
Debug.Print "--- 分割処理を開始します ---"
' 3. スライドを一つずつ走査(ループ)
For Each sld In sourcePres.Slides
slideCount = sld.SlideIndex
' 【ここが核心】幅と高さを比較して向きを判定
If sld.Parent.PageSetup.SlideWidth < sld.Parent.PageSetup.SlideHeight Then
' --- 縦向き(Portrait)の場合 ---
Debug.Print "Slide " & slideCount & ": 縦向きを検知"
CopySlideToPresentation sld, portraitPres
Else
' --- 横向き(Landscape)の場合 ---
Debug.Print "Slide " & slideCount & ": 横向きを検知"
CopySlideToPresentation sld, landscapePres
End If
Next sld
' 4. PDFとして書き出し
' 横向きプレゼンを出力
If landscapePres.Slides.Count > 0 Then
landscapePres.ExportAsFixedFormat _
Path:=folderPath & baseFileName & "_Landscape.pdf", _
FixedFormatType:=ppFixedFormatTypePDF
End If
' 縦向きプレゼンを出力
If portraitPres.Slides.Count > 0 Then
portraitPres.ExportAsFixedFormat _
Path:=folderPath & baseFileName & "_Portrait.pdf", _
FixedFormatType:=ppFixedFormatTypePDF
End If
MsgBox "完了しました!" & vbCrLf & "保存先: " & folderPath, vbInformation, "Success"
CleanUp:
' 5. 後始末(オブジェクトの解放)
' メモリを食いつぶさないよう、作成したプレゼンを閉じる
On Error Resume Next
landscapePres.Close
portraitPres.Close
Set landscapePres = Nothing
Set portraitPres = Nothing
Exit Sub
ErrorHandler:
MsgBox "エラーが発生しました: " & Err.Description, vbCritical, "Error"
Resume CleanUp
End Sub
''' <summary>
''' スライドを別のプレゼンテーションへコピーする補助ルーチン
''' </summary>
''' <param name="targetSlide">コピー元のスライド</param>
''' <param name="destPres">コピー先のプレゼンテーション</param>
Private Sub CopySlideToPresentation(targetSlide As Slide, destPres As Presentation)
Dim newSlide As Slide
' スライドをコピー
targetSlide.Copy
' コピー先のプレゼンテーションの末尾に貼り付け
' Pasteメソッドは、スライドのレイアウトや書式を保持したまま貼り付けます
destPres.Slides.Paste
' 貼り付けた直後のスライド(最後尾)を取得
Set newSlide = destPres.Slides(destPres.Slides.Count)
' 【重要】貼り付け先のPageSetupをコピー元に合わせる
' これを行わないと、レイアウトが崩れる原因になります
With newSlide.Parent.PageSetup
.SlideWidth = targetSlide.Parent.PageSetup.SlideWidth
.SlideHeight = targetSlide.Parent.PageSetup.SlideHeight
End With
End Sub
3. エンジニアの視点:なぜこのコードは「強い」のか?
ただ動くだけのコードと、プロのコードの違いはどこにあるのか。このコードに込めた「極限の知見」を解説します。
① オブジェクトのライフサイクル管理
コードの最後に `CleanUp` セクションを設けています。`Presentations.Add` で作成したプレゼンテーションは、たとえ中身が空であっても、メモリ上に存在し続けます。大量の処理を繰り返す自動化ツールにおいて、これらを適切に `.Close` し、`Nothing` を代入して解放することは、「メモリリーク(メモリの無駄遣い)」を防ぐための鉄則です。
② レイアウト崩れを防ぐ「PageSetupの同期」
ここが今回の最も重要なテクニカルポイントです。
単に `Slide.Copy` して `Paste` するだけでは、貼り付け先のプレゼンテーションの基本設定(例えば16:9)に引きずられて、図形や文字が歪んでしまうことがあります。
`CopySlideToPresentation` 内で、コピー先の `PageSetup` をコピー元の `Width/Height` と強制的に同期させている点に注目してください。これにより、どんな比率のスライドが来ても、見た目を完璧に維持できます。
③ 堅牢なエラーハンドリング
`On Error GoTo ErrorHandler` を実装しています。自動化プログラムにおいて、最大の敵は「予期せぬ停止」です。例えば、ファイルが読み取り専用だったり、保存先フォルダに権限がなかったりする場合でも、エラーメッセージを表示して、必ず「後始末(CleanUp)」を通ってから終了するように設計しています。
4. 陥りやすい罠(ハマりポイント)
中級者への階段を登る皆さんに、あえて「落とし穴」を教えておきましょう。
- 「スライドの向き」の判定ミス:
スライドの向きを `Orientation` プロパティだけで判定しようとすると、カスタムサイズのスライドで誤作動することがあります。今回のように `Width` と `Height` の数値比較を行うのが、最も確実で「嘘をつかない」判定方法です。
- 貼り付け時のフォーマット:
`Paste` メソッドは非常に強力ですが、非常に複雑なアニメーションや特殊なアドインによる図形が含まれている場合、稀に挙動が不安定になることがあります。その場合は、一度 `Slide.Copy` ではなく、スライドそのものをインポートする手法を検討しますが、まずはこの方法が最も軽量です。
最後に:ここをクリアすれば、VBAの基本はバッチリです
「スライドを検知する」「新しい器を作る」「属性をコピーして同期させる」という一連の流れを理解できれば、あなたはもう「マクロの記録」の呪縛から解き放たれています。
プログラミングの本質は、「複雑な事象を、小さな論理の積み重ねに分解すること」にあります。
今回のコードをベースに、「ファイル名を日付にするには?」「特定のフォルダ内の全ファイルを処理するには?」と、少しずつ改造してみてください。その試行錯誤の先に、真の自動化エンジニアとしての道が開けています。
応援していますよ。さあ、次の自動化へ行きましょう!
