サイトについて      連絡先   検索

VBA エラー処理 On Errer

はじめに

Excel VBA マクロのエラー処理 (On Error) をする方法を紹介します。

対処法は発生したエラーをキャッチして、原因となるものをデバッグして見つけます。

エラーを無視したり、エラー処理を無効にできます。Finally を使用して後処理ができます。

  • 目次
    • 対処する
    • キャッチする
    • 無視する
    • エラー処理を上書きする
    • エラー処理を無効にする
    • Finally

対処する

エラーが発生したときにできることは、次の 2 つです。

通常はエラーをキャッチします。キャッチとはエラーが発生したら、そのエラー情報を取得して適切な処理をすることです。エラーの原因をデバッグをするためにも、エラーをキャッチする必要があります。

無視するとは、エラーが発生していないかのように処理を継続させることです。ただし不正な値のままプログラムを動かすと、さらなるエラーが発生する危険性があります。

何もしないときは、エラーメッセージが表示されプログラムが終了します。

キャッチする

GoTo 文」を使用して、エラーが発生したときに指定したラベルに処理を移動できます。

On Error GoTo ラベル名のように入力します。エラーが発生したときに指定したラベルの位置に処理を移動します。On Error を付けることで、エラー発生時に GoTo 文を実行できます。

ラベル名:のように入力します。エラーが発生したときのラベルを付けます。


Sub 実行()
On Error GoTo Catch ' エラーが発生したら Catch へ移動する
    
    ' 処理

    Exit Sub
Catch: ' エラーが発生したらここから処理が始まる

    ' エラー処理

End Sub

Catch:の前に Exit Sub または Exit Function を入力します。これはエラーが発生していないときにエラー処理を行わないように、そこで関数を抜けます。

キャッチしたエラー処理の中で発生したエラーはキャッチできません。エラーメッセージが表示されます。対処法は下記の「Finally」をご覧ください。

有効範囲

On Errorの行から、その関数を抜けるまでに発生するエラーをキャッチします。その前に発生したエラーはキャッチできないので、必ず関数の直下に入力します。


Sub 実行()

    ' キャッチできない

On Error GoTo Catch 

    ' キャッチできる
       
End Sub

有効範囲内で別の関数を呼び出すと、その関数で発生したエラーもキャッチできます。

無視する

On Error Resume Nextのように入力します。エラーが発生したときは、次の行に処理を移動します。


Sub 実行()
On Error Resume Next ' エラーが発生したら次の行へ移動する
    
    ' 処理

End Sub

変数に代入するときにエラーが発生したときは、変数の値は変更されません。


Sub 実行()
On Error Resume Next
    
    Dim i As Integer
    i = 1
    i = "a" ' エラー、無視される
    
    Debug.Print (i) ' 1
End Sub

有効範囲

「キャッチする」と同じでOn Errorの行から関数を抜けるまでです。

絶対にエラーでプログラムを中断したくないときは、最初に呼び出される関数に入力します。これですべてのエラーを無視できます。ただし、その後に正常な処理ができる保証がないのでオススメしません。

エラー処理を上書きする

「キャッチする」または「無視する」の有効範囲内で別のエラー処理を入力すると、上書きできます。


Sub 実行()
On Error Resume Next

    ' 無視する

On Error GoTo Catch ' Resume Next を上書きする
    
    ' キャッチする

    Exit Sub
Catch: 

    ' エラー処理

End Sub

有効範囲内で別の関数を呼び出したときに、その関数にエラー処理が入力されているときは、その範囲内でのみ上書きされます。


Sub 実行()
On Error Resume Next 

    ' 無視する

    Call Tips ' Tips 関数の中だけ上書きされる
    
    ' 無視する
    
End Sub

Sub Tips()
On Error GoTo Catch ' 何から呼び出されても、この関数の Catch へ移動する

    ' キャッチする

    Exit Sub
Catch:
    
End Sub

キャッチしたエラー処理の中では上書きできません。


Sub 実行()
On Error GoTo Catch 

    Dim i As Integer
    i = "a" ' エラー、Catch へ移動する 
    
    Exit Sub
Catch: 
On Error Resume Next ' エラー処理の中の On Error では上書きできない、意味のないコード

    i = "a" ' エラー、無視されない

End Sub

エラー処理を無効にする

On Error GoTo 0のように入力します。入力している関数に対するエラー処理を無効にできます。


Sub 実行()
On Error Resume Next

    ' 無視する

On Error GoTo 0 ' 以降はエラー処理しない

    Dim i As Integer
    i = "a"  ' エラー
    
End Sub

入力している関数内だけ無効にします。それを呼び出した関数のエラー処理は無効になりません。


Sub 実行()
On Error Resume Next 

    ' 無視する
   
    Call Tips ' Tips 関数の中だけ無効になる
    
    ' 無視する
    
End Sub

Sub Tips()
On Error GoTo 0 ' この関数のエラー処理を無効にする

End Sub

「キャッチする」や「無視する」と同じように、有効範囲内だけ無効になります。

Finally

正常なときとエラーが発生したときの両方で、同じように後始末をしたいことがよくあります。それが Finally です。

VBA のエラー処理に Finally の機能はありませんが、上記のエラー処理を組み合わせて同じようなことができます。

Resume ラベル名のように入力して、キャッチしたエラー処理の中から指定したラベルに処理を移動できます。Resume 後は On Error でエラー処理を上書きできます。


Sub 実行()
On Error GoTo Catch 

    ' 正常な処理
    Debug.Print ("正常")

Finally:
On Error Resume Next
    
    ' Finally の処理
    Debug.Print ("Finally")
    
    Exit Sub  
Catch:
    
    ' エラー処理
    Debug.Print ("エラー")
    
    Resume Finally
End Sub

Finally:の中でエラーを発生させないようにします。保険の意味でOn Error Resume Nextを入力しています。

Catch: の中でエラーを発生させてはいけません。そのエラーはキャッチできずエラーメッセージが表示され、プログラムが終了します。

Catch:で発生する可能性のあるエラーを無視するには、次のように Catch2: を追加します。


Sub 実行()
On Error GoTo Catch 

    ' 正常な処理
    Debug.Print ("正常")

Finally:
On Error Resume Next
    
    ' Finally の処理
    Debug.Print ("Finally")
    
    Exit Sub 
Catch:
    
    ' 必要ならエラー情報を取得する
    Debug.Print (Err.Description)
    
    Resume Catch2 ' エラー処理は Catch2 で行う
Catch2:
On Error Resume Next
    
    ' エラー処理
    Debug.Print ("エラー")

    GoTo Finally
End Sub

Catch:ではエラー処理を行いません。発生したエラー情報の取得だけを行い、エラーが発生しないようにします。エラー処理は Catch2: で行います。

Catch2:でエラー処理を行います。Catch: からResumeで呼ばれるので、エラーを無視できます。

見ての通りエラー処理をするほどコードが見づらくなります。エラー処理を入力することで、逆にエラーが発生しないように注意します。
  • 目次
    • 対処する
    • キャッチする
    • 無視する
    • エラー処理を上書きする
    • エラー処理を無効にする
    • Finally