VBA のエラー処理モデル

VBA にはJavaやPythonのような try-catch-finally 構文がありません。代わりに On Error ステートメントでエラー発生時の挙動を3パターンから選択します。

ステートメント動作用途
On Error GoTo ラベルエラー発生時に指定ラベルへジャンプ一般的なエラー処理
On Error Resume Nextエラーを無視して次の行を実行エラーの存在確認・部分スキップ
On Error GoTo 0エラー処理を無効化(既定に戻す)Resume Next の解除

On Error GoTo — ラベルジャンプ型

最も基本的で推奨されるパターンです。エラー発生時に指定したラベルに処理が移ります。

VBA — On Error GoTo 基本パターン
Option Explicit

Sub OpenFileExample(ByVal filePath As String)
    Dim wb As Workbook

    On Error GoTo ErrHandler   ' エラーハンドラを登録

    Set wb = Workbooks.Open(filePath)
    ' ── 正常処理 ──
    MsgBox "開きました: " & wb.Name
    wb.Close SaveChanges:=False

    Exit Sub   ' ← 正常終了時はここで抜ける(ErrHandler を実行しない)

ErrHandler:
    MsgBox "エラー " & Err.Number & ": " & Err.Description, vbCritical
    ' 必要に応じてリソース解放
    If Not wb Is Nothing Then wb.Close SaveChanges:=False
End Sub

⚠️ Exit Sub を忘れずに

正常処理の末尾に Exit Sub(または Exit Function)を書かないと、正常終了時もエラーハンドラが実行されてしまいます。必ずセットで記述してください。

On Error Resume Next — スキップ型

エラーが発生しても次の行に進みます。使いどころは限定的で、エラーの存在チェックや「なければ無視」の処理に限定するのが鉄則です。

VBA — Resume Next の正しい使い方
Option Explicit

' ── シート存在確認の例 ──
Function SheetExists(ByVal sheetName As String) As Boolean
    Dim ws As Worksheet

    On Error Resume Next
    Set ws = ThisWorkbook.Worksheets(sheetName)
    On Error GoTo 0   ' ← 必ず解除する

    SheetExists = Not (ws Is Nothing)
End Function

' ── 使用例 ──
Sub CheckSheet()
    If SheetExists("データ") Then
        MsgBox "シートがあります"
    Else
        MsgBox "シートが存在しません"
    End If
End Sub

⚠️ On Error Resume Next を広範囲に使うと危険

On Error Resume Next をプロシージャ全体にかけると、すべてのエラーが握りつぶされます。必要な箇所だけに絞り、直後に On Error GoTo 0 で解除してください。

Err オブジェクト

エラーハンドラ内では Err オブジェクトからエラーの詳細を取得できます。

プロパティ / メソッド内容
Err.Numberエラー番号(0 はエラーなし)
Err.Descriptionエラーメッセージ
Err.Sourceエラーが発生したオブジェクト名
Err.ClearErr 情報をリセット
Err.Raise Number, Source, Description意図的にエラーを発生させる
VBA — Err オブジェクトの活用
Option Explicit

Sub ErrObjectExample()
    On Error GoTo ErrHandler

    ' 意図的にエラーを発生させる
    Err.Raise 9, "ErrObjectExample", "独自エラーメッセージ"

    Exit Sub

ErrHandler:
    Debug.Print "番号: " & Err.Number       ' → 9
    Debug.Print "内容: " & Err.Description  ' → インデックスが有効範囲にありません
    Debug.Print "発生元: " & Err.Source     ' → ErrObjectExample
    Err.Clear  ' エラー情報をクリア
End Sub

クリーンアップパターン(Finally相当)

Javaの finally に相当するリソース解放処理を実現するパターンです。

VBA — Finally 相当パターン
Option Explicit

Sub ProcessWithCleanup()
    Dim conn As Object   ' DB接続などのリソース
    Dim errNum As Long
    Dim errMsg As String

    On Error GoTo ErrHandler

    Set conn = CreateObject("ADODB.Connection")
    conn.Open "接続文字列"

    ' ── メイン処理 ──
    ' ...

Cleanup:
    ' 正常・エラー問わず必ず実行
    If Not conn Is Nothing Then
        If conn.State = 1 Then conn.Close  ' 接続中なら閉じる
        Set conn = Nothing
    End If
    If errNum <> 0 Then
        MsgBox "エラー " & errNum & ": " & errMsg, vbCritical
    End If
    Exit Sub

ErrHandler:
    errNum = Err.Number
    errMsg = Err.Description
    Resume Cleanup  ' ← Cleanup ラベルへジャンプ
End Sub

ポイント

エラー情報を変数に退避してから Resume Cleanup でクリーンアップラベルに移動するパターンが定石です。Resume Cleanup を使うと On Error ハンドラ内でもエラーを再発生させずにジャンプできます。

入れ子プロシージャでのエラー伝播

呼び出し先(子)でハンドルされなかったエラーは、呼び出し元(親)のエラーハンドラに伝播します。

VBA — エラー伝播の確認
Option Explicit

Sub Parent()
    On Error GoTo ErrHandler
    Call Child   ' Child 内でエラーが発生
    Exit Sub
ErrHandler:
    MsgBox "Parent がキャッチ: " & Err.Description
End Sub

Sub Child()
    ' On Error がない → エラーは Parent に伝播する
    Dim x As Long
    x = 1 / 0   ' ゼロ除算エラー
End Sub

まとめ:使い分けフロー

状況推奨パターン
一般的なエラー処理On Error GoTo ErrHandler
オブジェクトの存在チェックOn Error Resume NextOn Error GoTo 0
リソースを必ず解放したいCleanup ラベル + Resume Cleanup
意図的なエラー通知Err.Raise

次の章では…

PART 03 では モジュール分割設計 を解説します。標準モジュール・クラスモジュール・ThisWorkbook の役割を整理し、大規模マクロを保守しやすく設計する方法を紹介します。

→ PART 03 — モジュール分割設計へ