トップ > 備忘録 > エラー制御

エラー処理2012.11.10   [更新日]2024.11.30

VBAでのエラー制御についてまとめたメモです。


※サンプルコードがエラーで中断される場合
・VBEのオプション設定を変更 参照
・プロジェクトをロックする 参照
ブックファイルを配布の際に、プロジェクトをロックしておくと、ユーザーのVBE設定にかかわらず、On Errorステートメントが有効になる。


【お薦め】マクロ・プロシージャを管理する無料のツール!
 Excelマクロ管理ツール

On Errorステートメント

エラー発生時にステートメント実行位置を制御する。
エラー処理ルーチンを無効にするときにも使用できる。
Exit Subなどで、そのプロシージャを抜けた場合、エラー処理ルーチンは無効になる。

構文1:On Error GoTo line
引数[line]に指定した行から始まる、エラー処理ルーチンを有効にする。
引数[line]には任意の行ラベルまたは行番号を必ず指定。
実行時エラーが発生すると、[line]に指定したルーチンにプログラムの制御が移る。
指定する行は、On Errorステートメントと同じプロシージャ内に存在しなければならない。

構文2:On Error Resume Next
実行時エラーが発生してもプログラムを中断せず、エラーの次のステートメントから実行を継続する。
オブジェクトを伴うエラーは、Errオブジェクトで原因を探ることができるため、このステートメントを使用すると良い。

構文3:On Error GoTo 0
On Error GoTo line や On Error Resume Next を無効にする。


サンプルコード
エラー発生時の On Errorステートメントの Resume Next と GoTo line の動作の違いを確認する。

Sub OnErrorステートメントの動作の違い()
    Dim i         As Long
    Dim dblResult As Double
    
    '---------------------------------------
    ' On Error Resume Next
    '---------------------------------------
    ' エラーが発生した場合 無視して次に進む
On Error Resume Next
    dblResult = 100 / i     ' i = 0 のため 100 を 0 で除算することでエラーが発生する
On Error GoTo 0
    
    MsgBox dblResult, , "On Error Resume Next" ' 結果「1.#INF」: 0 除算により結果が誤った形式で表示される

    '---------------------------------------
    ' On Error GoTo ライン
    '---------------------------------------
    ' エラーが発生した場合 指定の行または行ラベルに制御を移す
On Error GoTo LBL_ERROR
    dblResult = 100 / i     ' 100 を 0 で除算しエラーが発生すると LBL_ERROR に制御を移す
On Error GoTo 0
    
    MsgBox dblResult, , "On Error Goto ライン" ' 結果「5」
    
    Exit Sub

'---------------------------------------
' エラー発生時の行ラベル
'---------------------------------------
LBL_ERROR:
    i = 20  ' i に 20 を代入
    Resume  ' エラーが発生箇所に制御を戻す
End Sub

VBAコードをカラーで印刷・Web掲載するためのツールはこちら


Resumeステートメント

エラー処理の最後に記述し、プログラムの再開位置を指定する。

構文1:Resume [0]
[0]は省略可能。
エラーの原因となったステートメントからプログラムを再開する。

構文2:Resume Next
エラーの原因となったステートメントの、次のステートメントからプログラムを再開する。

構文3:Resume line
引数[line]に指定した行からプログラムを再開する。

サンプルコード
Resumeステートメントの Resume Next 、 Resume 0 、 Resume line の動作の違いを確認する。

Sub Resumeステートメントの動作の違い()
    Dim i         As Long
    Dim dblResult As Double
    
    '---------------------------------------
    ' Resume Next
    '---------------------------------------
    i = 0
On Error GoTo LBL_ERROR_A
    dblResult = 100 / i                 ' 100 を 0 で除算しエラーが発生すると LBL_ERROR_A に制御を移す
On Error GoTo 0
    
    MsgBox dblResult, , "Resume Next"   ' 結果「1.#INF」: 0 除算により結果が誤った形式で表示される

    '---------------------------------------
    ' Resume 0
    '---------------------------------------
    i = 0
On Error GoTo LBL_ERROR_B
    dblResult = 100 / i                 ' 100 を 0 で除算しエラーが発生すると LBL_ERROR_B に制御を移す
On Error GoTo 0

    MsgBox dblResult, , "Resume 0"      ' 結果「5」

    '---------------------------------------
    ' Resume ライン
    '---------------------------------------
    i = 0
