【実務・中級編】【上級】Shape.UniqueIDによる永続的トラッキング:ファイル保存・再読み込み後も図形を追跡する – Visio VBA解析バイブル

スポンサーリンク

Visio VBAを掌握する極限の知見:Shape.UniqueIDによる永続的トラッキング

こんにちは。開発プロジェクトの現場で幾多のVisio自動化アーキテクチャを構築してきた私から、今日はVisio VBAにおける「最も深刻なデータ崩壊リスク」を回避するための極意を伝授しよう。

多くの開発者が、外部データベースやExcelとVisio図形を連携させる際、次のような安易なコードを書く。

‘ 【アンチパターン】絶対にやってはいけない図形特定
Dim shp As Visio.Shape
Set shp = ActivePage.Shapes.ItemU(“ProcessBox.12”)
shp.Text = “更新データ”

なぜ、この書き方が現場で破綻するのか?

Visioの `Shape.Name` や `Shape.NameID`(例: “ProcessBox.12″)は、ファイルを開き直したり、図形のコピー&ペースト、さらには図形の削除と追加を行ったりするだけで、いとも簡単に変化・再割り当てされる。この一時的な識別子に依存したシステムは、運用開始から数ヶ月で必ずデータ不整合を起こし、外部DBとのリンク切れという悪夢を引き起こす。

この地獄から抜け出す唯一にして最強の解が、`Shape.UniqueID` を用いた永続的トラッキングである。

今回は、ファイル保存や再読み込み、さらにはページ間移動をも超越して図形を完全に追跡する、プロダクション品質の堅牢な設計手法を公開する。

—

1. UniqueIDの本質とアーキテクチャ設計

UniqueIDとは何か?

Visioの `UniqueID` メソッドは、図形に対してグローバルに一意(あるいはページ内で一意)な GUID(UUID)を発行・取得する仕組みだ。名前やインデックスとは異なり、図形が別のページに移動しようとも、ファイルが保存・再読み込みされようとも、そのアイデンティティを死守する。

ただし、ここで重要な設計上の注意点がある。
`UniqueID` には取得・指定の方法によっていくつかのモード(`VisUniqueIDArgs`)が存在する。実務で最も安定するのは、ドキュメントスコープで一意のIDを取得する方式だ。

堅牢な連携システムのデータフロー

1. 初期化フェーズ: 図形生成時、または初回スキャン時に `UniqueID` を取得し、外部DBやShapeの `User-defined Cells`(カスタムセル)に永続化する。
2. 常時トラッキングフェーズ: ファイルを開き直した際、名前ベースではなく、保持している GUID(UniqueID)から `ActiveDocument.ShapesFromUniqueID` を使って図形オブジェクトを「逆引き」する。

—

2. 【プロダクションコード】UniqueIDによる完全追跡エンジン

以下のコードは、図形に独自のIDを付与して記憶させ、ファイル再読み込み後も正確にその図形を特定してプロパティを操作する実用モジュールである。コピペしてそのまま検証環境で試してほしい。

Option Explicit

‘ ==============================================================================
‘ モジュール名: MdlShapeTracker
‘ 概要: Shape.UniqueIDを利用した図形の永続的トラッキングと外部連携の模範実装
‘ ==============================================================================

‘ 1. 選択中の図形に永続IDをバインドし、イミディエイトウィンドウに出力するデモ
Public Sub BindUniqueIDToSelectedShapes()
Dim vsoSelection As Visio.Selection
Set vsoSelection = ActiveWindow.Selection

If vsoSelection.Count = 0 Then
MsgBox “対象の図形を選択してください。”, vbExclamation, “バリデーションエラー”
Exit Sub
End If

Dim shp As Visio.Shape
Dim uniqueIDStr As String

For Each shp In vsoSelection
‘ すでにIDが割り当てられているか確認、なければ新規発行
‘ visGetUniqueIDDataSet または visGetUniqueIDNone を使用
‘ ここでは標準的なドキュメントユニークIDを取得
uniqueIDStr = shp.UniqueID(visGetUniqueIDUnique)

‘ 開発者向けログ
Debug.Print “図形名: ” & shp.Name & ” | 発行されたUniqueID: ” & uniqueIDStr

‘ 【実務のコツ】
‘ 取得したUniqueIDを、図形のShapeSheet(Userセクション)に書き込んでおくと
‘ VBA側だけでなくShapeSheet数式からも参照できるようになり非常に堅牢になる。
Call SaveIDToShapeSheet(shp, uniqueIDStr)
Next shp

