【入門編】Shape.SpatialPropertiesによる空間検索:指定範囲内にあるシェイプ群の高速抽出手法 – Visio VBA解析バイブル

スポンサーリンク

こんにちは!Visio VBAの自動化の世界へようこそ。
マクロの記録ボタンを押して出てきたコードを眺めるだけの日々は、今日で終わりです。ここからは、Visioの心臓部であるオブジェクトモデルを意のままに操り、図面を「プログラムで思考させる」領域へと進みましょう。

今回は、Visio VBA上級者への登竜門であり、業務効率化の爆発的な武器となる「`SpatialProperties` を使った空間検索と高速抽出」について徹底解説します。

「指定した矩形(エリア)の中に含まれるシェイプを瞬時に見つけ出したい」
そんな現場の切実な課題を、スマートかつエレガントに解決する極意を授けましょう。ここをクリアすれば、あなたのVisio VBAスキルは間違いなく一段上のステージに到達します。

1. なぜ「空間検索(SpatialProperties)」なのか?

Visioで自動化を行っていると、次のような壁にぶつかります。

> 「図面上にある膨大なシェイプの中から、特定のエリア(例えば、倉庫図面の『Aゾーン』)に重なっている什器だけを抜き出して、一括で色を変えたい、あるいはデータを集計したい」

ここで、素朴なプログラミング初心者はどう書くでしょうか?
ページ上のすべてのシェイプを `For Each` でループさせ、1つずつ `.PinX` や `.PinY` の座標を数学的に比較する……。

ちょっと待ってください!そのアプローチ、実務では「御法度」です。

シェイプ数が数百、数千と増えるにつれて画面がフリーズしかねませんし、何よりコードが冗長になります。Visioのエンジンは、実はもっと強力な空間計算の機能を持っています。それが `SpatialProperties` メソッドです。これを使うことで、Visioのネイティブな空間インデックスを叩き、一瞬で条件に合致するシェイプ群を釣り上げることが可能になります。

2. SpatialProperties の正体と基本メカニズム

`SpatialProperties` は、すべての `Shape` オブジェクトが持っている隠れた強力なメソッドです。これを使用すると、ある特定の基準図形(または指定した幾何学的な領域)に対して、他のシェイプがどのような位置関係にあるかを調べることができます。

今回は、その中でも最も実用的な「指定した矩形(Bounding Box)と交差、または包含関係にあるシェイプのリスト(Selectionオブジェクト)を取得する」テクニックに絞って解説します。

空間検索のイメージ

+—————————————–+
| Page (ActivePage) |
| +———————–+ |
| | 検索エリア (Box) | |
| | +——-+ | |
| | | Shape | (Hit!) | |
| | +——-+ | |
| +———————–+ |
| +——-+ |
| | Shape | (Miss) |
| +——-+ |
+—————————————–+

Visioでは、ある図形を基準にして `SpatialNeighbors` というメソッドを呼び出すことで、空間的なヒットテスト(当たり判定)を行えます。

3. 実践!指定エリア内のシェイプを爆速抽出するVBAコード

百聞は一見に如かず。開発現場でそのままコピペして使える、極限まで洗練された実用コードをプレゼントします。

このコードは、ページ上に置いた「検索範囲を示すダミーの矩形(あるいは特定のエリア枠)」を基準にして、その内部、または交差する位置にあるすべてのシェイプを抽出し、ログに出力すると同時に赤色へ変化させるものです。

Sub ExtractShapesInArea()
‘ —————————————————————-
‘ 狙った空間内のシェイプを爆速で抽出し、一括操作するプロシージャ
‘ —————————————————————-

‘ 画面描画を停止し、処理速度を限界まで引き上げる(超重要テクニック!)
Application.ScreenUpdating = False

Dim vsoPage As Visio.Page
Set vsoPage = ActivePage

On Error GoTo ErrorHandler

‘ 1. 検索の基準となる「エリア枠(矩形シェイプ)」を特定する
‘ ※ここでは分かりやすく、選択中の最初のシェイプを「検索エリア」と仮定します
If ActiveWindow.Selection.Count = 0 Then
MsgBox “基準となるエリアシェイプを1つ選択してください。”, vbExclamation, “SpatialProperties 案内”
GoTo CleanUp
End If

Dim vsoTargetShape As Visio.Shape
Set vsoTargetShape = ActiveWindow.Selection(1)

