【Visio VBA極意】「迷子のシェイプ」を救え。レイヤー未設定シェイプを自動整理する、プロの品質管理術
こんにちは。現場の自動化を指揮するチーフアーキテクトです。
Visioで大規模な構成図やネットワーク図を描いていると、避けては通れない問題があります。それは「レイヤー管理の形骸化」です。
「この図面、特定のレイヤーを非表示にすればスッキリするはずなのに、なぜか消えない図形がある……」
「レイヤー分けをルール化しているのに、誰かがうっかりレイヤー設定を忘れたシェイプを置いてしまった……」
こうした「迷子のシェイプ(レイヤー未所属の図形)」が混入すると、図面の品質は一気に低下し、後工程でのフィルタリングや表示制御が効かなくなります。マクロの記録だけで満足している段階を卒業し、「図面の整合性を保つための自動検閲」ができるようになると、あなたのエンジニアとしての視座は一段高く引き上げられます。
今日は、ページ内の全シェイプを走査し、レイヤーが設定されていないシェイプを自動的に「デフォルトレイヤー」へ放り込む、実戦的な整理術を伝授しましょう。
1. 概念の理解:Visioのオブジェクトモデルを「視る」
コードを書く前に、まず頭の中に「地図」を描いてください。
マクロの記録は「操作のログ」に過ぎませんが、プロのコードは「オブジェクトの構造」を操作します。
今回のターゲットは以下の構造です。
1. Document(文書): 全てはここから始まる。
2. Page(ページ): 図面が描かれているキャンバス。
3. Shape(シェイプ): あなたが配置した一つ一つの図形。
4. Layer(レイヤー): シェイプに紐付けられる「属性」。
ここで重要なのは、「シェイプは複数のレイヤーに所属できるが、一つも所属していない状態もあり得る」という点です。私たちは、この「所属数(`LayerCount`)が 0 のもの」を探し出し、特定のレイヤーへ強制的に所属させるのです。
2. 実装:レイヤー自動整理マクロ
それでは、実際のコードを見ていきましょう。このコードは、単に動くだけでなく、「もし指定したレイヤーがなければ自動で作る」という、実務で絶対に求められる堅牢性(ロバストネス)を持たせています。
Option Explicit
''' <summary>
''' ページ内の全シェイプを走査し、レイヤー未設定のものを「Default Layer」へ移動する
''' </summary>
Sub OrganizeUnlayeredShapes()
Dim vsoPage As Visio.Page
Dim vsoShape As Visio.Shape
Dim vsoLayer As Visio.Layer
Dim targetLayerName As String
Dim targetLayer As Visio.Layer
Dim processedCount As Integer
' --- 設定エリア ---
targetLayerName = "Default Layer" ' 未設定シェイプを移動させる先のレイヤー名
processedCount = 0
' ------------------
' 現在表示しているページを対象にする
Set vsoPage = ActivePage
On Error GoTo ErrorHandler
' 1. ターゲットとなるレイヤーが存在するか確認し、なければ作成する
' ※ここがプロの仕事。エラーを未然に防ぐ「ガード句」の考え方です。
On Error Resume Next
Set targetLayer = vsoPage.Layers.Item(targetLayerName)
On Error GoTo ErrorHandler ' エラーハンドリングを元に戻す
If targetLayer Is Nothing Then
' レイヤーが存在しない場合は新しく作成
Set targetLayer = vsoPage.Layers.Add(targetLayerName)
Debug.Print "レイヤー '" & targetLayerName & "' を新規作成しました。"
End If
' 2. ページ内の全シェイプを走査
' Page.Shapes ではなく Page.AllShapes を使うのがコツです。
' AllShapes を使うことで、グループ化された中にあるシェイプも漏らさず捕捉できます。
For Each vsoShape In vsoPage.AllShapes
' シェイプのレイヤー所属数をチェック
' LayerCount が 0 なら、どのレイヤーにも属していない「迷子」です。
If vsoShape.LayerCount = 0 Then
' 指定したレイヤーに追加
vsoShape.AddLayer targetLayer
processedCount = processedCount + 1
End If
Next vsoShape
' 3. 結果報告
MsgBox "整理が完了しました!" & vbCrLf & _
"整理したシェイプ数: " & processedCount & " 個", vbInformation, "完了"
Exit Sub
ErrorHandler:
MsgBox "予期せぬエラーが発生しました。" & vbCrLf & _
"エラー番号: " & Err.Number & vbCrLf & _
"内容: " & Err.Description, vbCritical, "エラー"
End Sub
3. アーキテクトの視点:なぜこのコードなのか?
初学者の方が陥りやすい罠と、それを回避するための設計思想を解説します。
① `Shapes` ではなく `AllShapes` を使う理由
ここが最大のポイントです。
`vsoPage.Shapes` は、ページ直下に置かれているシェイプのみを指します。もし図形が「グループ化」されていた場合、グループの中にある個別の部品(子シェイプ)には手が届きません。
`AllShapes` を使うことで、階層構造の深さに関わらず、ページ内のすべてのオブジェクトをフラットに走査できます。「漏れを許さない」のがプロの設計です。
② レイヤーの存在チェック(エラーハンドリング)
`vsoPage.Layers.Item(“Default Layer”)` を実行したとき、もしそのレイヤーが存在しないと、VBAは即座に実行時エラーで停止してしまいます。
あえて `On Error Resume Next` を一時的に使い、存在を確認してから `Layers.Add` する。この「エラーをコントロールする技術」が、止まらないツールを作る鍵となります。
③ パフォーマンスへの配慮
このコードでは `Select` や `Activate` を一切使っていません。
マクロの記録を使うと、必ず `vsoShape.Select` のようなコードが生成されます。しかし、オブジェクトを「選択」する操作は、Visioの描画エンジンに負荷をかけ、処理速度を著しく低下させます。
「画面を動かさず、メモリ上のオブジェクトを直接操作する」。これが高速化の鉄則です。
4. まとめ:ここをクリアすれば、次の一歩が見える
今回のコードを通じて、以下の3点をマスターできました。
1. オブジェクトの階層構造を意識した走査 (`AllShapes`)
2. 存在しないオブジェクトへの安全なアクセス (エラーハンドリング)
3. 「選択」を排除した高速なオブジェクト操作
これらはVisio VBAに限らず、Excel VBAや他の自動化技術にも共通する「エンジニアリングの本質」です。
次にあなたが挑戦すべきは、「特定のレイヤーに所属しているシェイプだけを色付けする」あるいは「レイヤー名に基づいてシェイプのテキストを書き換える」といった、条件分岐を組み合わせた操作です。
「ツールに作らされる」のではなく、「ツールを支配する」。
その感覚を掴んだとき、あなたの業務自動化は真の次元へと到達します。
応援していますよ。また次のコードでお会いしましょう。
