PowerPoint VBAを掌握する:ミリ秒単位の「スライドショー・イベント監視」アーキテクチャ
PowerPointの標準機能に頼る時代は終わった。プレゼンテーションの現場において、「スライドが切り替わったか」「何ミリ秒経過したか」を正確に制御したいという要求は、高度な自動化やインタラクティブなデモにおいて不可欠なピースだ。
しかし、VBAの `OnSlideShowPageChange` だけでは、イベントの捕捉が遅延し、ミリ秒単位の厳密な同期は不可能に近い。ここでは、Windows API(`Winmm.dll`)の高精度タイマーと、`WithEvents` を組み合わせた「常駐監視システム」の構築術を伝授する。
—
1. なぜ「標準機能」では足りないのか
PowerPointのイベントモデルは、UIスレッドの優先順位に依存する。スライド切り替えのトリガーは、描画プロセスが完了した後に発火するため、厳密な時間計測には数ミリ秒から数十ミリ秒の「ゆらぎ(ジッター)」が生じる。
シニアエンジニアとして突き詰めるべきは、「イベントを待つ」のではなく、「メモリ空間に常駐するタイマーがイベントを監視する」というアーキテクチャへの転換である。
—
2. 実装:高精度タイマー・イベント・コントローラー
まずは、スライドショーのライフサイクルを監視する `Class Module` を作成する。
クラスモジュール:`clsSlideShowMonitor`
‘ プロジェクト名: PPSlideController
‘ 目的: Windows APIを用いたミリ秒単位の監視とスライドショーイベントの連結
Option Explicit
Private Declare PtrSafe Function timeGetTime Lib “winmm.dll” () As Long
Public WithEvents App As Application
Private m_StartTime As Long
‘ スライドショー開始時の初期化
Private Sub App_SlideShowBegin(ByVal Wn As SlideShowWindow)
m_StartTime = timeGetTime()
Debug.Print “監視開始: ” & m_StartTime
End Sub
‘ ページ切り替え時の厳密なミリ秒計測
Private Sub App_SlideShowNextSlide(ByVal Wn As SlideShowWindow)
Dim currentTime As Long
currentTime = timeGetTime()
‘ 経過時間をミリ秒で算出
Debug.Print “切替時間: ” & (currentTime – m_StartTime) & ” ms”
End Sub
‘ 終了時のメモリ解放(重要)
Private Sub App_SlideShowEnd(ByVal Pres As Presentation)
m_StartTime = 0
End Sub
—
3. オブジェクトライフサイクルの管理(メモリリークの排除)
VBAにおいて最も忌むべきは、`WithEvents` オブジェクトの「ゾンビ化」だ。プレゼンテーションを閉じてもインスタンスがメモリに残り続け、次回実行時に二重イベントが発生するバグは、レガシー環境の保守担当者が最も頭を悩ませるポイントである。
標準モジュール:`modEntryPoint`
Option Explicit
Private m_Monitor As clsSlideShowMonitor
‘ シングルトンパターンで監視インスタンスを制御
Public Sub StartMonitoring()
If m_Monitor Is Nothing Then
Set m_Monitor = New clsSlideShowMonitor
Set m_Monitor.App = Application
End If
End Sub
‘ 明示的な終了処理
Public Sub StopMonitoring()
Set m_Monitor.App = Nothing
Set m_Monitor = Nothing
End Sub
—
4. プロフェッショナルのための深掘り考察
1. タイマーの精度とパフォーマンス
`timeGetTime` はシステム起動時からの経過時間をミリ秒で返すため、高頻度の呼び出しにも非常に軽量である。もし、より厳密なパフォーマンス計測が必要な場合は `QueryPerformanceCounter`(QPC)を検討すべきだが、VBAの実行オーバーヘッドを考慮すれば `timeGetTime` が最もバランスが良い。
2. イベントループの汚染を防ぐ
`SlideShowNextSlide` 内で重い処理(外部API呼び出しやDB書き込み)を行ってはならない。イベント内で処理を行うと、PowerPointのUIスレッドをブロックし、プレゼン自体がフリーズする。処理は必ず別スレッドまたは非同期キューへ投げる設計が、システム間連携の鉄則だ。
3. レガシー環境での保守性
64bit版Office環境では `PtrSafe` 属性が必須である。古い32bitコードをそのまま移植して「動かない」と嘆くのは素人の仕事だ。常に `VBA7` コンパイル定数を使用して、クロスプラットフォームでの互換性を担保すること。
If VBA7 Then
Private Declare PtrSafe Function timeGetTime Lib “winmm.dll” () As Long
Else
Private Declare Function timeGetTime Lib “winmm.dll” () As Long
End If
—
結論:自動化の真髄
スライドショーを単なる「紙芝居」として扱うのではなく、「イベントを生成するデータソース」として捉えること。この視点を持つだけで、あなたのVBAコードはスクリプトの域を超え、堅牢なミドルウェアへと昇華する。
オブジェクトの解放を怠らず、イベントの連鎖を理解し、OSの深淵(API)にアクセスする。この一連の規律こそが、我々エンジニアがプロフェッショナルとして守るべき「聖域」である。