MsgBox vsoSelection.Count & ” 個の図形に永続IDをバインドしました。”, vbInformation, “完了”
End Sub

‘ 2. 【核心】保存・再読み込み後、UniqueIDから図形を完璧に復元して操作するデモ
Public Sub TrackAndModifyShapeByUniqueID()
‘ ※実際の運用では、このUniqueID文字列は外部DBやJSON、あるいは別シートから読み込む想定
Dim targetUniqueID As String
targetUniqueID = InputBox(“追跡したい図形のUniqueIDを入力してください:”, “UniqueID検索”, “{XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX}”)

If targetUniqueID = “” Or targetUniqueID = “{XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX}” Then Exit Sub

On Error GoTo ErrorHandler

Dim targetShp As Visio.Shape

‘ 【極意】ShapesFromUniqueIDメソッドを使い、ドキュメント全体から図形を逆引きする
‘ このメソッドはファイルを開き直した後でも、GUIDが一致する図形を正確に捕捉する
Set targetShp = ActiveDocument.ShapesFromUniqueID(targetUniqueID)

If targetShp Is Nothing Then
MsgBox “該当するUniqueIDを持つ図形は存在しません(削除された可能性があります)。”, vbCritical, “トラッキング失敗”
Exit Sub
End If

‘ 捕捉成功:図形が存在するページをアクティブにし、ハイライトしてテキストを変更
targetShp.ContainingPage.Activate
ActiveWindow.Select targetShp, visSelect

targetShp.Text = “【追跡成功】” & Format(Now, “hh:nn:ss”)
targetShp.Cells(“LineColor”).FormulaU = “RGB(255, 0, 0)” ‘ 赤枠に変更

MsgBox “UniqueIDによる図形の特定と更新に成功しました!”, vbInformation, “成功”
Exit Sub

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

‘ — 補助プロシージャ: ShapeSheetへのID永続化 —
Private Sub SaveIDToShapeSheet(shp As Visio.Shape, idStr As String)
Dim secIdx As Integer, rowIdx As Integer, cellIdx As Integer
secIdx = Visio.VisSectionIndices.visSectionUser

‘ User.ExternalGuid セルが存在するか確認、なければ追加
On Error Resume Next
cellIdx = shp.CellsU(“User.ExternalGuid”).Row
If Err.Number <> 0 Then
rowIdx = shp.AddRow(secIdx, visRowUser, visTagDefault)
shp.Section(secIdx).Row(rowIdx).Name = “ExternalGuid”
shp.CellsU(“User.ExternalGuid.Prompt”).FormulaU = “””External Database Link ID”””
End If
On Error GoTo 0

‘ セルにUniqueID文字列を格納(ダブルクォーテーションで囲む必要がある)
shp.CellsU(“User.ExternalGuid”).FormulaU = “””” & idStr & “”””
End Sub

—

3. 現場で嵌まりやすい罠とアーキテクトからの助言

罠1: 「図形の複製(コピペ)」時のUniqueIDの挙動

ユーザーがVisio上で図形をコピー&ペーストした際、Visioはデフォルトで新しいUniqueIDを自動生成する。これは重複を防ぐための仕様だ。
もし「マスタ図形とコピー先を同じIDで追跡したい」という要件がある場合は、ペーストイベント(`DocumentBeforeShapeAdd` 等)をフックし、必要に応じてUniqueIDを書き換えるロジックを組む必要がある。通常の外部DB連携であれば、コピー時に新規IDが発行される方が「別個の図形」として扱えるため都合が良いことが多い。

罠2: マスター図形(ステンシル)との混同

ステンシル内のマスター図形に対して `UniqueID` を取得しようとすると、期待通りに動作しない、あるいはエラーになる場合がある。`UniqueID` はあくまで「ドキュメント上のページに配置されたインスタンス(Shape)」に対して実行すべきものである。

—

総括

「動けばいい」というレベルのコードから脱却し、エンタープライズレベルの堅牢なVisio自動化を実現するためには、オブジェクトのライフサイクルを深く理解し、不安定なインデックスや名前に依存しない設計が不可欠である。

`Shape.UniqueID` をマスターしたあなたなら、ファイルがどう変形しようとも、外部DBのデータを完璧に図形へマッピングし続けるプロフェッショナルなソリューションを構築できるはずだ。

現場の信頼を勝ち取るクリーンで強靭なコードを、次のプロジェクトでもぜひ実装してほしい。

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