【入門編】【上級】Application.EventsEnabledを制御した無限ループ回避:イベント駆動型処理の安全な実装 – Visio VBA解析バイブル

スポンサーリンク

こんにちは! Visio VBAの世界へようこそ。
マクロの記録ボタンを押して、生成されたコードを眺めて「ふむふむ……」と頷くフェーズはもう卒業しましたか?おめでとうございます。ここから先は、Visioという巨大なドキュメントエンジンの心臓部に直接ダイブし、思い通りの自動化システムを組み上げる「本物のエンジニア」としての領域です。

さて、今日私たちが直面するのは、Visio VBA中級者から上級者への登竜門であり、避けて通れない最大の罠――「イベント駆動型プログラミングにおける無限ループの恐怖」です。

「図形を動かしたら、自動で連動する別の図形も動かしたい」
そんな野心的な試みを始めた瞬間、Visioがフリーズし、ファンがうなりを上げ、タスクマネージャーで強制終了する……。あなたもそんな経験はありませんか?

大丈夫。今日、その謎と完璧な解決策を完全にマスターしましょう。ここをクリアすれば、あなたのVisio VBAスキルは一気にプロの領域へと引き上げられますよ!

—

1. なぜ「イベントの連鎖」でVisioは崩壊するのか?

Visioの真骨頂は、ユーザーの操作やプログラムの変更に反応して処理を実行する「イベント駆動(Event-Driven)」にあります。例えば、「Shape(図形)が変更されたら(`ShapeChanged`)、そのプロパティを読み取って別の処理をする」といった具合です。

ここで、少し想像してみてください。

1. あなたがVBAで、ある図形Aのサイズを変更した。
2. Visioが「おっ、図形Aが変更されたぞ!」と検知し、あなたが仕込んだイベントプロシージャ(監視役)を呼び出す。
3. そのイベントプロシージャの中で、「図形Aが変わったんだから、ついでに図形Aの色も赤に変えよう!」と、再びコードで図形Aを変更する。
4. 【悲劇】 Visio「また図形Aが変わったぞ!」 ⇒ 2に戻る。

これが、無限ループの正体です。プログラムは自らの手で自分の尻尾を噛み続け、CPUを100%食いつぶした挙句、あえなくメモリ不足で沈没します。Visioのイベントシステムは、自分自身が引き起こした変更であっても、区別なく「新たなイベント」として拾ってしまう素直すぎる性格をしているのです。

—

2. 救世主:`Application.EventsEnabled` の正体

この暴走を防ぐためにVisioが用意してくれた絶対的なブレーキ、それが `Application.EventsEnabled` プロパティです。

  • `True`(デフォルト):イベントの監視が有効。Visioのあらゆる変化を敏感にキャッチします。
  • `False`:イベントの監視を一時停止。この状態の間は、VBAがどんなに図形をいじくり回そうとも、Visioは「我関せず」とイベントを発火させません。

つまり、「イベントが発生する ⇒ ブレーキを踏む(`False`にする) ⇒ 安全に図形を書き換える ⇒ ブレーキを解除する(`True`に戻す)」という黄金のパターンを作れば、無限ループの恐怖から完全に解放されるというわけです。

—

3. 実践!安全なイベント制御の実装コード

百聞は一見に如かず。実際に、図形が変更されたときに安全にプロパティを書き換えるコードの骨組みを見てみましょう。

今回は、ThisDocumentモジュールに記述するイベントハンドラの例です。

‘ =================================================================
‘ 模块: ThisDocument (または Visioのイベント用クラスモジュール)
‘ =================================================================

Private Sub Document_ShapeChanged(ByVal Shape As IVShape)

‘ 1. 【超重要】エラー発生時でも必ずイベントを復旧させるための防衛策
On Error GoTo ErrorHandler

‘ 2. すでにイベント処理の最中であれば、二重実行を防ぐために即座に抜け出す
‘ (※グローバル変数やStatic変数でフラグ管理するアプローチもありますが、
‘ 今回はよりプリミティブで確実な EventsEnabled を使います)

‘ 3. イベントの遮断(ブレーキを踏む!)
Application.EventsEnabled = False

‘ =================================================================
‘ 4. ここから安全地帯:自由に図形を操作しても無限ループしない
‘ =================================================================

‘ 例:変更された図形に特定のセリフ(プロパティ)を自動で書き込む
If Shape.Text <> “処理済み” Then
‘ この変更は EventsEnabled = False のおかげで ShapeChanged を再トリガーしない!
Shape.Text = “処理済み”

‘ 座標を少しずらすなどの追加処理も安全に行えます
‘ Shape.Cells(“PinX”).ResultIU = Shape.Cells(“PinX”).ResultIU + 0.1
End If

‘ =================================================================
‘ 5. 安全地帯ここまで
‘ =================================================================

ErrorHandler:
If Err.Number <> 0 Then
MsgBox “エラーが発生しました: ” & Err.Description, vbCritical, “イベント処理エラー”
End If

‘ 6. 【絶対必須】処理の最後(エラー時含む)には必ずイベントを再有効化する!
Application.EventsEnabled = True

End Sub

コードの解説とエンジニアの心得

1. `On Error GoTo ErrorHandler` の絶対性
もし `EventsEnabled = False` にした状態でコード内に予期せぬエラー(ゼロ除算やオブジェクトが存在しない等)が発生し、そのままプログラムが中断したらどうなるでしょうか?
Visioのイベントは永遠にオフのままになり、あなたのVisioは一切のイベントに反応しない「ゾンビ状態」になります。これを防ぐため、エラーハンドリングはセットで記述するのが鉄則です。
2. 必ず `True` で戻す
処理の最後、およびエラーハンドラーの通過時には、必ず `Application.EventsEnabled = True` を実行して元の世界に戻しましょう。

—

4. 陥りがちな罠とさらなる高みへ

この `EventsEnabled` ですが、実は「アプリケーション全体(Applicationレベル)」のスイッチです。つまり、あなたがこのコードを実行している間に、裏で開いている別の図面ファイル(Document)のイベントも同時に遮断されることになります。

通常の自動化ツールやアドイン開発であればこれで全く問題ありませんが、複数のドキュメントが複雑に絡み合う巨大なシステムを構築する場合は、影響範囲を意識する必要があります。

また、クラスモジュール(`VisEventProc` を実装する高度な方法)を使う場合も、基本の哲学は全く同じです。「イベントの中でさらに図形やドキュメントの状態を変化させるなら、必ず一時的にイベントの火を消せ」。この鉄則さえ守れば、Visio VBAで制御できない領域はありません。

—

まとめ:さあ、実務の自動化へ飛び出そう!

今回は、Visio VBAの根幹をなす「イベント駆動の安全な管理」について解説しました。

  • Visioのイベントは、自分自身の変更をもトリガーしてしまう。
  • 無限ループを防ぐためには、`Application.EventsEnabled = False` で一時的にブレーキを踏む。
  • エラー時でも確実にイベントを復旧させるため、`On Error` と組み合わせる。

ここをクリアしたあなたなら、もうマクロの記録に頼る必要はありません。図形が意思を持っているかのようにダイナミックに連動する、洗練されたVisioソリューションをご自身の手で組み上げることができるはずです。

分からないことがあれば、いつでもまたこのブログに帰ってきてください。
あなたのVBAライフが、エレガントでバグのない素晴らしいものになりますように。それではまた!

タイトルとURLをコピーしました