【入門編】【中級者向け】特定のレイヤーのみを非表示にしてPDF出力する「出力用レイヤー制御」の自動化 – Visio VBA解析バイブル

スポンサーリンク

こんにちは!Visioでの作図やドキュメント作成、日々の業務でお疲れ様です。

設計図や業務フロー図、ネットワーク構成図などをVisioで作っていると、「社内用コメント」や「作業用の寸法線・補助線」「機密情報を含む注釈」などを特定のレイヤーに分けて管理することがよくありますよね。

でも、いざ顧客提出用や配布用にPDFを出力しようとするとき、こんな経験はありませんか?

  • 出力のたびに「レイヤープロパティ」を開いて、対象レイヤーのチェックを手動で外している
  • 出力後に「あ、元の作業状態に戻すのを忘れて作業を続けてしまった!」と焦る
  • ページ数が多いドキュメントで、全ページのレイヤー設定をポチポチ切り替えるのが苦痛すぎる……

「マクロの記録」を試してみても、Visioのレイヤー操作は記録されにくかったり、出力処理が固定化されて柔軟に動かなかったりと、壁にぶつかりがちです。

今回は、そんな悩みを根本から解消するために、「出力前に指定したレイヤーを自動で非表示(または非印刷)にし、PDF出力が終わったら魔法のように元のレイヤー状態へ完全復元する」という本格的なVBAスクリプトを構築してみましょう。

ここをマスターすれば、Visio VBAのオブジェクト構造の基本と、実務で絶対に壊れない安全なコードの書き方がしっかり身につきますよ!

—

1. Visioの「レイヤー」の仕組みを正しく知ろう

コードを書く前に、Visioがレイヤーをどう管理しているのかを少しだけ覗いてみましょう。ここを知っておくと、コードが何をしているのかがスッと頭に入ってきます。

レイヤーは「ページごと」に独立して存在する

まず最も重要なポイントです。IllustratorやPhotoshopと異なり、Visioのレイヤーはドキュメント全体ではなく「ページごと」に所属しています。
そのため、VBAでレイヤーを操作するときは、必ず対象の `Page` オブジェクトを経由してアクセスします。

[ ActiveDocument (ドキュメント) ]
│
└─ [ Pages (ページ一覧) ]
│
└─ [ Page (特定のページ) ]
│
└─ [ Layers (レイヤー一覧) ]
│
└─ [ Layer (操作対象のレイヤー) ]

レイヤーの裏側には「ShapeSheet」のセルがある

Visioのすべてのグラフィックス設定は「ShapeSheet(シェイプシート)」と呼ばれるスプレッドシートのようなセル構造で動いています。レイヤーの表示・非表示も例外ではありません。

レイヤーのプロパティを変更するときは、Layerオブジェクトが持つ `CellsC` プロパティを使って該当セルを書き換えます。

  • 表示 / 非表示: `visLayerVisible`(値: 1 = 表示, 0 = 非表示)
  • 印刷する / しない: `visLayerPrint`(値: 1 = 印刷対象, 0 = 印刷対象外)

今回は画面上でもプレビューが崩れないよう、またPDF出力にも確実に反映されるよう、「表示(Visible)」と「印刷(Print)」の両方を安全にコントロールしていきます。

—

2. 失敗しないスクリプトの設計思想

中級者へのステップアップとして極めて大切なのが、「処理前の状態を覚えておき、何があっても元通りに戻す(ステート復元)」という設計です。

もし出力処理の途中でエラーが起きてマクロが止まってしまったらどうなるでしょうか?
作業レイヤーが消えたままになり、「図形が消えた!?」とユーザーがパニックになってしまいますよね。

そのため、処理の流れは次のように組み立てます。

【ステップ 1】現在の全ページのレイヤー状態(Visible / Print)をメモリに退避
↓
【ステップ 2】指定した除外レイヤー(例: “社内メモ”, “作業用グリッド”)を非表示・非印刷に設定
↓
【ステップ 3】PDFとしてエクスポートを実行
↓
【ステップ 4】(成功・失敗にかかわらず)メモリから元の状態を完全復元

この「何があっても元の状態に戻す」アプローチこそ、現場で信頼されるプロの自動化コードの証です。

—

3. 実践コード:出力用レイヤー制御&PDF出力マクロ

それでは、標準モジュールにそのまま貼り付けて使える実用コードを見てみましょう。
まずはコード全体を眺めてみてください。コメントも細かく記載しています。

Option Explicit