‘ 2. SpatialNeighbors メソッドで空間検索を実行
‘ 引数の意味:
‘ Criteria : どのような関係性を探すか (visSpatialContainedIn = 完全に含まれる, visSpatialIntersect = 重なっている)
‘ Flags : 検索の精度やオプション (visSpatialIncludeHidden = 非表示も含める等。通常は 0 でOK)
‘ Result : 該当したシェイプのコレクション(Selectionオブジェクト)が返る

Dim vsoSelResult As Visio.Selection
Set vsoSelResult = vsoTargetShape.SpatialNeighbors(visSpatialIntersect, 0, 0)

‘ 3. 抽出されたシェイプ群を一括操作する
Dim vsoShp As Visio.Shape
Dim count As Long
count = vsoSelResult.Count

If count = 0 Then
MsgBox “指定されたエリア内に該当するシェイプはありませんでした。”, vbInformation, “結果”
GoTo CleanUp
End If

Debug.Print “— 空間検索ヒット一覧 (計 ” & count & ” 件) —”

For Each vsoShp in vsoSelResult
‘ 自分自身(検索エリア枠)は除外する
If vsoShp.ID <> vsoTargetShape.ID Then
Debug.Print “Hit Shape Name: ” & vsoShp.Name & ” (ID: ” & vsoShp.ID & “)”

‘ 例として、ヒットしたシェイプの塗りつぶし色を赤に変更する
vsoShp.CellsU(“FillForegnd.Color”).ResultIU = RGB(255, 0, 0)
End If
Next vsoShp

MsgBox count & ” 個のシェイプを空間検出し、処理を完了しました!”, vbInformation, “成功”

CleanUp:
‘ 描画の復元
Application.ScreenUpdating = True
Exit Sub

ErrorHandler:
MsgBox “予期せぬエラーが発生しました: ” & Err.Description, vbCritical, “エラー”
Resume CleanUp
End Sub

4. コードの深掘りと「ここが落とし穴」

上記のコードで、Visio VBAの基礎を抜けたあなたなら「おっ」と気づくポイントがあります。現場でよくある失敗を防ぐための知見を共有しておきましょう。

① 画面描画の停止 (`ScreenUpdating = False`) はマスト

空間検索やその後のシェイプのプロパティ書き換えを大量に行う際、画面描画が有効のままだと、Visioは1回書き換えるごとに画面を再描画しようとして地獄のように遅くなります。
プロシージャの最初で止め、最後(あるいはエラー時)に必ず戻す。これはプロのエンジニアの鉄則です。

② 検索条件(Criteria)の選び方

今回のコードでは `visSpatialIntersect`(交差するものすべて)を使いましたが、要件に合わせてここを変更できます。

  • `visSpatialContainedIn` : エリアの中に完全に収まっているものだけを狙う場合
  • `visSpatialContain` : 逆に、指定したシェイプが「他のシェイプを包み込んでいる」関係を探す場合

作りたい自動化の仕様に合わせて、ここを自在に切り替えられるようにしておきましょう。

③ 自分自身がヒットすることへの対策

`SpatialNeighbors` は優秀ゆえに、「基準にしたシェイプ自身」も結果のSelectionに含まれてしまうことがあります。
コード内で `If vsoShp.ID <> vsoTargetShape.ID Then` とガードを入れているのはそのためです。これを忘れると、検索エリアの枠線自体の色が赤に変わってしまい、「あれ?」と頭を抱えることになります。

5. さあ、次のステップへ

今回は `SpatialProperties` の概念をベースにした `SpatialNeighbors` による高速空間検索の技術をお伝えしました。
座標をちまちま計算して「重なっているか判定する自作関数」を書く必要はもうありません。Visioが持つネイティブな空間演算エンジンを味方につければ、どんなに複雑なレイアウト図面であっても、一瞬で解析・自動化するプログラムが書けるようになります。

「ここをクリアすれば、Visio VBAの基本はバッチリですよ!」

オブジェクトのライフサイクルを意識し、無駄なループを排除したスマートなコードを書く快感を知れば、Visioを使った業務自動化はもはや単なる作業ではなく、最高にクリエイティブな「建築」に変わります。

ぜひ、あなたの実務の図面でこのコードを試してみてください。驚くほどのスピードと快適さに感動するはずです。それでは、次回の極限知見でお会いしましょう!

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