Visio VBAの限界を突破せよ:数千シェイプを秒速で捌く「極限最適化」の設計思想
Visio VBAで図面を自動生成する際、数千個のシェイプを扱うフェーズで「砂時計アイコンが消えない」「途中で応答なしになる」という壁にぶつかったことはないだろうか。
多くの初心者は、シェイプを一つ配置するたびにVisioが画面を再描画し、イベントを拾い、計算負荷の高いレイアウト調整を繰り返していることに気づかない。これはエンジニアリングの視点で見れば「極めて非効率なリソースの浪費」だ。
今日は、大規模図面を扱うプロフェッショナルが必ず実装している、「描画抑制(ScreenUpdating)」と「イベント遮断(EventEnabled)」による超高速化の極意を伝授する。
—
1. なぜ「そのまま」書くと遅いのか?
Visioは、シェイプの変更があるたびに以下の重い処理を裏側で実行している。
1. 画面の再描画(Repaint): グラフィックバッファの更新。
2. イベントハンドラの発火: `ShapeAdded` や `SelectionChanged` などのイベント監視。
3. 自動レイアウト計算: 接続線のルーティングや、コンテナのサイズ調整。
数個なら無視できるが、1,000個なら1,000回このオーバーヘッドが発生する。これを「処理の終了まで無効化する」のが、我々エンジニアの鉄則だ。
—
2. 破壊的な高速化を実現する「コンテキスト制御」の実装
以下のコードは、単なる高速化テクニックではない。処理中のエラー発生時にも確実に設定を復旧させるための「堅牢な設計」だ。
‘ — プロダクションコード:高速化のためのラッパークラス的設計 —
Public Sub OptimizeAndExecute()
‘ 実行前の状態を保存
Dim oldScreenUpdating As Boolean
Dim oldEventEnabled As Boolean
‘ 状態のキャプチャ
oldScreenUpdating = Application.ScreenUpdating
oldEventEnabled = Application.EventEnabled
‘ 極限最適化モードへの移行
Application.ScreenUpdating = False
Application.EventEnabled = False
On Error GoTo Cleanup ‘ 異常終了時でも設定を戻すためのガード
‘ — ここに大規模なシェイプ操作処理を記述 —
Call HeavyProcessingLogic
Cleanup:
‘ 異常終了しても、あるいは正常終了しても、必ず元の状態に戻す
Application.ScreenUpdating = oldScreenUpdating
Application.EventEnabled = oldEventEnabled
If Err.Number <> 0 Then
MsgBox “エラーが発生しました: ” & Err.Description, vbCritical
End If
End Sub
この設計のポイント
- `On Error GoTo` の必須化: 万が一ループ内でクラッシュしても、Visioの設定を「描画しない状態」で放置させない。これは開発者の責任ある実装だ。
- 状態のキャッシュ: `True/False` を直接書き込むのではなく、元の状態を保存してから戻す。これにより、他のアドインやメインアプリとの干渉を防ぐ。
—
3. さらに数倍速くする「シェイプ操作の作法」
描画を止めただけでは不十分な場合がある。以下の「重い処理」を避けることが、真のパフォーマンス改善に繋がる。
① `Shape.Cells` へのアクセスを最小限に
`shp.Cells(“Width”).ResultIU = 10` のような呼び出しは、内部で複雑な計算プロセスを呼ぶ。何度も同じプロパティにアクセスするなら、一度変数に格納すべきだ。
② レイヤーの非表示化
もしシェイプを配置するページに「コネクタ」などの複雑なレイヤーが存在するなら、処理前に `Page.Layers.Item(“Connector”).Visible = False` とすることで、ルーティング計算を劇的に抑制できる。
③ データベース連携時の落とし穴
外部DBから数千件のデータを読み込む際、「一行ずつVisioを操作する」のはタブーだ。
1. データを `Array` または `Collection` にメモリへ一括ロードする。
2. そのメモリデータをもとに、一気にシェイプ生成を行う。
3. 最後に `ActiveWindow.DeselectAll` などを実行し、画面を一度だけリフレッシュする。
—
4. プロの視点:アーキテクトからの助言
大規模な図面生成ツールを開発する際、コードが長くなると必ず「スパゲッティ化」が起きる。保守性を高めるためには、以下のルールを遵守してほしい。
- 「描画制御」はビジネスロジックから分離せよ:
メインの処理(`HeavyProcessingLogic`)には「画面がどうなっているか」を意識させない設計にする。描画制御はトップレベルの「コントローラー」のみが担当する。
- イベントの遮断は諸刃の剣:
`EventEnabled = False` にすると、当然ながらアドイン側で仕掛けているイベントトリガーも動かなくなる。ここを逆手に取り、データ整合性のための検証処理を「最後に一括実行」する設計に切り替えれば、処理速度は飛躍的に向上する。
結び
Visio VBAは古い言語だが、そのオブジェクトモデルは極めて強力だ。
「画面が動かない」という不安を捨て、「CPUサイクルをシェイプの生成に全集中させる」という意識改革を行えば、数千シェイプの生成ですら数秒で終わるようになる。
あなたの開発するツールが、単なる自動化ツールから「業務を変革するエンジン」へと進化することを期待している。健闘を祈る。
