【実務・中級編】Selectionオブジェクトを活用したユーザー選択図形の一括処理マクロの作り方 – Visio VBA解析バイブル

スポンサーリンク

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

”’

”’ 選択された図形に対して一括でカスタムプロパティ(Shape Data)を付与する
”’

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は古い言語に見えるかもしれない。しかし、オブジェクトモデルの理解を極めれば、これほど強力な「可視化自動化エンジン」は他に存在しない。

コードをコピペして満足するな。そのコードが「なぜ動くのか」、そして「どんなケースで壊れるのか」を常に想像せよ。それができる者だけが、業務を劇的に改善するツールを創り出せる。

君の次のマクロが、誰かの面倒なルーチンワークを消滅させることを期待している。

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