【入門編】Application.OnComponentEnterStateの検知によるモーダルダイアログ表示中のVBA誤作動・フリーズ防止策 – Visio VBA解析バイブル

スポンサーリンク

こんにちは!Visioのオートメーションの世界へようこそ。
マクロの記録ボタンを押して「なんとなくコードはできたけれど、少し複雑なことをさせようとするとすぐにVisioがフリーズする……」そんな壁にぶつかっていませんか?

今回は、Visio VBAの根幹をなすオブジェクトモデルの基礎を押さえつつ、現場のプロが必ず直面する「モーダルダイアログによるフリーズの罠」を回避する実践的なテクニックを伝授します。

ここをクリアすれば、あなたの書くマクロは「おもちゃ」から「業務に耐えうる頑健なシステム」へと生まれ変わります。さあ、一緒に扉を開けましょう!

1. Visio VBAの基礎:オブジェクトモデルのピラミッドを理解する

VBA(Visual Basic for Applications)でVisioをコントロールするということは、Visioという巨大なビルの中にある「部屋」や「家具」を順番に指定して、お片付けや模様替えをするようなものです。

Visioのオブジェクトモデルは、頂点に君臨する王様から、一番末端のパーツまで、綺麗に階層構造(ピラミッド)になっています。

👑 Application (Visioアプリそのもの)
└ 📂 Document (開いている図面ファイル)
└ 📄 Page (図面のページ)
└ 🔷 Shape (図形・文字・グループなど)

  • `Application`: あなたが操作しているVisioのウィンドウそのものです。
  • `Document`: 今開いている `.vsdx` などのファイルです。
  • `Page`: そのファイルの中にある「ページ1」「ページ2」です。
  • `Shape`: ページ上にポツンと置かれた四角形や、コネクタ、テキストなどの個々の図形です。

例えば、「現在開いている図面の、1ページ目にある、最初の図形の色を赤に変えたい!」という場合、コードは自然とこのピラミッドを上から順に降りていく形になります。

‘ オブジェクトの階層をドット(.)で繋いで指定する基本形
ActiveDocument.Pages(1).Shapes(1).CellsSRC(visSectionObject, visRowShape, visFillForegnd).ResultIU = 2
‘ ※上記は一例です。色を赤にするなど

この「今、どのオブジェクトを触っているのか」を意識することが、Visio VBAマスターへの第一歩です。

2. 現場の恐怖!「モーダルダイアログ・フリーズ」の正体

さて、ここからが本題です。
Visioを使っている最中、例えば「印刷」ボタンを押したり、「名前を付けて保存」のダイアログが開いたり、あるいはページ設定のプロパティ画面が開いたときのこと。

画面の向こうで、ユーザーが「OK」を押すまで、Visioのメイン画面はカチコチに固まりますよね。これがモーダル(Modal)状態です。

なぜVBAでフリーズが起きるのか?

あなたが組んだタイマー処理や、外部からのイベントトリガーによって、「Visioがダイアログで入力待ちをしている最中」にVBAコードが割り込んで実行されてしまったとします。

Visioのエンジンは「今、ユーザーからのモーダル入力を待っているから、他のことは一切受け付けません!」の状態です。そこにVBAから「この図形のテキストを変えて!」なんて命令を投げると、Visioの心臓部はパニックを起こし、容赦なく「応答なし(フリーズ)」に陥ります。

マクロの記録から脱却した初学者が、自動化スクリプトを組んだときに一番ハマる「原因不明の固まり現象」の大半はこれが原因です。

3. 解決策:`Application.OnComponentEnterState` で状態を監視せよ!

「じゃあ、ダイアログが開いているかどうかをどうやって検知するの?」
ここで登場するのが、今回の主役である `Application.OnComponentEnterState` です。

……と言いたいところですが、実はVisioの標準VBAイベントには、モーダルダイアログの開閉を直接キャッチしてキャンセルするような都合の良い魔法のスイッチはありません。

代わりに、私たちは「Visioがモーダル状態に入ったこと(あるいは処理を実行してよい状態か)を安全にハンドリングする設計パターン」を身につける必要があります。

実務で使える、最も確実でエレガントな「安全装置付きマクロのテンプレート」を伝授しましょう。

実装コード:安全設計のテンプレート

以下のコードを、標準モジュールに貼り付けてみてください。VBAを実行する前に「今、Visioが勝手に動いて危ない状態じゃないか?」をチェックするガード節(Guard Clause)の役割を果たします。

