【PowerPoint VBA】沈まないアドインの作り方:Selectionの深淵と「極限のガード句」
PowerPointアドインを配布する際、避けては通れないのが「ユーザーの操作による予期せぬ状態」だ。特に `ActiveWindow.Selection` は、PowerPointのオブジェクトモデルの中でも最も不安定で、かつ「実行時のコンテキスト」に依存する危険な存在である。
何も考えずに `ActiveWindow.Selection.ShapeRange` を叩けば、ユーザーがスライド一覧表示中にマクロを起動した瞬間に「実行時エラー 424: オブジェクトが必要です」が突きつけられる。これはプロフェッショナルのコードではない。
今回は、どんな地獄のようなコンテキストでも死なない、堅牢なガード句の実装パターンを伝授する。
—
1. Selectionの階層構造と「生存条件」
PowerPointのSelectionは、現在の「表示モード(ViewType)」と「選択物の型(Type)」という二軸で動的に変化する。
- ViewType: 編集モードか、スライド一覧か、標準表示か。
- Type: スライドか、テキストか、図形か、それとも何も選択されていないか。
初心者は `Selection.Type` だけを見て判断しようとするが、これでは甘い。そもそも `ActiveWindow` が存在しない(スライドショー実行中など)ケースを考慮していないからだ。
陥りやすい罠:Typeプロパティの盲点
`Selection.Type` は、スライドショー実行中や、何も選択されていない状態ではプロパティ自体がエラーを返すことがある。まずは「ウィンドウが存在するか」、次に「そのウィンドウで何が選択可能か」という順序でスタックを積む必要がある。
—
2. 実装:鉄壁のガード句パターン
以下に、あらゆる環境で安全に動作する「ガード・クラス(モジュール)」のコアロジックを示す。
‘ @description: 実行環境を厳密に検証し、安全を担保するガード関数
‘ @return: 実行可能であればTrue, 不可能であればFalse
Public Function IsExecutionSafe() As Boolean
‘ 1. アプリケーションの生存確認
If Application Is Nothing Then Exit Function
‘ 2. アクティブウィンドウの有無(スライドショー中は取得不可)
On Error Resume Next
Dim activeWin As DocumentWindow
Set activeWin = Application.ActiveWindow
If Err.Number <> 0 Or activeWin Is Nothing Then
Err.Clear
Exit Function
End If
On Error GoTo 0
‘ 3. 編集モードの判定(スライド一覧やノート表示では操作不可とする)
If activeWin.ViewType <> ppViewNormal And _
activeWin.ViewType <> ppViewSlide Then
Exit Function
End If
‘ 4. オブジェクトの明示的解放
Set activeWin = Nothing
IsExecutionSafe = True
End Function
—
3. シニアエンジニアが意識する「メモリとライフサイクル」
VBAのガーベジコレクションは信用するな。特にアドイン開発では、`ActiveWindow` や `Selection` を何度も呼び出すとメモリリークの温床になる。
最適化の鉄則
1. オブジェクトのキャッシュ: `ActiveWindow` を毎回 `Application` 経由で取得してはならない。一度変数に格納し、処理が終われば即座に `Nothing` を代入して参照カウントを減らす。
2. 遅延バインディングの活用: クライアント環境のOfficeバージョンが混在する場合、早期バインディング(参照設定)はトラブルの元だ。徹底して `Object` 型で受け、必要に応じて判定を行うことで、バージョン間の依存関係を排除する。
3. On Error Resume Next の限定: `On Error` を使う際は、必ず「対象の数行」だけに限定すること。広範囲に書くのは、バグを闇に葬る行為だ。
—
4. 実践:図形操作を行う際の「真・ガード」
例えば、選択中の図形に対して何かを行う場合、以下のように実装する。
Public Sub SafeShapeProcess()
‘ ガード句で即時リターン
If Not IsExecutionSafe() Then
MsgBox “現在この操作は実行できません。”, vbCritical
Exit Sub
End If
‘ 厳密な型判定
Dim sel As Selection
Set sel = Application.ActiveWindow.Selection
‘ Selection.TypeがppSelectionShapesであることを確認
If sel.Type = ppSelectionShapes Then
‘ ここで初めて処理を行う
Debug.Print “選択された図形の数: ” & sel.ShapeRange.Count
Else
MsgBox “図形を選択してから実行してください。”
End If
‘ オブジェクトの解放
Set sel = Nothing
End Sub
—
結論:コードは「環境との対話」である
VBAが「古い技術」だと侮る者は、結局のところ「実行される環境の重み」を理解していない。PowerPointはマルチスレッド環境ではないが、ユーザーの操作(UIイベント)が非同期的に割り込んでくる環境だ。
今日紹介したガード句は、単なるエラー回避ではない。「システムが制御できない外部要因を、開発者の制御下に置く」ための境界線である。
この境界線を適切に引ける者だけが、配布しても問い合わせでパンクしない、真にプロフェッショナルなアドインを構築できる。コードを書く前に、まず「どこで、どんな状態だと、何が起きるか」を想像せよ。それが伝説への入り口だ。
