【実務・中級編】【中級】グループ化された図形の再帰的走査:階層構造を持つ複雑なシェイプの内部を操作する – Visio VBA解析バイブル

スポンサーリンク

Visio VBAの深淵を征く:グループ化されたシェイプを「再帰」で完璧に制御する設計論

Visioにおけるシェイプ操作は、単なる「図形の移動」ではない。それは「階層構造を持つツリーデータの探索」である。

多くのエンジニアが陥る罠は、`Shapes`コレクションをループで回すだけの浅い実装だ。グループの中にグループがある「ネスト構造」を前にして、コードは破綻し、条件分岐のスパゲッティコードが生まれる。

今日、我々が目指すのは「どのような複雑な階層構造であっても、確実にターゲットを射抜く再帰的アルゴリズム」の習得だ。

—

1. なぜ「再帰」でなければならないのか

Visioのデータ構造は、`Page` → `Shape` → `Shapes`(グループの場合)という再帰的な定義を持っている。
階層が深くなるたびにループをネストさせるのは、拡張性を自ら殺す愚行だ。

「深さ優先探索(DFS)」を採用せよ。関数が自分自身を呼び出し、再帰的に階層を潜る設計にすれば、グループが10階層あろうが100階層あろうが、コードは常に一定のシンプルさを保つ。

—

2. 実装の要諦:堅牢な走査関数

以下のコードは、単なるサンプルではない。プロダクション環境でそのまま使える、エラーハンドリングと再帰ロジックを融合させた「テンプレート」だ。

‘ @description: シェイプの階層構造を再帰的に走査し、条件に合致するシェイプを処理する
‘ @param shp: 処理対象のシェイプ
‘ @param targetName: 検索対象の名称(または識別子)
Public Sub TraverseShapes(ByVal shp As Visio.Shape, ByVal targetName As String)
‘ 1. 現在のシェイプに対する処理(ビジネスロジック)
If shp.Name = targetName Then
Debug.Print “Found: ” & shp.Name & ” (ID: ” & shp.ID & “)”
‘ ここに属性変更処理を記述(例: 色の変更、テキストの抽出)
shp.Cells(“FillForegnd”).ResultIU = 6 ‘ 赤色
End If

‘ 2. グループであれば再帰的に潜る
‘ GroupShapesコレクションが存在するかを判定するのがポイント
If shp.Type = Visio.VisShapeTypes.visTypeGroup Then
Dim subShp As Visio.Shape
For Each subShp In shp.Shapes
TraverseShapes subShp, targetName
Next subShp
End If
End Sub

このコードが「プロ仕様」である理由

  • 型の明示: `Visio.Shape` を明示的に指定することで、IntelliSenseを最大限に活用し、実行時の予期せぬ型エラーを防ぐ。
  • 構造の分離: 検索条件と実行処理を分離しているため、メンテナンス性が高い。
  • 再帰のベースケース: `visTypeGroup` の判定により、グループでないシェイプに到達した時点でループが自然に終了する安全な設計。

—

3. 現場で直面する「落とし穴」と回避策

A. グループの「ロック」と「保護」

Visioでは、グループ化された個別のシェイプが「編集保護(Lock)」されていることがよくある。APIで変更しようとしてエラーになる場合は、`Cells(“LockCalcWH”).Formula` などが設定されていないか、`Shape.Type` だけでなく保護属性を確認するロジックを組み込む必要がある。

B. パフォーマンスの最適化

大規模な図面で再帰を行うと、描画更新が走って非常に低速になる。これを防ぐには以下の呪文を冒頭に追加せよ。

Application.ScreenUpdating = False
‘ … 処理本体 …
Application.ScreenUpdating = True

C. データベース連携時の注意点

Visio図形から抽出したデータをDBに送る際、`Shape.Name` はユーザーが変更すると一意性を失う。必ず `Shape.UniqueID` (GUID) を使用すること。 これが、図形とデータを論理的に紐付ける唯一の正解だ。

—

4. チーフアーキテクトからの提言

「コードが動く」ことと「コードが保守可能である」ことは、天と地ほどの差がある。

今回紹介した再帰的走査は、Visio自動化の「背骨」になる技術だ。この基盤の上に、Excelからのデータ流し込みや、図面内のパーツ集計といった高次な自動化を積み重ねてほしい。

最後に一つ。
再帰関数を書く際は、無限ループを避けるために、必ず「どのような場合に再帰が止まるか」を意識すること。今回の `For Each subShp In shp.Shapes` は、コレクションが空であれば自然に終わるため、その点でも非常に堅牢だ。

さあ、あなたの図面を「静的な絵」から「動的なデータベース」へと進化させる準備は整った。次のステップに進もう。

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