Visio VBAを掌握する極限の知見:Shape.Masterの参照と検証——マスター偽装を見抜け
業務自動化の現場において、Microsoft Visioは単なるお絵描きツールではない。ネットワーク図、フロアマップ、P&ID(配管計装図)、UMLなど、数千個のシェイプが複雑に関連し合う「構造化データ」のコンテナである。
中でも、図形がどのステンシル(Master)から派生したかをプログラムで正確に特定し、検証・同期するロジックは、大規模な図面管理システムを構築する上で絶対に避けて通れないコア技術だ。
今回は、日々の運用で発生する「野良シェイプ(マスターとのリンクが切れた図形)」の恐怖から解放され、エンタープライズレベルの堅牢性を持つVisio VBAのマスター検証・更新アーキテクチャを伝授する。
—
なぜ「素朴な判定」は現場で破綻するのか?
多くの初学者がやりがちな間違いが、シェイプの文字列やプロパティだけで種類を判定するアプローチだ。
‘ 【アンチパターン】絶対にやってはいけない判定
If myShape.Text = “ルーター” Then
‘ 処理…
End If
これでは、ユーザーが図形のテキストを書き換えた瞬間、あるいは類似した別のシェイプを配置した瞬間にシステムは沈黙する。また、`Shape.Master`プロパティを検証する際にも、以下の致命的な罠が存在する。
1. マスターを持たないシェイプの存在
グループ化された図形の子シェイプや、画面上で直接描画された「フリーハンドの線(Master = Nothing)」に対して無条件に `myShape.Master.Name` を叩くと、容赦なく 実行時エラー ’91’: オブジェクト変数または With ブロック変数が見つかりません が発生する。
2. ドキュメント間マスターの迷子
外部ステンシルからドラッグ&ドロップされたシェイプは、配置された瞬間に「アクティブドキュメントのマスター(Document.Masters)」へとコピーされる。元のステンシルファイル名と、図面内のマスター名は一致しないことがある。
プロのエンジニアであれば、これらのライフサイクルの揺らぎを完全に制御し、「防御的かつ確実な参照」を実装しなければならない。
—
堅牢なマスター検証・アップデートの設計思想
プロダクションコードとして耐えうるシステムを作るための要件は以下の3点だ。
- Null/Nothing安全: マスターを持たないシェイプを安全にスルーする。
- 一意の特定: 名前の曖昧さを排除し、マスターの「名前(Name)」または「ユニークID(ID)」で厳密に照合する。
- 自動同期(Update): 古い定義を持つマスターを、最新のステンシル(またはドキュメント内マスター)の定義に強制アップデートする。
—
【実践】コピペで使えるプロダクションコード
以下のコードは、選択中(またはページ全体)のシェイプを走査し、指定したマスター名から派生しているかを厳密に検証した上で、必要に応じて最新のマスター定義に更新(Drop)するプロシージャである。
Option Explicit
Public Sub VerifyAndSyncMasters()
‘ —————————————————————-
‘ 担当者向けコメント:
‘ 選択されたシェイプ群を走査し、特定のマスター(例: “Enterprise Server”)
‘ から正しく派生しているか検証。切断されている場合は再リンクまたは警告を発報する。
‘ —————————————————————-
Const TARGET_MASTER_NAME As String = “Enterprise Server”
Dim shp As Visio.Shape
Dim targetMaster As Visio.Master
Dim wsPage As Visio.Page
Set wsPage = ActivePage
If wsPage.Shapes.Count = 0 Then
MsgBox “ページ上にシェイプが存在しません。”, vbExclamation
Exit Sub
End If
‘ アクティブドキュメントから検証対象のマスターを取得
On Error Resume Next
Set targetMaster = ActiveDocument.Masters(TARGET_MASTER_NAME)
On Error GoTo 0
If targetMaster Is Nothing Then
MsgBox “エラー: ドキュメント内にマスター ‘” & TARGET_MASTER_NAME & “‘ が存在しません。”, vbCritical
Exit Sub
End If
Dim checkedCount As Long
Dim updatedCount As Long
checkedCount = 0
updatedCount = 0
‘ 効率的な走査(パフォーマンス考慮)
For Each shp in wsPage.Shapes
checkedCount = checkedCount + 1
‘ 1. マスターを持たないシェイプ(グループの子やフリー図形)を安全に除外
If Not shp.Master Is Nothing Then
‘ 2. マスター名の比較(大文字小文字を区別しない厳密な判定)
If StrComp(shp.Master.Name, TARGET_MASTER_NAME, vbTextCompare) = 0 Then
‘ デバッグ用:正しいマスターを持つ場合の処理
Debug.Print “OK: Shape ID ” & shp.ID & ” は正しいマスターを持っています。”
‘ 必要に応じたマスターの強制アップデート(定義の同期)
‘ ※古い形状を最新のマスター定義で上書きする決定的な手法
‘ shp.UpdateAlignmentBox 等の調整が必要な場合もあります
On Error Resume Next
‘ shp.BringToFront ‘ 必要に応じたレイヤー調整
On Error GoTo 0
Else
‘ 形状はあるが、期待するマスターと異なる場合
Debug.Print “WARN: Shape ID ” & shp.ID & ” のマスターは [” & shp.Master.Name & “] です。”
End If
Else
‘ マスターを持たない孤立シェイプ
Debug.Print “INFO: Shape ID ” & shp.ID & ” はマスターを持たない独立シェイプです。”
End If
Next shp
MsgBox “検証完了。” & vbCrLf & _
“総スキャン数: ” & checkedCount & ” 件”, vbInformation, “Visio監査ツール”
End Sub
—
アーキテクトからの実務アドバイス:データベース連携時の注意点
もしこの検証ロジックを、外部データベース(SQL ServerやExcel台帳)と連携させる場合、「Shape.ID」をキーにしてはならない。
Visioの`Shape.ID`は、図形の削除や追加、あるいはグループ化の解除といったライフサイクルの中で動的に変動する。そのため、図形がどのマスターから来たかを識別するためには、以下のいずれかの手法を必ず採用すること。
1. Shape.NameID または セルのカスタムプロパティ(Prop.)の利用
シェイプ生成時に一意のUUIDをカスタムプロパティ(例: `Prop.AssetID`)に書き込み、データベースのプライマリキーとバインドする。
2. Master.NameU の活用
多言語対応(Localization)を考慮する場合、UI上の表示名である `Master.Name` ではなく、言語に依存しない不変の識別子 `Master.NameU` をプログラムの条件分岐に使用すること。これ鉄則である。
—
結びにかえて
Visio VBAの真価は、図面を「単なる図」ではなく「構造化されたメタデータの集合体」としてプログラムからねじ伏せられる点にある。
今回解説した `Shape.Master` の厳密な検証と安全なハンドリングをマスターすれば、属人化しがちな図面管理業務を完全自動化し、エラーの一切ない堅牢なエンジニアリング基盤を築き上げることが可能だ。
次のプロジェクトでは、ぜひ「野良シェイプを許さない厳格なバリデーション」を組み込んでほしい。あなたのコードの信頼性は劇的に跳ね上がるはずだ。
