【入門編】【上級者向け】Visio VBAでのエラーハンドリング:ページ操作失敗時に「どのページで何が起きたか」を詳細に記録する – Visio VBA解析バイブル

スポンサーリンク
スポンサーリンク

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の基本はバッチリですよ。さあ、自信を持って次の自動化に挑戦しましょう!

タイトルとURLをコピーしました