こんにちは! Visioの定型作業に日々頭を悩ませていませんか?
「同じ図面なのに、社内用にはすべての情報を載せ、顧客用には機密情報を隠したバージョンを作りたい」
「しかも、それを数十枚の図面ファイルに対して毎回手作業でレイヤーをポチポチ切り替えてPDF書き出し……考えただけで発狂しそう!」
よくぞこのページにたどり着きました。
今回は、マクロの記録の先にある「真のVisio自動化」の世界へあなたを招待します。Visio VBAを駆使して、レイヤーの表示状態をプログラムで自在に操り、ワンクリックで複数のPDFバリエーションを爆速生成する極意を伝授しましょう。
ここをクリアすれば、あなたのVisio VBAスキルは間違いなく中級者の領域に突入します。さあ、一緒にコードの海へ繰り出しましょう!
—
なぜ「レイヤー制御×PDF出力」でVBAを使うのか?
Visioの図面(.vsdx)には、情報を整理するための「レイヤー(Layer)」という強力な機能があります。
手動でPDFを出力する場合、以下のような手順を踏むはずです。
1. [表示] タブ > [レイヤー プロパティ] を開く
2. 不要なレイヤーの「表示」チェックを外す
3. [ファイル] > [名前を付けて保存] でPDF形式を選択し、出力する
4. 再びレイヤー画面を開き、別のパターンに切り替えて……(繰り返し)
これを複数ページ、複数ファイルでやったらどうなるでしょう? 想像しただけでヒューマンエラーの温床になりますよね。
VBAを使えば、この一連の泥臭い作業をコンマ数秒のバッチ処理に変換できます。しかも、元の図面の状態を汚さず(作業後に元の状態へ復元して)、メモリ上で華麗にPDFを量産することが可能です。
—
実装の全体像とアーキテクチャの極意
今回作成するマクロの戦略はこうです。
1. 対象ページの特定: アクティブなページの全レイヤーオブジェクトを走査する。
2. 状態のバックアップ: 処理前のレイヤーの表示/非表示状態を退避させておく(これ、プロの鉄則です!)。
3. バリエーションごとの切り替え: 「社内用」「顧客用」などのルールに従い、レイヤーの `CellsC(visLayerVisible)` プロパティを書き換える。
4. PDF出力: `ExportAsFixedFormat` メソッドを叩く。
5. 復元: 処理が終わったら、ステップ2で退避させた状態に戻す。
それでは、実際のコードを見ていきましょう。開発画面(`Alt + F11`)を開き、標準モジュールに貼り付けてください。
—
実用VBAコード:レイヤー切り替えPDFバッチ出力エンジン
Option Explicit
‘ ==============================================================================
‘ 概要: アクティブなVisioページのレイヤー状態を動的に切り替え、
‘ 「社内用」「顧客用」の2パターンのPDFを同時に自動出力するプロシージャ
‘ ==============================================================================
Public Sub ExportPdfVariants()
Dim vsoPage As Visio.Page
Dim vsoLayer As Visio.Layer
Dim i As Long
‘ エラーハンドリングの基本(トラブル時に図面が壊れたままになるのを防ぐ)
On Error GoTo ErrorHandler
‘ 1. 現在アクティブなページを取得
Set vsoPage = Visio.ActivePage
If vsoPage Is Nothing Then
MsgBox “処理対象のページが見つかりません。”, vbCritical, “エラー”
Exit Sub
End If
‘ 2. レイヤーが存在するかチェック
If vsoPage.Layers.Count = 0 Then
MsgBox “このページにはレイヤーが設定されていません。”, vbExclamation, “確認”
Exit Sub
End If
‘ 出力先のパスを設定(ここではデスクトップを指定)
Dim deskTopPath As String
deskTopPath = CreateObject(“WScript.Shell”).SpecialFolders(“Desktop”) & “\”
Dim baseFileName As String
baseFileName = Left(Visio.ActiveDocument.Name, InStrRev(Visio.ActiveDocument.Name, “.”) – 1)
If baseFileName = “” Then baseFileName = “VisioOutput”
‘ ==========================================
‘ パターンA:「社内用」PDFの出力(全レイヤーを表示)
‘ ==========================================
Debug.Print “— 社内用PDFの出力開始 —”
For i = 1 to vsoPage.Layers.Count
Set vsoLayer = vsoPage.Layers(i)
‘ 担当者メモや非公開レイヤーも含めてすべて表示する (1 = 表示, 0 = 非表示)
vsoLayer.CellsC(visLayerVisible).FormulaU = “1”
Next i
‘ PDFエクスポート実行
Call OutputPdf(vsoPage, deskTopPath & baseFileName & “_【社内用】.pdf”)
‘ ==========================================
‘ パターンB:「顧客用」PDFの出力(特定のレイヤーを隠す)
‘ ==========================================
Debug.Print “— 顧客用PDFの出力開始 —”
For i = 1 to vsoPage.Layers.Count
Set vsoLayer = vsoPage.Layers(i)
‘ レイヤー名に「社内秘」が含まれている場合は強制的に非表示にする
If InStr(1, vsoLayer.Name, “社内秘”, vbTextCompare) > 0 Then
vsoLayer.CellsC(visLayerVisible).FormulaU = “0”
Else
vsoLayer.CellsC(visLayerVisible).FormulaU = “1”
End If
Next i
‘ PDFエクスポート実行
Call OutputPdf(vsoPage, deskTopPath & baseFileName & “_【顧客用】.pdf”)
MsgBox “すべてのPDFバッチ出力が完了しました!”, vbInformation, “成功”
Exit Sub
ErrorHandler:
MsgBox “予期せぬエラーが発生しました: ” & Err.Description, vbCritical, “致命的なエラー”
End Sub
‘ ==============================================================================
‘ 内部関数: 渡されたページを指定パスへPDFとして出力するヘルパー関数
‘ ==============================================================================
Private Sub OutputPdf(targetPage As Visio.Page, outputPath As String)
‘ VisioのExportAsFixedFormatメソッドを使用
‘ 第1引数: 形式 (visFixedFormatPDF = 1)
‘ 第2引数: 出力ファイルパス
‘ 第3引数: 発行範囲 (visDocSelection = 1, visDocCurrentPage = 2 など)
‘ 第4引数: 品質・オプション設定
targetPage.ExportAsFixedFormat _
Visio.VisFixedFormatTypes.visFixedFormatPDF, _
outputPath, _
Visio.VisPrintixenOptions.visPrintAllPages, _
Visio.VisDocExPrintRange.visDocExAll
Debug.Print “出力完了: ” & outputPath
End Sub
—
ジュワッとコードが染み込んできた頃でしょうか。ここからは、中級者として絶対に押さえておかなければならない「Visio VBAの急所」を解説します。
1. なぜ `.CellsC(visLayerVisible).FormulaU = “1”` なのか?
Visioのオブジェクトモデルにおいて、レイヤーの「表示/非表示」はシェイプシート(ShapeSheet)のセルとして管理されています。
直接プロパティ(例: `vsoLayer.Visible = True` のようなもの)が存在しないケースが多いVisioの世界では、「セルの数式(Formula)を書き換える」というアプローチが基本になります。
`”1″` は「表示(True)」、`”0″` は「非表示(False)」を意味する文字列(FormulaU)として渡すのがVisio VBAのお作法です。末尾の `U` は Universal(言語非依存の英語表記)を意味し、多言語環境でのバグを防ぐプロの必須テクニックです。
2. `InStr` 関数によるレイヤー名の動的判定
コード内では、レイヤー名に「社内秘」という文字列が含まれているかどうかを `InStr` 関数で判定しています。
これにより、図面ごとにレイヤーのインデックス番号(何番目か)が変わってしまっても、「レイヤー名 さえルール通りに命名されていれば、コードが崩れない」という堅牢性(ロバストネス)の高い設計を実現しています。
—
現場でよくある「ハマりどころ」と対策
罠その1:PDF出力後にレイヤーの状態が戻らなくて焦る
上記のコードでは説明の簡略化のために省いていますが、実務では「処理が異常終了したときのために、元のレイヤー状態を配列等に退避させ、Finally句的なアプローチ(あるいはエラー処理内)で復元する」実装が望ましいです。
`On Error` を使う場合は、エグジット前に必ず状態を復元するルーチンを通すように心がけましょう。
罠その2:Adobe Acrobatとのバッティングで保存エラー
VisioからPDFを書き出す際、出力先のファイルがすでに開かれていたり(Acrobatなどでプレビュー中)、書き込み権限がないフォルダーを指定していると、`ExportAsFixedFormat` メソッドで容赦なくランタイムエラーが発生します。
実務で組む際は、出力前に `Dir` 関数などで同名ファイルが存在するかチェックし、上書き確認やリネーム処理を挟むと完璧です。
—
おわりに:ここから先を目指すあなたへ
お疲れ様でした! このコードをマスターすれば、あなたは単なる「Visioの操作係」から「業務自動化エンジニア」へとシフトアップ完了です。
ここをクリアしたあなたなら、次は「1つの図面ファイルだけでなく、指定フォルダー内にあるすべての `.vsdx` ファイルをループ処理して、このPDF一括変換をバッチ処理する」という上位課題にも挑戦できるはずです(FileSystemObjectの出番ですね)。
Visio VBAは一見とっつきにくいですが、オブジェクトの構造さえ掴めば最強の相棒になります。ぜひ、日々の業務をコードの力でハックしてみてください。それでは、また次の極知見でお会いしましょう!
