Visio VBAを掌握する極限の知見:エラーを「ただの失敗」で終わらせない、堅牢なログ設計術
こんにちは。現場の設計と自動化の最前線で、日々複雑なシステムと格闘しているチーフアーキテクトです。
「マクロの記録」から一歩踏み出し、自分でコードを書き始めたあなた。素晴らしい一歩です。しかし、ここで多くのエンジニアが直面する「壁」があります。それが「エラーハンドリング(例外処理)」です。
「コードを書いたときは動いたのに、大量のページがある図面を処理させたら、途中で止まってしまった……」
「エラーが出たことはわかるが、一体どのページで、どんな操作をしようとして、なぜ失敗したのかがさっぱりわからない……」
もしあなたが一度でもこう感じたことがあるなら、あなたはすでに「単なるプログラマ」から「システムを設計するエンジニア」への脱皮を始めています。
今日は、複雑なページ操作(サイズ変更やレイヤー操作)を自動化する際に、「エラーを詳細に記録しつつ、処理を止めずに次へ進む」という、プロの現場で必須となる極限のテクニックを伝授しましょう。
1. なぜ「On Error Resume Next」だけでは不十分なのか?
初心者が最初に手にする武器が `On Error Resume Next` です。これは「エラーが起きても無視して次の行に進め」という命令です。
確かに、エラーでプログラムが止まることは防げます。しかし、これには致命的な弱点があります。
- 原因不明の不整合: ページ設定の変更に失敗したのに、そのまま処理が進んでしまうため、最終的な図面が「中途半端に壊れた状態」で完成してしまう。
- ブラックボックス化: どこで失敗したのかの痕跡が一切残らないため、デバッグ(修正作業)に膨大な時間を溶かすことになる。
プロの設計では、エラーを「無視」するのではなく、「適切に捕捉(キャッチ)し、状況を記録し、安全にリカバリ(復旧)する」という考え方をします。
2. 理想的なエラーハンドリングの設計思想
今回私たちが実装するのは、以下の3つの要素を備えた「スタックトレース風・堅牢ログ・システム」です。
1. コンテキストの保持: 「今、どのページの、どの操作をしているか」という情報を常に変数に持っておく。
2. 詳細なログ出力: エラー番号、エラー内容、そして「コンテキスト」をセットで記録する。
3. 継続的処理(スキップ機構): 1つのページで失敗しても、そのページを「失敗」として記録した上で、次のページへ処理を移す。
3. 実装コード:ページ一括設定自動化エンジン
それでは、実際のコードを見ていきましょう。このコードは、ドキュメント内の全ページをループし、ページ設定(サイズ変更など)を試みるものです。
Option Explicit
' =================================================================
' 概要: 全ページに対してページ設定の自動変更を試みるメインルーチン
' 特徴: エラー発生時に詳細な情報を記録し、処理を中断せずに次へ進む
' =================================================================
Sub BatchProcessPageSettings()
Dim vsoPage As Visio.Page
Dim currentContext As String ' 現在の操作状況を記録する変数
Dim errorCount As Long
errorCount = 0
Debug.Print "--- 処理開始: " & Now & " ---"
' ドキュメント内の全ページをループ
For Each vsoPage In ActiveDocument.Pages
' 【重要】コンテキスト(現在の状況)を更新
' これにより、エラー時に「どのページで何をしたか」が明確になる
currentContext = "Page: [" & vsoPage.Name & "] - Operation: SetPageSetup"
' エラーハンドリングの開始
On Error GoTo ErrorHandler
' --- ここから実際のページ操作(例:ページサイズをA4にする) ---
' 意図的にエラーを起こすテストとして、存在しないプロパティに触れる等の操作を想定
With vsoPage.PageSetup
.PageWidth = 21
.PageHeight = 29.7
' ここでエラーが起きる可能性がある(例:ロックされたレイヤーがある等)
End With
' --- 操作終了 ---
' 正常終了した場合のログ(必要に応じて)
' Debug.Print "Success: " & currentContext
' 次のループへ進むためにエラーハンドラをリセット
On Error GoTo 0
Next vsoPage
Debug.Print "--- 処理完了: 全ページのスキャンが終了しました ---"
MsgBox "処理が完了しました。エラー数: " & errorCount, vbInformation
Exit Sub
' =================================================================
' エラーハンドリング・ルーチン
' =================================================================
ErrorHandler:
errorCount = errorCount + 1
' 【極限の知見】エラーの発生場所と詳細を詳細に記録する
' エラー番号、説明、そして事前に定義したコンテキストを結合
Dim errorMsg As String
errorMsg = "【ERROR】" & vbCrLf & _
"Context: " & currentContext & vbCrLf & _
"Error No: " & Err.Number & vbCrLf & _
"Description: " & Err.Description
' イミディエイトウィンドウに出力(開発時のデバッグ用)
Debug.Print errorMsg
' 現場ではここを「テキストファイルへの書き出し」や「Excelへの記録」に置き換える
' 今回はデバッグ用にメッセージボックスを表示(大量エラー時はコメントアウト推奨)
' MsgBox errorMsg, vbCritical, "エラー発生"
' エラーをクリアして、次のページ処理へ進む準備をする
Err.Clear
' エラーハンドラを解除し、メインループの「次のステップ」へ戻す
On Error GoTo 0
Resume Next
End Sub
4. コードの解説:ここがプロの設計ポイント
このコードをただコピーするだけでなく、なぜこのように書くのか、その「意図」を理解してください。
① コンテキスト変数 `currentContext` の活用
これが最大のポイントです。`On Error GoTo ErrorHandler` だけでは、VBAは「エラーが起きたこと」しか教えてくれません。
あらかじめ `currentContext = “Page: [” & vsoPage.Name & “]…”` と変数に「今何をしているか」を書き込んでおくことで、エラー発生時に「どのページで、何の操作中に起きたのか」という、スタックトレースに近い情報を自前で生成できるのです。
② `Err.Clear` と `On Error GoTo 0` の使い分け
- `Err.Clear`: エラーオブジェクトの状態をリセットします。これを忘れると、次のエラー判定が正しく行われないことがあります。
- `On Error GoTo 0`: エラーハンドリングを一時的に解除します。ループ内で「エラーが起きたときだけ特別な処理をしたい」場合、エラーが起きていない時にハンドラが残っていると、予期せぬ動作を招くため、適切にリセットするのが美しい設計です。
③ `Resume Next` による「回復」
`Resume Next` は、エラーが発生した行の「次の行」から処理を再開させる命令です。これを使うことで、「1つのページがダメでも、諦めずに次のページへ進む」という、堅牢なバッチ処理が実現できます。
5. さらなる高みへ:現場での応用
もしあなたがこのコードを実務で使うなら、以下のステップアップを検討してください。
1. ログのファイル出力: `Debug.Print` ではなく、`Open “C:\log.txt” For Append As #1` を使って、テキストファイルにエラーログを書き出すようにしましょう。これにより、夜間に回した自動化処理の結果を翌朝確認できます。
2. オブジェクトのライフサイクル管理: ページを削除する操作を行う場合、そのページを参照している変数(`vsoPage`)が「無効なオブジェクト」にならないよう、操作の順序に細心の注意を払ってください。
まとめ
エラーハンドリングは、単にプログラムを止めないための技術ではありません。「何が起きたのかを可視化し、後から人間が調査できるようにするための、エンジニアの優しさ」です。
この「コンテキストを保持しながらエラーを捕捉する」というパターンをマスターすれば、あなたの作るVisio VBAツールは、プロが使う「業務システム」へと昇華されます。
ここをクリアすれば、Visio VBAの基本はバッチリですよ。さあ、自信を持って次の自動化に挑戦しましょう!
