【実務中級】Presentation.SlideShowSettingsを操作し、特定の「カスタムスライドショー」を動的に作成・実行する自動化
PowerPoint VBAの真価は、単なる「図形の自動生成」や「一括置換」にあるのではない。プレゼンテーションの構造そのものを、実行時にロジックで動的に再構築する点にこそ、真のアーキテクチャとしての価値が宿る。
現場のビジネスシーンにおいて、このような課題に直面したことはないだろうか。
「全100スライドあるマスタ資料から、今日の取締役会向けに特定の10枚だけを抽出し、しかも特定の順序で上映したい」
「手動でカスタムスライドショーの設定画面を開き、ポチポチとスライドを選択して名前を付ける作業を、毎回の会議前に行うのは耐えられない」
この課題をエレガントに、かつミリ秒単位のオーバーヘッドで解決するのが、`Presentation.SlideShowSettings` オブジェクトと `NamedSlideShows` コレクションを組み合わせた動的制御だ。
今回は、実務の最前線で求められる「メモリ効率」「エラー耐性」「既存構造への非破壊性」を完全に担保した、プロフェッショナル向けの実装アプローチを解説する。
—
1. PowerPointオブジェクトモデルの深層:NamedSlideShowsのライフサイクル
PowerPointのプレゼンテーション内には、スライドの物理的な順序(`Slides` コレクション)とは別に、上映用のビューポートを定義する `SlideShowSettings` が存在する。
その中核をなすのが `NamedSlideShows` コレクションだ。これは「名前付きカスタムスライドショー」のコンテナであり、ここに動的にスライドのインデックス配列を登録することで、プレゼンテーションの実行パスを完全に制御できる。
ここで、素朴なVBAプログラマが陥る致命的な罠がある。
「作成したカスタムスライドショーを、処理の終了後やプレゼン終了後にどう掃除するか」 というライフサイクルの管理だ。
`NamedSlideShows` に追加されたカスタムショーは、明示的に削除(`.Delete`)しない限り、プレゼンテーションファイル(`.pptm` / `.pptx`)の内部メタデータとして永続化される。一時的な動的生成であれば、実行時または終了時に必ず破棄し、ファイルサイズやゴミデータを肥大化させないのがシニアエンジニアの流儀である。
—
2. 実装アーキテクチャ:動的カスタムスライドショー生成エンジンの設計
以下のコードは、アクティブなプレゼンテーションから、特定のタグ(例: `Category = “BoardMeeting”`)を持つスライドのみを動的に抽出し、一時的なカスタムスライドショーとして即座に全画面上映するための実務コードだ。
余計なオブジェクト変数の乱用を避け、ガベージコレクションの挙動を意識したクリーンな実装としている。
Option Explicit
‘ =================================================================================
‘ 処理名 : LaunchDynamicCustomSlideShow
‘ 概要 : 指定された条件(今回はスライドのノートまたはタイトル)に一致するスライドを
動的に抽出し、一時的なカスタムスライドショーとして実行する
‘ =================================================================================
Public Sub LaunchDynamicCustomSlideShow()
Dim targetPres As Presentation
Set targetPres = ActivePresentation
Const TEMP_SHOW_NAME As String = “_Temp_Dynamic_Show_”
‘ 1. 既存の同名一時カスタムショーが存在する場合は安全にパージする
Call PurgeExistingCustomShow(targetPres, TEMP_SHOW_NAME)
‘ 2. 条件に合致するスライドのインデックス配列を動的に収集
Dim slideIndices() As Long
slideIndices = CollectTargetSlideIndices(targetPres, “【要人向け】”)
If UBound(slideIndices) < LBound(slideIndices) Then
MsgBox "条件に合致するスライドが見つかりませんでした。", vbExclamation, "処理中断"
Exit Sub
End If
' 3. NamedSlideShows へカスタムショーを動的登録
Dim customShow As NamedSlideShow
On Error GoTo ErrorHandler
' Add メソッドの引数: (Name As String, PointerArray As Variant)
Set customShow = targetPres.SlideShowSettings.NamedSlideShows.Add(TEMP_SHOW_NAME, slideIndices)
' 4. SlideShowSettings の構成と実行
With targetPres.SlideShowSettings
.ShowType = ppShowTypeSpeaker ' 発表者として表示
.RangeType = ppShowNamedSlideShow ' 名前付きカスタムショーを使用
.SlideShowName = TEMP_SHOW_NAME ' 登録した名前を指定
.LoopUntilStopped = False
' スライドショーの実行(非同期実行ではなく、ウィンドウを占有)
Dim slideShowWin As SlideShowWindow
Set slideShowWin = .Run
End With
' 注: スライドショー終了後のクリーンアップは、イベントハンドラや
' モニタリング機構で行うのが理想だが、簡易的には手動終了後に
' PurgeExistingCustomShow が次回実行時にクリーンアップする設計とする。
GoTo CleanUp
ErrorHandler:
MsgBox "カスタムスライドショーの実行中にエラーが発生しました: " & Err.Description, vbCritical, "致命的エラー"
CleanUp:
' オブジェクト参照の明示的な解放(メモリ最適化)
Set slideShowWin = Nothing
Set customShow = Nothing
Set targetPres = Nothing
End Sub
' =================================================================================
' 補助関数 : 既存の同名カスタムショーの安全な削除
' =================================================================================
Private Sub PurgeExistingCustomShow(ByVal pres As Presentation, ByVal showName As String)
Dim nss As NamedSlideShows
Set nss = pres.SlideShowSettings.NamedSlideShows
Dim i As Long
For i = nss.Count To 1 Step -1
If nss(i).Name = showName Then
nss(i).Delete
Exit For
End If
Next i
Set nss = Nothing
End Sub
' =================================================================================
' 補助関数 : 条件に合致するスライドインデックスの動的収集
' =================================================================================
Private Function CollectTargetSlideIndices(ByVal pres As Presentation, ByVal keyword As String) As Long()
Dime tempIndices() As Long
Dim count As Long
count = 0
' 最大サイズで動的配列を初期化(後で Redim Preserve)
ReDim tempIndices(1 To pres.Slides.Count)
Dim sld As Slide
Dim i As Long
For i = 1 To pres.Slides.Count
Set sld = pres.Slides(i)
' 条件判定ロジック:ここではスライド内のシェイプテキスト、
' またはノートに特定キーワードが含まれるかを判定
If EvaluateSlideCondition(sld, keyword) Then
count = count + 1
tempIndices(count) = i
End If
Set sld = Nothing
Next i
' ヒット数が0の場合のハンドリング
If count = 0 Then
CollectTargetSlideIndices = Split("", ",") ' 空の配列を返すイディオム
Exit Function
End If
' 実際にヒットしたサイズにリサイズ
ReDim Preserve tempIndices(1 To count)
CollectTargetSlideIndices = tempIndices
End Function
' =================================================================================
' 判定ロジックのカプセル化
' =================================================================================
Private Function EvaluateSlideCondition(ByVal sld As Slide, ByVal keyword As String) As Boolean
' サンプルとして、タイトルシェイプまたはノートにキーワードが含まれるかを検証
Dim shp As Shape
For Each shp In sld.Shapes
If shp.HasTextFrame Then
If shp.TextFrame.HasText Then
If InStr(1, shp.TextFrame.TextRange.Text, keyword, vbTextCompare) > 0 Then
EvaluateSlideCondition = True
Exit Function
End If
End If
End If
Next shp
‘ ノートの検証
If sld.HasNotesPage Then
Dim notesTxt As String
notesTxt = sld.NotesPage.Shapes.Placeholders(2).TextFrame.TextRange.Text
If InStr(1, notesTxt, keyword, vbTextCompare) > 0 Then
EvaluateSlideCondition = True
Exit Function
End If
End If
EvaluateSlideCondition = False
End Function
—
3. チーフアーキテクトが指摘する「実務上の罠」とパフォーマンス最適化
上記のコードをそのままエンタープライズ環境に投入するにあたり、シニアエンジニアとして押さえておくべき極限の知見をいくつか共有しておこう。
1. 配列の型と `NamedSlideShows.Add` の厳格な仕様
`NamedSlideShows.Add` の第2引数(`IndexPtrArray`)は、「1から始まるLong型の1次元配列(Variant可)」を要求する。
VBAの `Array()` 関数や `Split()` 関数が返す配列は `Variant(String)` や 0始まりの配列であることが多く、これらをそのまま渡すと型ミスマッチ(エラー 13)や引数不正(エラー 5)を引き起こす。
上記のコードで行っているように、明示的に `Long` 型の配列として確保し、インデックスを `1` から構築することが、予期せぬクラッシュを防ぐ絶対条件である。
2. COMオブジェクトの解放とメモリリーク対策
PowerPoint VBAにおいて、`For Each` ループやコレクションの走査で取得したオブジェクト変数(`Slide`, `Shape` など)をループごとに解放せず放置すると、VBAランタイムの背後にあるCOM参照カウンタが肥大化し、最悪の場合ExcelやPowerPointプロセス全体のメモリリークや強制終了を招く。
ループの最後で `Set sld = Nothing` や `Set shp = Nothing` を明示的に記述する習慣は、長期間稼働するマクロにおいて生命線となる。
3. モーダルウィンドウとプレゼンテーション実行の排他制御
`.SlideShowSettings.Run` を実行すると、VBAの実行スレッドはスライドショーウィンドウの制御権に移る(あるいは非同期でウィンドウが立ち上がる)。プレゼンテーション実行中に背後でVBAからスライド構造をいじろうとすると、PowerPointの描画エンジンと競合し、例外をスローする。
動的カスタムショーは、あくまで「表示するビューの切り替え」に留め、データ構造自体の破壊的変更はプレゼンテーション非実行時(編集モード時)に完結させるべきである。
—
総括
PowerPoint VBAにおける `SlideShowSettings` と `NamedSlideShows` の掌握は、単なる「ショートカットの自動化」を超えた、プレゼンテーション・インフラストラクチャの動的プログラミングである。
静的なスライドの束を、ビジネスの文脈に合わせて瞬時に再定義し、最適なインサイトだけをオーディエンスに届ける。この自動化の仕組みをあなたの組織に組み込んだ瞬間から、PowerPointは単なる「スライド作成ソフト」ではなく、リアルタイムな意思決定を加速させる強力なシステムへと変貌を遂げる。
