こんにちは!Visioの図面整理に日々追われていませんか?
「10個も20個もある図面のフォントサイズを一括で変えたい…」「古いフォーマットの図面を一斉に別名保存し直したい…」そんな絶望的な単調作業に直面したとき、マクロの記録ボタンをポチポチ押すだけでは、複数ファイルを跨ぐ巨大な荒波を乗りこなすことはできません。
今回は、Visio VBAの心臓部である`Documents`コレクションを完全に手なずけ、開いている複数の図面ファイルを華麗に横断・一括処理する極意を伝授します。
ここをクリアすれば、あなたのVisio VBAの基本はバッチリですよ。さあ、ワンランク上の自動化の世界へ一緒に入りましょう!
—
1. なぜ「Documentsコレクション」を知る必要があるのか?
Visioを起動すると、目に見えるキャンバス(図面)の裏側で、アプリケーション全体を統括する巨大な階層構造(オブジェクトモデル)が動いています。
Application (Visioそのもの)
┗ Documents (現在開いている全図面の束)
┣ Document 1 (図面A.vsdx)
┃ ┗ Pages
┗ Document 2 (図面B.vsdx)
┗ Pages
「マクロの記録」で作られるコードは、大抵の場合、今まさにアクティブになっている1つの図面(`ActiveDocument`)を相手にするのが精一杯です。
しかし、実務では「現在Visioで開いているすべての図面に対して、一括で処理を実行したい」という場面が多々あります。
そんな時に頼りになるのが、開かれているすべての図面ファイルを内包するリストボックス、すなわち`Documents`コレクションなのです。
—
2. 複数ファイルを横断する基本の「For Each」ループ
まずは、現在開いているすべての図面ファイルの名前をイミディエイトウィンドウにズラリと書き出すコードを見てみましょう。
複数ファイルを一括操作するための「基本のキ」がここに詰まっています。
Sub ListAllOpenDocuments()
‘ 変数の定義
Dim doc As Visio.Document
‘ 開いているすべてのドキュメントを順番に処理する
For Each doc In Application.Documents
‘ 開発者用テンプレートやステンシル(Visio内部の特殊ファイル)を除外する
If doc.Type = visTypeDrawing Then
Debug.Print “ファイル名: ” & doc.Name & ” (パス: ” & doc.Path & “)”
End If
Next doc
MsgBox “すべての図面スキャンが完了しました!”, vbInformation
End Sub
ここがプロの知見:`doc.Type = visTypeDrawing` の重要性
Visioの世界には、私たちが普段編集する「図面(`visTypeDrawing`)」だけでなく、ステンシル(`visTypeStencil`)やテンプレート(`visTypeTemplate`)も`Documents`コレクションに混ざって存在しています。
これらを区別せずに処理しようとすると、「ステンシルにはページがない!」といった予期せぬエラー(ランタイムエラー)でマクロがクラッシュします。実務では必ず`Type`プロパティでフィルタリングする優しさを持ちましょう。
—
3. 【実践】開いている全図面の特定のプロパティを一括変更して保存する
それでは、少し実践的なコードをお見せします。
「現在開いているすべての図面に対して、特定のレイヤー設定を変更し、そのまま上書き保存して閉じる」という、実務で失神するほどありがたい自動化マクロです。
Sub BatchUpdateAndSaveDocuments()
Dim doc As Visio.Document
Dim targetShape As Visio.Shape
Dim processedCount As Long
processedCount = 0
‘ 念のため確認メッセージ
If MsgBox(“現在開いているすべての図面を一括更新して上書き保存します。よろしいですか?”, vbYesNo + vbQuestion) = vbNo Then
Exit Sub
End If
‘ 画面描画を停止して爆速化&チラつき防止
Application.ScreenUpdating = False
On Error GoTo ErrorHandler ‘ エラーハンドリングの罠を回避
For Each doc In Application.Documents
‘ 通常の図面ファイルのみを対象にする
If doc.Type = visTypeDrawing Then
‘ 【ここに一括で行いたい処理を記述】
‘ 例として、全ページの全シェイプの線種やプロパティを変更するイメージ
‘ (今回は分かりやすく、ドキュメント自体のプロパティ変更や保存を想定)
‘ ※もし図面が「読み取り専用」で開かれていたら保存でエラーになるためチェック
If Not doc.ReadOnly Then
‘ 変更を加えて上書き保存
doc.Save
processedCount = processedCount + 1
End If
End If
Next doc
‘ 画面描画を復元
Application.ScreenUpdating = True
MsgBox processedCount & “件の図面を正常に一括処理・保存しました!”, vbInformation
Exit Sub
ErrorHandler:
‘ エラーが起きても画面描画のフリーズを必ず解除する(これ重要!)
Application.ScreenUpdating = True
MsgBox “エラーが発生しました: ” & Err.Description, vbCritical
End Sub
ここがプロの知見:`Application.ScreenUpdating = False` とエラーハンドリング
大量のファイルをループ処理するとき、Visioは親切心からファイルが切り替わるたびに画面を再描画します。これが動作を激重にする原因です。`ScreenUpdating = False` で描画を止め、処理をマッハにしましょう。
ただし、万が一エラーで止まったときに画面がフリーズしたままになるのを防ぐため、必ず `On Error GoTo` を使って、終了時に描画を `True` に戻す安全装置(クリーンアップ処理)を組み込むのが一流のエンジニアの作法です。
—
4. 陥りやすい罠とエラー回避の極意
複数ファイルを扱うマクロで、初学者が必ずと言っていいほどハマる罠が2つあります。
罠①:「ファイルを閉じる」処理をループ内に入れてしまう
もしマクロの中で `doc.Close` を実行すると、その瞬間に `Documents` コレクションの数が減り、`For Each` のインデックスが狂って強制終了や無限ループを引き起こします。
【対策】
開いているファイルをその場で閉じたい場合は、`For Each` ではなく、後ろから数える逆順の `For` ループを使うのが鉄則です。
Dim i As Long
For i = Application.Documents.Count To 1 Step -1
Set doc = Application.Documents(i)
If doc.Type = visTypeDrawing Then
‘ 処理…
‘ doc.Close ‘ 必要に応じてここで閉じる
End If
Next i
罠②:そもそもファイルを開いていない(あるいは複数開くのが面倒)
今回のテーマは「開いた図面を横断する」でしたが、そもそも「指定したフォルダにある100個のファイルを自動で開いて、処理して、閉じる」という完全自動バッチをやりたい場合もありますよね。
その場合は、`Application.Documents.Open` メソッドをループ内で使って、ディスクから次々とメモリ上に読み込ませて処理していくアプローチをとります。
—
まとめ:自動化の翼を手に入れよう
今回は、Visio VBAにおける `Documents` コレクションを駆使した、複数ファイル横断の一括処理について解説しました。
- `Application.Documents` で開いている全ファイルの束にアクセスできる
- `visTypeDrawing` で図面とステンシルをしっかり選別する
- `ScreenUpdating = False` とエラー対策でパフォーマンスと安全性を担保する
- ファイルを閉じる処理を入れるときは「後ろからループ(逆順)」にする
この基本原則さえ押さえておけば、どれだけ大量の図面ファイルを突きつけられても、コーヒーを飲んでいる間にVBAがすべて終わらせてくれます。
ここをクリアしたあなたなら、もうVisio VBAの基礎はバッチリです。ぜひ実務の現場でこのテクニックを試し、圧倒的な作業効率を手に入れてくださいね!
