【入門編】【中級者向け】ページ内の全シェイプを走査し、レイヤーが未設定のシェイプを特定して警告するツール – Visio VBA解析バイブル

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

マクロ記録の先へ。Visio VBAで「設計の秩序」を自動化する:レイヤー未設定シェイプの検知と整理

こんにちは。業務自動化の世界へようこそ。

「マクロの記録」ボタンを押して、自分の操作をコードに変換することからVBAの旅は始まります。でも、もしあなたが「もっと複雑なことをしたい」「バラバラになった図面を、一瞬でルール通りに整えたい」と願うなら、今こそ「オブジェクトの構造」という本質的な概念に踏み込む時です。

今日、私があなたに伝授するのは、単なるコードの書き方ではありません。
大規模な図面(ダイアグラム)において、メンテナンス性を劇的に向上させるための「秩序の自動生成」という考え方です。

具体的には、「どのレイヤーにも属していない、迷子のシェイプ」を特定し、自動的に『未分類』レイヤーへ隔離するツールを構築していきます。

なぜ「レイヤー管理」が重要なのか?

大規模なシステム構成図やネットワーク図を想像してみてください。
「サーバー層」「クライアント層」「ネットワーク機器層」……。これらがレイヤー分けされていれば、特定の層だけを非表示にしたり、一括で印刷したりすることが容易です。

しかし、誰かが新しいシェイプをポンと置いたとき、レイヤー設定を忘れてしまうことがあります。これが積み重なると、図面は「制御不能なカオス」へと変貌します。

「ルールに従っていないものを、自動で見つけて、正しい場所に収める」

このロジックをマスターすることは、エンジニアとして「自動化の神髄」に触れる第一歩なのです。

核心となるロジック:オブジェクトの階層を理解する

このツールを作るために、私たちはVisioの「オブジェクトモデル」という地図を読み解く必要があります。

1. Page(ページ): 図面の舞台です。
2. Layer(レイヤー): 図面上の「属性」の集合です。ページに紐づいています。
3. Shape(シェイプ): 実際に描かれている図形です。
4. Shape.LayerCount: これが今回の鍵です。シェイプが現在いくつのレイヤーに所属しているかを数値で返します。

「もし `LayerCount` が `0` なら、そのシェイプは迷子である」
このシンプルな判断を、ページ内の全シェイプに対して高速に実行していきます。

実装:未分類シェイプ整理ルーチン

それでは、プロフェッショナルのコードを見ていきましょう。単に動くだけではなく、エラーに強く、パフォーマンスを意識した構成にしています。

Option Explicit

