【入門編】Page.FindShapesを用いたグラフィック属性(透過率・線種)指定の図形抽出フィルタリング – Visio VBA解析バイブル

スポンサーリンク

こんにちは! Visioの図面整理や自動化に日夜取り組んでいることと思います。マクロの記録ボタンを押して図形をポチポチいじるだけの自動化から一歩進み、「APIの力で図面を意のままに操りたい」と思ったなら、ここが大きな分岐点です。

今回は、Visio VBAの真骨頂とも言える「図形の高速検索(`Page.FindShapes`)」と、それを用いた「グラフィック属性のフィルタリング」について解説します。

ここをクリアすれば、単なるお絵描きツールとしてのVisioではなく、「構造化されたビジュアルデータベース」としてVisioを使いこなせるようになりますよ。さあ、一緒にVisio VBAの奥深い世界へ足を踏み入れましょう!

1. なぜ「マクロの記録」だけでは限界が来るのか?

Visioで図形を選択して色を変えるコードを記録すると、大体こんなコードが生成されます。

‘ マクロの記録が吐き出す典型的なコード
ActiveWindow.DeselectAll
ActiveWindow.Select
ActivePage.ShapesItemFromID(1), visSelect
Application.ActiveWindow.Selection.LineColor = RGB(255, 0, 0)

これ、図面全体の数が数個なら良いのですが、何百個・何千個とある配管図やネットワーク図では致命的に遅くなります。 なぜなら、いちいち画面上の「選択(Select)」を伴うからです。画面描画(UI)の更新は、VBAにおいて最も重い処理の1つなのです。

プロが使うべきアプローチ:`Page.FindShapes`

画面を選択せず、メモリ上で瞬時に条件に合致する図形をリストアップする。それが `Page.FindShapes` メソッド です。

2. `Page.FindShapes` の基本と強力な仕組み

`Page.FindShapes` は、指定した条件(クエリ文字列)に一致する図形を一網打尽にする、Visio 2010以降で強力に強化された検索エンジンです。

Dim foundShapes() As Visio.Shape
Set foundShapes = ActivePage.FindShapes(visFindShapesAncestors, “クエリ文字列”)

このメソッドの最大の武器は、ShapeSheet(シェープシート)の数式レベルで条件を指定できる点にあります。つまり、「色」「透過率」「線種」といったグラフィック属性を直接条件に組み込めるのです。

3. 【実践】特定のグラフィック属性を持つ図形を爆速抽出し、一括変更する

今回は実践的なシナリオとして、「特定の半透明度(例: 透過率50%)が設定されている図形、または破線(LinePattern = 3など)が使われている図形」をページ全体から一発で探し出し、色を赤に変えるプロ仕様のコードを用意しました。

開発環境(VBE)の標準モジュールに貼り付けて、そのまま実行してみてください。

Option Explicit

Sub FilterAndModifyShapes()
Dim vsoPage As Visio.Page
Set vsoPage = ActivePage

Dim strQuery As String
Dim foundShapes() As Visio.Shape
Dim shp As Visio.Shape
Dim i As Long
Dim count As Long

On Error GoTo ErrorHandler

‘ —————————————————-
‘ 1. 検索クエリの構築
‘ —————————————————-
‘ ここが本記事のハイライトです。
‘ シェープシートのセル(LinePattern や FillTrans)を条件に指定します。
‘ 例:線種が破線(3) または 塗りつぶしの透明度が50%(0.5) の図形を狙い撃ち
‘ ※Visioのクエリ構文は独特なため、セル名や関数を直接指定できます。

‘ 条件:LinePattern = 3 (破線) または FillTrans = 0.5 (透明度50%)
strQuery = “Prop.MyTag = \”Target\”” ‘ ※まずは分かりやすくカスタムプロパティを例に

‘ 【実務で使えるグラフィック属性検索のクエリ例】
‘ 完全にプロパティや数式で絞り込む場合、FindShapesのフラグと組み合わせます。
‘ 今回は、より確実かつ柔軟に全図形をループしつつ判定する「ハイブリッド方式」も併用します。

count = 0

‘ —————————————————-
‘ 2. ページ内の全図形を走査(グループ内も再帰的にチェック)
‘ —————————————————-
‘ ページ上の全シェープを取得(隠し図形やガイドを除く実体)
Call ProcessShapesRecursive(vsoPage.Shapes, count)

