Visio VBAを掌握する:イベント駆動による「リアルタイム自動化」の極意
多くのエンジニアがVisio VBAに挫折する理由は一つ。「ボタンを押して処理を開始する」という、あまりに原始的な設計に固執しているからだ。
真に自動化を極めるのであれば、ユーザーが図面をいじったその瞬間にシステムが呼応する「イベント駆動型アーキテクチャ」を構築しなければならない。今回は、Visioのオブジェクトモデルを深く理解し、堅牢な常駐型マクロを実装するための設計思想を伝授する。
—
1. なぜ「イベントハンドラ」が必要なのか
「Shapeが追加されたら自動でIDを振る」「プロパティが変わったら外部DBと同期する」。これらをタイマー監視(`OnTime`)で実装するのは悪手だ。CPUリソースの無駄であり、何よりユーザーの操作と同期が取れず、不整合の温床となる。
我々が狙うべきは、`Application`および`Document`レベルで発行される「イベント」をフックすることだ。これにより、Visioの内部エンジンが変更を検知した「その瞬間」に、貴方のロジックを割り込ませることができる。
—
2. 堅牢な設計のための「クラスモジュール」活用
標準モジュールにイベントコードを書いて満足しているなら、今すぐ捨ててほしい。イベント管理には必ず「クラスモジュール」を介在させる。
設計の鉄則:
1. シングルトン管理: イベントを検知するクラスを`Application`レベルで保持する。
2. イベントの遮断: 自身の処理で「変更」が発生し、それがまたイベントを誘発する「イベントの再帰ループ」を制御する。
3. エラーハンドリング: イベント内で未処理の例外が発生すると、Visio自体がクラッシュする可能性がある。全ての処理を `On Error GoTo` で囲うのがプロの最低ラインだ。
—
3. 実装コード:常駐型イベント監視の実用雛形
以下は、図形が追加された瞬間にその名前を検知し、ログを吐き出す最小構成のテンプレートだ。
クラスモジュール名:`clsVisioMonitor`
Option Explicit
‘ Applicationイベントを監視するためのオブジェクト
Public WithEvents AppEvents As Visio.Application
‘ 図形追加イベントのハンドラ
Private Sub AppEvents_ShapeAdded(ByVal Shape As IVShape)
On Error GoTo ErrorHandler
‘ イベント再帰防止用のフラグ制御などが必要な場合はここに記述
Debug.Print “検知: 図形が追加されました – ” & Shape.Name
‘ ここにデータベース連携や属性更新のロジックを注入する
‘ 例: Shape.Cells(“Prop.Status”).Formula = “””Active”””
Exit Sub
ErrorHandler:
Debug.Print “Error in ShapeAdded: ” & Err.Description
End Sub
標準モジュール:`modMain`
Option Explicit
‘ クラスのインスタンスを保持するグローバル変数(これが常駐する)
Public monitor As clsVisioMonitor
Public Sub InitializeMonitor()
‘ インスタンスを生成し、Visio Applicationを紐付ける
Set monitor = New clsVisioMonitor
Set monitor.AppEvents = Application
MsgBox “監視システムを起動しました。”
End Sub
—
4. プロダクション環境における「3つの注意点」
実務でこのアーキテクチャを運用する場合、以下の落とし穴を回避しなければならない。
① イベントの再帰呼び出し(Stack Overflowの回避)
イベントハンドラ内で図面を変更すると、再びそのイベントが発火する。これを防ぐには、処理の開始直後に `Application.EnableEvents = False` を設定し、処理終了後に `True` に戻すという「防波堤」を必ず設置すること。
② Visioの終了とメモリ解放
`Application`レベルのイベントを掴んでいると、Visioが正常に終了できなくなるケースがある。必ず `Document_BeforeDocumentClose` などのイベントで、変数の解放(`Set monitor = Nothing`)を明示的に行う習慣をつけよ。
③ 外部DB/ファイル連携のレイテンシ
イベントハンドラはVisioのメインスレッドで動作する。ここで重い外部DBへの接続処理などを同期的に書くと、図面の操作感が著しく低下する。通信が必要な場合は、処理を非同期にするか、キューに入れてバッチ処理を行うのがアーキテクトとしての判断だ。
—
結論:自動化は「受動」から「能動」へ
イベント駆動をマスターした瞬間、貴方が作るツールは「単なるマクロ」から「Visioと一体化したシステム」へと昇華する。
まずは上記のテンプレートをコピペして、`ShapeAdded` イベントの挙動を体感してほしい。そこから先は、`CellChanged` や `BeforeSelectionDelete` といったイベントを組み合わせ、貴方の業務プロセスに特化した「生きているツール」を設計してほしい。
コードは嘘をつかない。設計の甘さだけがバグを生む。
次回の開発では、この「イベントの連鎖」を制御する設計思想をぜひ取り入れてみてほしい。それが、プロの業務自動化エンジニアとしての第一歩だ。
