【例外処理】エラートラップの方法

今回の目標

  • プログラムを予期せぬエラーで止まらないようにする

説明

エラートラップとは

プログラムにエラーが発生すると、メッセージボックスが表示されて処理が止まってしまいますが、 「エラートラップ」を使うと、プログラム実行中にエラーが発生しても処理を制御できます。 この処理のことを「例外処理」と言います。
※ VBAでは “エラートラップ” と呼びますが、多言語では『エラーキャッチ』と呼ぶようです。

例外処理とは

例外処理とは、プログラム実行中にエラー(例外)が発生したときに、あらかじめ用意した別の処理を実行する仕組みです。 通常、エラーが発生するとプログラムはそこで停止してしまいますが、 例外処理を組み込んでおけば、エラー発生時に専用の処理(コード)を実行して、 プログラムを安全に続行させたり、ユーザーにわかりやすいメッセージを表示させることができます。

● Sub プロシージャの場合

On Error Goto ラベル名
    通常の処理を記載
    Exit Sub
ラベル名:
    エラー発生時の処理を記載

● Function プロシージャの場合

On Error Goto ラベル名
    通常の処理を記載
    Exit Function
ラベル名:
    エラー発生時の処理を記載

「ラベル名」とありますが、変数のように自由に名前を付けられます。
ラベル名の後ろに ”:” (半角コロン)を付ける必要があります。 本ページのラベル名は ”ErrHandler” で統一します。 慣例的には「ErrorHandler」 や 「ErrHandler」なども使われます。

ラベル名の前に、「Exit Sub」や「Exit Function」でプロシージャから抜けましょう。 なぜなら、エラー専用の処理を通常の場合も実行してしまうためです。

エラー発生時に専用の処理を実行する

次のプログラムをF8ボタンでステップインしてみましょう。
ステップインとはプログラムを1行ずつ実行することです。
ステップインした状態で、更にF8ボタンを押すとその分だけプログラムが実行されます。
なお、ステップインは[デバッグ]→[ステップイン]からでも可能です。

Sub Sample1()
On Error Goto ErrHandler
    ' 処理を入力する
    Dim num As Integer
    num = 1000 * 800        'Integer型の最大値32,767を超えるため、エラー
    MsgBox "数値は" & num & "です。"
ErrHandler:
    If (Err.Number <> 0) Then
        ' ここにエラー発生時の専用のプログラムを入力する
        MsgBox Err.Description, vbOKOnly, "Error"
    End If
End Sub

エラーが発生すると同時に、ErrHandler(ラベル)までステップが移動します。
移動すると同時に、命令文にはありませんが、Errオブジェクトにエラー情報が格納されます(下表参照)。
そのエラー情報をもとにエラー処理を行います。

メンバ説明
Description発生したエラーに対する説明文がString型で格納されます。
エラーが発生していないときは、空の文字列(vbNullString)が格納されています。
Number発生したエラーの番号がLong型で格納されます。
エラーが発生していないときは、数値0が格納されています。
HelpFileエラー発生時、MsgBox関数の第四引数に指定する値が格納されます。
HelpContextエラー発生時、MsgBox関数の第五引数に指定する値が格納されます。

下記はMicrosoft社のリファレンスを一部引用してかみ砕いたサンプルです。
MsgBox関数の第二引数・第四引数・第五引数を使って、
エラー番号を表示し、ユーザーがヘルプを見られるようにしています。
ですが、マクロを作成できないユーザーがヘルプを見ても混乱するだけなので、表示しないべきでしょう。

' 下記はMicrosoft社のリファレンスを一部引用。
Sub SampleEx()
On Error Goto ErrHandler
    Dim num As Integer
    num = 1000 * 800
    MsgBox "数値は" & num & "です。"
ErrHandler:
    If (Err.Number <> 0) Then
        ' エラー表示の文中に番号を表示させている。
        Dim ErrMsg As String
        ErrMsg = "ErrorNumber:" & Str(Err.Number) & vbNewLine & Err.Description
        ' メッセージボックスにヘルプボタンを追加。
        MsgBox ErrMsg, vbMsgBoxHelpButton, "Error", Err.HelpFile, Err.HelpContext
    End If
End Sub

強制的にエラーを発生させる

使い道はほぼありませんが、強制的にエラーを発生させることもできます。