On Error GoTo LBL_ERROR_C
    dblResult = 100 / i                 ' 100 を 0 で除算しエラーが発生すると LBL_ERROR_C に制御を移す
On Error GoTo 0

    MsgBox dblResult, , "Resume ライン" ' (メッセージは表示されない)

LBL_RESUME_LINE:

    MsgBox "終了"
    Exit Sub
    
'---------------------------------------
' エラー発生時の各行ラベル
'---------------------------------------
LBL_ERROR_A:
    i = 20                  ' i に 20 を代入
    Resume Next             ' エラー発生箇所の次のステートメントに制御を移す
    
LBL_ERROR_B:
    i = 20                  ' i に 20 を代入
    Resume 0                ' エラー発生箇所に制御を移す

LBL_ERROR_C:
    i = 20                  ' i に 20 を代入
    Resume LBL_RESUME_LINE  ' LBL_RESUME_LINE に制御を移す
End Sub

Errオブジェクト

コードの実行時にエラーが発生した場合に、エラーに関する情報がErr.オブジェクトに格納される。

Errオブジェクトの主なメンバ
主なメンバタイプ説明
Numberプロパティエラー発生時にエラー番号が設定される
Sourceプロパティエラー発生元のオブジェクトまたはアプリケーションの名前が設定される
Descriptionプロパティエラー発生時にエラーに関連する説明の文字列をが設定される
ClearメソッドErrオブジェクトのすべてのプロパティの設定値をクリアする
Raiseメソッド実行時エラーを生成する

サンプルコード
Errオブジェクトの動作確認

Sub Errオブジェクトの動作確認1()
    '---------------------------------------
    ' エラー情報確認
    '---------------------------------------
    MsgBox "エラー番号:" & Err.Number & vbLf & _
           "エラー説明:" & Err.Description & vbLf & _
           "エラーソース:" & Err.Source
       
    '---------------------------------------
    ' エラーを発生させる
    '---------------------------------------
On Error Resume Next
    Dim dblResult As Double
    dblResult = 100 / 0    ' 100 を 0 で除算することでエラーが発生する

    '---------------------------------------
    ' エラー情報確認
    '---------------------------------------
    MsgBox "エラー番号:" & Err.Number & vbLf & _
           "エラー説明:" & Err.Description & vbLf & _
           "エラーソース:" & Err.Source
    
    '---------------------------------------
    ' エラー情報クリア
    '---------------------------------------
    Err.Clear

    '---------------------------------------
    ' エラー情報確認
    '---------------------------------------
    MsgBox "エラー番号:" & Err.Number & vbLf & _
           "エラー説明:" & Err.Description & vbLf & _
           "エラーソース:" & Err.Source
End Sub

コード実行結果




Errオブジェクトの各プロパティは、エラー処理ルーチン内の次のステートメントの後で
0 または長さ 0 の文字列 ("") にリセットされる。
 ・Resume Next
 ・GoTo 0
 ・GoTo ライン

サンプルコード
Errオブジェクトのリセット確認① On Error Resume Next

Sub Errオブジェクトのリセット確認1()
    '---------------------------------------
    ' エラーを発生させる
    '---------------------------------------
On Error Resume Next
    Dim dblResult As Double
    dblResult = 100 / 0     ' 100 を 0 で除算することでエラーが発生する

    '---------------------------------------
    ' エラー情報確認
    '---------------------------------------
    MsgBox "エラー番号:" & Err.Number & vbLf & _
           "エラー説明:" & Err.Description & vbLf & _
           "エラーソース:" & Err.Source
           
On Error Resume Next        ' エラー情報がリセットされる
    '---------------------------------------
    ' エラー情報確認
    '---------------------------------------
    MsgBox "エラー番号:" & Err.Number & vbLf & _
           "エラー説明:" & Err.Description & vbLf & _
           "エラーソース:" & Err.Source
End Sub

コード実行結果


サンプルコード
Errオブジェクトのリセット確認② Resume Next

Sub Errオブジェクトのリセット確認2()
    '---------------------------------------
    ' エラーを発生させる
    '---------------------------------------
On Error GoTo LBL_ERROR
    Dim dblResult As Double
    dblResult = 100 / 0     100 を 0 で除算しエラーが発生すると LBL_ERROR に制御を移す

    '---------------------------------------
    ' エラー情報確認②
    '---------------------------------------
    MsgBox "エラー番号:" & Err.Number & vbLf & _
           "エラー説明:" & Err.Description & vbLf & _
           "エラーソース:" & Err.Source
           
    Exit Sub

