0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

Err.Clear と On Error GoTo -1 は同じ?!

Last updated at Posted at 2022-08-07

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
  • 処理の流れ
    1. Err.Raise (1):エラーが発生
    2. On Error GoTo errHandlerにより、errHandler:にジャンプ
    3. On Error GoTo -1:Errオブジェクトをクリア
    4. Err.Raise (2):エラーハンドラ内で別のエラーが発生
    5. 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
  • 処理の流れ
    1. Err.Raise (1):エラーが発生
    2. On Error GoTo errHandlerにより、errHandler:にジャンプ
    3. On Error GoTo -1:Errオブジェクトをクリア
    4. Err.Raise (2):エラーハンドラ内で別のエラーが発生
    5. On Error Resume Nextにより、次の行から処理を継続

出力

Sub Sample()
errHandler:
End Sub

メモ:On Error Resume NextOn 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
  • 処理の流れ
    1. Err.Raise (1):エラーが発生
    2. On Error GoTo errHandlerにより、errHandler:にジャンプ
    3. Err.Clear:Errオブジェクトをクリア
    4. Err.Raise (2):エラーハンドラ内で別のエラーが発生
    5. エラーダイアログが表示される
      err2.png

出力

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 ステートメント

参考:Clear メソッド(VBA) - Microsoft Docs

もしそうなら、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 "エラー終了"
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?