‘ ==============================================================================
‘ 処理名: ExportPdfWithHiddenLayers
‘ 概要 : 指定されたレイヤーを一時的に非表示/非印刷にしてPDFを出力し、
‘ 出力完了後に元のレイヤー状態を完全復元する
‘ ==============================================================================
Public Sub ExportPdfWithHiddenLayers()
Dim targetDoc As Visio.Document
Set targetDoc = Visio.ActiveDocument

‘ ドキュメントが開かれていない場合は終了
If targetDoc Is Nothing Then
MsgBox “対象のVisioドキュメントが開かれていません。”, vbExclamation, “中断”
Exit Sub
End If

‘ ————————————————————-
‘ 1. 出力設定:非表示にしたいレイヤー名とPDF出力先パスを指定
‘ ————————————————————-
Dim excludeLayerNames As Variant
‘ 非表示にしたいレイヤー名を配列で指定(大文字・小文字は区別されません)
excludeLayerNames = Array(“社内メモ”, “作業用”, “Internal_Note”, “DRAFT”)

‘ 出力するPDFのフルパス(元ファイルと同じフォルダに出力)
Dim pdfPath As String
If Len(targetDoc.Path) = 0 Then
‘ 保存されていない新規ドキュメントの場合のフォールバック
pdfPath = Environ(“USERPROFILE”) & “\Desktop\” & “Output_” & Format(Now, “yyyymmdd_hhnnss”) & “.pdf”
Else
pdfPath = targetDoc.Path & Replace(targetDoc.Name, “.vsdx”, “”) & “_Export.pdf”
End If

‘ ————————————————————-
‘ 2. 高速化 & 画面描画の停止
‘ ————————————————————-
Dim app As Visio.Application
Set app = Visio.Application

Dim prevScreenUpdating As Boolean
prevScreenUpdating = app.ScreenUpdating
app.ScreenUpdating = False ‘ 画面のチラつきを防止し高速化

‘ 状態を保存するためのDictionaryオブジェクト (Scripting.Dictionary)
Dim layerStateSnapshot As Object
Set layerStateSnapshot = CreateObject(“Scripting.Dictionary”)

On Error GoTo ErrorHandler

‘ ————————————————————-
‘ 3. レイヤー状態の退避 & 対象レイヤーの非表示化
‘ ————————————————————-
Dim pg As Visio.Page
Dim lyr As Visio.Layer
Dim pageKey As String
Dim lyrKey As String
Dim isExclude As Boolean
Dim i As Long

For Each pg In targetDoc.Pages
‘ 背景ページではなく前景ページのみを対象にする場合は条件を追加可能
pageKey = pg.Name

For Each lyr In pg.Layers
lyrKey = pageKey & “::” & lyr.Name

‘ 現在の状態を退避 (Visible, Print)
‘ 配列として格納: (0) = visLayerVisible, (1) = visLayerPrint
layerStateSnapshot.Add lyrKey, Array( _
lyr.CellsC(visLayerVisible).ResultStr(“”), _
lyr.CellsC(visLayerPrint).ResultStr(“”) _
)

‘ 除外レイヤー名に一致するかチェック
isExclude = False
For i = LBound(excludeLayerNames) To UBound(excludeLayerNames)
If StrComp(Trim(lyr.Name), Trim(excludeLayerNames(i)), vbTextCompare) = 0 Then
isExclude = True
Exit For
End If
Next i

‘ 対象レイヤーの場合、非表示かつ非印刷に設定
If isExclude Then
lyr.CellsC(visLayerVisible).FormulaU = “0”
lyr.CellsC(visLayerPrint).FormulaU = “0”
End If
Next lyr
Next pg

‘ ————————————————————-
‘ 4. PDF出力の実行
‘ ————————————————————-
‘ ExportAsFixedFormat を使用して全ページを高品質PDFに出力
targetDoc.ExportAsFixedFormat _
visFixedFormatPDF, _
pdfPath, _
visDocExIntentPrint, _
visPrintAll

MsgBox “PDFの出力が完了しました!” & vbCrLf & pdfPath, vbInformation, “完了”

CleanUp:
‘ ————————————————————-
‘ 5. レイヤー状態の完全復元 (後始末)
‘ ————————————————————-
If Not layerStateSnapshot Is Nothing Then
For Each pg In targetDoc.Pages
pageKey = pg.Name
For Each lyr In pg.Layers
lyrKey = pageKey & “::” & lyr.Name
If layerStateSnapshot.Exists(lyrKey) Then
‘ 退避していた元の設定値に戻す
lyr.CellsC(visLayerVisible).FormulaU = layerStateSnapshot(lyrKey)(0)
lyr.CellsC(visLayerPrint).FormulaU = layerStateSnapshot(lyrKey)(1)
End If
Next lyr
Next pg
End If

