Visio VBAを極める:Selectionオブジェクトで「選択図形」を制し、自動化のボトルネックを排除せよ
Visioの自動化において、初心者が最初に陥る罠が「全シェイプへの無差別アクセス」だ。`ActivePage.Shapes` をループで回し、条件分岐で判定する……そんなコードは、図面が巨大化した瞬間に破綻する。
真の自動化エンジニアが選ぶのは、`Selection` オブジェクトを起点としたインタラクティブな設計だ。ユーザーが「今、何を意図して選択したか」を起点に処理を走らせる。これが、UXとパフォーマンスを両立させる唯一の解である。
なぜ「Selection」にこだわる必要があるのか
`ActivePage.Shapes` を全走査する場合、図面の総シェイプ数 `N` に対して計算量は `O(N)` となる。一方、`ActiveWindow.Selection` を使えば、処理対象は「ユーザーが選んだもの」だけに限定される。
さらに重要なのが「排他制御と意図の明確化」だ。
全走査は往々にしてグループ化されたシェイプや、不可視のメタデータ用シェイプを誤って巻き込む。Selectionオブジェクトは、ユーザーが明示的に選択したという「意思」をプログラミングの入力値として受け取るため、誤作動のリスクを極限まで低減できる。
堅牢なSelection処理の設計パターン
プロダクション環境で耐えうるコードを書くための鉄則は3つだ。
1. Selectionの有無を必ず検証する: ユーザーが何も選択していない状態でマクロを走らせてもエラーを吐かない「安全装置」を実装する。
2. 型を絞る: `Selection` 内にはコネクタやグループなど、意図しない形状が混じる可能性がある。`ObjectType` で処理対象を厳密にフィルタリングする。
3. イベントの遮断: 大量処理を行う際は `Application.ScreenUpdating` を `False` にし、描画負荷を排除する。
—
【実戦コード】堅牢な一括属性付与ツール
以下は、選択したシェイプに対して一括で「ステータス」プロパティを付与し、色を変えるための実用的なコードだ。
Option Explicit
”’
”’
Public Sub BatchUpdateSelectedShapes()
Dim vsoWindow As Visio.Window
Dim vsoSelection As Visio.Selection
Dim vsoShape As Visio.Shape
‘ 1. スクリーン更新を停止し、処理速度を向上させる
Application.ScreenUpdating = False
On Error GoTo ErrorHandler
Set vsoWindow = ActiveWindow
Set vsoSelection = vsoWindow.Selection
‘ 2. 選択チェック(安全装置)
If vsoSelection.Count = 0 Then
MsgBox “対象となる図形が選択されていません。”, vbExclamation
GoTo Cleanup
End If
‘ 3. Selection内の各シェイプを走査
For Each vsoShape In vsoSelection
‘ ここでシェイプの種類や属性によるフィルタリングを行う
‘ 例: グループ図形を除外したい場合は If vsoShape.Type <> visTypeGroup Then …
‘ カスタムプロパティ(Shape Data)への値書き込み例
‘ ※事前にシェイプに “Status” という名前のプロパティが存在すると仮定
If vsoShape.CellExists(“Prop.Status”, visExistsAnywhere) Then
vsoShape.Cells(“Prop.Status”).Formula = Chr(34) & “Processed” & Chr(34)
vsoShape.Cells(“FillForegnd”).ResultIU = RGB(100, 200, 100)
End If
Next vsoShape
Cleanup:
Application.ScreenUpdating = True
Exit Sub
ErrorHandler:
MsgBox “予期せぬエラーが発生しました: ” & Err.Description, vbCritical
Resume Cleanup
End Sub
プロダクション開発における注意点
1. グループ化シェイプの扱い
`Selection` にグループ図形が含まれる場合、`For Each` でループしてもグループの中身まで辿らない。もしグループ内の子シェイプまで操作したい場合は、`If vsoShape.Type = visTypeGroup Then` で再帰的な関数を呼ぶ設計が必要だ。ここを適当に済ませると、複雑な図面で必ずバグる。
2. 外部データ(Excel/DB)連携との親和性
この「Selection」方式は、外部データとの連携に最適だ。
例えば、「選択した図形名(Shape.Name)をキーにしてExcelから属性を引っ張ってくる」といった処理を組む場合、`Selection` を使えば、図面全体をパースする手間が省けるため、処理時間が数秒単位で短縮される。
3. 保守性への投資
上記のコードでは、`CellExists` 関数を使用している。これは、存在しないプロパティにアクセスしてエラーを吐くのを防ぐための「防御的プログラミング」の基本だ。Visioは図面ごとにシェイプの定義が異なることが多いため、こうした「存在確認」のプロセスを省略してはならない。
最後に:エンジニアとしてのマインドセット
Visio VBAは古い言語に見えるかもしれない。しかし、オブジェクトモデルの理解を極めれば、これほど強力な「可視化自動化エンジン」は他に存在しない。
コードをコピペして満足するな。そのコードが「なぜ動くのか」、そして「どんなケースで壊れるのか」を常に想像せよ。それができる者だけが、業務を劇的に改善するツールを創り出せる。
君の次のマクロが、誰かの面倒なルーチンワークを消滅させることを期待している。
