VBAのエラー処理は On Error GoTo ラベル名 を使って末尾に一箇所まとめると、コードがスッキリして保守しやすくなります。処理ごとに個別にエラーを書くと冗長になりますが、GoTo方式なら処理の流れを崩さずにエラー対応を集約できます。
この記事では、次の内容を順番に解説します。
- On Error GoToの基本構文と書き方
- Exit Subでエラー処理部分をスキップする理由
- Err.NumberとErr.Descriptionの使い方
- 後処理(EnableEvents・ScreenUpdatingの復元)を確実に行う方法
On Error GoToの基本構文を知るには?
処理の先頭に On Error GoTo ラベル名 を1行書いておくと、以降の処理でエラーが発生したとき自動的にそのラベルに処理がジャンプします。
Sub SampleProcess()
On Error GoTo ErrHandler 'エラーが起きたらErrHandlerへ
'--- 通常処理 ---
Dim v As Double
v = Cells(1, 1).Value '数字以外のセルがあるとエラーになる
MsgBox "正常終了しました。"
Exit Sub '正常終了時はここでSubを抜ける(ErrHandlerへ行かない)
ErrHandler:
MsgBox "エラーが発生しました:" & Err.Description, vbExclamation
End Sub
Exit Sub を入れておくことが重要です。これがないと正常終了時でもErrHandlerの処理が実行されてしまいます。
| コードの要素 | 役割 |
|---|---|
On Error GoTo ErrHandler | エラー発生時にErrHandlerラベルへジャンプする設定 |
Exit Sub | 正常終了時にErrHandlerをスキップする |
ErrHandler: | エラー発生時の処理を書くラベル |
Err.Description | エラーの内容を文字列で取得 |
Err.Number | エラー番号を取得(種類の判別に使う) |
エラー処理を末尾にまとめると何が良くなるか知るには?
処理ごとにOn Error Resume Nextを使ってエラーを個別処理する書き方と、GoToで末尾にまとめる書き方を比べます。
'分散させた書き方(読みにくく保守しにくい)
Sub BadExample()
On Error Resume Next
Cells(1, 1).Value = 1 / 0
If Err.Number <> 0 Then
MsgBox "1つ目でエラー"
Err.Clear
End If
Cells(1, 2).Value = CInt("abc")
If Err.Number <> 0 Then
MsgBox "2つ目でエラー"
Err.Clear
End If
End Sub
'末尾にまとめた書き方(読みやすく保守しやすい)
Sub GoodExample()
On Error GoTo ErrHandler
Cells(1, 1).Value = 1 / 0
Cells(1, 2).Value = CInt("abc")
MsgBox "処理完了"
Exit Sub
ErrHandler:
MsgBox "エラーが発生しました:" & Err.Description, vbExclamation
End Sub
後処理を確実に実行する書き方を知るには?
処理の途中でエラーが発生した場合でも、Application.EnableEvents や Application.ScreenUpdating などは必ず元に戻す必要があります。正常終了・エラー終了のどちらでも後処理を実行するには、共通の後処理をまとめたラベルを使います。
Sub SafeProcess()
On Error GoTo ErrHandler
'事前設定
Application.ScreenUpdating = False
Application.EnableEvents = False
'--- 処理本体 ---
Worksheets("データ").Range("A1").Value = "処理中"
'(何か重い処理)
MsgBox "正常に完了しました。"
GoTo CleanUp '正常時もCleanUpへ
ErrHandler:
MsgBox "エラーが発生しました:" & Err.Description, vbExclamation
CleanUp:
'正常終了・エラー終了どちらでも必ず実行される後処理
Application.ScreenUpdating = True
Application.EnableEvents = True
End Sub
エラー番号で種類を判別するには?
Err.Number でエラーの種類を確認し、エラーの内容に応じてメッセージや処理を変えることができます。
ErrHandler:
Select Case Err.Number
Case 9 'インデックスが有効範囲にありません
MsgBox "シートが見つかりません。シート名を確認してください。", vbExclamation
Case 13 '型が一致しません
MsgBox "数値以外のデータが含まれています。", vbExclamation
Case 1004 'アプリケーション定義またはオブジェクト定義のエラー
MsgBox "セルまたは範囲の指定が正しくありません。", vbExclamation
Case Else
MsgBox "予期しないエラーが発生しました(" & Err.Number & "):" & Err.Description, vbCritical
End Select
まとめ
On Error GoTo ラベル名を先頭に1行書き、エラー処理は末尾のラベルにまとめると読みやすく保守しやすいExit Subを正常処理の最後に入れないと、エラーがなくてもErrHandlerが実行されてしまうErr.Numberでエラー種別を判別し、内容に応じたメッセージや対処を出し分けられる- ScreenUpdating・EnableEventsなどの後処理は CleanUpラベル にまとめて、正常・エラーどちらでも実行されるようにする
- 開発中は
On Error GoToをコメントアウトして、エラーをVBEで直接確認するのがデバッグしやすい
よくある質問
On Error Resume NextとOn Error GoToはどう使い分けますか?
On Error Resume Nextは「エラーを無視して次の行に進む」設定です。特定の処理だけエラーを無視したいとき(シートの存在確認など)に短い範囲で使い、直後にOn Error GoTo 0でリセットするのが安全な使い方です。On Error GoToはSubやFunction全体のエラー処理に使います。
On Error GoTo 0とはどういう意味ですか?
エラー処理の設定を解除して、エラーが起きたときに通常のVBAエラー表示に戻す命令です。On Error Resume NextやOn Error GoToを使った後、効力を終わらせたい場所に書きます。
エラーが発生した行番号を知るには?
VBAには標準でエラー発生行番号を取得する機能がありません。デバッグ目的であれば、主要な処理の前後にDebug.Printで進捗を記録しておき、イミディエイトウィンドウで確認する方法が実用的です。
エラー処理(ErrHandler)の中で、さらにエラーが起きたらどうなりますか?
エラー処理の場所(ErrHandler)は、いわば「トラブルが起きた時の避難所」です。
残念ながら、避難所の中でさらにトラブルが起きた場合、それを助けてくれる仕組みはもうありません。 マクロはそこで完全に止まってしまいます。
そのため、エラー処理の場所(ErrHandler)には、難しい処理は書かないのが鉄則です。「エラーが起きたことを伝えるメッセージを出す」「設定を元に戻す」といった、シンプルで失敗しにくい内容にするのが基本です。
複数のSubそれぞれにエラー処理を書く必要がありますか?
はい、On Error GoToはそのSubの中だけで有効です。呼び出し先のSubでエラーが発生した場合、呼び出し元のErrHandlerには飛ばず、呼び出し先でエラーが処理されます。そのため重要な処理を行うSubにはそれぞれエラー処理を書くのが安全です。
動画で学びたい方へ
「記事を読んでも、実際に自分で書けるか不安…」という方には、動画で基礎からじっくり学べる講座がおすすめです。
VBAが初めての方を前提に、つまずきやすいポイントを先回りして解説しています。サンプル動画は無料でご覧いただけます。