LBL_ERROR:
    '---------------------------------------
    ' エラー情報確認①
    '---------------------------------------
    MsgBox "エラー番号:" & Err.Number & vbLf & _
           "エラー説明:" & Err.Description & vbLf & _
           "エラーソース:" & Err.Source
           
    Resume Next             ' エラー情報がリセットされる(エラー発生箇所の次のステートメントに制御を移す)
End Sub

コード実行結果


サンプルコード
Errオブジェクトのリセット確認③ On Error GoTo 0

Sub Errオブジェクトのリセット確認3()
    '---------------------------------------
    ' エラーを発生させる
    '---------------------------------------
On Error Resume Next
    Dim dblResult As Double
    dblResult = 100 / 0     ' 100 を 0 で除算することでエラーが発生する

    '---------------------------------------
    ' エラー情報確認
    '---------------------------------------
    MsgBox "エラー番号:" & Err.Number & vbLf & _
           "エラー説明:" & Err.Description & vbLf & _
           "エラーソース:" & Err.Source
    
On Error GoTo 0             ' エラー情報がリセットされる
    
    '---------------------------------------
    ' エラー情報確認
    '---------------------------------------
    MsgBox "エラー番号:" & Err.Number & vbLf & _
           "エラー説明:" & Err.Description & vbLf & _
           "エラーソース:" & Err.Source
End Sub

コード実行結果


サンプルコード
Errオブジェクトのリセット確認④ On Error GoTo ライン

Sub Errオブジェクトのリセット確認4()
    '---------------------------------------
    ' エラーを発生させる
    '---------------------------------------
On Error Resume Next
    Dim dblResult As Double
    dblResult = 100 / 0     ' 100 を 0 で除算することでエラーが発生する

    '---------------------------------------
    ' エラー情報確認
    '---------------------------------------
    MsgBox "エラー番号:" & Err.Number & vbLf & _
           "エラー説明:" & Err.Description & vbLf & _
           "エラーソース:" & Err.Source
    
On Error GoTo LBL_NEXT     ' エラー情報がリセットされる

LBL_NEXT:

    '---------------------------------------
    ' エラー情報確認
    '---------------------------------------
    MsgBox "エラー番号:" & Err.Number & vbLf & _
           "エラー説明:" & Err.Description & vbLf & _
           "エラーソース:" & Err.Source
End Sub

コード実行結果




次のステートメントではErrオブジェクトの各プロパティはリセットされない。
 ・End Sub
 ・End Function
 ・End Property
 ・Exit Sub
 ・Exit Function
 ・Exit Property

サンプルコード
Errオブジェクトのリセット確認⑤

Sub Errオブジェクトのリセット確認5()
    '---------------------------------------
    ' エラー発生プロシージャを呼び出す
    '---------------------------------------
    Call エラー発生

    '---------------------------------------
    ' エラー情報確認②
    '---------------------------------------
    MsgBox "エラー番号:" & Err.Number & vbLf & _
           "エラー説明:" & Err.Description & vbLf & _
           "エラーソース:" & Err.Source
           
End Sub

Private Sub エラー発生() On Error Resume Next Dim dblResult As Double dblResult = 100 / 0 ' 100 を 0 で除算することでエラーが発生する '--------------------------------------- ' エラー情報確認① '--------------------------------------- MsgBox "エラー番号:" & Err.Number & vbLf & _ "エラー説明:" & Err.Description & vbLf & _ "エラーソース:" & Err.Source End Sub

コード実行結果





Errオブジェクトの Raise メソッドは、実行時エラーを発生させる。
構文:Err.Raise Number, [Source], [Description], [HelpFile], [HelpConText]

Number(エラー番号)の 0 から 512 はシステム エラー用に予約されており、513 から 65535 は、ユーザー定義エラーに使用できる。
[参考]Microsoft Learn Challenge Raise メソッド
    Microsoft Learn Challenge トラップ可能なエラー

サンプルコード
Err.Raise メソッドの動作確認① 実行時エラーの発生を確認する。

Sub ErrRaiseメソッドの動作確認1()

On Error Resume Next
    ' エラー番号 91 のエラーを発生させる
    Err.Raise 91
    
    '---------------------------------------
    ' エラー情報確認
    '---------------------------------------
    MsgBox "エラー番号:" & Err.Number & vbLf & _
           "エラー説明:" & Err.Description & vbLf & _
           "エラーソース:" & Err.Source
