【入門編】【上級者向け】大規模なVSDXファイルを分割保存する際、各ページを個別の図面として切り出す高速処理 – Visio VBA解析バイブル

スポンサーリンク

こんにちは。現場で「Visioの魔術師」と呼ばれているチーフアーキテクトです。

Visio VBAの世界へようこそ。マクロの記録を卒業し、「より速く、より確実に、よりプロフェッショナルな自動化」を目指そうとしているあなたの情熱、素晴らしいですね。

今日は、大規模なVisioファイル(VSDX)を扱う実務で必ず直面する難問、「100ページある図面を、1ページずつの独立したファイルに高速に分割する」というテーマを攻略しましょう。

初心者のうちは「新しいファイルを作って、そこに図形をコピー&ペーストする」と考えがちですが、それは茨の道です。なぜなら、Visioには「マスターシェイプ」や「スタイル」といった、目に見えない複雑なデータ構造があるからです。

今回は、「全体を保存してから、不要なものを削ぎ落とす」という、プロが使う逆転の発想と、処理を爆速にする極意を伝授します。ここをマスターすれば、Visio VBAの基本と応用はバッチリですよ!

—

1. なぜ「コピペ」ではなく「複製して削除」なのか?

まず、設計思想の話をさせてください。
1ページずつ新しいファイルにコピペする方法には、大きな落とし穴が3つあります。

1. 書式が崩れる: コピー先に同じマスターシェイプがない場合、図形の見た目が変わってしまうことがあります。
2. 遅い: 大量の図形をクリップボード経由で動かすのは、PCにとって非常に重い処理です。
3. 背景ページが消える: ページに設定された背景やロゴが、コピペではうまく引き継がれません。

「極限の知見」としての正解はこれです:
> 「元ファイルをそのまま別名で保存(SaveAs)し、その中から『そのページ以外』をすべて削除する」

これなら、マスターも背景もスタイルも完全に保持されたまま、一瞬で「1ページだけのファイル」が完成します。

—

2. 処理を爆速にする「三種の神器」

コードを書く前に、Visioの描画エンジンを黙らせる魔法のプロパティを紹介します。これを設定しないと、ページを削除するたびにVisioが画面を再描画し、処理時間が数倍に膨れ上がります。

  • `Application.ScreenUpdating = False` (画面更新の停止)
  • `Application.EventsEnabled = False` (イベント発生の停止)
  • `Application.DeferRecalc = True` (計算の保留)

これらは、いわば「工事中にシャッターを閉める」ようなものです。作業が終わってからシャッターを開ければ、ユーザーには完成した状態だけが見え、動作も劇的に軽くなります。

—

3. 実践コード:高速分割・保存処理

では、具体的なコードを見ていきましょう。このコードは、アクティブなドキュメントの各ページを抽出し、個別のVSDXファイルとPDFとして保存する実戦的な構成です。

Sub SplitVisioPagesHighSpeed()
Dim srcDoc As Visio.Document
Dim targetDoc As Visio.Document
Dim pg As Visio.Page
Dim i As Integer, j As Integer
Dim filePath As String
Dim folderPath As String
Dim pageName As String

‘ 1. 最適化:描画エンジンを一時停止
With Visio.Application
.ScreenUpdating = False
.EventsEnabled = False
.DeferRecalc = True
End With

Set srcDoc = ActiveDocument
folderPath = srcDoc.Path ‘ 元ファイルと同じフォルダに出力

‘ 2. ページごとにループ処理
‘ 後ろのページから処理するのではなく、SaveAs方式なので順方向でOK
For i = 1 To srcDoc.Pages.Count
Set pg = srcDoc.Pages(i)

‘ 背景ページはスキップ(前景ページのみをファイル化するため)
If pg.Background = False Then
pageName = pg.Name
filePath = folderPath & pageName & “.vsdx”

‘ — ここがプロの技:複製して削る —

‘ 元ファイルを別名でコピー保存(元ファイルは開いたまま)
srcDoc.SaveCopyAs filePath