' On Error Goto とセットで使用しないと純粋なエラーになる
Err.Raise エラー番号

上記「エラー番号」にはエラー発生時に『Err.Number』に格納される数値を入れます。
例えば、オーバーフローの発生なら、エラー番号は「6」です。

Sub Sample4()
On Error GoTo ErrHandler
    Dim num As Integer
    Err.Raise 6
    MsgBox "エラーラベルまでスキップされるため、表示されません。"
ErrHandler:
    If (Err.Number <> 0) Then
        MsgBox Err.Description, , "Error"
    End If
End Sub

エラーを無視して処理を続ける

エラー発生時に、そのエラーを無視して次のステップに移動させることができます。 プロシージャ開始後に次の命令を入力します。

On Error Resume Next

次のサンプルは数値型の変数に文字列を入力してしまったサンプルです。

Sub Sample5()
On Error Resume Next
    Dim num As Integer
    num = "1000 * 800"
    MsgBox "数値は" & num & "です。"
End Sub

上記サンプルを実行してみるとわかりますが、エラーが発生した命令は次のステップに飛ばされます。
少しトリッキーな使用法ですが、次のようにGotoでラベルまでスキップした後に、
エラーが発生した次の行まで戻すことができます。

On Error Goto ErrHandler
    通常の処理①     ・・・A
    エラーが発生する処理 ・・・B
    通常の処理②     ・・・C
    Exit Sub        ・・・D
ErrHandler:
    エラー発生時の処理  ・・・E
    Resume Next      ・・・F

上記を順を追って説明します。

  1. 「A」の処理が行われます。
  2. 「B」を実行しますがエラーが発生するため、エラーラベルのある「E」へスキップします。
  3. 「E」を実行します。
  4. 「F」を実行します(=Cに戻ります)。
  5. 「C」を実行します。
  6. 「D」を実行して終了します。("Exit Sub"は、Subプロシージャの終了させる命令)。

この構文は、VBAからエクセル関数であるVlookup関数を使用する場合に用いると良いでしょう。
例えば、下図の表があるとします。


これをA列を参照して取得する場合、VBAだけで検索して値を調べると処理に手間取ります。
VLookup関数を使用すれば1行で済みますが、検索値が表に存在しないとエラーが発生し、止まってしまいます。
この弱点を補うのが、Resume Next です。

Sub Sample6()
On Error GoTo ErrHandler
    Dim dat As String
    dat = WorksheetFunction.VLookup(1, Range("A2:B9"), 2, False)
    MsgBox dat
    Exit Sub
ErrHandler:
    dat = "データが見つかりませんでした。"
    Resume Next
End Sub

通常、検索値に「9」指定すると、エラーになりプログラムが止まってしまいますが、
この方法なら問題ありません。
ただし、Resume Next を常用するとバグを見逃す原因になるため注意が必要です。

デバッグを行う時の注意点

On Error構文をコメントアウトしましょう。
エラーが発生するとエラーラベルまでスキップしてしまい、
どの行(ステップ)でエラーが発生したか、分からなくなるためです。

下記の構文でErrオブジェクトやエラー発生時のラベルへのスキップを解除(初期化)できます。

On Error Goto 0

Gotoの後ろは、数字のゼロです。
必要に応じて初期化してください。

メッセージボックスにエラーのヘルプを用意する

メッセージボックスにエラーに対するヘルプボタンを設置します。
このボタンを押すと、発生したエラーに関する情報が表示されます。 HelpFile はヘルプファイル(通常はMicrosoft公式サイト)へのリンク、HelpContext はその中のトピック番号を表します。

ただし、実務でこのヘルプを利用することは少ないです。 ユーザーが難しいヘルプファイルを見ても解決できないからです。
通常は、この方法よりも、独自のエラーメッセージを表示させた方が親切です。

Sub Sample7()
    On Error GoTo ErrHandler
    ' Worksheets(-1) でエラーが発生する
    ThisWorkbook.Worksheets(-1).Range("A1") = "Test"
ErrHandler:
    If (Err.Number <> 0) Then
        MsgBox Err.Description, vbMsgBoxHelpButton, "Error", _
                    Err.HelpFile, Err.HelpContext
    End If
End Sub
【出力結果】
プログラム実行前の画像
※ 「ヘルプ」のボタンが設置されました。
  クリックすると、Microsoft の HP に移動します。

関連リンク

ページの先頭へ