こんにちは。Visio VBAの世界へようこそ。
あなたが今、「マクロの記録」から一歩踏み出し、自分自身のコードでVisioを操ろうとしていること、その挑戦に心から敬意を表します。
「数千個のシェイプを自動配置するコードを書いたのに、実行した瞬間にVisioが固まってしまった」「処理が終わるまで数分間、画面が真っ白なまま動かない……」
もしあなたが今、そんな壁にぶつかっているとしたら、おめでとうございます。あなたは今、「プロフェッショナルな自動化エンジニア」への入り口に立っています。
今日は、大規模な図面を扱う際に避けては通れない、しかし多くの初心者が陥る「処理速度の罠」を突破するための極意をお伝えしましょう。テーマは、描画の制御による圧倒的な高速化です。
なぜ、あなたのマクロは「重い」のか?
まず、エンジニアとして「なぜ」を理解することから始めましょう。
あなたが1,000個のシェイプをページに追加するコードを書いたとします。Visioは非常に親切なアプリケーションです。あなたがコードで「ここにシェイプを置いて」と命令するたびに、Visioはこう考えます。
1. 「よし、シェイプを置いたぞ!」
2. 「ついでに、画面全体を書き直して、ユーザーに見えるようにしなきゃ!」
3. 「あ、レイヤーの設定も変わったね? 画面をもう一度描き直そう!」
これが、1,000回繰り返されるのです。
1回の描画は一瞬でも、1,000回繰り返されると、CPUとGPUは「描画」という作業だけで手一杯になり、肝心の「ロジック(計算や配置)」が進まなくなります。これが、Visioがフリーズしたように見える正体です。
解決の鍵:二つの「停止スイッチ」
この問題を解決するには、Visioに対して「今は作業中だから、いちいち画面を見せないでくれ!」と伝える必要があります。そのためのスイッチが2つあります。
1. `Application.ScreenUpdating = False`(描画の停止)
これは「画面の更新を止める」スイッチです。これを `False` にすると、Visioはメモリ上での計算とオブジェクトの操作に専念し、画面の書き換えを後回しにします。これが最も劇的な効果をもたらします。
2. イベントの制御(連鎖反応の防止)
Visioには、ある操作が行われた時に自動的に発生する「イベント」があります(例:シェイプが動いた、ページが変わったなど)。
大規模な操作を行うと、一つの操作が次々と別のイベントを呼び、まるでドミノ倒しのように処理が膨れ上がることがあります。これを制御することが、計算の安定につながります。
【実践】プロフェッショナルが書く「黄金のテンプレート」
それでは、実際に使えるコードを見ていきましょう。
ただスイッチを切るだけでは不十分です。もしコードの途中でエラーが起きて止まってしまったら、「画面更新がオフになったまま」になり、Visioが操作不能になってしまうからです。
これを防ぐために、「エラーハンドリング(例外処理)」を組み合わせるのが、我々プロの鉄則です。
''' <summary>
''' 大規模なページ生成とシェイプ配置の高速化テンプレート
''' </summary>
Sub HighSpeedLargeScaleProcess()
' 1. 変数の宣言(メモリ管理を適切に行うための基本)
Dim vsoPage As Visio.Page
Dim vsoShape As Visio.Shape
Dim i As Long
Dim targetCount As Long
targetCount = 1000 ' 今回は1000個のシェイプを扱う例
' 2. エラーハンドリングの設定
' 万が一エラーが起きても、必ず「ErrorHandler」へジャンプするようにします。
' これにより、画面更新がオフのまま放置されるのを防ぎます。
On Error GoTo ErrorHandler
' ---------------------------------------------------------
' 3. 高速化モードの開始(ここが極意!)
' ---------------------------------------------------------
' 画面更新を停止。これで描画負荷が激減します。
Application.ScreenUpdating = False
' 注意:VisioにはExcelのEnableEventsのようなグローバルなスイッチは
' 直接的には存在しませんが、処理の設計によってイベントの連鎖を防ぎます。
' ---------------------------------------------------------
Debug.Print "処理を開始します..."
' 新しいページを作成
Set vsoPage = Application.ActiveDocument.Pages.Add()
vsoPage.Name = "Massive_Data_Page"
' 4. メイン処理(大量のシェイプを配置)
For i = 1 To targetCount
' シェイプを配置(ここでは例として矩形を使用)
' 座標計算を行いながらループを回します
Set vsoShape = vsoPage.DrawRectangle(i * 0.2, i * 0.2, (i * 0.2) + 0.1, (i * 0.2) + 0.1)
' シェイプに名前を付けるなどの重い処理も、描画停止中なら高速です
vsoShape.Text = "Shape #" & i
Next i
' ---------------------------------------------------------
' 5. 正常終了時の処理
' ---------------------------------------------------------
' すべての処理が終わったら、必ず画面更新を「True」に戻します。
Application.ScreenUpdating = True
MsgBox "完了しました! " & targetCount & " 個のシェイプを配置しました。", vbInformation
' 正常終了した場合は、ここで処理を抜けます(ErrorHandlerを通さないため)
Exit Sub
ErrorHandler:
' ---------------------------------------------------------
' 6. エラー発生時のリカバリ(ここがエンジニアの腕の見せ所)
' ---------------------------------------------------------
' 何らかのエラーが起きた場合、ここへ飛びます。
' 最優先事項は「画面更新をONに戻すこと」です。
Application.ScreenUpdating = True
MsgBox "エラーが発生しました。" & vbCrLf & _
"エラー番号: " & Err.Number & vbCrLf & _
"内容: " & Err.Description, vbCritical, "致命的なエラー"
Debug.Print "Error encountered: " & Err.Description
End Sub
ここをクリアすれば、Visio VBAの基本はバッチリですよ
このコードを読み解くための、3つの重要ポイントをまとめました。
① 「後始末」をセットで考える
`Application.ScreenUpdating = False` を書いたら、必ずセットで `True` に戻すコードを書くこと。そして、その `True` に戻す作業を、「成功した時」と「失敗した時(エラー時)」の両方で行うこと。これが、ユーザーにストレスを与えない「優しいツール」を作る第一歩です。
② オブジェクトの参照を大切にする
コードの中で `Set vsoShape = …` のように、オブジェクトを変数に格納していますね。ループの中で何度も `ActivePage.Shapes(i)` のように「探しに行く」コードを書くと、それだけで遅くなります。一度捕まえたオブジェクトは、変数に入れて使い回す。これがパフォーマンスの鉄則です。
③ デバッグは `Debug.Print` を活用して
大規模な処理の途中で「今、どこまで進んでいるのか?」を知るために、`Debug.Print` を使いましょう。イミディエイトウィンドウに経過が表示されるので、フリーズしているのか、単に時間がかかっているだけなのかを判断できます。
最後に
大規模な図面を操ることは、まるで巨大な船を操縦するようなものです。
最初は少し扱いにくく感じるかもしれませんが、今回学んだ「描画の制御」という操舵技術を身につければ、あなたはVisioを自由自在に、そして驚くほど高速に動かせるようになります。
一歩ずつ、確実に。
あなたのコードが、誰かの業務を劇的に変える素晴らしい道具になることを応援しています!