‘ コピーしたファイルを「不可視モード」で開く(高速化の肝)
Set targetDoc = Documents.OpenEx(filePath, visOpenHidden)

‘ 不要なページを削除(自分以外のページを消す)
‘ ページ削除はインデックスがずれるので「後ろから」消すのが鉄則
For j = targetDoc.Pages.Count To 1 Step -1
If targetDoc.Pages(j).Name <> pageName Then
‘ 背景ページでない、かつ対象ページでない場合は削除
‘ ※背景ページを残したい場合はロジックを調整します
If targetDoc.Pages(j).Background = False Then
targetDoc.Pages(j).Delete (True)
End If
End If
Next j

‘ 3. 保存とPDF出力
targetDoc.Save ‘ 1ページだけになった状態で上書き保存

‘ PDFとしても出力したい場合(オプション)
‘ targetDoc.ExportAsFixedFormat visFixedFormatPDF, _
‘ Replace(filePath, “.vsdx”, “.pdf”), visDocExIntentPrint

‘ 4. ライフサイクル管理:開いたドキュメントを確実に閉じる
targetDoc.Close
Set targetDoc = Nothing
End If
Next i

‘ 5. 最適化の解除:設定を元に戻す
With Visio.Application
.ScreenUpdating = True
.EventsEnabled = True
.DeferRecalc = False
End With

MsgBox “分割処理が完了しました!”, vbInformation, “チーフアーキテクトからの報告”
End Sub

—

4. コードの深層解説:なぜこれで動くのか

`SaveCopyAs` の魔法

`SaveAs` ではなく `SaveCopyAs` を使っているのがポイントです。`SaveAs` は現在の作業ファイルを切り替えてしまいますが、`SaveCopyAs` は「現在のファイルはそのままに、バックグラウンドでコピーを作る」メソッドです。これにより、メインのループ処理が安定します。

`visOpenHidden` で忍者のように

`Documents.OpenEx(filePath, visOpenHidden)` というフラグを使っていますね。これは Visio のウィンドウを表示せずにファイルを開く設定です。GUIを描画するリソースを一切消費しないため、目にも止まらぬ速さで処理が進みます。

逆順ループ(Step -1)の重要性

ページを削除する際、`1 To Count` で回すと、1ページ目を消した瞬間に2ページ目が1ページ目に繰り上がり、削除漏れが発生します。「コレクションから要素を消すときは後ろから」。これはVisioに限らず、すべてのプログラミングにおける鉄則です。

—

5. 陥りやすいエラーと対策

もしコードが途中で止まってしまったら、以下のポイントをチェックしてみてください。

1. 同名ファイルが開いている: 保存先に同じ名前のファイルが開いているとエラーになります。実行前に閉じておきましょう。
2. 背景ページの依存関係: 背景ページを削除してしまうと、前景ページのデザインが崩れることがあります。私のコードでは背景ページを残す考慮を入れていますが、複雑な階層構造を持つ図面の場合は、背景ページの `Name` を特定して保持するロジックを追加してください。
3. マスタシェイプの肥大化: `SaveCopyAs` 方式は便利ですが、元ファイルにあるすべてのマスタが残ります。ファイルサイズを極限まで小さくしたい場合は、最後に `targetDoc.PurgeMaint`(未使用のマスタを削除)を呼ぶと完璧です。

—

終わりに

お疲れ様でした!今回の「複製して削る」というアプローチは、Visio VBAにおけるオブジェクト管理の真髄です。

マクロの記録から一歩踏み出し、オブジェクトのライフサイクル(生成・保存・破棄)を意識できるようになれば、あなたはもう初心者ではありません。このスクリプトをベースに、自分なりのカスタマイズを加えてみてください。

もし「特定の図形があるページだけ抽出したい」といった要望が出てきたら、それはあなたが次のステップに進む準備ができた証拠です。その時はまた、この知見を思い出してくださいね。

応援していますよ!

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