Visio VBAの深淵:Shape.IDの幻想を捨て、UniqueIDによる「不変のトレーサビリティ」を実装せよ
業務自動化の現場で、Visioを単なる作図ツールとして扱っているうちは二流だ。Visioは「空間情報を保持したデータストア」である。
多くのエンジニアが犯す致命的なミスがある。それは`Shape.ID`をDBの主キーとして扱ってしまうことだ。`.vsdx`の再保存、ページの複製、あるいはグループ化の解除。これらの操作一つでIDは容易に書き換わる。IDは「その瞬間のポインタ」に過ぎず、永続的なアイデンティティではない。
真に堅牢なシステムを構築したいなら、`Shape.UniqueID`(GUID)こそが唯一の拠り所となる。今日は、この「Visioオブジェクトの魂」を追跡するためのアーキテクチャを語る。
—
1. なぜ Shape.ID を信じてはいけないのか
Visioの内部構造において、`Shape.ID`はインデックスに過ぎない。ドキュメントの再構築時にページ内の順番が変われば、IDは即座に再割り当てされる。
一方、`Shape.UniqueID`は、`visGetOrMakeGUID`を用いて生成される、そのシェイプに永続的に紐付くGUIDである。これを活用することで、Visioの図面と外部のSQL ServerやNoSQLデータベースを、再保存後も寸分の狂いなく同期させることが可能になる。
2. 永続ID生成の実装:技術的指針
`Shape.UniqueID`を取得する際、未割り当ての場合はエラーを吐くか、あるいは明示的に生成させる必要がある。以下のコードは、既存のIDを確実に取得し、存在しない場合は即座に生成して確保する、実戦仕様のルーチンだ。
‘ @description: シェイプから永続IDを取得。なければ生成する。
‘ @param shp: 対象のShapeオブジェクト
‘ @return: GUID文字列
Public Function GetPersistentID(ByVal shp As Visio.Shape) As String
On Error GoTo ErrHandler
Dim strGuid As String
‘ すでにGUIDが割り当てられているか確認
strGuid = shp.UniqueID(visGetOrMakeGUID)
GetPersistentID = strGuid
Exit Function
ErrHandler:
‘ 予期せぬエラーは握り潰さず、スタックトレースを意識してログに叩き込む
Debug.Print “Error in GetPersistentID: ” & Err.Description
GetPersistentID = “”
End Function
—
3. シニアエンジニアが意識すべき「メモリとパフォーマンス」
VisioのCOMオブジェクトは、安易に`.`(ドット)で繋いでプロパティを呼び出すと、内部で無数のオブジェクトが生成され、メモリリークを誘発する。特に大規模なフロー図を解析する場合、このコストは無視できない。
オブジェクトの明示的解放とキャッシュ戦略
ループ内で頻繁に`shp.UniqueID`を叩くのは愚策だ。必要な場合は一度ローカル変数に格納せよ。また、`Application`や`Document`といったルートオブジェクトをループの中で参照し続けることは避けろ。
‘ 最適化されたシェイプ走査例
Public Sub ProcessShapes(ByVal pg As Visio.Page)
Dim shps As Visio.Shapes: Set shps = pg.Shapes
Dim i As Long
Dim shp As Visio.Shape
‘ 繰り返し処理ではIDをキャッシュし、COM呼び出し回数を最小化する
For i = 1 To shps.Count
Set shp = shps.Item(i)
‘ 外部DBとの同期キーとしてGUIDを活用
Dim uid As String: uid = shp.UniqueID(visGetOrMakeGUID)
‘ ここで外部DBの更新クエリを叩く設計にする
‘ SyncToDatabase uid, shp.Text
‘ 参照の明示的クリア
Set shp = Nothing
Next i
Set shps = Nothing
End Sub
—
4. 外部システム連携のための設計思想
UniqueIDを活用する最大の利点は、「図面が何を指しているか」をVisioの外に定義できることにある。
1. Visio側: `Shape.UniqueID`をキーとして、カスタムプロパティ(Shape Data)にメタデータを格納。
2. 外部DB側: `UniqueID`を外部キーとして、詳細な仕様書や進捗状況を保持。
3. 同期プロセス: `visApp.DocumentSaved`イベントをトリガーに、差分のみを抽出してDBを更新する。
このアーキテクチャにより、図面ファイルそのものが「単なるビューアー」となり、実データはDBで一元管理されるという、モダンなシステム構成が完成する。
—
5. 最後に:伝説のアーキテクトからの助言
レガシーなVBA環境であっても、現代的な設計思想を適用することは可能だ。
「動けばいい」というコードは、1年後の自分を殺す。`Shape.ID`に依存したコードは、仕様変更の一撃で崩れ去る砂上の楼閣だ。
`UniqueID`を導入せよ。そして、Visioを単なる描画ソフトから、データ駆動型のエンタープライズ・アセットへと昇華させるのだ。
技術とは、魔法ではなく論理の積み重ねである。美しく、かつ強靭な設計を心がけろ。以上だ。
