【入門編】【中級者向け】ページ内の全シェイプを走査し、レイヤー設定が空のシェイプを自動的に「デフォルトレイヤー」へ移動する整理術 – Visio VBA解析バイブル

スポンサーリンク
スポンサーリンク

【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や他の自動化技術にも共通する「エンジニアリングの本質」です。

次にあなたが挑戦すべきは、「特定のレイヤーに所属しているシェイプだけを色付けする」あるいは「レイヤー名に基づいてシェイプのテキストを書き換える」といった、条件分岐を組み合わせた操作です。

「ツールに作らされる」のではなく、「ツールを支配する」。
その感覚を掴んだとき、あなたの業務自動化は真の次元へと到達します。

応援していますよ。また次のコードでお会いしましょう。

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