【入門編】【実務直結】特定のレイヤーに含まれるシェイプのみを対象とした、ページ間コピー&ペーストの自動化 – Visio VBA解析バイブル

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

【実務直結】Visio VBAで「特定のレイヤーだけ」を別ページに抽出・コピーする極意

「マクロの記録」を使って、なんとか自動化の第一歩を踏み出したあなた。素晴らしい一歩です!
でも、現実に直面していませんか?

*「記録したマクロは、ページ上の全部をコピーしてしまう……」*
*「電気設備レイヤーだけを抜き出して、別の図面ページに移したいのに、壁や家具までついてくる……」*

そう、マクロの記録は「あなたがマウスで何をしたか」をなぞるだけです。「条件によって対象を変える」という、プログラミングの真髄である「ロジック(論理)」を組み込むことはできません。

今日は、マクロの記録という殻を破り、「特定のレイヤーに属するシェイプだけを狙い撃ちしてコピーする」という、実務で最も重宝されるテクニックを伝授します。ここをマスターすれば、Visio VBAの基本はバッチリですよ。

1. コンセプト: 「全選択」から「条件付き選択」へのパラダイムシフト

これまでの「マクロの記録」によるコピーは、おそらくこうでした。
1. `ActivePage.SelectAll`(全部選ぶ)
2. `Selection.Copy`(コピーする)

これでは、不要なものまで付いてきてしまいます。
私たちが目指す「プロの自動化」のロジックは、全く異なります。

理想的なアルゴリズム(手順)

1. ターゲットの特定: コピーしたい「レイヤー名」を決める。
2. 空の選択状態を作る: 一旦、何も選んでいない状態にする。
3. 全シェイプをスキャン: ページ内のシェイプを一つずつ「検問」にかける。
4. レイヤー判定(検問): 「君は『電気設備』レイヤーに入っているかな?」と聞き、YESなら選択リストに追加する。
5. 実行: 選ばれた精鋭たち(シェイプ)だけをコピー&ペーストする。

この「一つずつ調べて、条件に合うものだけを集める」という考え方が、プログラミングにおける「ループ(繰り返し)」と「条件分岐」の基本です。

2. 実装コード: レイヤー抽出コピー・マクロ

さあ、実際に動くコードを見てみましょう。初心者の方でも読みやすいよう、丁寧にコメントを添えました。

Sub CopyShapesByLayerName()
    ' ===========================================================
    ' 目的: 特定のレイヤーに属するシェイプのみを抽出し、別ページへコピーする
    ' ===========================================================
    
    Dim srcPage As Visio.Page       ' コピー元ページ
    Dim destPage As Visio.Page      ' コピー先ページ
    Dim shp As Visio.Shape          ' スキャン中のシェイプ
    Dim targetLayerName As String   ' 抽出したいレイヤーの名前
    Dim sel As Visio.Selection      ' 選択状態を保持するオブジェクト
    Dim i As Integer                ' レイヤー確認用のインデックス
    Dim isMatch As Boolean          ' レイヤーが一致したかどうかのフラグ
    
    ' --- 設定エリア(ここを書き換えて使います) ---
    targetLayerName = "電気設備"    ' ★抽出したいレイヤー名を正確に指定
    ' ------------------------------------------

    ' 1. ページの設定
    ' 現在表示しているページをコピー元、2ページ目をコピー先とする例
    Set srcPage = ActivePage
    On Error Resume Next
    Set destPage = ActiveDocument.Pages(2) ' 2ページ目が存在しないとエラーになるため注意
    On Error GoTo 0
    
    If destPage Is Nothing Then
        MsgBox "コピー先のページ(2ページ目)が見つかりません。", vbCritical
        Exit Sub
    End If

    ' 2. 選択状態の初期化
    ' 一旦、現在の選択をすべて解除します(重要!)
    Set sel = ActiveWindow.Selection
    sel.Clear

    ' 3. シェイプのスキャン(検問プロセス)
    ' コピー元ページの全シェイプに対してループ処理を行う
    For Each shp In srcPage.Shapes
        isMatch = False
        
        ' シェイプが複数のレイヤーを持っている可能性があるため、
        ' そのシェイプが持つ全レイヤーをチェックします
        For i = 1 To shp.LayerCount
            If shp.Layer(i).Name = targetLayerName Then
                isMatch = True
                Exit For ' 一致するものが見つかったら、このシェイプの調査は終了
            End If
        Next i
        
        ' 4. 条件に合致した場合、選択リストに追加
        If isMatch Then
            sel.Add shp
        End If
    Next shp

    ' 5. コピー&ペーストの実行
    If sel.Count > 0 Then
        ' 条件に合うシェイプが見つかった場合
        sel.Copy
        
        ' コピー先ページへ移動して貼り付け
        ' ※ActiveWindowを切り替えないと貼り付け先が制御できないため
        ActiveWindow.Page = destPage
        destPage.Paste
        
        MsgBox targetLayerName & " レイヤーのシェイプをコピーしました。", vbInformation
    Else
        ' 条件に合うシェイプが一つもなかった場合
        MsgBox targetLayerName & " レイヤーに属するシェイプは見つかりませんでした。", vbExclamation
    End If