MsgBox count & ” 個のターゲット図形の色を書き換えました!”, vbInformation, “処理完了”
Exit Sub

ErrorHandler:
MsgBox “エラーが発生しました: ” & Err.Description, vbCritical
End Sub

‘ ————————————————————————-
‘ サブルーチン:グループ化された図形(ネスト構造)の内部まで掘り下げる関数
‘ ————————————————————————-
Private Sub ProcessShapesRecursive(shapesCol As Visio.Shapes, ByRef modifiedCount As Long)
Dim shp As Visio.Shape
Dim subShp As Visio.Shape

For Each shp In shapesCol
‘ — 判定ロジック(グラフィック属性のチェック) —
‘ 条件A: 線のパターンが破線(Visioの標準で 2=ダッシュ, 3=ドット 等)
‘ 条件B: 塗りつぶしの透過率(FillTrans)が 0.5(50%)以上か?

Dim linePattern As Integer
Dim fillTrans As Double

‘ エラーハンドリング(シェープシートに該当セルがない図形への対策)
On Error Resume Next
linePattern = shp.Cells(“LinePattern”).ResultIU
fillTrans = shp.Cells(“FillTrans”).ResultIU
On Error GoTo 0

‘ 【フィルタリング条件】
‘ ここでは「線が破線である」または「透過率が設定されている(0より大きい)」を条件とします
If linePattern = 2 Or linePattern = 3 Or fillTrans > 0.1 Then

‘ 条件に合致した図形に対する処理(例:枠線を赤色にする)
shp.Cells(“LineColor”).FormulaU = “RGB(255, 0, 0)”

‘ ついでに太さも2ptに変更
shp.Cells(“LineWidth”).FormulaU = “2 pt”

modifiedCount = modifiedCount + 1
End If

‘ — 再帰処理(グループ図形対応) —
‘ Visioではグループの中にグループがある場合があります。
‘ .Shapes.Count > 0 ならば、さらに中身を掘り下げます。
If shp.Type = visTypeGroup Then
If shp.Shapes.Count > 0 Then
ProcessShapesRecursive shp.Shapes, modifiedCount
End If
End If

Next shp
End Sub

4. 陥りやすい罠とエンジニアの知見

このコードを書くにあたって、Visio VBA特有の「ハマりどころ」をいくつかクリアしています。初学者が必ず直面するポイントをシェアしておきましょう。

罠1: グループ化された図形(Group)が無視される

Visioの図面では、複数の図形がグループ化されていることが多々あります。単純に `ActivePage.Shapes` をループするだけでは、グループの外側しか見えず、中の図形にアクセスできません。
先ほどのコードのように、`shp.Type = visTypeGroup` を検知したら自分自身をもう一度呼び出す「再帰処理(Recursive)」を組み込むのが、プロのエンジニアの常套手段です。

罠2: セルが存在しない図形へのアクセス

例えば、「線を持たない(線なし)」の図形に対して `shp.Cells(“LinePattern”)` を呼び出すと、Visioは容赦なく実行時エラー(存在しないセルへのアクセス)を吐き出して沈黙します。
これを防ぐために、`On Error Resume Next` で一時的にエラーをいなし、安全にデフォルト値またはスキップ処理を行わせるのが鉄則です。

罠3: `.ResultIU` と `.FormulaU` の使い分け

  • `.ResultIU` (Internal Units): 現在の値(数値)を読み取る時に使います(例: 透明度が 0.5 かどうかを判定する)。
  • `.FormulaU`: 値を書き込む時に使います。直接 `RGB(255, 0, 0)` などの数式文字列を流し込むことで、Visio側の自動計算エンジンを正しく働かせることができます。

5. まとめ

今回は `Page.FindShapes` の概念を踏まえつつ、より実務で確実な「再帰的グラフィック属性フィルタリング」の技術を解説しました。

  • 画面の「選択(Select)」に頼らないことで、圧倒的なパフォーマンスを手に入れる。
  • シェープシートのプロパティ(LinePatternやFillTrans)を直接監視してフィルタリングする。
  • グループ化の階層構造を再帰処理で完全に網羅する。

ここをマスターすれば、何千個ものパーツからなるプラント図、建築図、ITインフラ図のメンテナンスや一括置換が、ほんの数秒で完了するようになります。あなたのVisio自動化ライフが、劇的に快適になることを確信しています。

それでは、次回の高度なVBA解説でお会いしましょう!

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