Visio VBAの「死」を回避せよ:無限ループを遮断するイベント制御の鉄則
Visioの自動化において、イベント駆動プログラミングは諸刃の剣だ。`ShapeAdded`や`CellChanged`といったイベントをフックし、図形の配置や属性変更を自動化するのは強力だが、多くの開発者がここで躓く。
「図形を操作した瞬間に処理が再帰的に呼び出され、Visioがフリーズする(あるいはスタックオーバーフローで落ちる)」
これは、Visioのオブジェクトモデルを深く理解していない初心者が必ず通る「通過儀礼」である。しかし、プロフェッショナルな現場において、このバグは許されない。今回は、`Application.EventsEnabled`を駆使し、イベントの再帰発火を完璧に封じ込める堅牢なアーキテクチャを伝授する。
—
なぜ「無限ループ」は起きるのか?
Visioのイベントモデルは、あなたのコードによる「変更」をも「ユーザーによる変更」と区別しない。
1. `ShapeAdded` イベントが発火する。
2. イベントハンドラ内で、図形にメタデータを書き込む(`Cell.Formula`等を変更)。
3. その変更がトリガーとなり、再度 `ShapeAdded` または `CellChanged` が発火する。
4. 1に戻る。
これが「Visioが死ぬ」メカニズムだ。この連鎖を物理的に遮断する唯一の安全弁が `Application.EventsEnabled` プロパティである。
—
現場で使うべき「鉄壁」のイディオム
単にフラグをオフにするだけでは不十分だ。エラー発生時にフラグが「オフのまま」になると、その後のVisio操作が一切イベントを受け付けなくなるという、別の深刻なバグを生む。
必ず 「例外処理(Error Handling)で確実に復帰させる」 構造を維持すること。
実装例:堅牢なイベントハンドラ
‘ クラスモジュール (例: EventSink)
Private WithEvents AppEvents As Visio.Application
Private Sub Class_Initialize()
Set AppEvents = Visio.Application
End Sub
Private Sub AppEvents_ShapeAdded(ByVal Shape As IVShape)
‘ 1. イベント処理を一時停止
Dim oldEventsEnabled As Boolean
oldEventsEnabled = Visio.Application.EventsEnabled
Visio.Application.EventsEnabled = False
On Error GoTo Cleanup
‘ — ここからが実務処理 —
‘ 図形操作を行っても、再帰的なイベント発火は起きない
Shape.Cells(“Prop.Status”).Formula = “””Initialized”””
‘ — 実務処理ここまで —
Cleanup:
‘ 2. 異常終了時も必ずイベントを有効化して戻す
Visio.Application.EventsEnabled = oldEventsEnabled
‘ エラーが発生した場合はスタックトレースを残す等の処理
If Err.Number <> 0 Then
Debug.Print “Error in ShapeAdded: ” & Err.Description
End If
End Sub
—
アーキテクトからの助言:3つの設計原則
このコードをプロダクション環境に実装する際、以下の3点を意識してほしい。
1. 処理の最小化
`EventsEnabled = False` の範囲は、必要最低限のコードに限定せよ。このフラグをオフにしている間、Visioは他の重要なイベントもすべて無視する。処理が長すぎると、ユーザーの操作性が低下するだけでなく、外部データベース連携などの非同期処理との整合性が取れなくなる。
2. 状態管理の局所化
大規模なツールを作る場合、`EventsEnabled` をグローバル変数で管理するのは悪手だ。上記のようにクラスモジュールでイベントをカプセル化し、そのクラス内でフラグの状態を完結させること。これにより、複数のアドインやマクロが混在しても干渉を防げる。
3. データベース連携時の落とし穴
図形情報と外部DB(SQL Server等)を連携させる際、イベント内でDB更新を行うケースが多いだろう。もしDB接続がタイムアウトした場合、`EventsEnabled` が `False` のままコードが止まると、そのVisioファイルは「イベントを受け付けないゾンビ状態」になる。
DB通信は必ずタイムアウト制御を入れ、エラーハンドラを通るように設計すること。
—
まとめ:エンジニアの誇りとして
「とりあえず動く」コードを書くのは容易い。しかし、「異常系でも決して死なない」コードを書くことこそが、業務自動化エンジニアの付加価値だ。
Visioのイベントモデルは強力だが、その制御権を握っているのはあなた自身だ。`EventsEnabled` を適切にハンドリングし、再帰処理を支配下に置くこと。それができれば、あなたの作るツールは、チームにとって「信頼できる自動化エンジン」となるだろう。
次は、このイベントハンドラをいかにして「永続的なAdd-in」としてパッケージングし、保守性を高めるかについて議論したいところだが、それはまた別の機会にしよう。まずは今のコードの安全性を再確認してほしい。
