« 虫食い | トップページ | エラーを無視してエラーを使う »

2011年8月 6日 (土)

2度目のエラーは捕えない

エラートラップを作っても
エラーを捕えられない。
このようなことを経験したことはありませんか?

もっと詳細に言うと、
1回目のエラーは捕えることができて
再度、実行しているプロシージャに戻ってから起こる
2回目のエラーはエラートラップに行かずに
デバッグモードになってしまう。

下のコードの次の箇所

Err.Raise 1004

で疑似エラーを起こしています。
1回目の疑似エラーで「ErrHandle」行ラベルのところへ飛びます。
そこでエラーをクリアして
エラーのカウントを1増やしてから

GoTo Retry

で「Retry」行ラベルのところへ飛び、
最初から実行します。

それで2回目の疑似エラーで
「ErrHandle」行ラベルのところへ飛ばず、
次のようなダイアログが表示されます。
Vba20110806a

コードはこちら

2度目のエラーを起こすコード:

Sub macro110806a()
'2度目のエラーは捕えない

    Dim ErrCount As Integer
    ErrCount = 0 'エラーのカウント
   
Retry:
    On Error GoTo ErrHandle
        Err.Raise 1004
    On Error GoTo 0
   
Exit Sub
ErrHandle:
    Err = 0 'エラーをクリア
    ErrCount = ErrCount + 1
    On Error GoTo 0
    GoTo Retry
   
End Sub

エラーは故意に引き起こしていますから
エラーになるのは当然ですが
なぜエラートラップが反応しないのでしょうか?

おそらく「そういうもの」なのだと
捉えています。

ではどうすればそのプロシージャを実行し続けられるか?
繰り返し持続して実行したいプロシージャがあるとして、
1つの例を示します。

まずは、エラーを捕まえたら
そこでそのプロシージャを一旦終了することです。

上のプロシージャのように
GoToステートメントで戻ると2回目のエラーが起きたときに
デバッグモードになってしまい中断されてしまうからです。

しかし、このままではプロシージャが終了してしまいます。
そこでOnTimeメソッドで再度同じプロシージャを実行します。
そうすればエラーが起きても、
それは1回目のエラーですから
エラーは捕えられます。

このような仕組みにしておくと
エラーが起きた時点で処理が途中になってしまいます。

そこでエラーを捕えらときに、
途中の処理をすべて消すなどして
最初からプロシージャを実行しても問題がないような状態にします。

簡単な例を示します。
次のコードは、
1から100までの数字を
A列に入れていくことを目的としています。
ただし途中でエラーがある確率で起こるようにしてあります。

エラーが起きた時は
「ErrHandle」行ラベルに行き終了しますが、
OnTimeメソッドで3秒後に再び実行されます。

途中で終了してから
再度最初から実行しても
冒頭のIf文でiの値を調整しますので
iは順番通りの数になります。

コードはこちら

2度目のエラーに中断されないコード:

Sub macro110806b()
'2度目のエラーに中断されない

    Dim i As Integer
   
    If Cells(1, 1) = 100 Then
        Exit Sub
    Else
        i = Cells(1, 1) + 1
    End If
   
    On Error GoTo ErrHandle
        For i = i To 100
            Rows(101).Delete
            Rows(1).Insert
            Cells(1, 1) = i
            If Rnd < 0.2 Then
                'エラーをある率で起こす
                Err.Raise 1004
            End If
        Next i
    On Error GoTo 0
   
Exit Sub
ErrHandle:
    Cells(1, 2) = "エラー発生"
    Application.OnTime Now() + TimeValue("00:00:03"), _
        "macro110806b"
       
End Sub

実行後のシートの一部:
Vba20110806b

基本はこのような仕組みにすれば
持続的に実行し続けられると思います。

|

« 虫食い | トップページ | エラーを無視してエラーを使う »

コメント

この記事へのコメントは終了しました。

トラックバック


この記事へのトラックバック一覧です: 2度目のエラーは捕えない:

« 虫食い | トップページ | エラーを無視してエラーを使う »