VBAのエラー処理

エラー

はじめに

 ExcelVBAでは、エラーに対してどのように対処するかをプログラミングで制御できます。

 ExcelVBAでのエラー処理は、On Errorステートメントで行います。主な機能は以下のようになります。

On Errorステートメント 機 能
On Error Resume Next エラーを無視して次の処理へ進む
On Error GoTo ラベル エラーが発生したらラベル位置へジャンプ
On Error GoTo 0 設定したエラー処理を無効化する

 例を見ていきましょう。ここでは以下のようなシートの表で、D列に B列をC列で割った値を代入する事を想定しています。

エラーを無視して次へ

 プロシージャの途中で、On Error Resume Next とすると、その後エラーが発生しても無視して次に進むようになります。

 On Error Resume Next の効果は、On Error GoTo 0で設定を解除するか、そのプロシージャの最後まで続きます。On Error GoTo 0 については後述します。)

'On Error Resume Next
Sub macro1()
    Dim i As Long

    On Error Resume Next    'エラーを無視して次へ

    For i = 2 To 7
        Cells(i, "D") = Cells(i, "B") / Cells(i, "C")
    Next i
    
End Sub

 結果は以下のように割り算が出来る時のみD列に値が入り、割り算ができないセルは無視されます。
エラー表示はされません。
 尚、On Error Resume Next の効果はプロシージャが終了した時点でなくなります。

エラーが発生したらラベルへ飛ぶ

'On Error GoTo ラベル, Resume Next
Sub macro2()
    Dim i As Long, cnt As Long

    On Error GoTo ERR_LABEL 'ラベルへジャンプ
    
    cnt = 0
    For i = 2 To 7
        Cells(i, "D") = Cells(i, "B") / Cells(i, "C")
    Next i
    
    If cnt > 0 Then MsgBox cnt & "個のエラーがあります。"
    
    Exit Sub
    
ERR_LABEL:
    cnt = cnt + 1
    Resume Next
End Sub

 On Error GoTo ラベル を使用すると、エラーが発生した際にラベルにジャンプします。ラベルにジャンプした後で、Resume Next でエラー箇所の次に戻ります。

 上記のプログラムでは、エラーが発生した時、ERR_LABEL:に進んだ後、カウンタ変数をインクリメントしてFor文内部に戻ります。結果、エラーの回数をカウントして最後にメッセージボックスで表示します。

 ラベルの前に Exit Sub を忘れないようにしましょう。

Errオブジェクト

 VBAではエラーが発生すると、Errオブジェクトにその内容が入るので、プロパティで確認できます。
プロパティはエラー番号を示す Numberプロパティ内容を説明する Description プロパティがよく使われます。

'Errオブジェクト
Sub macro3()
    Dim i As Long

    On Error GoTo ERR_LABEL 'ラベルへジャンプ

    For i = 2 To 7
        Cells(i, "D") = Cells(i, "B") / Cells(i, "C")
    Next i
    
    Exit Sub
    
ERR_LABEL:
    MsgBox i & "行目" & vbCrLf & _
            " エラー番号: " & Err.Number & vbCrLf & _
            " " & Err.Description
    Resume Next
End Sub

 実行すると上記のように3回メッセージボックスが表示され、エラーが起こった行、エラー番号、エラーの説明が表示されます。

エラー番号で分岐

'エラー番号で分岐
Sub macro4()
    Dim i As Long

    On Error GoTo ERR_LABEL 'ラベルへジャンプ

    For i = 2 To 7
        Cells(i, "D") = Cells(i, "B") / Cells(i, "C")
    Next i
    
    Exit Sub
    
ERR_LABEL:
    Select Case Err.Number
        Case 13
            MsgBox i & "行目でエラーです。" & vbCrLf & _
            "C列,D列の値を確認してください。"
            
        Case 6
            MsgBox i & "行目でエラーです。" & vbCrLf & _
            "D列の値を確認してください。"
    
        Case Else
            MsgBox i & "行目" & vbCrLf & _
            " エラー番号: " & Err.Number & vbCrLf & _
            " " & Err.Description
    End Select
End Sub

 このプログラムでは、エラー番号で処理を分岐するため、エラー内容によるメッセージを表示できるようになります。

On Error 処理を中断する

 On Error 処理は、プロシージャの最後に無効となりますが、手動で処理を中断させるには
On Error GoTo 0
 とします。こうするとプロシージャの最後でなくても途中で効力を無効化させることができます。

'On Error GoTo 0
Sub macro5()
    Dim i As Long
    For i = 2 To 7
        On Error GoTo ERR_LABEL 'ラベルへジャンプ
        
        If Cells(i, "B") = "" And Cells(i, "C") = "" Then
            'エラー制御を戻す
            On Error GoTo 0
        End If
        
        Cells(i, "D") = Cells(i, "B") / Cells(i, "C")
    Next i
    
    Exit Sub
    
ERR_LABEL:
    MsgBox i & "行目" & vbCrLf & _
            " エラー番号: " & Err.Number & vbCrLf & _
            " " & Err.Description
    Resume Next
End Sub

 今回のプログラムでは、B列とC列が空白の時に、エラー制御を外してエラーが発生するようにしています。
ケースによっては、エラーをカバーするだけでなくキチンとエラーを発生させるのも1つの考え方でしょう。

 On Error GoTo 0 を使うケースは少ないかもしれません。

まとめ

 プログラマーであれば、エラーがでないようにコードを書くのは当然ですが、時にはエラーをきっかけに処理を分岐させるような手法もあります。このようなケースでは、Errオブジェクトが必須の機能となります。

コメント

タイトルとURLをコピーしました