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 "エラー終了"
