Visio VBAの限界を突破する:数千シェイプを「一瞬」で描き切るための極限最適化術
こんにちは。業務自動化の現場でVisioと格闘している皆さん、お疲れ様です。
Visio VBAで図面を描画しているとき、シェイプが増えるにつれて「処理がどんどん重くなる」「画面がチラついて止まったように見える」という壁にぶつかったことはありませんか?
実は、Visioの描画エンジンは非常に優秀ですが、「何も対策せずに」数千個のシェイプを操作するのは、エンジンに全速力で走りながら毎回急ブレーキをかけさせているようなものです。
今日は、Visio VBAの内部構造を理解し、マクロの実行速度を劇的に(それこそ桁違いに)向上させる「禁断の高速化テクニック」を伝授します。これを知れば、あなたの自動化ツールは「重たいお荷物」から「瞬時に図面を生成する最強の武器」に変わります。
—
なぜVisioは重くなるのか?
まず、敵を知ることから始めましょう。Visioが遅くなる主な原因は以下の2つです。
1. 画面更新(Screen Updating): シェイプが1つ生成されるたびに、Visioは画面を再描画しようとします。数千回繰り返せば、それだけでPCは悲鳴を上げます。
2. イベントの連鎖(Event Firing): シェイプが動くたびに、Visioは「シェイプが移動した!」「変更があった!」というイベントを逐一検知し、計算を実行します。これが計算コストを爆増させます。
これらを「一時的に遮断する」ことこそが、プロの自動化エンジニアの第一歩です。
—
【実践】超高速化のためのテンプレートコード
以下に、私が大規模開発の現場で必ず使用する「高速化ラッパー」のコードを公開します。このパターンをコードの前後で呼び出すだけで、劇的な速度向上が期待できます。
Sub OptimizedDrawingProcess()
‘ 高速化のための重要フラグ
Dim oldScreenUpdating As Boolean
Dim oldEventEnabled As Boolean
‘ 1. 現在の設定を保存(復元するために必須!)
oldScreenUpdating = Application.ScreenUpdating
oldEventEnabled = Application.EventEnabled
‘ 2. 描画とイベントを完全に遮断
Application.ScreenUpdating = False
Application.EventEnabled = False
‘ — ここからがメインの重たい処理 —
On Error GoTo Cleanup ‘ エラー発生時でも設定を戻すための保険
Call GenerateMassiveShapes ‘ 数千個生成する関数を想定
‘ — メイン処理終了 —
Cleanup:
‘ 3. 必ず設定を元に戻す(戻さないとVisioがバグります)
Application.ScreenUpdating = oldScreenUpdating
Application.EventEnabled = oldEventEnabled
If Err.Number <> 0 Then MsgBox “エラーが発生しました: ” & Err.Description
End Sub
コードの解説
- `Application.ScreenUpdating = False`: これが最も強力です。処理が終わるまで画面を「フリーズ」させることで、再描画のコストをゼロにします。
- `Application.EventEnabled = False`: シェイプの変更イベント(`ShapeAdded`など)を無効化します。連鎖的な計算を防ぐ最強の手段です。
- `On Error GoTo Cleanup`: これが非常に重要です。もし処理の途中でエラーが起きてプログラムが止まった場合、設定が`False`のままVisioが残ってしまいます。それを防ぐための「安全装置」です。
—
陥りやすい罠:これだけは守ってほしい
初心者がよくやるミスは、「設定を戻し忘れること」です。
もし`EventEnabled = False`のまま処理を終えると、その後のVisio操作で「シェイプを動かしても何も起きない」「自動配置が機能しない」といった致命的な挙動不審に陥ります。
必ず「処理が終わったら必ず元の状態に戻す」という一連の流れを、上記のように`Cleanup`ラベルや`Finally`相当の構造で担保してください。
—
さらに上のステージへ:シェイプの「一括更新」
数千個のシェイプを生成する際、一つ一つ`Shape.Cells(“Width”).Formula = “10mm”`のように操作していませんか?
これも実は非効率です。Visioには「計算を保留して一括で反映させる」テクニックがあります。
- `Application.BeginUndoScope` / `EndUndoScope`: 処理全体を1つの「操作」として扱うことで、Undo(元に戻す)の履歴管理コストを減らし、パフォーマンスを向上させます。
- `Cells.Formula`ではなく`Cells.FormulaU`を使う: `U`がつくメソッドは「ユニバーサル形式(英語)」で処理されます。言語設定に依存せず高速に動作し、予期せぬエラーも防げます。
—
最後に:エンジニアとしての心構え
「コードが動く」ことと「プロフェッショナルとして通用する」ことの間には、大きな隔たりがあります。
今回紹介した技術は、単なる高速化テクニックではありません。「Visioという巨大なオブジェクトモデルを、いかに制御下に置くか」という設計思想そのものです。
まずは、今書いているコードにこの `ScreenUpdating` と `EventEnabled` を組み込んでみてください。処理時間が半分、いや1/10になる瞬間、あなたはまた一つ、Visio VBAの壁を越えたことになります。
次回の記事では、さらに踏み込んで「オブジェクトの参照を最小化するメモリ最適化術」について解説します。質問や「こんな現象で困っている」という相談があれば、ぜひコメント欄で教えてください。
一緒に、最高の自動化環境を構築していきましょう!