End Sub

3. アーキテクトの視点: ここが「ハマりどころ」だ!

コードをただコピーするだけでは、一流のエンジニアにはなれません。なぜこの書き方なのか、陥りやすい罠はどこかを理解しましょう。

① `shp.LayerIndex` ではなく `shp.Layer(i).Name` を使う理由

Visioのシェイプは、「複数のレイヤーに同時に所属できる」という特性を持っています。
例えば、「電気設備レイヤー」と「メンテナンス用レイヤー」の両方に所属しているシェイプです。
もし `If shp.LayerIndex = 1` のように番号だけで判定してしまうと、レイヤーの順番が変わった瞬間にマクロが壊れてしまいます。「名前(Name)」で判定するのが、堅牢なコードを書く鉄則です。

② `Selection.Clear` の重要性

もし、マクロを実行する前にユーザーが図面の一部を手動で選択していたらどうなるでしょう?
`sel.Clear` を忘れると、「ユーザーが選んでいたもの + プログラムが選んだもの」が一緒にコピーされてしまいます。自動化ツールは、「常にクリーンな状態から始まる」ことを保証しなければなりません。

③ `ActiveWindow.Page` の切り替え

VBAの世界では、オブジェクト(PageやShape)を操作することと、画面(Window)を操作することは別物です。
`destPage.Paste` と書くだけでは、Visioは「今画面に見えているページ」に貼り付けようとします。確実に指定したページへ貼り付けるには、`ActiveWindow.Page = destPage` を使って、Visioの「視点」を切り替えてあげる必要があります。

4. さらなる高みへ: パフォーマンスを意識する

もし、図面が数千、数万のシェイプを持つ超巨大なものだった場合、`For Each` で一つずつ回す処理は少し重くなるかもしれません。

しかし、初学者の段階では、「正しく動くこと」と「ロジックを理解すること」が最優先です。このコードは、読みやすさと確実性を重視して設計しています。

「何が起きているのか」が手に取るようにわかるコードを書けるようになれば、あなたはもう「マクロの記録」の呪縛から解き放たれています。

まとめ

今回の極意を振り返りましょう。

1. 全選択ではなく、条件に合うものだけを `Selection.Add` で集める。
2. レイヤー判定は、番号ではなく「名前」で行うのが安全。
3. 貼り付けの前には、必ず「視点(ActiveWindow.Page)」を切り替える。

ここをクリアすれば、Visio VBAの基本はバッチリですよ。
次は、コピーした後に「サイズを自動で調整する」なんて処理にも挑戦してみましょう。

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

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