Visio VBAの深淵:Page.DropManyによる「秒速配置」の極意
多くのVBAエンジニアは、Visioで大量のシェイプを扱う際、安易に `Page.Drop` をループの中に書き込むという過ちを犯す。
「数百個程度のシェイプなら動くから問題ない」?
否。それは実装ではなく、ただの「遅延」という名の負債だ。
Visioの `Drop` メソッドは、呼び出されるたびに内部トランザクションを発生させ、再描画のオーバーヘッドを伴う。1000個のシェイプを配置すれば、1000回の再計算とUI更新がトリガーされる。これがレガシー環境や複雑な図面で致命的なフリーズを招く元凶だ。
真にプロフェッショナルなアーキテクトは、`Page.DropMany` を用いて、このオーバーヘッドを物理的に消し去る。今回は、この「極限の最適化」をコードに落とし込む作法を伝授する。
—
なぜ DropMany なのか:アーキテクチャの視点
`DropMany` は、単なる「まとめて配置するメソッド」ではない。これは、Visioの描画エンジンに対する「バッチ処理の命令」だ。
- トランザクションの統合: メソッド内で配置処理を完結させるため、イベントの連鎖や再描画を最小限に抑える。
- メモリの最適化: オブジェクト生成のオーバーヘッドをVM(Virtual Machine)側で一括処理する。
- スループットの最大化: 従来のループ処理と比較し、数千個単位のシェイプ配置で100倍以上の速度差が出るのは、もはや必然である。
—
実践:DropMany を駆使した高速配置の定石
以下は、マスターシェイプから配列を介して高速に配置する実装例だ。単に動くだけのコードではなく、メモリリークを許さない堅牢な構造を意識している。
Sub FastDropShapes()
‘ 伝説的なアーキテクチャでは、常にObjectを明示的に解放する
Dim vsoPage As Visio.Page
Dim vsoMaster As Visio.Master
Dim vsoShapes() As Visio.Shape
Dim xyCoords() As Double
Dim i As Long, count As Long
Set vsoPage = ActivePage
Set vsoMaster = Documents(“Stencil.vssx”).Masters(“Process”)
count = 1000 ‘ 配置したい個数
ReDim xyCoords(0 To (count 2) – 1)
‘ 座標を配列に格納(ループ内でのアクセスを最小化)
For i = 0 To count – 1
xyCoords(i 2) = (i Mod 10) 2 ‘ X座標
xyCoords(i 2 + 1) = Int(i / 10) 2 ‘ Y座標
Next i
‘ DropManyの核:配列を一度に流し込む
‘ 第1引数: マスターの配列(単一の場合は単一のマスター)
‘ 第2引数: 配置座標配列
‘ 第3引数: 出力用シェイプ配列
vsoPage.DropMany Array(vsoMaster), xyCoords, vsoShapes
‘ メモリのクリーンアップは儀式である
Set vsoPage = Nothing
Set vsoMaster = Nothing
Erase vsoShapes
Erase xyCoords
End Sub
—
極限を追求するための「隠れた制約」
この手法を実戦投入する際、シニアエンジニアとして知っておくべき「落とし穴」がある。
1. 座標系の罠
`DropMany` はピクセル単位ではなく、Visio内部の「インチ単位(内部座標)」で動作する。`ActiveWindow.Page.PageScale` を考慮した座標変換を怠ると、配置場所が狂う。API連携を行う際は、必ず座標の正規化を行え。
2. イベントの制約
`DropMany` を実行すると、個別の `ShapeAdded` イベントが大量に発行される可能性がある。大規模なシステム連携を行う際は、処理開始前に `Application.EventEnabled = False` にし、終了後に戻すことで、イベントハンドラの暴走を防ぐのが定石だ。
3. Windows APIとの調和
万が一、パフォーマンスが頭打ちになるほどの超大規模データを扱う場合は、`WaitMessage` 等のAPIを呼び出し、UIスレッドを死なせない工夫が必要になる。しかし、`DropMany` を正しく使っていれば、その領域に達する前に処理は完了しているはずだ。
—
結論:コードは「対話」である
VBAを単なる「自動化ツール」と見なすか、OSのリソースを制御する「システムエンジニアリング」と見なすか。その差が、書くコードの質に現れる。
`DropMany` は、Visioという巨大なオブジェクトグラフを効率的に操作するためのインターフェースだ。これを使いこなすことは、Visioのメモリ管理機構を掌中に収めることに他ならない。
次にあなたが Visio でループ処理を書こうとした時、一瞬立ち止まってほしい。
「そのループ、本当に必要か? `DropMany` で配列に詰め込めないか?」
その問いかけこそが、凡庸なコードから脱却し、伝説のエンジニアへと近づく唯一の道である。
