概要
Excel VBAでOn Error Resume Nextのスコープを気にしなかったらミスしたのでメモです。
簡単に言うと、On Error Resume Nextを実行する関数があって、そいつが呼び出した関数でエラーがあった場合、呼び出した関数が途中までしか実行されないという話です。
通常のケース
On Error Resume Nextを実行すれば、エラーがあっても止まらずに続行します。
Sub Main()
On Error Resume Next
Debug.Print "Main Begin"
Err.Raise 1, "エラー" 'エラーがあっても止まらず続行する
Debug.Print "Main End" '続行するので、ここも実行する
End Sub
実行結果
Main Begin
Main End
呼び出した関数が最後まで実行されないケース!!
On Error Resume Nextを実行した関数があって、そいつが呼び出した関数でエラーがあると、エラーで抜け出してしまい途中までしか実行されません。
下記の例だと"Child End"も出力して欲しいですが、出力されません。
実行されてないことに気づけないので非常に厄介です。
Sub Main()
On Error Resume Next
Debug.Print "Main Begin"
Call Child
Err.Raise 1, "エラー"
Debug.Print "Main End"
End Sub
Sub Child()
Debug.Print " Child Begin"
Err.Raise 1, "エラー" 'ここで関数を抜け出す
Debug.Print " Child End" 'ここは実行されない!
End Sub
実行結果
Main Begin
Child Begin
Main End
呼び出した関数を最後まで実行するためには
呼び出し先の関数でもOn Error Resume Nextを実行すれば、エラーがあっても継続されます。
Sub Main()
On Error Resume Next
Debug.Print "Main Begin"
Call Child
Err.Raise 1, "エラー"
Debug.Print "Main End"
End Sub
Sub Child()
On Error Resume Next 'これを追加すれば"Child End"が出力される
Debug.Print " Child Begin"
Err.Raise 1, "エラー" 'エラーがあっても抜け出さない
Debug.Print " Child End" 'ここまで実行される
End Sub
実行結果
Main Begin
Child Begin
Child End
Main End
呼び出し先だけでOn Error Resume Nextした場合
ちなみに、呼び出し先だけでOn Error Resume Nextした場合は、呼び出し元でエラーがあればそこで停止します。
Sub Main()
Debug.Print "Main Begin"
Call Child
Err.Raise 1, "エラー" 'ここでポップアップが出て停止する
Debug.Print "Main End"
End Sub
Sub Child()
On Error Resume Next
Debug.Print " Child Begin"
Err.Raise 1, "エラー" 'エラーがあっても抜け出さない
Debug.Print " Child End" 'ここまで実行される
End Sub
実行結果
Main Begin
Child Begin
Child End
※ ここで「アプリケーション定義またはオブジェクト定義のエラーです」のポップアップが表示されて停止する。