この記事で解決できる悩み
✅ On Error GoToとResume Nextの違いが分からない
✅ エラー処理を書いてもマクロが止まる
✅ On Error GoTo 0の使いどころが分からない
✅ Err.NumberとErr.Descriptionの使い方が分からない
✅ 実務で使えるエラーハンドリングテンプレートが欲しい
この記事を読むと…
- 3つのOn Error構文の使い分けが完璧に理解できる
- 実例コード20個でエラー処理の実装が即座にできる
- エラーログ出力テンプレートをコピペで使える
- ベストプラクティスで保守性の高いコードが書ける
VBAエラー処理の3大構文を3分で理解
📌 3つのOn Error構文の役割
| 構文 | 役割 | 使用場面 | リスク |
|---|---|---|---|
| On Error GoTo [ラベル] | エラー発生時に指定ラベルへジャンプ | 本番環境、重要処理 | ⭐低(推奨) |
| On Error Resume Next | エラーを無視して次の行へ進む | 一部の処理のみ | ⚠️高(要注意) |
| On Error GoTo 0 | エラー処理を解除(標準に戻す) | Resume Next解除時 | ⭐低(推奨) |
🔍 3つの違いを図で理解
【パターン1: On Error GoTo】
Sub Main()
On Error GoTo ErrorHandler ← エラー監視開始
処理1 ✅
処理2 ❌エラー発生! → ErrorHandler へジャンプ
処理3 (実行されない)
Exit Sub
ErrorHandler:
MsgBox "エラー発生: " & Err.Description
End Sub
【パターン2: On Error Resume Next】
Sub Main()
On Error Resume Next ← エラー無視開始
処理1 ✅
処理2 ❌エラー発生! → でも無視して次へ
処理3 ✅実行される(危険!)
On Error GoTo 0 ← 必ず解除!
End Sub
【パターン3: On Error GoTo 0】
Sub Main()
On Error Resume Next
処理A ← エラー無視
On Error GoTo 0 ← エラー処理解除
処理B ← 標準エラー表示に戻る
End Sub
On Error GoTo:基本構文と実例5パターン
📝 基本構文
Sub 基本テンプレート()
On Error GoTo ErrorHandler 'エラー監視開始
'通常処理をここに記述
Debug.Print "処理実行中"
Exit Sub '正常終了時はここで抜ける(重要!)
ErrorHandler: 'エラー処理ラベル
MsgBox "エラー発生: " & Err.Description
End Sub
💡 重要ポイント
- Exit Sub/Exit Functionは必須: これが無いと正常終了時もエラー処理が実行される
- ラベル名は自由: ErrorHandler、ErrProc、Errorなど任意
- ラベルの位置: 必ずExit Sub/Exit Functionの後に配置
実例1: ファイル操作エラーの捕捉
Sub FileOpenSafe()
Dim wb As Workbook
On Error GoTo FileError
'存在しないファイルを開こうとする
Set wb = Workbooks.Open("C:\存在しないファイル.xlsx")
Debug.Print "ファイルを開きました"
wb.Close
Exit Sub
FileError:
MsgBox "ファイルが見つかりません。" & vbCrLf & _
"エラー番号: " & Err.Number & vbCrLf & _
"エラー内容: " & Err.Description, _
vbExclamation
End Sub
実例2: データベース接続エラー
Sub DatabaseConnect()
Dim conn As Object
On Error GoTo DBError
Set conn = CreateObject("ADODB.Connection")
conn.Open "Provider=SQLOLEDB;Data Source=localhost;..."
Debug.Print "データベース接続成功"
conn.Close
Set conn = Nothing
Exit Sub
DBError:
Select Case Err.Number
Case -2147467259 '接続エラー
MsgBox "データベースに接続できません。サーバーを確認してください。"
Case 429 'ActiveXコンポーネント作成不可
MsgBox "ADODBライブラリがインストールされていません。"
Case Else
MsgBox "予期しないエラー: " & Err.Description
End Select
End Sub
実例3: ゼロ除算エラー
Function SafeDivision(numerator As Double, denominator As Double) As Variant
On Error GoTo DivError
SafeDivision = numerator / denominator 'ゼロ除算発生可能性あり
Exit Function
DivError:
If Err.Number = 11 Then 'エラー11: 0で除算しました
SafeDivision = "#DIV/0!"
Else
SafeDivision = "#ERROR!"
End If
End Function
'使用例
Sub TestDivision()
Debug.Print SafeDivision(10, 2) '→ 5
Debug.Print SafeDivision(10, 0) '→ #DIV/0!
End Sub
実例4: シート名エラー
Function SheetExists(sheetName As String) As Boolean
Dim ws As Worksheet
On Error GoTo SheetNotFound
Set ws = ThisWorkbook.Worksheets(sheetName)
SheetExists = True 'シートが存在する
Exit Function
SheetNotFound:
SheetExists = False 'シートが存在しない
End Function
'使用例
Sub TestSheetExists()
If SheetExists("データ") Then
Debug.Print "シート「データ」は存在します"
Else
Debug.Print "シート「データ」は存在しません"
End If
End Sub
実例5: 複数エラー処理の統合
Sub MultipleErrorHandling()
Dim ws As Worksheet
Dim rng As Range
On Error GoTo ErrorHandler
'処理1: シート取得
Set ws = ThisWorkbook.Worksheets("データ")
'処理2: 範囲選択
Set rng = ws.Range("A1:Z1000")
'処理3: データ処理
rng.Value = Application.WorksheetFunction.Trim(rng.Value)
MsgBox "処理完了!"
Exit Sub
ErrorHandler:
Select Case Err.Number
Case 9 'インデックスが有効範囲にありません
MsgBox "シート「データ」が見つかりません。", vbCritical
Case 1004 'アプリケーション定義エラー
MsgBox "範囲指定が不正です。", vbCritical
Case 13 '型が一致しません
MsgBox "データ型が不正です。", vbCritical
Case Else
MsgBox "予期しないエラーが発生しました。" & vbCrLf & _
"エラー番号: " & Err.Number & vbCrLf & _
"エラー内容: " & Err.Description, _
vbCritical
End Select
End Sub
On Error Resume Next:正しい使い方と危険性
⚠️ 警告: Resume Nextは諸刃の剣
On Error Resume Nextは便利ですが、エラーを完全に隠蔽してしまうため、デバッグが困難になります。使用後は必ずOn Error GoTo 0で解除してください。
❌ 悪い例: Resume Nextの乱用
Sub BadExample()
On Error Resume Next '← 最初に宣言して放置(危険!)
'処理1
Range("A1").Value = "test"
'処理2: エラーが起きても気づかない!
Workbooks.Open "存在しないファイル.xlsx"
'処理3: エラーが伝播して意図しない結果に
ActiveWorkbook.Close
'On Error GoTo 0 が無いため、ずっとエラー無視状態(最悪!)
End Sub
✅ 良い例: 限定的な使用+即座に解除
Sub GoodExample()
Dim ws As Worksheet
'シート削除時のみエラー無視(シートが無い場合)
On Error Resume Next
Application.DisplayAlerts = False
ThisWorkbook.Worksheets("一時データ").Delete
Application.DisplayAlerts = True
On Error GoTo 0 '← すぐに解除!
'以降は通常のエラー処理
On Error GoTo ErrorHandler
Set ws = ThisWorkbook.Worksheets.Add
ws.Name = "新しいシート"
Exit Sub
ErrorHandler:
MsgBox "エラー: " & Err.Description
End Sub
📌 Resume Nextの正しい使用場面
| 使用場面 | 理由 | コード例 |
|---|---|---|
| シート削除 | 存在しないシートを削除してもエラーにしない | On Error Resume Next: ws.Delete: On Error GoTo 0 |
| オブジェクトの存在確認 | Is Nothing判定の補助 | On Error Resume Next: Set obj = GetObject(...): On Error GoTo 0 |
| プロパティ取得失敗 | 存在しないプロパティへのアクセス | On Error Resume Next: val = obj.Property: On Error GoTo 0 |
実例6: オブジェクト存在確認
Function IsExcelRunning() As Boolean
Dim xlApp As Object
On Error Resume Next
Set xlApp = GetObject(, "Excel.Application")
On Error GoTo 0 '← すぐに解除
If xlApp Is Nothing Then
IsExcelRunning = False
Else
IsExcelRunning = True
Set xlApp = Nothing
End If
End Function
実例7: 複数シート削除
Sub DeleteTempSheets()
Dim sheetNames As Variant
Dim i As Long
sheetNames = Array("一時1", "一時2", "一時3")
Application.DisplayAlerts = False
For i = LBound(sheetNames) To UBound(sheetNames)
On Error Resume Next 'シートが無くてもエラーにしない
ThisWorkbook.Worksheets(sheetNames(i)).Delete
On Error GoTo 0 '毎回解除
Next i
Application.DisplayAlerts = True
Debug.Print "一時シート削除完了"
End Sub
On Error GoTo 0:エラー処理の解除方法
📌 On Error GoTo 0の役割
On Error GoTo 0は、VBAのエラー処理を標準状態に戻す命令です。
これにより、On Error Resume NextやOn Error GoToで設定したエラーハンドリングが解除され、通常のエラーダイアログが表示されるようになります。
🔍 3つの使用場面
| 場面 | 理由 | コード例 |
|---|---|---|
| Resume Next解除 | エラー無視を終了 | On Error Resume Next → 処理 → On Error GoTo 0 |
| デバッグ時 | エラー箇所を特定 | On Error GoTo 0 '一時的に標準エラー表示 |
| 部分的なエラー処理 | 特定範囲のみエラー処理 | On Error GoTo Label → 処理 → On Error GoTo 0 |
実例8: Resume Nextの正しい解除
Sub ProperResumeNextUsage()
Dim ws As Worksheet
'【フェーズ1】エラー無視して一時シート削除
On Error Resume Next
Application.DisplayAlerts = False
ThisWorkbook.Worksheets("一時データ").Delete
Application.DisplayAlerts = True
On Error GoTo 0 '← 解除!
'【フェーズ2】通常のエラー処理に切り替え
On Error GoTo ErrorHandler
Set ws = ThisWorkbook.Worksheets.Add
ws.Name = "新しいデータ"
ws.Range("A1").Value = "ヘッダー"
MsgBox "処理完了!"
Exit Sub
ErrorHandler:
MsgBox "エラー発生: " & Err.Description, vbCritical
End Sub
実例9: デバッグ用の一時解除
Sub DebugMode()
Const DEBUG_MODE As Boolean = True '← デバッグ時はTrue
If Not DEBUG_MODE Then
On Error GoTo ErrorHandler
Else
On Error GoTo 0 '← デバッグ時は標準エラー表示
End If
'通常処理
Range("A1").Value = "test"
Range("存在しない範囲").Select '← エラー発生
Exit Sub
ErrorHandler:
MsgBox "本番環境でのエラー: " & Err.Description
End Sub
Errオブジェクト完全解説(Number/Description/Source)
📌 Errオブジェクトの主要プロパティ
| プロパティ | 説明 | 使用例 |
|---|---|---|
| Err.Number | エラー番号(例: 9, 91, 424, 1004) | If Err.Number = 9 Then... |
| Err.Description | エラーの説明文 | MsgBox Err.Description |
| Err.Source | エラー発生元のプロジェクト名 | Debug.Print Err.Source |
| Err.Clear | エラー情報をクリア(メソッド) | Err.Clear |
| Err.Raise | 独自エラーを発生させる(メソッド) | Err.Raise 9999, , "カスタムエラー" |
実例10: Err.Numberによる条件分岐
Sub ErrorNumberHandling()
Dim ws As Worksheet
On Error GoTo ErrorHandler
Set ws = ThisWorkbook.Worksheets("存在しないシート")
ws.Range("A1").Value = "test"
Exit Sub
ErrorHandler:
Select Case Err.Number
Case 9 'インデックスが有効範囲にありません
MsgBox "指定されたシートは存在しません。" & vbCrLf & _
"シート一覧を確認してください。", vbExclamation, "シート不存在"
Case 91 'オブジェクト変数が設定されていません
MsgBox "オブジェクトが正しく設定されていません。", vbCritical
Case 424 'オブジェクトが必要です
MsgBox "Setステートメントを確認してください。", vbCritical
Case 1004 'アプリケーション定義またはオブジェクト定義のエラー
MsgBox "範囲指定または操作が不正です。", vbCritical
Case Else
MsgBox "予期しないエラーが発生しました。" & vbCrLf & _
"エラー番号: " & Err.Number & vbCrLf & _
"エラー内容: " & Err.Description & vbCrLf & _
"発生元: " & Err.Source, _
vbCritical, "エラー詳細"
End Select
End Sub
実例11: Err.Raiseでカスタムエラーを発生
Function Divide(numerator As Double, denominator As Double) As Double
Const ERR_ZERO_DIVISION As Long = vbObjectError + 1001
If denominator = 0 Then
'カスタムエラーを発生させる
Err.Raise Number:=ERR_ZERO_DIVISION, _
Source:="Divide関数", _
Description:="ゼロ除算は許可されていません。"
End If
Divide = numerator / denominator
End Function
'使用例
Sub TestCustomError()
On Error GoTo ErrorHandler
Dim result As Double
result = Divide(10, 0) '← カスタムエラー発生
Exit Sub
ErrorHandler:
MsgBox "カスタムエラー検出!" & vbCrLf & _
"番号: " & Err.Number & vbCrLf & _
"発生元: " & Err.Source & vbCrLf & _
"内容: " & Err.Description
End Sub
実例12: Err.Clearでエラー情報をリセット
Sub MultipleAttempts()
Dim i As Long
Dim maxRetry As Long
maxRetry = 3
For i = 1 To maxRetry
On Error Resume Next
'ファイルを開く試行
Workbooks.Open "C:\data.xlsx"
If Err.Number = 0 Then
Debug.Print "ファイルを開きました"
Exit For
Else
Debug.Print "試行 " & i & " 失敗: " & Err.Description
Err.Clear '← エラー情報をクリア
Application.Wait Now + TimeValue("00:00:02") '2秒待機
End If
On Error GoTo 0
Next i
If Err.Number <> 0 Then
MsgBox "3回試行しましたが、ファイルを開けませんでした。", vbCritical
End If
End Sub
実務で使える汎用テンプレート3選
📋 テンプレート1: エラーログ出力付き完全版
Option Explicit
Sub CompleteErrorHandlingTemplate()
Const PROC_NAME As String = "CompleteErrorHandlingTemplate"
On Error GoTo ErrorHandler
'========== 通常処理 ==========
Debug.Print "処理開始: " & Now
'あなたの処理をここに記述
Range("A1").Value = "test"
Debug.Print "処理完了: " & Now
Exit Sub
ErrorHandler:
'========== エラー処理 ==========
Dim errMsg As String
errMsg = "【エラー詳細】" & vbCrLf & _
"プロシージャ: " & PROC_NAME & vbCrLf & _
"エラー番号: " & Err.Number & vbCrLf & _
"エラー内容: " & Err.Description & vbCrLf & _
"発生元: " & Err.Source & vbCrLf & _
"発生時刻: " & Now
'エラーログをファイル出力
Call WriteErrorLog(errMsg)
'ユーザーに通知
MsgBox errMsg, vbCritical, "エラー発生"
End Sub
'エラーログ出力関数
Sub WriteErrorLog(logMessage As String)
Dim fso As Object
Dim logFile As Object
Dim logPath As String
On Error Resume Next
logPath = ThisWorkbook.Path & "\error_log.txt"
Set fso = CreateObject("Scripting.FileSystemObject")
Set logFile = fso.OpenTextFile(logPath, 8, True) '8=追記モード
logFile.WriteLine String(50, "=")
logFile.WriteLine logMessage
logFile.WriteLine String(50, "=")
logFile.Close
Set logFile = Nothing
Set fso = Nothing
On Error GoTo 0
End Sub
📋 テンプレート2: リトライ機能付きエラー処理
Function OpenFileWithRetry(filePath As String, maxRetry As Long) As Workbook
Dim wb As Workbook
Dim i As Long
Dim success As Boolean
success = False
For i = 1 To maxRetry
On Error Resume Next
Set wb = Workbooks.Open(filePath)
On Error GoTo 0
If Not wb Is Nothing Then
success = True
Exit For
Else
Debug.Print "試行 " & i & " / " & maxRetry & " 失敗"
If i < maxRetry Then
Application.Wait Now + TimeValue("00:00:02") '2秒待機
End If
End If
Next i
If success Then
Set OpenFileWithRetry = wb
Else
MsgBox "ファイルを開けませんでした: " & filePath, vbCritical
Set OpenFileWithRetry = Nothing
End If
End Function
'使用例
Sub TestRetry()
Dim wb As Workbook
Set wb = OpenFileWithRetry("C:\data.xlsx", 3)
If Not wb Is Nothing Then
Debug.Print "ファイルを開きました: " & wb.Name
End If
End Sub
📋 テンプレート3: バッチ処理用エラー集約
Sub BatchProcessWithErrorCollection()
Dim errorList As Object 'Dictionary
Dim i As Long
Dim ws As Worksheet
Dim errMsg As String
Set errorList = CreateObject("Scripting.Dictionary")
'各シートを処理
For Each ws In ThisWorkbook.Worksheets
On Error Resume Next
'各シートで何らかの処理
ws.Range("A1").Value = "処理済: " & Now
If Err.Number <> 0 Then
'エラーをDictionaryに記録
errMsg = "シート: " & ws.Name & " / エラー: " & Err.Description
errorList.Add ws.Name, errMsg
Err.Clear
End If
On Error GoTo 0
Next ws
'エラーサマリーを表示
If errorList.Count > 0 Then
Dim summary As String
summary = "【バッチ処理エラー集約】" & vbCrLf & _
"エラー件数: " & errorList.Count & vbCrLf & vbCrLf
Dim key As Variant
For Each key In errorList.Keys
summary = summary & errorList(key) & vbCrLf
Next key
MsgBox summary, vbExclamation, "エラーサマリー"
Else
MsgBox "全シートの処理が正常に完了しました!", vbInformation
End If
Set errorList = Nothing
End Sub
エラーハンドリングのベストプラクティス7箇条
✅ 7つの鉄則
- Option Explicit必須: モジュール先頭に必ず記述
- Exit Sub/Exit Functionは必須: 正常終了時の処理分岐
- On Error Resume Nextは最小限: 使用後は必ずOn Error GoTo 0で解除
- Err.Numberで条件分岐: エラー番号ごとに適切な処理を実装
- エラーログを残す: 本番環境では必須(デバッグが容易に)
- カスタムエラーを活用: Err.Raiseで独自エラーを定義
- デバッグモードを用意: 開発時はOn Error GoTo 0でエラー箇所を特定
📊 良い例 vs 悪い例
| 項目 | ❌ 悪い例 | ✅ 良い例 |
|---|---|---|
| Exit Sub | Exit Subを忘れる→正常時もエラー処理実行 | Exit Subで処理を終了→エラー処理をスキップ |
| Resume Next | 先頭で宣言して放置 | 限定的に使用+即座にGoTo 0で解除 |
| エラー内容 | 「エラーです」のみ表示 | Err.Number・Descriptionを表示 |
| ログ出力 | ログを残さない | error_log.txtに日時・エラー詳細を記録 |
よくある質問(FAQ)7問
Q1. On Error GoToとResume Nextはどう使い分ける?
A. 基本はOn Error GoToを使い、特定の1〜2行だけエラー無視したい場合にResume Nextを使うのが原則です。
On Error GoTo: 本番環境、重要処理(99%のケース) Resume Next: シート削除、オブジェクト存在確認など限定的な用途(1%のケース)
Q2. Exit SubとExit Functionを忘れるとどうなる?
A. **正常終了時もエラー処理が実行されてしまいます。**これは非常によくあるミスです。
悪い例:
Sub Test()
On Error GoTo ErrHandler
Debug.Print "処理"
'Exit Subが無い!
ErrHandler:
MsgBox "エラー発生" '← 正常時も実行される
End Sub
Q3. On Error GoTo 0はいつ使う?
A. 主に以下の3つの場面で使います。
- On Error Resume Nextを解除: エラー無視を終了
- デバッグ時: エラー箇所を特定するため標準エラー表示に戻す
- 部分的なエラー処理: 特定範囲のみエラー処理を有効にする
Q4. Err.Numberが0の意味は?
A. **Err.Number = 0は「エラーが発生していない」**ことを意味します。
On Error Resume Next使用時に、エラーが発生したかどうかを判定する際に活用します。
If Err.Number = 0 Then
Debug.Print "正常終了"
Else
Debug.Print "エラー発生: " & Err.Description
End If
Q5. エラー処理内でさらにエラーが発生したら?
A. エラー処理内では別のエラーハンドリングを設定できません。
エラー処理内でエラーが発生すると、VBAが停止してしまいます。そのため、エラー処理内ではOn Error Resume Nextを使って、安全に処理を進めます。
ErrorHandler:
On Error Resume Next '← エラー処理内でエラー無視
Call WriteErrorLog(Err.Description)
On Error GoTo 0
Q6. Resume、Resume Next、Resume [ラベル]の違いは?
A. 3つのResumeステートメントの違いは以下の通りです。
- Resume: エラーが発生した行に戻って再実行
- Resume Next: エラーが発生した次の行から再開
- Resume [ラベル]: 指定ラベルから再開
実務ではResume Nextが最も多用されます。
Q7. On Error GoToのラベル名は何でもいい?
A. **はい、自由に命名できます。**一般的なラベル名は以下の通りです。
- ErrorHandler: 最も一般的
- ErrProc: 短縮形
- HandleError: 動詞+名詞形
- Catch: Try-Catch風
プロジェクト内で統一することが重要です。
まとめ
✅ この記事で学んだこと
- On Error GoTo・Resume Next・GoTo 0の使い分け完全理解
- Errオブジェクト(Number/Description/Source)の活用法
- 実例コード20個で実装方法を習得
- エラーログ出力・リトライ機能・バッチ処理テンプレート取得
- ベストプラクティス7箇条を実践

コメント