マクロ記録の壁を越える:レイヤー表示状態を「モード」として制御する設計思想
「マクロの記録」ボタンを押して、一生懸命に操作を記録する。
多くのエンジニアが最初に通る道です。しかし、ある時あなたは気づくはずです。
「記録されたコードは、特定の操作の断片でしかない。『設計』ができていない」と。
例えば、複雑な電気配線図を描いているときを想像してください。
「配線だけを見たい」「機器の配置だけを確認したい」「すべてを俯瞰したい」……。
これらをいちいち手動でレイヤーの目玉アイコンをクリックして切り替えるのは、プロフェッショナルの仕事ではありません。
今日は、単なる操作の自動化ではなく、「レイヤーの表示状態を『モード(プリセット)』として管理する」という、一歩上のアーキテクチャ(設計)についてお話ししましょう。ここをマスターすれば、あなたのVisioマクロは「単なる記録」から「洗練されたツール」へと進化します。
1. なぜ「レイヤー切り替え」は単なる記録ではダメなのか?
マクロの記録でレイヤーを非表示にすると、コードには以下のように記録されます。
`ActivePage.Layers(“配線レイヤー”).Cells(“Visible”).Formula = “0”`
これ自体は間違っていません。しかし、問題は「状態の整合性」です。
「配線モード」に切り替えるとき、配線レイヤーを「ON」にするだけでなく、他の「機器レイヤー」や「寸法レイヤー」を適切に「OFF」にする必要があります。
マクロの記録だけでこれをやろうとすると、モードが増えるたびにコードがスパゲッティのように絡まり、修正時に「あ、このモードのときにこのレイヤーを消し忘れた!」というミスが多発します。
解決策:
「どのモードのときに、どのレイヤーがどうあるべきか」という定義(データ)と、それを実行するロジック(命令)を分離して考えるのです。
2. 実装の設計図:モード管理のメカニズム
私たちが構築するのは、以下のような構造です。
1. 定義部: 「配線モードならAはON、BはOFF」というルールを決める。
2. エンジン部: 定義に従って、ページ内の全レイヤーの状態を書き換える共通関数。
3. UI部: ボタン一つでエンジンを叩く、ユーザーインターフェース。
図解するとこのようなイメージです。
[ユーザー操作: ボタンClick]
v
[UI関数: SwitchToMode("配線モード")]
v
[エンジン関数: ApplyLayerPreset(ModeName)] <-- ここが心臓部
+-- ModeName が "配線" なら?
| |-- Layer "Wiring" -> Visible = 1
| |-- Layer "Equip" -> Visible = 0
| └-- Layer "Text" -> Visible = 1
+-- ModeName が "機器" なら?
|-- Layer "Wiring" -> Visible = 0
|-- Layer "Equip" -> Visible = 1
└-- Layer "Text" -> Visible = 0
3. 極限のコード:プロフェッショナルな実装例
では、実際に動くコードを見ていきましょう。
このコードの肝は、「レイヤーが存在しない場合のエラーを回避しつつ、一括で制御する」という堅牢さにあります。
Option Explicit
' =================================================================
' プリセット管理モジュール
' =================================================================
''' <summary>
''' モード名を指定してレイヤーの表示状態を一括切り替えするメインエンジン
''' </summary>
''' <param name="modeName">切り替えたいモード名 ("Wiring", "Equipment", "All")</param>
Public Sub ApplyLayerPreset(ByVal modeName As String)
Dim pg As Visio.Page
Dim lay As Visio.Layer
Dim targetVisible As Boolean
Set pg = ActivePage
' 1. まず、すべてのレイヤーを一旦「非表示」にリセットする設計思想
' (これにより、モードごとの「消し忘れ」を防ぎ、状態をクリーンにします)
On Error Resume Next ' レイヤーが存在しない場合に備える
For Each lay In pg.Layers
lay.Cells("Visible").Formula = "0"
Next lay
On Error GoTo 0 ' エラーハンドリングを元に戻す
' 2. 指定されたモードに基づいて、表示すべきレイヤーを「ON」にする
' ここが「定義」の部分です。モードが増えたらここを編集するだけ。
Select Case modeName
Case "Wiring"
' 【配線モード】配線とテキストだけを表示
SetLayerVisibility pg, "配線レイヤー"
SetLayerVisibility pg, "テキストレイヤー"
Case "Equipment"
' 【機器配置モード】機器とテキストだけを表示
SetLayerVisibility pg, "機器レイヤー"
SetLayerVisibility pg, "テキストレイヤー"
Case "All"
' 【全表示モード】すべてを表示
For Each lay In pg.Layers
lay.Cells("Visible").Formula = "1"
Next lay
Exit Sub ' 全表示の場合はここで終了
Case Else
MsgBox "指定されたモード '" & modeName & "' は定義されていません。", vbExclamation
Exit Sub
End Select
' 完了通知(ユーザーへのフィードバックは親切な設計の基本です)
' MsgBox modeName & " モードに切り替えました。"
End Sub
''' <summary>
''' 指定したレイヤーが存在する場合のみ、表示状態を変更する補助関数
''' </summary>
Private Sub SetLayerVisibility(ByRef pg As Visio.Page, ByVal layerName As String)
Dim lay As Visio.Layer
On Error Resume Next
Set lay = pg.Layers.Item(layerName)
On Error GoTo 0
' レイヤーが存在する場合のみ、表示をONにする
If Not lay Is Nothing Then
lay.Cells("Visible").Formula = "1"
Else
' デバッグ用:レイヤーが見つからない場合はイミディエイトウィンドウに警告
Debug.Print "Warning: レイヤー '" & layerName & "' が見つかりません。"
End If
End Sub
' =================================================================
' UI呼び出し用プロシージャ(ボタンに登録する用)
' =================================================================
Public Sub Button_WiringMode()
ApplyLayerPreset "Wiring"
End Sub
Public Sub Button_EquipmentMode()
ApplyLayerPreset "Equipment"
End Sub
Public Sub Button_ShowAll()
ApplyLayerPreset "All"
End Sub
4. ここが重要!陥りやすいエラーとエンジニアの知恵
このコードを読み解く際、初心者が躓きやすいポイントが3つあります。ここをクリアすれば、あなたはもう「マクロ記録レベル」ではありません。
① 「レイヤーが存在しない」という恐怖
Visioでは、存在しないレイヤーに対して操作を行おうとすると、即座に実行時エラーで止まってしまいます。
私のコードでは、`SetLayerVisibility` という専用の関数を作り、その中で `On Error Resume Next` を使って「レイヤーがある時だけ処理する」というガード(防護柵)を設けています。これが「堅牢なコード」の第一歩です。
② 「リセット」の重要性
多くの人は「表示したいレイヤーをONにする」コードだけを書きます。しかし、それだと「以前にOFFにしたレイヤー」がそのまま残ってしまいます。
「一度すべてをOFFにしてから、必要なものだけをONにする」。この「初期化(リセット)」のプロセスを入れることで、常に予測可能な、クリーンな状態を作り出せるのです。
③ パフォーマンスの重み
レイヤーの数やオブジェクトの数が多い図面では、ループ処理の書き方一つで動作が重くなります。
今回は `pg.Layers` をループしていますが、もし図面が極端に巨大な場合は、表示状態を変えるたびに画面が再描画されるため、Visioの描画更新を一時停止するテクニック(`Application.ScreenUpdating = False` ※Visioでは直接的なプロパティがない場合があるため、描画を抑制する工夫が必要)を検討する段階に入ります。
5. 次のステップへ:さらなる高みを目指すあなたへ
今回の実装では、モードの定義を `Select Case` 文の中に直接書き込みました。これは小〜中規模のツールとしては非常に分かりやすく、メンテナンスもしやすい優れた手法です。
もし、あなたが「数百ものモードを管理したい」「ユーザーが自分でモードを保存できるようにしたい」と考えるなら、次は「設定の外部化」に挑戦してください。
- モードの定義を、Excelのシートに書き出す。
- あるいは、Visioの「ドキュメントプロパティ」や「隠しシェイプ」にデータを格納する。
そうすることで、コードを一行も書き換えることなく、新しい表示パターンを自由に追加できる、真の「プラットフォーム」へと進化させることができます。
まとめ
1. 「操作」を記録するのではなく、「状態」を設計せよ。
2. 「リセット(初期化)」を工程に組み込み、状態の不整合を防げ。
3. 「存在チェック」を怠らず、エラーに強いコードを書け。
一歩ずつ、着実に。
コードの裏側にある「オブジェクトの動き」を意識し始めたとき、あなたの自動化スキルは飛躍的に向上します。応援していますよ!
