巨大なステンシルに振り回されないために。Visio VBAで「必要なものだけ」をスマートに扱う極限の技術
「マクロの記録」から一歩踏み出し、自分だけの自動化ツールを作ろうとしているあなたへ。
Visio VBAの世界へようこそ。ここまで来られたあなたは、すでに「手作業を自動化する」という素晴らしい第一歩をクリアしています。しかし、開発を進めていくと、必ずと言っていいほど一つの「壁」にぶつかります。
それは、「巨大なステンシルファイルを開こうとした瞬間に、Visioがフリーズしたかのように重くなる」という問題です。
数百、数千のマスターシェイプが含まれたプロフェッショナル向けのステンシル。それを `Documents.Open` で力任せに開いていませんか? もしそうなら、あなたのコードは「重い荷物をすべて背負って全力疾走しようとしている」状態です。
今日は、そんな非効率な実装から脱却し、プロフェッショナルが実践する「必要なマスターだけを、最小限の負荷で呼び出す」ための、`OpenEx` メソッドを駆使した高速化テクニックを伝授します。
1. なぜ「普通に開く」と遅いのか? オブジェクトの重みを知る
まず、私たちが戦っている「敵」の正体を理解しましょう。
一般的な `Documents.Open` メソッドを使用すると、Visioはステンシルファイル内のすべてのマスターシェイプ、すべての接続ポイント、すべての形状定義(Geometry)をメモリ上に展開し、ユーザーインターフェース(UI)に表示しようとします。
たとえあなたが「その中のたった一つのシェイプ」しか使わない予定だったとしても、Visioは律儀に全データを読み込みます。これが、巨大なステンシルを開く際の「待ち時間」の正体です。
プロの視点:オブジェクトのライフサイクル
エンジニアとして意識すべきは、「メモリ(RAM)への展開コスト」です。
不要なマスターをロードすることは、CPUの計算資源とメモリを無駄に消費し、結果としてマクロ全体の実行速度を低下させるだけでなく、ユーザー体験(UX)を著しく損なうのです。
2. 救世主 `Document.OpenEx` と魔法のオプション
ここで登場するのが、`Documents.OpenEx` メソッドです。
これは `Open` メソッドの強化版であり、第2引数に「どのようにファイルを開くか」を指定するフラグ(オプション)を渡すことができます。
特に重要なのが、以下のフラグです。
- `visOpenExReadOnly`: 読み取り専用で開きます。書き込み権限のチェックやロックのプロセスをスキップできるため、読み込みが高速化されます。
- `visOpenExOpenAsMaster`: (用途によりますが)ステンシルをマスターとして扱う際の挙動を制御します。
しかし、真の高速化の鍵は、オプションそのものよりも「開き方と使い方の戦略」にあります。
戦略:バックグラウンド・ロード・パターン
プロは、ステンシルを「ユーザーに見える形」で開くことはしません。
1. ステンシルを読み取り専用(ReadOnly)かつバックグラウンドで開く。
2. 必要なマスターシェイプだけを、現在のドキュメントにコピーする。
3. 用が済んだら、すぐにステンシルを閉じる。
この「必要なものだけを抜き取って、すぐに片付ける」というサイクルこそが、高速化の極意です。
3. 実戦コード:マスターシェイプを高速に抽出する
それでは、実際に使えるコードを見てみましょう。
以下の関数は、巨大なステンシルから指定した名前のマスターだけを探し出し、アクティブな図面に配置するものです。
Option Explicit
''' <summary>
''' 巨大なステンシルから特定のマスターを高速に抽出し、図面に配置する
''' </summary>
''' <param name="stencilPath">ステンシルファイルのフルパス</param>
''' <param name="masterName">取得したいマスターの名前</param>
Sub FastExtractMaster(ByVal stencilPath As String, ByVal masterName As String)
Dim stencilDoc As Visio.Document
Dim targetMaster As Visio.Master
Dim activePage As Visio.Page
Dim droppedShape As Visio.Shape
On Error GoTo ErrorHandler
' 1. 現在の図面のページを特定
Set activePage = ActivePage
' 2. 【重要】OpenEx を使い、読み取り専用(visOpenExReadOnly)でステンシルを開く
' これにより、ファイルロックの回避と読み込みの高速化を図る
Debug.Print "ステンシルを読み込み中: " & stencilPath
Set stencilDoc = Documents.OpenEx(stencilPath, visOpenExReadOnly)
' 3. ステンシル内のマスターを検索
' すべてをロードしていても、検索はメモリ上で行われるため、
' ユーザーに巨大なUIを表示させるより遥かに低負荷です
On Error Resume Next
Set targetMaster = stencilDoc.Masters(masterName)
On Error GoTo ErrorHandler
If targetMaster Is Nothing Then
MsgBox "エラー: マスター '" & masterName & "' が見つかりませんでした。", vbCritical
GoTo CleanUp
End If
' 4. 必要なマスターだけを、現在のページにドロップ(配置)する
' ここで「マスターのコピー」が行われ、図面側に実体化されます
Set droppedShape = activePage.Drop(targetMaster, 0, 0)
Debug.Print "成功: '" & masterName & "' を配置しました。"
CleanUp:
' 5. 【極めて重要】使い終わったステンシルは即座に閉じる
' これを忘れると、メモリ上に不要なオブジェクトが残り続け、動作が重くなります
If Not stencilDoc Is Nothing Then
stencilDoc.Close
Set stencilDoc = Nothing
Debug.Print "ステンシルを安全に閉じました。"
End If
Exit Sub
ErrorHandler:
MsgBox "予期せぬエラーが発生しました: " & Err.Description, vbExclamation
Resume CleanUp
End Sub
''' <summary>
''' テスト実行用メインルーチン
''' </summary>
Sub TestFastLoading()
' 実際のパスに書き換えて実行してください
Dim myPath As String
myPath = "C:\Users\Public\Documents\MyHugeStencil.vssx"
' 取得したいマスター名を指定
Call FastExtractMaster(myPath, "Standard_Rectangle")
End Sub
4. ここをクリアすれば、Visio VBAの基本はバッチリですよ
このコードを理解するために、覚えておいてほしいポイントが3つあります。
① `OpenEx` のフラグによる「振る舞いの制御」
`Documents.Open` は「人間がファイルを開く」動作に近いですが、`OpenEx` は「プログラムがデータを読み込む」動作に近いです。`visOpenExReadOnly` を指定することで、Visioに「このファイルは変更しないから、余計な準備(書き込み準備)をしなくていいよ」と教えてあげているのです。
② 「参照」と「実体」を使い分ける
ステンシルからシェイプを配置する際、私たちはステンシルの「マスター(設計図)」を参照し、図面の上に「シェイプ(実体)」を作り出しています。
コード内で `stencilDoc.Close` をしても、すでに配置された `droppedShape` は消えません。なぜなら、配置した瞬間に図面側に独立したデータとしてコピーされているからです。この「使い終わったら設計図(ステンシル)をすぐ片付ける」という感覚を掴んでください。
③ エラーハンドリングとクリーンアップ
プロのコードと初心者のコードの決定的な違いは、「失敗したときに後片付けができるか」です。
もしマスターが見つからなかったとき、ステンシルを開いたままエラーで終了してしまったらどうなるでしょう? そのステンシルは「使用中」としてロックされ続け、次に開こうとしたときにエラーになります。`CleanUp` ラベルを使って、必ず `Close` を通るように設計するのが鉄則です。
最後に
巨大なデータを扱うとき、力任せに突破しようとするのではなく、「いかに最小限のデータに触れるか」を考える。これが、エンジニアリングにおける「知性」です。
今回学んだ `OpenEx` とバックグラウンド・ロードの考え方は、Visioだけでなく、あらゆる業務自動化に応用できる普遍的な原則です。
さあ、このコードをあなたのプロジェクトに取り入れてみてください。今まで「重いな……」と感じていたあの待ち時間が、驚くほど軽やかになるはずですよ。
応援しています。次なるステップへ、進んでいきましょう!
