Err.Clear と On Error GoTo -1 は異なる
Err.Clear
を使うと、それ以降の処理でエラーが発生した場合に、
エラーダイアログが表示されてしまう(Resume Nextが効かない)
NGコード:エラーハンドラ内でエラーが発生したら無限ループに陥る
NGコード
Sub Sample()
On Error GoTo errHandler
Debug.Print "Sub Sample()"
Err.Raise (1) 'エラーが発生
Debug.Print "Exit Sub"
Exit Sub
errHandler:
On Error GoTo -1 'Errオブジェクトをクリア
Debug.Print "errHandler:"
Err.Raise (2) 'エラーハンドラ内で別のエラーが発生
Debug.Print "End Sub"
End Sub
- 処理の流れ
-
Err.Raise (1)
:エラーが発生 -
On Error GoTo errHandler
により、errHandler:にジャンプ -
On Error GoTo -1
:Errオブジェクトをクリア -
Err.Raise (2)
:エラーハンドラ内で別のエラーが発生 -
On Error GoTo errHandler
により、:errHandler:にジャンプ
-
出力
Sub Sample()
errHandler:
errHandler:
errHandler:
...
エラーハンドラ内で発生したエラーは無視する
コード
Sub Sample()
On Error GoTo errHandler
Debug.Print "Sub Sample()"
Err.Raise (1) 'エラーが発生
Debug.Print "Exit Sub"
Exit Sub
errHandler:
On Error Resume Next '追加:エラーが発生したら、次の行から処理を継続
On Error GoTo -1 'Errオブジェクトをクリア
Debug.Print "errHandler:"
Err.Raise (2) 'エラーハンドラ内で別のエラーが発生
Debug.Print "End Sub"
End Sub
- 処理の流れ
-
Err.Raise (1)
:エラーが発生 -
On Error GoTo errHandler
により、errHandler:にジャンプ -
On Error GoTo -1
:Errオブジェクトをクリア -
Err.Raise (2)
:エラーハンドラ内で別のエラーが発生 -
On Error Resume Next
により、次の行から処理を継続
-
出力
Sub Sample()
errHandler:
End Sub
メモ:
On Error Resume Next
とOn Error GoTo -1
の記述順
この2つは、記述順を前後させても同じ結果になった
Err.ClearでもErrオブジェクトをクリアできる
Sub Sample()
On Error GoTo errHandler
Debug.Print "Sub Sample()"
Err.Raise (1) 'エラーが発生
Debug.Print "Exit Sub"
Exit Sub
errHandler:
On Error Resume Next 'エラーが発生したら、次の行から処理を継続
Err.Clear '変更:Errオブジェクトをクリア
Debug.Print "errHandler:"
Err.Raise (2) 'エラーハンドラ内で別のエラーが発生
Debug.Print "End Sub"
End Sub
- 処理の流れ
出力
Sub Sample()
errHandler:
Err.Clear と On Error GoTo -1 の違い
Err.Clear
を使うと、それ以降の処理でエラーが発生した場合に、
エラーダイアログが表示される(Resume Nextが効かない)
Err.Clearは自動的に実行される
マイクロソフトのドキュメントには、次のことが書かれている
Err.Clearは、次のいずれかが実行される場合は必ず、自動的に呼び出される
- すべてのResumeステートメント
- Exit Sub/Exit Function/Exit Property
- On Error ステートメント
もしそうなら、On Error Resume Next
で自動的にErr.Clear
されるので、
明示的にErr.Clear
する必要はないのでは
先程のコードにDebug.Print Err.Number
を2つ追加して検証してみる
Sub Sample()
On Error GoTo errHandler
Debug.Print "Sub Sample()"
Err.Raise (1) 'エラーが発生
Debug.Print "Exit Sub"
Exit Sub
errHandler:
Debug.Print Err.Number '追加:エラー番号を出力
On Error Resume Next 'エラーが発生したら、次の行から処理を継続
'Err.Clear '削除:Errオブジェクトをクリア
Debug.Print Err.Number '追加:エラー番号を出力
Debug.Print "errHandler:"
Err.Raise (2) 'エラーハンドラ内で別のエラーが発生
Debug.Print "End Sub"
End Sub
出力
Sub Sample()
1
0
errHandler:
エラー番号が0なら、エラーの発生がない状態なので、
確かにクリアされている
補足:Exit Subではクリアされない?!
Exit Subが実行される場合に、Errオブジェクトがクリアされるか確認したが、
されなかった。
いろいろ試した結果、On Error Goto xxx
のように、
何らかのエラーハンドラが設定されていないと、クリアされないみたい。
参考
参考にさせて頂いたサイト
この記事を書くにあたり、「VBAの部品庫」さんの記事を参考にさせて頂きました。
その中で、「VBAの部品庫」さんの記事に掲載されているコードを次のように変更した方が
良いのではないかと思いました
※連絡先が見当たらないため、こちらに記載
元のコード(「VBAの部品庫」さんの記事から引用)
エラー発生:
On Error GoTo 0
On Error Resume Next
'Err.Raise (1)
On Error GoTo -1
Err.Raise (1)
Debug.Print "エラー終了"
変更したコード
エラー発生:
On Error Resume Next '暗黙的にErr.Clearされる
'Err.Raise (1) 'ここでエラーが発生した場合、前回のエラーは上書きされて消える
On Error GoTo -1 'On Error Resume Nextを有効にするため、再度、Errオブジェクトをクリア
Err.Raise (1)
Debug.Print "エラー終了"
追記
変更したコード2
エラーハンドラ内からプロシージャを呼び出す場合、
On Error GoTo 0
が必要で、
プロシージャ内でエラーが発生する & プロシージャ内にエラーハンドラがない場合、
エラー発生:
ラベルにジャンプするため、無限ループに陥る
※プロシージャを呼ぶ → プロシージャ内でエラー発生→エラー発生
ラベルにジャンプ→プロシージャを呼ぶ→...
エラー発生:
On Error GoTo 0
On Error Resume Next '暗黙的にErr.Clearされる
'Err.Raise (1) 'ここでエラーが発生した場合、前回のエラーは上書きされて消える
On Error GoTo -1 'On Error Resume Nextを有効にするため、再度、Errオブジェクトをクリア
Err.Raise (1)
Debug.Print "エラー終了"