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 で呼ばれるので、エラーを無視できます。

見ての通りエラー処理をするほどコードが見づらくなります。エラー処理を入力することで、逆にエラーが発生しないように注意します。