【実務・中級編】【中級】Page.DropManyを用いた図形の超高速一括配置:ループ処理のボトルネックを解消する – Visio VBA解析バイブル

スポンサーリンク

【Visio VBA】1,000個の図形を瞬殺せよ:DropManyによる「超高速一括配置」の極意

Visioの自動化において、初心者が必ず陥る罠がある。それは、`Page.Drop`をループ内で呼び出し続ける「地獄の反復処理」だ。

「100個程度の図形なら問題ない」と高を括っているうちに、データ量が数千件を超えた瞬間、描画エンジンは悲鳴を上げ、PCはフリーズする。なぜなら、`Drop`メソッドを呼ぶたびに、Visioは描画の再計算、イベントのトリガー、Undoスタックへの書き込みを律儀に繰り返すからだ。

真の自動化エンジニアなら、「描画は一度のトランザクションで完結させる」という鉄則を忘れてはならない。今回は、Visioの描画ボトルネックを物理的に破壊する`Page.DropMany`の極意を伝授する。

—

1. なぜ「Drop」を連打してはいけないのか

`Page.Drop`は個別の図形を配置するには便利だが、以下のコストをその都度支払っている。

1. 描画再計算: 配置のたびに画面の再描画が行われる。
2. イベント発行: `ShapeAdded`などのイベントがその都度発生し、リスナーが登録されていれば処理が重なる。
3. Undo管理: 1回ずつUndoスタックに記録されるため、メモリを激しく消費する。

これらを解決するのが、配列を渡して一括配置する`Page.DropMany`だ。これは言わば「バルクインサート」であり、描画エンジンに対して「これらを一度に描け」と指示する、極めて低レイヤーに近いアプローチである。

—

2. 実践:DropManyによる爆速配置コード

このコードは、実務で頻出する「マスター図形を特定の座標リストに一括配置する」パターンを想定している。

‘ ———————————————————
‘ 目的: 配列データを用いて図形を高速に一括配置する
‘ ———————————————————
Public Sub BulkDropShapes()
Dim vsoPage As Visio.Page
Dim vsoMaster As Visio.Master
Dim vsoShapes() As Visio.Shape
Dim xyArray(0 To 1) As Double
Dim posArray() As Double
Dim i As Long
Dim count As Long: count = 100 ‘ 配置したい図形の数

Set vsoPage = ActivePage
Set vsoMaster = Application.Documents(“StencilName.vssx”).Masters(“ShapeName”)

‘ 配置座標用配列の準備 (x1, y1, x2, y2, …)
ReDim posArray(0 To (count 2) – 1)

‘ 座標計算(ここをDBやCSVからの読み込みに差し替える)
For i = 0 To count – 1
posArray(i 2) = i 0.5 ‘ X座標
posArray(i 2 + 1) = i 0.5 ‘ Y座標
Next i

‘ 重要: 描画更新を一時停止して高速化を最大化
Application.ScreenUpdating = False

‘ DropManyを実行
‘ 第1引数: 配置するマスター図形の配列 (今回は単一種類を複数)
‘ 第2引数: 座標ペアの配列
‘ 第3引数: 返り値として配置されたShapeオブジェクトが入る
vsoPage.DropManyArray vsoMaster, posArray, vsoShapes

‘ 後処理
Application.ScreenUpdating = True

Debug.Print “配置完了: ” & UBound(vsoShapes) + 1 & ” 個の図形を配置しました。”
End Sub

—

3. 堅牢な設計のための「3つの鉄則」

現場で動くコードにするためには、技術的なコツだけでなく、「異常系への備え」が不可欠だ。

① 描画更新の抑制 (`ScreenUpdating`)

`Application.ScreenUpdating = False` は必須だ。これを行わないと、`DropMany`を使っていても、内部的に描画リクエストが走る可能性がある。最後に必ず `True` に戻すよう、エラーハンドラで確実に制御すること。

② 座標データのバリデーション

`DropMany`に渡す `posArray` は「Double型の一次元配列」でなければならない。DBから取得したデータをそのまま突っ込むのではなく、必ず型変換と要素数の整合性を確認するバリデーションを挟むこと。ここを怠ると、Visioは容赦なくクラッシュする。

③ Undoスコープの活用

`Application.BeginUndoScope` と `EndUndoScope` を使用し、一括配置全体を一つの「Undo単位」にまとめること。これにより、誤った配置を一瞬でロールバックできるようになり、ユーザーの信頼を獲得できる。

—

4. プロの視点:ファイル・DB連携の注意点

大規模な配置処理を行う際、データソース(ExcelやSQL Serverなど)からの読み込みがボトルネックになることが多い。

  • メモリ上のバッファリング: ループ内で毎回DBクエリを投げるのは愚の骨頂だ。最初に全データを配列にロード(配列への一括読み込み)し、VBAのメモリ上で座標計算を完結させてから `DropMany` に渡す。これが「プロのエンジニア」が書くコードの標準だ。
  • マスター図形のキャッシュ: `vsoMaster` の取得はループの外で行い、オブジェクト参照を使い回す。これだけで数ミリ秒の差が出る。

最後に

`DropMany` は、単なるメソッドではない。それは「Visioの内部処理を理解しているか」というエンジニアの試金石だ。

もし、今あなたが書いているコードが `for` ループの中で `Drop` を呼び出しているなら、それは今すぐ書き換えるべき技術的負債である。この記事の知見を武器に、誰よりも速いVisioソリューションを構築してほしい。

検討を祈る。

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