''' <summary>
''' ページ内の全シェイプを走査し、レイヤー未設定のものを「未分類」レイヤーへ移動させる
''' </summary>
Sub OrganizeUnclassifiedShapes()
    Dim targetPage As Visio.Page
    Dim targetLayer As Visio.Layer
    Dim shp As Visio.Shape
    Dim unclassifiedLayerName As String
    Dim layerExists As Boolean
    Dim count As Integer
    
    ' --- 設定領域 ---
    unclassifiedLayerName = "未分類"
    Set targetPage = ActivePage ' 現在開いているページを対象にする
    ' ----------------
    
    ' 処理中の画面更新を停止してパフォーマンスを向上させる(プロの作法です)
    Application.ScreenUpdating = False
    
    On Error GoTo ErrorHandler
    
    ' 1. 「未分類」レイヤーが存在するか確認し、なければ作成する
    layerExists = False
    For Each targetLayer In targetPage.Layers
        If targetLayer.Name = unclassifiedLayerName Then
            layerExists = True
            Exit For
        End If
    Next targetLayer
    
    If Not layerExists Then
        Set targetLayer = targetPage.Layers.Add(unclassifiedLayerName)
        Debug.Print "レイヤー '" & unclassifiedLayerName & "' を新規作成しました。"
    Else
        Set targetLayer = targetPage.Layers(unclassifiedLayerName)
    End If

    ' 2. ページ内の全シェイプを走査
    count = 0
    
    ' 重要:Page.Shapes は「直下のシェイプ」のみを指す場合があります。
    ' グループ化された中のシェイプまで確実に捕まえたい場合は、
    ' 再帰的に走査するか、AllShapesコレクションを使用するのが定石です。
    For Each shp In targetPage.AllShapes
        
        ' シェイプが一つもレイヤーに属していない(LayerCount = 0)場合
        If shp.LayerCount = 0 Then
            ' 指定したレイヤーに追加
            shp.AddLayer targetLayer
            count = count + 1
        End If
        
    Next shp

    ' 3. 結果の報告
    Application.ScreenUpdating = True
    
    If count > 0 Then
        MsgBox count & " 個のシェイプを '" & unclassifiedLayerName & "' レイヤーに移動しました。", vbInformation, "整理完了"
    Else
        MsgBox "未分類のシェイプは見つかりませんでした。", vbInformation, "確認完了"
    End If
    
    Exit Sub

ErrorHandler:
    Application.ScreenUpdating = True
    MsgBox "予期せぬエラーが発生しました:" & vbCrLf & Err.Description, vbCritical, "エラー"
End Sub

ここがプロの視点!設計のポイント解説

コードをただコピペするだけでは、あなたの成長は止まってしまいます。なぜこのような書き方をしたのか、その意図を解説します。

① `AllShapes` の選択(重要!)

初心者の方は `targetPage.Shapes` を使いがちです。しかし、`Shapes` コレクションは「ページ直下のシェイプ」しか見てくれません。もしシェイプが「グループ化」されていたら、その中身(子要素)は見逃してしまいます。
`AllShapes` を使うことで、グループの奥深くに隠れた迷子のシェイプまで、一網打尽にできるのです。

② `Application.ScreenUpdating = False`

大量のシェイプを操作する場合、Visioが一つ一つの移動を画面に描画しようとすると、動作が極端に重くなります。
「描画を止めて、メモリ上で計算を終わらせてから、最後にパッと見せる」
これは、業務自動化エンジニアが必ず守るべき、パフォーマンス向上の鉄則です。

③ エラーハンドリングの重要性

図面が保護(Protect)されていたり、特殊なオブジェクトが含まれていると、マクロは途中で止まってしまいます。`On Error GoTo ErrorHandler` を記述しておくことで、万が一の際にも「画面更新を再開させてから、エラー内容を丁寧に伝える」という、ユーザーに優しい挙動を実現しています。

陥りやすいエラーと対策

このツールを使っていると、次のような壁にぶつかるかもしれません。

  • 「アクセスが拒否されました」というエラー
  • 原因: ページやシェイプが「保護(Protect)」されている可能性があります。
  • 対策: `targetPage.Protect = False` を実行するか、図面の保護設定を確認してください。
  • 「レイヤー名が重複しています」
  • 原因: 既に同じ名前のレイヤーがあるのに、`Layers.Add` を実行しようとした。
  • 対策: 今回のコードのように、必ず「存在チェック(`If Not layerExists`)」を挟むように設計しましょう。

まとめ:一歩ずつ、アーキテクトへ

お疲れ様でした。これであなたは、「ただマクロを記録する人」から、「図面の構造を制御するエンジニア」へと一歩踏み出しました。

今回学んだ「コレクションの走査」「条件によるオブジェクトの状態判定」「エラーとパフォーマンスへの配慮」は、Visioに限らず、あらゆるプログラミングに通じる普遍的な知見です。

このツールをベースに、「未分類のシェイプの色を赤に変える」機能や、「特定の名前を持つシェイプを別レイヤーに分ける」機能など、自分なりの拡張を加えてみてください。

その試行錯誤こそが、あなたを伝説のエンジニアへと導く唯一の道なのです。
応援していますよ。

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