Visio VBAの限界を突破せよ:`DropMany`で実現する「秒速」図形配置の極意
こんにちは。現場で泥臭い自動化を積み重ねてきたエンジニアの視点から、Visio VBAの「真の力」を引き出す極意をお伝えします。
皆さんは、数百個の図形をページに並べる際、こんな書き方をしていませんか?
‘ 【やってはいけない:低速なコード】
For i = 1 To 500
ActivePage.Drop MasterObj, x, y
Next i
もし心当たりがあるなら、今すぐその手を止めてください。この書き方では、Visioはループのたびに「描画の更新」と「イベントの発生」を律儀に処理します。結果、処理が進むにつれてどんどん重くなり、PCは悲鳴を上げます。
今日は、「ループを捨て、配列で殴る」。Visioのエンジンを直撃する高速配置メソッド、`DropMany`について深く掘り下げていきます。
—
1. なぜ「一つずつDrop」は遅いのか?
Visioのオブジェクトモデルにおいて、`Drop`メソッドは非常に強力ですが、「重い」処理です。
- 描画更新のオーバーヘッド: 1つ配置するたびに、Visioは画面の再描画を試みます。
- Undoスタックの肥大化: 1回1回が独立した操作として記録されるため、メモリを激しく消費します。
私たちが目指すのは、「Visioに一度だけ命令を出し、あとは一気に計算させる」こと。それが `DropMany` です。
—
2. DropMany の正体
`DropMany` は、複数の図形を一括して処理するためのメソッドです。最大の特徴は、「位置座標やマスターシェイプを配列として渡す」点にあります。
基本的なデータ構造
`DropMany` を使いこなすには、以下の2つの配列が必要です。
1. Masters配列: 配置したいマスターシェイプの参照配列。
2. XY配列: 配置先の座標(X, Y)を格納した配列。
—
3. 実践:100倍速い図形配置コード
以下のコードは、100個の図形を瞬時に配置するためのテンプレートです。これをそのままコピペして、あなたのプロジェクトのベースにしてください。
Sub DropMany_HighSpeed()
Dim vsoPage As Visio.Page
Dim vsoMaster As Visio.Master
Dim i As Long
Dim count As Long: count = 100
‘ 配置座標を格納する配列 (0 to (count2)-1)
‘ 奇数インデックスにX、偶数にYを格納します
Dim xyArray() As Double
ReDim xyArray(0 To (count 2) – 1)
‘ マスターシェイプの配列
Dim masters() As Visio.Master
ReDim masters(0 To count – 1)
Set vsoPage = ActivePage
Set vsoMaster = ActiveDocument.Masters(“Rectangle”) ‘ 自分のマスター名に変更
‘ 配列にデータを流し込む
For i = 0 To count – 1
masters(i) = vsoMaster
xyArray(i 2) = (i Mod 10) 1.5 ‘ X座標
xyArray(i 2 + 1) = (i \ 10) 1.5 ‘ Y座標
Next i
‘ ここが極意:DropManyで一括配置!
‘ 内部処理が最適化され、驚異的な速度で完了します
vsoPage.DropMany masters, xyArray, Nothing
MsgBox “配置完了!”, vbInformation
End Sub
コードの解説
- `xyArray` の構造: `DropMany` は非常に厳格です。`[x1, y1, x2, y2, x3, y3…]` というフラットな配列を要求します。`i 2` と `i 2 + 1` でインデックスを操作するのが定石です。
- `Nothing` 引数: `DropMany` の第3引数には、作成されたシェイプを受け取るための `Selection` オブジェクトを渡せますが、不要なら `Nothing` でOKです。
—
4. 陥りやすい罠と解決策
初学者が必ず突き当たる壁が2つあります。
① 「マスターシェイプが見つからない」エラー
`ActiveDocument.Masters(“名前”)` を使う場合、そのマスターが現在のドキュメントのステンシルに含まれている必要があります。外部ファイルから読み込む場合は、あらかじめ `Documents.Open` でステンシルを開いておきましょう。
② 座標系(Units)の罠
VisioのVBAでは、座標は「インチ」で計算されるのがデフォルトです。もし「センチメートル」で配置したい場合は、`Application.ConvertResult` を使って変換しましょう。
‘ 例:5cmを指定したい場合
x = Application.ConvertResult(5, visCentimeters, visInches)
—
5. まとめ:エンジニアとしての一歩先へ
`DropMany` を使いこなせるようになると、単なる「マクロ記録者」から「自動化アーキテクト」へとレベルアップできます。
- 小規模なら `Drop` で十分。
- 10個を超えたら `DropMany` を検討する。
この感覚こそが、世界最高峰の現場で求められる「パフォーマンスへの嗅覚」です。Visioの内部エンジンは、私たちが思う以上に賢い。その賢さを引き出すための橋渡しをするのが、私たちの役割です。
さあ、あなたのコードを高速化し、空いた時間で美味しいコーヒーでも飲みに行きましょう。また次の技術解説でお会いしましょう!
