Word VBAの深淵:エラーハンドリングを「設計」するということ
Word VBAを書く際、多くのエンジニアが「On Error Resume Next」という名の麻薬に手を染める。だが、それを書いた瞬間、君が書いたコードは「予測不能な爆弾」へと変貌する。
Wordのオブジェクトモデルは極めて繊細だ。`Range`を操作中にユーザーが別の箇所を編集したり、あるいは削除されたテーブルを掴もうとした瞬間に、Wordは容赦なく「実行時エラー 462: リモートサーバーがないか、利用できません」や「オブジェクトが削除されました」を吐き出す。
伝説的なアーキテクトとして、一つだけ断言する。エラーハンドリングとは「回避」ではなく「管理」だ。 今回は、Word VBAにおけるエラーの構造的ハンドリングの真髄を伝授しよう。
—
1. On Error Resume Next は「ピンポイントの外科手術」であれ
多くのアマチュアは、プロシージャの先頭に `On Error Resume Next` を置き、その後一切の後始末をしない。これは「全盲で時速200kmの車を運転する」ようなものだ。
`On Error Resume Next` を使うのは、「APIの仕様上、どうしても発生を避けられない瞬間の、わずか1〜2行」に限定せよ。そして、直後に必ずエラー判定(`Err.Number <> 0`)を行い、フラグをリセットする。
‘ 良い例:特定のオブジェクトへのアクセス時のみを限定的に保護する
Public Sub SafeDeleteParagraph(targetRange As Range)
On Error Resume Next
targetRange.Delete
If Err.Number <> 0 Then
‘ エラーを握りつぶさず、ログを吐くか、制御を戻す
Debug.Print “削除失敗: ” & Err.Description
Err.Clear
End If
On Error GoTo 0 ‘ 即座に無効化し、予期せぬエラーが隠蔽されるのを防ぐ
End Sub
—
2. オブジェクトの「生存確認」という設計思想
Word VBAにおいて、「オブジェクトが存在するかどうか」を事前に判定するのは最もコストが高い。だからといって、エラーが出るまで放置して例外処理で回すのは、メモリスタックを無駄に消費する。
私が推奨するのは、「クエリインターフェースの概念」をVBAで模倣することだ。オブジェクトを操作する前に、その親(Parent)のステータスを確認し、存在しない場合は再取得を試みる。
‘ 非常に堅牢なDocument取得のパターン
Public Function GetTargetDoc(docName As String) As Document
Dim doc As Document
‘ WordのDocumentsコレクションを直接探索する前に、
‘ エラーの発生を予測したセーフティガードを配置
On Error Resume Next
Set doc = Documents(docName)
If Err.Number <> 0 Then
Err.Clear
‘ ここで再試行ロジックや、必要に応じた例外スローを行う
Set GetTargetDoc = Nothing
Else
Set GetTargetDoc = doc
End If
On Error GoTo 0
End Function
—
3. レガシー環境でのメモリ最適化:Set Nothing の真実
VBAはガベージコレクションが脆弱だ。特にWordの `Application` オブジェクトや `Document` オブジェクトを長時間保持すると、メモリリークは確実に発生する。
「VBAは自動解放されるから不要」という言説は半分正解だが、Wordという肥大化しやすいプロセスを扱う場合、「スコープを抜ける直前に手動でNothingを代入する」のが最も安全だ。特にWordのプロセスがゾンビ化(終了したはずなのにタスクマネージャーに残る)する問題は、オブジェクトの解放順序と `Set Nothing` の欠如が主原因である。
Public Sub CleanupExample()
Dim doc As Document
Dim rng As Range
On Error GoTo ErrorHandler
Set doc = ActiveDocument
Set rng = doc.Range(0, 0)
‘ 処理ロジック…
ExitPoint:
‘ 逆順で解放する。これがWord VBAの作法だ。
Set rng = Nothing
Set doc = Nothing
Exit Sub
ErrorHandler:
MsgBox “Error: ” & Err.Description
Resume ExitPoint
End Sub
—
4. 伝説的アーキテクトからの提言
システム間連携や大規模なWordドキュメント生成を行う際、VBAだけで解決しようとしてはいけない。
1. 複雑なロジックは分離せよ: VBAは「Wordを制御するインターフェース」に徹し、重い計算やデータ処理は外部DLL(C#で書いたCOMコンポーネントや、JSONを扱うためのWinHTTPライブラリなど)に委ねるべきだ。
2. イベント駆動を捨てよ: Wordのイベント(`DocumentChange`等)は、時に再帰的なエラーを引き起こす。可能な限り、明示的な呼び出しによる同期実行を心がけよ。
結論
`On Error GoTo` は単なる「例外処理」ではない。それは、君がコードの実行パスを完全に支配しているという宣言だ。
エラーを隠すな。エラーを定義し、制御し、ログに残し、そしてメモリを掃除せよ。その丁寧な積み重ねだけが、何年も保守され続ける「伝説的なシステム」を生み出す唯一の道である。
さあ、コードを書け。ただし、次に誰かがそのコードを読んだとき、その者が「このコードは死ぬほど丁寧に設計されている」と驚嘆するようなものを。
