Visio接続解析の深淵:GluedShapesメソッドによる「物理的接続」の完全掌握
Visioを単なる作図ツールと呼ぶのは、エンジニアとしての怠慢だ。
Visioの本質は、空間的な配置情報を保持した「多次元グラフデータベース」にある。多くの開発者が `ConnectedShapes` メソッドの簡便さに逃げる中、プロフェッショナルなアーキテクトが直面するのは、「どのコネクタの、どの接続点(Glue)が、どのシェイプの、どのピンに刺さっているか」という、より厳密なトポロジー情報の欠如だ。
本稿では、`GluedShapes` メソッドを軸に、Visioの接続モデルを解体し、堅牢なシステムを構築するための極限の知見を共有する。
—
1. ConnectedShapes と GluedShapes の決定的な断絶
`ConnectedShapes` はあくまで「関係性」を抽象化したラッパーに過ぎない。対して `GluedShapes` は、Visioの描画エンジンが管理する「Glue(接着)」という物理的な拘束条件を直接叩くメソッドだ。
- ConnectedShapes: 接続の有無を高速に取得するが、接続点(Connection Point)の特定は不可能。
- GluedShapes: 特定の接続点ID(インデックス)を指定し、そこから伸びるコネクタや、その先に結合されたシェイプを「方向(In/Out)」とともに抽出できる。
ネットワーク構成図や複雑なフローチャートの自動検証において、この「接続点単位の追跡」ができなければ、論理的な整合性の担保は不可能である。
—
2. 実装の要諦:オブジェクトのライフサイクルとメモリ管理
VBAはガベージコレクションが甘い。大規模なVisioドキュメントを解析する際、不用意に `Shape` オブジェクトをループ内で生成し続ければ、メモリリークは必至だ。
特に `GluedShapes` は `Long` 型の配列を返す。この配列のハンドリングが、プロとしての腕の見せ所となる。
実践:接続先トラッキングのロジック
以下は、特定のシェイプから伸びるコネクタと、その先にあるシェイプをIDベースで完全追跡するコードだ。
‘ @brief 特定シェイプの全接続点から「何が」「どう」接続されているかを抽出する
Public Sub TraceConnections(ByVal shpSource As Visio.Shape)
Dim lngDirection As Visio.VisGluedShapesFlags
Dim lngConnectIDs() As Long
Dim i As Long
Dim shpTarget As Visio.Shape
‘ 接続点(Connection Points)をループ処理する
‘ 効率化のため、RowType = visRowConnectionPt の行をスキャンする
Dim rowIdx As Long
For rowIdx = 0 To shpSource.RowCount(visSectionConnectionPts) – 1
‘ visGluedShapesIncoming: 接続点に入ってくるコネクタ
‘ visGluedShapesOutgoing: 接続点から出ていくコネクタ
lngDirection = visGluedShapesOutgoing
‘ GluedShapesの実行(戻り値はID配列)
On Error Resume Next ‘ 接続がない場合はエラーになるためガード
shpSource.GluedShapes lngDirection, lngConnectIDs, “”
On Error GoTo 0
If Not IsEmpty(lngConnectIDs) Then
For i = LBound(lngConnectIDs) To UBound(lngConnectIDs)
Set shpTarget = shpSource.Document.Pages(1).Shapes.ItemFromID(lngConnectIDs(i))
‘ ここで詳細な検証ロジックを記述
Debug.Print “Source: ” & shpSource.Name & ” -> Target: ” & shpTarget.Name
‘ オブジェクトの明示的解放(VBAではSet = Nothingが鉄則)
Set shpTarget = Nothing
Next i
Erase lngConnectIDs
End If
Next rowIdx
End Sub
—
3. レガシー環境とWindows APIの活用
VisioのVBA環境は、往々にして古いドキュメント(.vsd)の互換性問題に悩まされる。特に大規模な階層構造を持つ図面では、Visioのオブジェクトモデルだけでは再描画のオーバーヘッドが無視できない。
ここで、`DoEvents` を多用してUIを固まらせるような素人仕事は禁止だ。もし、解析中に描画パフォーマンスが著しく低下する場合は、`Application.ScreenUpdating = False` を利用するのはもちろんのこと、必要に応じてWindows API(`SendMessage`)を呼び出し、Visioのメインループを制御することも視野に入れるべきである。
- 極限のヒント: 巨大な図面を解析する場合、`Application.ActiveWindow.Select` を行うとパフォーマンスが劇的に悪化する。`Select` を使わず、`Shape` オブジェクトへの直接参照のみでロジックを構築すること。
—
4. アーキテクトからの提言:データ保全の哲学
あなたが構築しているのは、ただの「自動化マクロ」ではない。Visioが保持する「接続データ」という資産を、他のシステム(SQL ServerやGraph DBなど)へ橋渡しする「データ変換エンジン」である。
1. IDの永続化を信用しない: `Shape.ID` はページ内の順序が変われば再割り当てされる可能性がある。真に重要なデータには `Shape.UniqueID` を使用せよ。
2. エラーハンドリングの徹底: 接続が切断された「浮き」コネクタは、`GluedShapes` で予期せぬエラーを吐く。必ず `Err.Number` を監視し、例外をログとして吐き出させること。
3. モジュール化: このロジックは必ず「解析層」と「出力層」に分けよ。解析したデータを一度 `Collection` オブジェクトに格納してから後処理を行うことで、保守性が格段に向上する。
Visio VBAはオワコンなどではない。正しく扱えば、これほどまでに強力な「視覚的メタデータ管理システム」は他に存在しない。コードの細部に宿る執念こそが、システムの寿命を決める。健闘を祈る。
