Visio VBAの限界を突破せよ:DropManyUによる「秒速」シェイプ配置の極意
Visioの自動化において、最も初歩的かつ致命的なミスは「ループ内で `Page.Drop` を繰り返すこと」です。もしあなたが、数百個の機器シェイプを配置するために `For Each` ループの中で `Drop` メソッドを叩いているのなら、今すぐそのコードを破棄してください。
Visioのレンダリングエンジンは、オブジェクトが生成されるたびに再計算と再描画のオーバーヘッドを発生させます。数百個の配置で数分待たされるのは、コードのせいではなく、あなたの「設計思想」の問題です。
今回は、Visio APIの深淵に触れる `DropManyU` メソッドを使い、メモリ消費を抑えつつ、一瞬で数百の図形をページに叩き込む「極限の最適化」を伝授します。
—
1. なぜ「DropManyU」なのか:パフォーマンスの正体
`DropManyU` は、単なる `Drop` の一括処理版ではありません。これは「Visioのトランザクションを最小化し、内部的なシェイプテーブルの更新を一度に行う」ためのインターフェースです。
- 通常のDrop: 1回ごとに描画・イベント発火・Undoスタックへの記録が行われ、CPUとメモリを浪費する。
- DropManyU: 座標配列とマスター配列を一括で渡し、エンジンが「バルク処理」として内部メモリ上で計算を完結させる。
大規模なダイアグラムを生成する場合、処理速度は数十倍から数百倍の差になります。
—
2. 実装の要諦:プロダクションコード
このコードは、汎用性を担保しつつ、メモリリークを防ぐための堅牢な設計を施しています。
Option Explicit
‘ ———————————————————
‘ 大量シェイプを一括配置する最適化関数
‘ @param targetPage 配置先ページ
‘ @param masterObj 配置するマスターシェイプ
‘ @param xyArray (0 to 1, 0 to n) の配列(x, y)
‘ ———————————————————
Public Sub BatchDropShapes(targetPage As Visio.Page, masterObj As Visio.Master, xyArray() As Double)
Dim count As Long
count = UBound(xyArray, 2) + 1
‘ DropManyUに必要な配列を用意
‘ masters: 配置するマスターの配列
‘ xy: 配置する座標の配列
Dim masters() As Object
ReDim masters(0 To count – 1)
Dim i As Long
For i = 0 To count – 1
Set masters(i) = masterObj
Next i
‘ 画面更新を停止してさらなる高速化
Dim oldScreenUpdating As Boolean
oldScreenUpdating = Application.ScreenUpdating
Application.ScreenUpdating = False
‘ 一括配置実行
‘ DropManyU(マスター配列, 座標配列)
targetPage.DropManyU masters, xyArray
Application.ScreenUpdating = oldScreenUpdating
End Sub
このコードの設計ポイント
1. Application.ScreenUpdatingの制御: 必須です。これがないと、どれだけ高速なメソッドを使っても描画負荷がボトルネックになります。
2. 配列の次元数: `DropManyU` が要求するのは `Double` 型の2次元配列 `(0 to 1, 0 to n)` です。0行目がX座標、1行目がY座標であることを忘れないでください。
3. マスターオブジェクトのキャッシュ: ループ内で `Documents.Item(…).Masters.ItemU(…)` を叩くのは厳禁です。あらかじめ変数にセットし、メモリ上の参照を渡してください。
—
3. 現場で直面する「罠」と対策
データベース連携の注意点
外部のCSVやSQLから座標データを読み込む際、「文字列型」のまま計算してはいけません。 `CDbl()` を使い、必ず `Double` 型に明示的に変換してから配列へ格納してください。型不一致エラーは `DropManyU` では非常にデバッグしにくい「実行時エラー」を招きます。
座標系の理解
Visioの座標は「ページの下・左」が原点 `(0,0)` です。データベース側が「画面左上を原点」としている場合、必ず以下の変換式を挟んでください。
- `VisioY = PageHeight – DatabaseY`
大規模配置時の「Undo」リスク
数千個単位で一括配置する場合、Undoスタックが溢れてVisioがクラッシュすることがあります。大規模なバッチ処理を行う場合は、処理の前後で `Application.UndoEnabled = False` にし、安全を期すなら処理完了後に一度ファイルを保存し直す戦略を推奨します。
—
結論:エンジニアの誇りとして
「動けばいい」コードは、誰でも書けます。しかし、Visioという重厚なオブジェクトモデルを制御し、メモリの鼓動を感じながら「一瞬で描画を完了させる」コードこそが、プロフェッショナルの仕事です。
この `DropManyU` を使いこなすことは、単なる高速化ではありません。あなたの業務ツールが、ただの「自動化スクリプト」から、現場を支える「インフラ」へと昇華する第一歩なのです。
さあ、あなたのコードを極限まで研ぎ澄ましてください。健闘を祈ります。