End Sub

コード実行結果


サンプルコード
Err.Raise メソッドの動作確認② 呼出先のプロシージャでの実行時エラーの発生を確認する。

Sub ErrRaiseメソッドの動作確認2()

On Error GoTo LBL_ERROR
    ' 処理Aを呼び出す
    Call 処理A

    Exit Sub
    
LBL_ERROR:
    '---------------------------------------
    ' エラー情報確認
    '---------------------------------------
    MsgBox "エラー番号:" & Err.Number & vbLf & _
           "エラー説明:" & Err.Description & vbLf & _
           "エラーソース:" & Err.Source
End Sub

Private Sub 処理A() ' エラー番号 513 (ユーザー定義)のエラーを発生させる Err.Raise 513, "処理A", "Raiseメソッド動作確認2" End Sub

コード実行結果


サンプルコード
Err.Raise メソッドの動作確認③ 呼出先のプロシージャの更に呼出先のプロシージャでの実行時エラーの発生を確認する。

Sub ErrRaiseメソッドの動作確認3()

On Error GoTo LBL_ERROR
    ' 処理Bを呼び出す
    Call 処理B

    Exit Sub
    
LBL_ERROR:
    '---------------------------------------
    ' エラー情報確認
    '---------------------------------------
    MsgBox "エラー番号:" & Err.Number & vbLf & _
           "エラー説明:" & Err.Description & vbLf & _
           "エラーソース:" & Err.Source
End Sub

Private Sub 処理B() ' 処理Cを呼び出す Call 処理C ' エラー番号 513 (ユーザー定義)のエラーを発生させる Err.Raise 513, "処理B", "Raiseメソッド動作確認3" End Sub
Private Sub 処理C() ' エラー番号 514 (ユーザー定義)のエラーを発生させる Err.Raise 514, "処理C", "Raiseメソッド動作確認3" End Sub

コード実行結果




サンプルコード
ErrRaiseメソッドを用いたエラー制御例

Sub ErrRaiseメソッドを用いたエラー制御例()

On Error GoTo LBL_ERROR
    ' 処理Dを呼び出す
    Call 処理D
    
    ' エラー番号 515 (ユーザー定義)のエラーを発生させる
    Err.Raise 515, "呼出元", "ErrRaiseメソッドを用いたエラー制御例"
    
    Exit Sub

LBL_ERROR:
    '---------------------------------------
    ' エラー情報確認
    '---------------------------------------
    MsgBox "エラー番号:" & Err.Number & vbLf & _
           "エラー説明:" & Err.Description & vbLf & _
           "エラーソース:" & Err.Source
End Sub

Private Sub 処理D() On Error GoTo LBL_ERROR ' 処理Eを呼び出す Call 処理E ' 2分の1の確率で実行時エラーを発生させる If WorksheetFunction.RandBetween(0, 1) = 1 Then Dim i As Long i = "サンプル" End If Exit Sub LBL_ERROR: If Err.Source = "VBAProject" Then Err.Source = "処理D" ' エラーオブジェクトの情報に基づきエラーを発生させる Err.Raise Err.Number, Err.Source, Err.Description End Sub
Private Sub 処理E() On Error GoTo LBL_ERROR ' 2分の1の確率で実行時エラーを発生させる If WorksheetFunction.RandBetween(0, 1) = 1 Then Dim dblResult As Double dblResult = 100 / 0 End If Exit Sub LBL_ERROR: If Err.Source = "VBAProject" Then Err.Source = "処理E" ' エラーオブジェクトの情報に基づきエラーを発生させる Err.Raise Err.Number, Err.Source, Err.Description End Sub

コード実行結果


上記のエラー制御では、
処理を開始する呼出元プロシージャ「ErrRaiseメソッドを用いたエラー制御例」に、エラー時に情報を確認するコードを準備している。
そして呼出先プロシージャ「処理D」や「処理E」では、エラー発生時にErrオブジェクトのプロパティにプロシージャ名を設定し Err.Raise メソッドを実行している。
この仕組みで Err.Raise メソッドを実行すると、結果として呼出元のエラー情報確認コードに制御が移る。

このような仕組みを構築することにより、エラー発生箇所やエラー内容を特定をしやすくなる。

ページトップへ戻る
Copyright(C) 2009- 坂江 保 All Rights Reserved.