【実務・中級編】【中級】マスターシェイプのドロップイベントをフックして自動設定を行う – Visio VBA解析バイブル

スポンサーリンク
スポンサーリンク

Visio VBAを掌握する:マスターシェイプ・ドロップイベントを制し、自動設計の「聖域」を築く

Visioで「シェイプを配置するたびにプロパティを入力する」という手作業を繰り返しているなら、それはエンジニアとして敗北だ。

業務自動化の現場において、Visioは単なる作図ソフトではない。「データと図形の同期エンジン」であるべきだ。今回解説するのは、シェイプがドロップされた瞬間にVBAを割り込ませ、自動でメタデータやスタイルを注入する「イベント駆動型アーキテクチャ」の核心である。

中途半端なコードは、ドキュメントの肥大化やクラッシュの温床となる。本気で「使える」システムを構築するための極意を伝授しよう。

1. なぜ「EventSink」が必須なのか?

初心者はよく「タイマーで全シェイプを監視する」といった愚策を講じるが、これはパフォーマンスの自殺行為だ。我々が使うべきは `Visio.EVisioEventCodes.visEvtAdd` をフックするイベントシンク(EventSink)である。

これを使えば、システムは「配置された瞬間」だけをピンポイントで監視し、それ以外の時間はCPUリソースを一切消費しない。

2. 堅牢な設計:クラスモジュールによるイベントハンドリング

標準モジュールにイベント処理を書くのは、保守性の観点から最悪だ。イベントハンドラを制御するための「クラスモジュール」を分離し、ライフサイクルを管理せよ。

手順1:クラスモジュール `clsDropHandler` を作成する

' クラスモジュール: clsDropHandler
Option Explicit

Private WithEvents m_vsoApp As Visio.Application
Private m_sink As Visio.EventList

' イベントの初期化
Public Sub Init(app As Visio.Application)
    Set m_vsoApp = app
    ' Applicationレベルで「シェイプの追加」イベントをフックする
    Set m_sink = m_vsoApp.EventList.Add(visEvtAdd + visEvtShape, visActCodeRunVBA, "OnShapeDropped")
End Sub

' イベント発生時の処理は標準モジュールのプロシージャに委譲する

手順2:標準モジュールで処理を実装する

ここで重要なのは、「どのシェイプがドロップされたのか」を確実に特定することだ。`Application.EventInfo` を活用する。

' 標準モジュール: modEventProcessor
Option Explicit

Public Sub OnShapeDropped()
    Dim vsoShape As Visio.Shape
    Dim eventInfo As String
    
    ' イベント発生源のシェイプを取得
    eventInfo = Visio.Application.EventInfo(visEvtIdMostRecent)
    Set vsoShape = Visio.Application.ActivePage.Shapes.ItemFromID(CLng(eventInfo))
    
    ' マスターシェイプ名で判定(フィルタリング)
    If vsoShape.Master Is Nothing Then Exit Sub
    
    Select Case vsoShape.Master.Name
        Case "サーバー装置"
            Call ApplyServerDefaults(vsoShape)
        Case "ルーター"
            Call ApplyNetworkDefaults(vsoShape)
    End Select
End Sub

Private Sub ApplyServerDefaults(shp As Visio.Shape)
    ' エラーハンドリングは必須
    On Error Resume Next
    ' プロパティの自動注入
    shp.Cells("Prop.Status").Formula = Chr(34) & "稼働中" & Chr(34)
    shp.Cells("Prop.InstalledDate").Formula = Chr(34) & Format(Date, "yyyy/mm/dd") & Chr(34)
End Sub

3. 現場で「バグ」を生ませないための3つの鉄則

① イベントの二重登録を阻止せよ

`Application.EventList.Add` を不用意に呼び出すと、イベントが多重登録され、同じシェイプを置くたびに処理が10回、20回と走る地獄を見る。`Init` プロシージャを呼ぶ際は、必ず既存のイベントを確認するか、フラグ管理を行うこと。

② データベース・外部連携の落とし穴

ドロップと同時にDBへアクセスするのは、通信ラグによりVisioのUIをフリーズさせる原因になる。「遅延読み込み」あるいは「ローカルキャッシュ(DictionaryやCollection)」を介して処理せよ。API通信が必要な場合は、非同期処理を検討するか、まずはローカルでデータを完結させる設計にすべきだ。

③ ユーザー定義セル(ShapeSheet)を信じろ

シェイプの属性をVBAの変数で管理しようとするな。必ず ShapeSheetの `User` セルや `Prop` セルに書き込むこと。Visioは図形データ構造そのものがデータベースである。この原則を無視すると、保存・再読み込みのたびにデータが消失する羽目になる。

結論:自動化は「設計」で決まる

今回紹介したイベント駆動モデルは、単なるコードのコピペ以上の価値がある。それは、「操作者のミスを未然に防ぐインフラ」を構築することと同義だ。

「なぜこの処理を自動化するのか?」
「この設定が漏れると誰が困るのか?」

その問いに対する答えがコードに宿っているとき、あなたのVBAは単なるスクリプトから、組織を支える強力なツールへと進化する。

さあ、コードを開け。手作業を根絶し、エンジニアとして本来注力すべき「設計」の時間を取り戻すのだ。何か技術的な壁に突き当たったら、またいつでも戻ってくるといい。この戦場には、常に我々のようなアーキテクトが必要なのだから。

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