‘ 画面描画を元に戻す
app.ScreenUpdating = prevScreenUpdating
Exit Sub

ErrorHandler:
MsgBox “PDF出力中にエラーが発生しました。” & vbCrLf & _
“エラー番号: ” & Err.Number & vbCrLf & _
“エラー内容: ” & Err.Description, vbCritical, “エラー”
Resume CleanUp
End Sub

—

4. プロの技を紐解く!コードの解説

「動いたからOK!」で終わらせず、中身でどんな工夫をしているのかを深掘りしてみましょう。ここが分かると、Visio VBAの他の自動化にも応用が効くようになりますよ。

① `layerStateSnapshot`(Dictionary)による状態の退避

レイヤーのキーとして `ページ名::レイヤー名` という文字列を作っています。
冒頭でお話しした通り、Visioのレイヤーはページごとに独立しています。そのため、「レイヤー名」だけで保存してしまうと、同名のレイヤーが複数ページにある場合に設定が上書きされて混ざってしまいます。
ページ名とセットでキーにしてDictionaryに退避させるのが、破綻しないための鉄則です。

② `.FormulaU = “0”` で確実に書き換える

セルの値を変更するときに、`.Result` ではなく `.FormulaU = “0”` を使っています。
ShapeSheetの仕様上、セルの論理値(TRUE/FALSE や 1/0)を設定する際は、言語環境に左右されないユニバーサルプロパティ(`FormulaU`)に `”0″` や `”1″` の文字列として渡すのが最も安全です。

③ `On Error GoTo ErrorHandler` と `CleanUp:` ラベル

プログラムに予期せぬトラブル(例:出力先のPDFが別アプリで開かれていてロックされていた、など)が起きても、絶対にレイヤーを非表示にしたまま終わりたくありません。
そのため、エラーが発生した場合は即座に `ErrorHandler` にジャンプし、最終的に必ず `CleanUp:` を通過してレイヤーを元通りに修復してから終了する構造にしています。

④ `Application.ScreenUpdating = False`

Visioで多数のページやレイヤーのプロパティをループ処理で書き換えると、画面が激しく再描画され、処理速度が大幅に低下します。
開始時に `ScreenUpdating = False` にしておき、最後に `True` に戻すことで、実行スピードが格段に上がり、スマートな挙動になります。

—

5. つまずきやすいポイントとTips

現場でこのコードを適用する際、よくある疑問やカスタマイズ方法をまとめました。

Q. 「特定のページだけ」出力したい場合は?

`ExportAsFixedFormat` メソッドの引数を少し変えるだけで対応できます。
例えば、現在のページだけを出力したい場合は、第4引数を以下のように書き換えてみてください。

targetDoc.ExportAsFixedFormat _
visFixedFormatPDF, _
pdfPath, _
visDocExIntentPrint, _
visPrintCurrentPage ‘ ← カレントページのみを出力

Q. レイヤー名を部分一致で判定したい

「メモ」という文字が含まれるレイヤーをすべて除外したい場合は、コード内の比較部分で `InStr` 関数を使うと便利です。

‘ 部分一致で判定したい場合(例:「メモ」が含まれていたら除外)
If InStr(1, lyr.Name, “メモ”, vbTextCompare) > 0 Then
isExclude = True
End If

—

まとめ:ここをクリアすれば、Visio VBAの基本はバッチリ!

今回は、手作業でやると面倒でミスの温床になりやすい「特定レイヤーを非表示にしてのPDF出力」を、状態復元まで含めて完全自動化する方法を学びました。

今回のポイントをおさらいしましょう:
1. Visioのレイヤーは「ページごと」に存在する(Pageオブジェクトから取得)
2. レイヤーの表示・非表示は `visLayerVisible` / `visLayerPrint` セルで操作する
3. 「退避 → 変更 → 出力 → 復元」の流れを作り、エラー処理で確実に元の状態へ戻す

この「ShapeSheetセルを意識した操作」と「エラーに強いステート管理」ができれば、もうマクロ記録初心者は完全に卒業です。胸を張って実務の効率化に役立ててくださいね!

もし試してみて分からない点や、追加で自動化したいアイデアがあれば、いつでも気軽に相談してください。快適なVisio自動化ライフを応援しています!

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