やあ、業務自動化の世界へようこそ!Visio VBAの深遠な魅力を伝える技術ブログへようこそ。
ExcelやWordのマクロを触ったことがある方でも、VisioのVBAに足を踏み入れると「あれ、なんだか勝手が違うぞ?」と戸惑うことがよくあります。特に、大規模なネットワーク構成図や複雑な業務フローチャートを扱っていると、「大量のページを自動で作成・整理したい」「条件に合わせて不要なページを消し去りたい」という場面に必ず直面します。
マクロの記録から一歩踏み出し、Visioの「図面空間」を自在にコントロールできるようになると、業務効率は桁違いに跳ね上がります。
今回は、Visioの心臓部であるPageオブジェクトに焦点を当て、アクティブページの切り替え、ページの動的追加・削除の完全自動化について、本質からしっかり解説します。ここをクリアすれば、Visio VBAの基本はバッチリですよ!
—
1. Visioの「図面空間」を理解する:オブジェクトモデルの階層構造
コードを書く前に、まずはVisioが裏側でどのようにページを管理しているのか、その構造(オブジェクトモデル)を頭に描いてみましょう。
[ Application ] (Visio全体)
│
└── [ ActiveDocument / Documents ] (ファイル)
│
└── [ Pages ] (ページコレクション)
│
├── [ Page 1 ] ── [ Shapes ] (図形群)
├── [ Page 2 ] ── [ Shapes ]
└── [ Page 3 (Background) ]
UI(画面)で見えているものと、VBAが見ているものの違い
ユーザーがマウスでタブをクリックして切り替えているのは、画面上の「表示(Window)」です。しかし、VBAの内部では「画面に表示されていなくても、メモリ上に存在するページ」を直接操作できます。
- `Application.ActiveWindow.Page`: 今、画面上でユーザーの目に触れているページ(UI依存)。
- `Document.Pages(“ページ名”)`: 画面表示とは無関係に、メモリ上で直接参照するページ(UI非依存・高速)。
プロのエンジニアは、可能な限り「画面の表示切替」を行わずに、裏側で(メモリ上で)処理を完結させます。これが処理速度を極限まで高め、画面のチラつきを防ぐ極意なのです。
—
2. 実践①:アクティブページの切り替えと安全な巡回
まずは、図面内のページを安全に切り替える・巡回する基本パターンを学びましょう。
画面上の表示ページを切り替えるには、`ActiveWindow.Page` プロパティに目的の `Page` オブジェクトを代入します。
サンプルコード:全ページを巡回して名前を表示する
Public Sub TraverseAllPages()
Dim visDoc As Visio.Document
Dim targetPage As Visio.Page
‘ 現在アクティブなドキュメントを取得
Set visDoc = Visio.ActiveDocument
‘ ドキュメントが存在しない場合は安全に抜け出す
If visDoc Is Nothing Then
MsgBox “ドキュメントが開かれていません。”, vbExclamation
Exit Sub
End If
‘ 描画更新を一時停止(パフォーマンス向上&画面チラつき防止)
Visio.Application.ScreenUpdating = False
On Error GoTo ErrorHandler
‘ Pagesコレクションをループ処理
For Each targetPage In visDoc.Pages
‘ バックグラウンドページ(背景)かフォアグラウンドページかを判定
If targetPage.Background = 0 Then
Debug.Print “フォアグラウンドページ: ” & targetPage.Name
‘ 必要に応じて画面上のアクティブページを切り替える
‘ Visio.ActiveWindow.Page = targetPage
Else
Debug.Print “背景ページ: ” & targetPage.Name
End If
Next targetPage
MsgBox “全ページの巡回が完了しました!”, vbInformation
CleanUp:
‘ 画面描画の再開(必ず元に戻す!)
Visio.Application.ScreenUpdating = True
Exit Sub
ErrorHandler:
MsgBox “エラーが発生しました: ” & Err.Description, vbCritical
Resume CleanUp
End Sub
💡 先輩からのワンポイント解説
- `Visio.Application.ScreenUpdating = False`:
画面の再描画をストップさせる魔法の命令です。ページ数が多くなると描画負荷で処理が極端に遅くなりますが、これを挟むだけで数倍〜数十倍の高速化が図れます。処理終了時には必ず `True` に戻すのが鉄則です。
- `targetPage.Background`:
Visioのページには「前面(フォアグラウンド: `0`)」と「背景(バックグラウンド: `1`)」があります。自動化処理の対象が前面だけの場合は、このプロパティでチェックを挟むのが作法です。
—
3. 実践②:ページの動的追加(ライフサイクルの制御)
次に、条件に応じて新しいページを自動生成してみましょう。
ページを追加するには `Pages.Add` メソッドを使用します。しかし、単純に追加するだけでは「同名のページがすでに存在してエラーになる」という落とし穴にハマりがちです。
サンプルコード:重複チェック付きのスマートなページ追加
Public Sub AddNewPageSmart()
Dim visDoc As Visio.Document
Dim newPage As Visio.Page
Dim newPageName As String
Set visDoc = Visio.ActiveDocument
newPageName = “詳細設計図_01”
‘ 1. すでに同名のページが存在するか確認
If PageExists(visDoc, newPageName) Then
MsgBox “ページ ‘” & newPageName & “‘ は既に存在します。”, vbInformation
Exit Sub
End If
‘ 2. ページの追加
‘ Pages.Add メソッドを実行すると、新しい Page オブジェクトが返されます
Set newPage = visDoc.Pages.Add
‘ 3. ページ名の設定
newPage.Name = newPageName
‘ 4. 用紙サイズや向きをコードから設定(例:A4横向きに設定)
‘ ※ Visioの標準セル(PageWidth / PageHeight)を操作します
newPage.PageSheet.CellsSRC(visSectionObject, visRowPage, visPageWidth).FormulaU = “297 mm”
newPage.PageSheet.CellsSRC(visSectionObject, visRowPage, visPageHeight).FormulaU = “210 mm”
MsgBox “新しいページ ‘” & newPage.Name & “‘ を作成しました!”, vbInformation
End Sub
‘ — ヘルパー関数:ページの存在チェック —
Private Function PageExists(ByVal doc As Visio.Document, ByVal pageName As String) As Boolean
Dim pg As Visio.Page
On Error Resume Next
‘ 指定した名前のページを直接取得してみる
Set pg = doc.Pages(pageName)
On Error GoTo 0
‘ オブジェクトが取得できれば「存在(True)」
PageExists = Not (pg Is Nothing)
End Function
💡 コードの意味とポイント
`Pages.Add` を呼び出すと、Visioは自動的にデフォルト名(`Page-1` など)で新しいページを最背面に作成します。生成された `Page` オブジェクトに対して `.Name` を上書き指定するのが安全な流れです。
また、`PageSheet`(シェイプシート)のセルを操作して、用紙サイズをA4横(297mm × 210mm)にプログラムから動的変更している点も、実際の開発現場で重宝するテクニックです。
—
4. 実践③:ページの自動削除と「逆順ループ」の鉄則
仕様変更やデータクリーンアップの際、「特定の条件を満たす不要なページを一括削除したい」というニーズが発生します。ここにはプログラミング初学者が最も陥りやすい巨大な罠が存在します。
🚨 陥りやすい罠:コレクションの順方向ループ削除
例えば、1ページ目から順番に削除しようとするとどうなるでしょうか?
‘ ❌ ダメな例:インデックスがずれてエラーや飛ばしが発生する!
For i = 1 To visDoc.Pages.Count
If visDoc.Pages(i).Name Like “Temp” Then
visDoc.Pages(i).Delete 1 ‘ 1を消すと、2だったページが1にズレる!
End If
Next i
要素を削除すると、後ろにあった要素の番号(インデックス)が1つずつ前に詰まります。その結果、ループのカウントだけが進んで処理がスキップされたり、存在しないインデックスにアクセスしてエラーになります。
正解:末尾からの「逆順ステップループ(Step -1)」
コレクションの削除処理は、常に一番後ろの要素から前へ向かって行うのが黄金律です。
サンプルコード:特定条件ページの安全な一括削除
Public Sub DeleteTemporaryPages()
Dim visDoc As Visio.Document
Dim i As Long
Dim targetPage As Visio.Page
Set visDoc = Visio.ActiveDocument
Visio.Application.ScreenUpdating = False
On Error GoTo ErrorHandler
‘ 最後のページから最初のページに向かって逆順でループ!
For i = visDoc.Pages.Count To 1 Step -1
Set targetPage = visDoc.Pages(i)
‘ 条件判定:名前に “Temp” または “一時” が含まれているか?
If targetPage.Name Like “Temp” Or targetPage.Name Like “一時” Then
‘ 最後の1枚のページを消そうとするとVisio仕様上エラーになるため保護
If visDoc.Pages.Count = 1 Then
MsgBox “ドキュメントには最低1つのページが必要です。削除を中断します。”, vbExclamation
Exit For
End If
Debug.Print “削除中: ” & targetPage.Name
‘ Delete(1) の 引数 ‘1’ は「関連するオブジェクトも含めて削除する」の意(定数: visDeleteRefShapes)
targetPage.Delete 1
End If
Next i
MsgBox “不要ページのクリーンアップが完了しました!”, vbInformation
CleanUp:
Visio.Application.ScreenUpdating = True
Exit Sub
ErrorHandler:
MsgBox “削除処理中にエラーが発生しました: ” & Err.Description, vbCritical
Resume CleanUp
End Sub
—
5. 現場で勝つための「ハマりポイント」回避マニュアル
開発現場でトラブルに直面したときは、以下のチェックリストを思い出してください。
| 現象・エラー | 原因 | 解決策 |
| :— | :— | :— |
| `ページを削除できません` | ドキュメント内の「最後の1枚」を削除しようとしている | 事前に `Pages.Count > 1` を確認するチェックガードを入れる |
| 画面がフリーズしたように見える | `ScreenUpdating = False` のままマクロがエラー終了した | エラーハンドラ(`ErrorHandler`)の `CleanUp:` 節で必ず `True` に戻す |
| 削除時にダイアログが止める | 削除の警告ダイアログが表示されている | `Visio.Application.AlertResponse = vbYes` で応答を自動化するか、`Delete(1)` を使用する |
| 追加したページが変な場所に入る | デフォルトの追加位置制御 | 追加後にページの順序を並べ替える場合は `Page.Index` を調整する |
—
まとめ:ページ空間を制する者がVisioを制す
今回はVisio VBAの根幹をなす Pageオブジェクト を扱い、以下の極意を学びました。
1. 画面の切り替え(`ActiveWindow.Page`)とメモリ上の操作(`Pages(“名”)`)を意識して使い分ける
2. `ScreenUpdating = False` で描画を止め、処理速度を爆発的に引き上げる
3. 動的な追加時は同名チェック、削除時は「逆順ループ(`Step -1`)」を絶対ルールとする
この3つの原則さえ身につけておけば、何百枚に及ぶ大規模な図面ドキュメントであっても、一瞬で生成・整形・クリーンアップする強力な自動化ツールを構築できます。
ここをクリアできれば、Visio VBAの基本はバッチリですよ!
次は、各ページの中に配置される「Shape(図形)オブジェクト」の自動制御にチャレンジしてみましょう。あなたの業務自動化ライフが、より一層輝くことを応援しています!
