Visioの迷宮を解読せよ:オブジェクト階層を完全掌握する再帰走査エンジンの設計思想
Visio VBAを触るエンジニアの多くが、最初の数時間で「なぜこのコードは期待通りに動かないのか」という壁にぶつかる。その理由は単純だ。Visioのオブジェクトモデルが、他Office製品とは異質な「幾何学的階層構造」を持っているからだ。
単にShapeを操作したいだけなら `ActivePage.Shapes` を叩けばいい。しかし、業務自動化の深淵に踏み込むなら、`Document`、`Page`、`Shape`、そしてその奥にある`Cell`や`Section`に至るまでの「血流」を把握しなければならない。
今日は、Visioの全貌を透視し、デバッグの迷宮から脱出するための「再帰走査エンジン」を授ける。これは単なるデバッグツールではなく、君が今後開発するあらゆる自動化ツールの「羅針盤」となるはずだ。
—
1. なぜ「再帰走査」なのか:Visio構造の真実
Visioのオブジェクトモデルは、単なるリストではない。「コンテナの中にコンテナがあり、その中に図形があり、さらにその中にプロパティ(Cell)が潜んでいる」という再帰的なツリー構造だ。
- Document: 全ての起点。
- Page: 図面の実体。
- Shape: 1D/2Dの境界線。グループ化されたShapeは、さらにその下に`Shapes`コレクションを持つ。
- Cell: 数値や式の最小単位。
この階層を理解せず、`For Each`文で浅瀬をなぞるだけのコードを書けば、グループ化された図形の深層を見逃し、バグを量産することになる。再帰処理こそが、この迷宮を制する唯一の鍵だ。
—
2. 実装:Visioオブジェクト再帰走査エンジン
以下のコードは、`Application`から`Cell`までを再帰的に掘り下げ、イミディエイトウィンドウにその系譜を刻み込む。保守性を考慮し、インデントで階層を視覚化するように設計した。
Option Explicit
‘ メインエントリーポイント:アクティブドキュメントを起点に走査を開始
Public Sub InspectVisioHierarchy()
Dim doc As Visio.Document
Set doc = Application.ActiveDocument
Debug.Print “— Visio Hierarchy Audit Start —”
Debug.Print “Doc: ” & doc.Name
‘ Pageの走査
Dim pg As Visio.Page
For Each pg In doc.Pages
Debug.Print ” Page: ” & pg.Name
‘ Shapeの走査(再帰関数の呼び出し)
Call TraverseShapes(pg.Shapes, 2)
Next pg
Debug.Print “— Audit Complete —”
End Sub
‘ Shapeを再帰的に掘り下げるプロシージャ
Private Sub TraverseShapes(shapes As Visio.Shapes, indentLevel As Integer)
Dim shp As Visio.Shape
Dim indent As String
indent = Space(indentLevel 2)
For Each shp In shapes
Debug.Print indent & “Shape: ” & shp.Name & ” (ID: ” & shp.ID & “)”
‘ Cellの走査(Shapeの物理特性を覗き見る)
Call InspectCells(shp, indentLevel + 1)
‘ グループ図形がある場合、さらに潜る
If shp.Shapes.Count > 0 Then
Call TraverseShapes(shp.Shapes, indentLevel + 1)
End If
Next shp
End Sub
‘ Cellを抽出する(実務で最も重要なプロパティ群)
Private Sub InspectCells(shp As Visio.Shape, indentLevel As Integer)
Dim cell As Visio.Cell
Dim indent As String
indent = Space(indentLevel 2)
‘ 例:位置情報(X, Y)だけを抽出して表示。必要に応じてセクションごとにループさせる
If shp.CellExists(“PinX”, False) Then
Debug.Print indent & ” [Cell] PinX: ” & shp.Cells(“PinX”).ResultIU
End If
End Sub
—
3. エンジニアとして知っておくべき「落とし穴」
このツールを使う際、以下の3点に注意せよ。これらを無視すると、自動化ツールは「重い・落ちる・制御不能」の三重苦に陥る。
① 再帰の深さとスタックオーバーフロー
非常に複雑な階層を持つVisioファイルでは、再帰が深くなりすぎる可能性がある。業務ツールとして実装する場合は、深さ制限(Depth Limit)を設けるか、キューを用いた非再帰的アプローチへの書き換えを検討せよ。
② Cellへのアクセスは「コスト」がかかる
`shp.Cells(“PinX”)`のような呼び出しは、実はそれなりに重い処理だ。大量の図形をループで回す際、毎回このプロパティにアクセスするとパフォーマンスが著しく低下する。必要な情報はキャッシュしておくか、走査の目的を明確に絞り込むこと。
③ データベース連携の注意点
このツールで得た情報をデータベースに記録したい場合、「Shape ID」は不変ではないことに注意しろ。図形の削除や再描画でIDは再割り当てされる。永続的な管理が必要なら、`UniqueID`プロパティを利用するアーキテクチャを設計しなければならない。
—
結論:コードは「可読性」ではなく「可視性」を求めている
Visioの自動化において、最もコストがかかるのは「図形がどこにいて、どういうプロパティを持っているか」という仕様確認の工数だ。今回提供した再帰走査エンジンは、その工数をゼロにするための「現場の武器」である。
君たちが書くコードが、単なる自動化スクリプトではなく、メンテナンス可能な「資産」になることを期待している。さあ、次は君自身の業務の深淵を走査し、無駄を削ぎ落としてくれ。