Option Explicit

‘ メインの処理を実行するプロシージャ
Sub SafeExecuteMyMacro()

‘ 【安全装置 1】Visioがモーダルダイアログ表示中、または編集ロック状態かチェック
If IsVisioBusy(Application) Then
MsgBox “現在、Visioでダイアログが開いているか、処理を実行できない状態です。” & vbCrLf & _
“ダイアログを閉じてから再度実行してください。”, vbExclamation, “実行中止”
Exit Sub
End If

‘ 【安全装置 2】画面描画をロックしてパフォーマンスを爆上げ&余計な干渉を防ぐ
Application.ScreenUpdating = False

On Error GoTo ErrorHandler

‘ — ここから実際のメイン処理 —
Dim shp As Visio.Shape
For Each shp in ActivePage.Shapes
‘ 例:すべての図形に名前をつける処理など
‘ shp.NameU = “ProcessedShape”
Next shp
‘ ———————————

MsgBox “処理が正常に完了しました!”, vbInformation
GoTo Finally

ErrorHandler:
MsgBox “エラーが発生しました: ” & Err.Description, vbCritical

Finally:
‘ 【後始末】必ず描画ロックを解除する
Application.ScreenUpdating = True

End Sub

‘ —————————————————————–
‘ Visioの現在の状態(ビジー状態やモーダルダイアログ表示の可能性)を判定する関数
‘ —————————————————————–
Function IsVisioBusy(visApp As Visio.Application) As Boolean

‘ 簡易的な判定:
‘ Visioオブジェクトモデルにおいて、モーダル画面が開いている最中は
‘ ドキュメントの操作や特定のプロパティアクセスでエラー(トラップ)が発生するか、
‘ または Applicationの特定のステータスに影響が出ます。

Dim isBusy As Boolean
isBusy = False

On Error Resume Next

‘ あえて現在のドキュメントのReadOnlyプロパティなどを叩いてみることで、
‘ Visioが完全にモーダルブロックされているかを検知するプローブ(探針)技術
Dim dummy As Boolean
dummy = visApp.ActiveDocument.ReadOnly

If Err.Number <> 0 Then
‘ エラーが発生する場合、Visioはダイアログ表示中などの異常・ビジー状態とみなす
isBusy = True
Err.Clear
End If

On Error GoTo 0

IsVisioBusy = isBusy

End Function

4. コードの解説:なぜこの書き方が「プロ仕様」なのか?

1. ガード節(`If IsVisioBusy(…) Then Exit Sub`)の徹底
処理の最初に「今、動いていい環境か?」を確認します。これにより、ユーザーが印刷ダイアログを出している最中にマクロが暴発してVisioがフリーズする悲劇を未然に防ぎます。
2. プローブ(探針)による状態チェック
VBAからあえて軽いプロパティ(`ActiveDocument.ReadOnly` など)にアクセスし、エラー(`Err.Number <> 0`)が返ってくるかどうかで、Visioの裏側の硬直状態をスマートに察知しています。
3. `ScreenUpdating = False` による防御壁
処理が実行できると判断されたら、画面描画をロックします。これにより、マクロ実行中の余計なユーザー操作(クリックなど)をシャットアウトし、誤作動を防ぎつつ処理速度を何倍にも跳ね上げることができます。
4. `Finally` ラベルによる確実な後始末
万が一エラーが起きた場合でも、必ず `Application.ScreenUpdating = True` が実行されるように `GoTo` 構文で後始末を保証しています。これがないと、処理後にVisioの画面がフリーズしたままのように見え、ユーザーをパニックにさせてしまいます。

まとめ:基礎の先にある「プロの配慮」をあなたに

今回は、Visio VBAの基礎であるオブジェクトモデルのおさらいから、現場で最も恐れられる「モーダルダイアログによるフリーズ」を回避するための安全設計までを解説しました。

動くコードを書くだけなら初心者でもできます。しかし、「どんな状況で実行されても絶対にVisioを落とさない、壊さない」というディフェンシブなコードを書けることこそが、優れた自動化エンジニアの証です。

ここをクリアしたあなたなら、もうマクロの記録の卒業生ではありません。
ぜひ、あなたの業務自動化ツールにこの安全設計を取り入れて、快適で堅牢なVisioライフを送ってくださいね!

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