Word VBAの真実:なぜあなたのマクロは「重い」のか?
Word VBAを扱う多くのエンジニアが犯す最大の過ちは、オブジェクトモデルの「重さ」を無視することだ。WordはExcelと異なり、カーソル位置(Selection)や画面描画(ScreenUpdating)の状態が、処理速度に直接かつ致命的な負荷をかける。
あなたが書いたコードが、100ページのドキュメントを処理するのに数分かかるなら、それはあなたのコードが「CPU」ではなく「描画エンジン」を酷使している証拠だ。
本稿では、プロフェッショナルとして最低限守るべき「実行速度」と「安定性」のための設計思想を伝授する。
—
1. 速度改善の二大原則:ScreenUpdatingとDisplayAlerts
Word VBAにおいて、画面描画の更新と警告の表示は、処理の足を引っ張る最大のボトルネックだ。
- `Application.ScreenUpdating = False`:
Wordはコードが一行進むたびに「今どこを編集したか」をGUIに反映しようとする。これを停止させるだけで、処理速度は数倍〜数十倍に跳ね上がる。
- `Application.DisplayAlerts = wdAlertsNone`:
ファイルを開く際や閉じる際の「保存しますか?」といったダイアログは、自動化の大敵だ。処理を完全に自動化するなら、これを握りつぶす必要がある。
なぜ「エラーハンドリング」が必須なのか
ここで重要な注意点がある。`ScreenUpdating = False` のままマクロがエラーで落ちると、ユーザーのWordは「画面が更新されないままフリーズしたように見える」という最悪のUXを引き起こす。
だからこそ、「エラーが起きても必ず設定を戻す」という、堅牢な設計(Clean-up処理)が必須なのだ。
—
2. 実装コード:プロダクションレベルの「黄金パターン」
以下は、私が業務自動化ツールを設計する際に必ずベースとして用いるテンプレートだ。`Finally`句のような構造をVBAで再現するための「Gotoラベル」による制御を推奨する。
Sub ExecuteHighPerformanceTask()
‘ 実行前の状態を退避(必要に応じて)
Dim originalScreenUpdating As Boolean
originalScreenUpdating = Application.ScreenUpdating
‘ 1. 環境設定の最適化
On Error GoTo ErrorHandler
Application.ScreenUpdating = False
Application.DisplayAlerts = wdAlertsNone
‘ — ここからメイン処理 —
‘ 例:Rangeオブジェクトを直接操作し、Selectionを使わないのが鉄則
Dim doc As Document
Set doc = ActiveDocument
‘ ここに重い処理を記述
‘ Selection.Move… ではなく doc.Range(0, 0)… を使うこと
‘ ————————-
CleanExit:
‘ 2. 確実に設定を戻す(ここが最重要)
Application.ScreenUpdating = originalScreenUpdating
Application.DisplayAlerts = wdAlertsAll
Exit Sub
ErrorHandler:
‘ エラー発生時のログ出力や通知
MsgBox “エラーが発生しました: ” & Err.Description, vbCritical
Resume CleanExit
End Sub
—
3. 現場で差がつく3つの知見
① Selectionオブジェクトを追放せよ
`Selection`は現在カーソルがある場所を指し示すため、Wordが逐一GUIを更新しようとする。対して`Range`オブジェクトはメモリ上で完結する。可能な限り`Selection`を使わず、`Range`オブジェクトで処理を完結させること。これが真のパフォーマンスチューニングだ。
② ファイル・DB連携時の排他制御
大規模な処理では、外部ファイルやDBとの連携を行うだろう。その際、`Application.DisplayAlerts = wdAlertsNone` を過信してはいけない。読み取り専用で開く、あるいは `Document.Open` の引数で `ReadOnly:=True` を明示的に指定するなど、Word側のロックを回避する設計を心がけるべきだ。
③ モジュールを分割する
数千行のコードを単一の標準モジュールに書くのは、保守性の観点から自殺行為だ。
- `Lib_Common`: 設定のON/OFFなどのユーティリティ
- `Core_Logic`: ビジネスロジック
- `Main`: 処理の呼び出し
このように責務を分離し、`ErrorHandler`も共通関数化することで、どのマクロでも同じ品質でエラーログを取得できるようにしておくこと。
—
最後に:エンジニアとしての矜持
自動化ツールは「動けばいい」のではない。「止まらず、速く、かつメンテナンスしやすいこと」が求められる。
今回紹介した「画面更新の制御」と「エラーハンドリングの徹底」は、単なるテクニックではなく、システムに対する敬意だ。Wordという巨大なオブジェクトモデルを、あなたが手足のように操れるようになることを期待している。
さあ、コードを書こう。そして、無駄な待ち時間を世界から削り取ってほしい。
