マクロの記録から卒業しよう。Visio VBAで実現する「特定ページの一括抽出」という魔法
こんにちは。現場で数々の自動化プロジェクトを指揮してきた、チーフアーキテクトの私です。
「数百枚もある図面の中から、特定のプロジェクト名が入ったページだけを抜き出して、新しいファイルにまとめてほしい」
こんな依頼を上司から受けたとき、あなたならどうしますか?
一つひとつページを選び、コピーし、新しいファイルを作って貼り付ける……。もしそう考えているなら、少しだけ立ち止まってください。その作業、たった数秒の「コード」で終わらせることができるんです。
今日は、マクロの記録機能(レコーダー)の限界を超え、プログラムに「思考」を持たせるための第一歩。「特定の文字列を含むページを検索し、別ファイルへ自動エクスポートするツール」の作り方を伝授します。
ここをクリアすれば、あなたは「Visioを使える人」から「Visioを操るエンジニア」へと進化できるはずですよ。
1. 「マクロの記録」と「VBA」の決定的な違い
まず、大切なマインドセットの話をしましょう。
多くの初心者は「マクロの記録」ボタンを押します。これは、あなたがマウスで行った操作を、Visioが「手順」として記録してくれる機能です。しかし、レコーダーには致命的な弱点があります。それは、「条件分岐(もし〜だったら)」ができないということです。
レコーダーは「Aというページをコピーする」ことは記録できますが、「もしページ名に『2023年度』という文字が入っていたら、コピーする」という判断はできません。
今回作るツールに必要なのは、単なる操作の記録ではなく、「検索して、判断して、実行する」というロジック(論理)です。これがVBA(Visual Basic for Applications)の本質なのです。
2. 抽出ツールの設計図(アルゴリズム)
いきなりコードを書き始めるのは、設計図なしで家を建てるようなものです。まずは、プログラムがどのような手順で動くのか、頭の中で整理しましょう。
1. 準備: 検索したい「キーワード」を決める。
2. 器作り: 抽出したページを格納するための「新しいVisioファイル」をメモリ上に用意する。
3. 探索(ループ): 元のファイルの全ページを、端から順番に見ていく。
4. 判定(条件分岐):
- ページ名に「キーワード」が含まれているか?
- 含まれていれば $\rightarrow$ そのページの中身をコピーして、新しいファイルに貼り付ける。
- 含まれていなければ $\rightarrow$ 次のページへ進む。
5. 完了: 新しいファイルを保存して終了。
この「順番に見ていく(ループ)」と「もし〜なら(条件分岐)」という2つの武器さえあれば、どんな複雑な自動化も実現できます。
3. 実装:ページ抽出エクスポート・マクロ
それでは、魂を込めたコードを公開します。このコードは、そのままVisioのVBAエディタに貼り付けて動作するように設計しています。
Option Explicit
''' <summary>
''' 特定の文字列を含むページを検索し、新しいファイルへ抽出するメインルーチン
''' </summary>
Sub ExportPagesByKeyword()
Dim srcDoc As Visio.Document
Dim destDoc As Visio.Document
Dim pg As Visio.Page
Dim newPg As Visio.Page
Dim shp As Visio.Shape
Dim searchKeyword As String
Dim foundCount As Integer
Dim savePath As String
' --- 設定エリア ---
' 抽出したいキーワードを指定してください
searchKeyword = "プロジェクトA"
' 保存先のパス(デスクトップに「抽出結果.vsdx」として保存する例)
savePath = Environ("USERPROFILE") & "\Desktop\抽出結果.vsdx"
' ------------------
Set srcDoc = ActiveDocument
foundCount = 0
' 1. 新しいドキュメントを作成(抽出用の器)
' ※ここではテンプレートを使用せず、新規作成します
Set destDoc = Documents.Add
On Error GoTo ErrorHandler ' エラーが発生した場合の備え
' 2. 元のドキュメントの全ページをループで回す
For Each pg In srcDoc.Pages
' 3. ページ名にキーワードが含まれているか判定 (InStr関数を使用)
' vbTextCompare を指定することで、大文字・小文字を区別せずに検索します
If InStr(1, pg.Name, searchKeyword, vbTextCompare) > 0 Then
foundCount = foundCount + 1
Debug.Print "発見: " & pg.Name ' イミディエイトウィンドウにログ出力
' 4. 新しいドキュメントにページを追加
' 元のページの構成に合わせるため、新しいページを作成
Set newPg = destDoc.Pages.Add
newPg.Name = pg.Name ' ページ名を同じにする
' 5. シェイプのコピー&ペースト
' ページ内のすべてのシェイプをループしてコピーします
For Each shp In pg.Shapes
shp.Copy
newPg.Paste
Next shp
' ※補足:ページ設定(サイズ等)を厳密に合わせる場合は、
' ここで newPg.PageSetup を調整する処理を追加します。
End If
Next pg
' 6. 結果の処理
If foundCount > 0 Then
' 抽出できたページがある場合、最初の空ページ(デフォルトで作られるもの)を削除
' (destDoc.Pages(1) が空のページである前提)
Application.EnableEvents = False ' イベントによる警告を抑止
If destDoc.Pages.Count > foundCount Then
destDoc.Pages(1).Delete
End If
Application.EnableEvents = True
' ファイルを保存
destDoc.SaveAs savePath
MsgBox foundCount & " 個のページを抽出しました。" & vbCrLf & "保存先: " & savePath, vbInformation, "完了"
Else
' 1つも見つからなかった場合、作成した空のファイルを閉じる
destDoc.Close
MsgBox "キーワード '" & searchKeyword & "' を含むページは見つかりませんでした。", vbExclamation, "終了"
End If
Exit Sub
ErrorHandler:
Application.EnableEvents = True
MsgBox "エラーが発生しました: " & Err.Description, vbCritical, "エラー"
End Sub
4. プロの視点:コードの「深部」を解説する
このコードをただコピペするだけでは、あなたはまだ「使い手」に過ぎません。エンジニアとして、コードの裏側にある「重み」を理解しましょう。
① `InStr` 関数:検索の要
`InStr(1, pg.Name, searchKeyword, vbTextCompare)`
この一行が、このツールの心臓部です。`InStr` は、ある文字列の中に別の文字列が含まれているかを調べる関数です。
ここで重要なのは `vbTextCompare` という引数です。これを入れることで、「ProjectA」と「projecta」を同じものとして扱ってくれます。これがないと、大文字・小文字のわずかな違いで検索に失敗する、非常にデリケートなツールになってしまいます。
② `For Each` ループ:集合の走査
`For Each pg In srcDoc.Pages`
これは「コレクション(集合)」を扱うための最も洗練された方法です。Visioのページは「ページの集合体」として管理されています。`For Each` を使うことで、ページが10枚でも10,000枚でも、プログラムは機械的に、かつ正確に最後まで辿り切ることができます。
③ `On Error GoTo ErrorHandler`:堅牢性の確保
実務で使うツールにおいて、最も重要なのがこれです。もし途中でファイルがロックされていたり、メモリ不足が起きたりしたとき、エラーでプログラムが突然死すると、中途半端なファイルが残ってしまいます。エラーを「キャッチ」して、ユーザーに優しく伝える。これがプロの仕事です。
5. 陥りやすい罠(エンジニアへのアドバイス)
このツールを運用する上で、初心者が必ずと言っていいほどぶつかる壁が2つあります。
1. ページ設定(Page Setup)の不一致
上記のコードは「シェイプ(図形)」をコピーしていますが、ページのサイズ(A3なのかA4なのか)まではコピーしていません。もし、元の図面が特殊なサイズである場合は、`newPg.PageSetup.PageSheet.CellsU(“PageWidth”).Formula = …` のように、ページ設定自体もコピーする処理が必要になります。
2. コネクタ(線)の切断
シェイプを一つずつコピーして貼り付ける手法は、単純ですが、複雑なコネクタ(線)が絡み合う図面では、線がうまく繋がらないことがあります。より高度な自動化では、ページそのものの「複製」や「データ転送」の概念が必要になりますが、まずはこの「シェイプ単位のコピー」をマスターすることから始めましょう。
最後に
いかがでしたか?
「ページを検索して、別ファイルに作る」という単純な動作の中に、プログラミングの基礎となる「ループ」「条件分岐」「エラーハンドリング」がすべて詰まっています。
マクロの記録から一歩踏み出し、自分でロジックを組み立てる感覚を掴めたなら、あなたのVisio活用能力は飛躍的に向上しています。次は、もっと複雑な条件、例えば「特定のレイヤーに図形がある場合だけ抽出する」といった挑戦をしてみてください。
道は続いています。一歩ずつ、楽しんでコードを書いていきましょう。応援していますよ。
