VBAにおけるOn Error処理の上書きについて。

下記マクロ実行時、「!!」の箇所でnormalErrorに飛ばしたいのですが、fatalErrorに飛びます。
normalErrorに飛ばしたいときの表現ってありますか?初歩的な質問かもしれませんがよろしくお願いします。
Sub test()
Dim i As Long
On Error GoTo fatalError
On Error GoTo normalError
i = 1 / 0 '!!
normalError:
fatalError:
End Sub

回答の条件
  • 1人2回まで
  • 13歳以上
  • 登録:
  • 終了:2010/11/23 02:11:57
※ 有料アンケート・ポイント付き質問機能は2023年2月28日に終了しました。

ベストアンサー

id:SALINGER No.3

回答回数3454ベストアンサー獲得回数969

ポイント27pt

エラーを切り分ける場合、エラーがどのコードで起こったかで分けるか、エラーの種類で分けるかの2通りになります。

 

1 コードの場所の場合

on error goto 0 でエラー処理を停止させ該当の場所だけを違うエラー処理にする。

Sub test()
    Dim i As Long
    
    On Error GoTo normalError
    '処理
    On Error GoTo 0
    
    On Error GoTo fatalError
    i = 1 / 0 '!!
    On Error GoTo 0
    
    On Error GoTo normalError
    '処理
    Exit Sub
    
normalError:
    'エラー処理
    Exit Sub
fatalError:
    'エラー処理
End Sub

2 エラーの種類で分ける。

on error resume next でエラーが起きても処理を止めずに、err.numbarでエラーの種類を判断します。

Sub test2()
    Dim i As Long
    
    On Error Resume Next
    
    i = 1 / 0  '!!
    
    Select Case Err.Number
        Case 11
            GoTo normalError
        Case 13
            GoTo fatalError
    End Select
    
    On Error GoTo 0
    
    '処理
    Exit Sub
    
normalError:
    'エラー処理
    Exit Sub
fatalError:
    'エラー処理
End Sub

11というのは0の除算のエラーで、13は型の不一致です。

エラーの種類はこちらをみてください。

http://support.microsoft.com/kb/146864/ja

id:ReoReo7

ありがとうございます。

err.number

で分かるのですね。

On Error GoTo 0

の意味も初めて知りました。

コードの書き方として参考にさせて頂きました。ありがとうございます。

2010/11/19 15:21:29

その他の回答2件)

id:spyglass No.1

回答回数455ベストアンサー獲得回数29

ポイント27pt

fatalErrorとの違いは何でしょうか?

normalErrorだけなら単純なエラー処理は出来るのですが。

--------------------------------

Sub OnErrorTest()

   On Error GoTo normalError

   i = 1 / 0 '!!

Exit Sub

normalError:

   MsgBox "エラー番号:" & Err.Number

   MsgBox "エラー内容:" & Err.Description

   Resume Next

End Sub

--------------------------------

id:ReoReo7

ありがとうございます。具体的には以下のイメージです。

sub main()

on error goto fatalerror

shori1()

shori2()

fatalerror:

debug.print "致命的エラーです。"

end sub

sub shori1()

on error goto shori1error

i=2/0

shori1error:

debug.print "計算ミスです。処理を続行します。"

end sub

sub shori2()

debug.print "以下の処理は絶対に成功させなければならないので、ミスったら致命的エラーになります。"

'いろんな処理

end sub

回答3まで頂いた後での追記:上記サンプルコードは例が悪いです。無視して下さい。やりたいことが逆に難しくなってしまいました。混乱させてしまう結果となり、すみません。

また、質問文にあるコードで

「「!!」の箇所でnormalErrorに飛ばしたい」とありますが、

質問文のコードでnormalErrorにちゃんと飛んでいるようです(F8でステップ実行したときに、エラー箇所でF8を押したときにEnd Subにカーソルが行くので、normalErrorではなくてfatalErrorに飛んでいるものと思った。これではエラー再現できていることになりません・・・)。

質問がまずかったのですが、質問の趣旨はまったく違うものです。

以下、少し長いですが質問のコードの構造(1000行以上あるのでここにコピーペーストできませんので、骨組みの概略だけ書きます)を書かせて頂きます。

Sub testParent()

On Error GoTo myError

Call testChild

myError:

Debug.Print "ここに飛ぶはずが無い。"

End Sub

Sub testChild()

Dim i As Long

On Error GoTo error1

Debug.Print "何かの命令処理。"

On Error GoTo 0 'この行は挿入しなくても、飛ぶ箇所は同じなんですね。

On Error GoTo error2

Debug.Print "何かの命令処理。"

On Error GoTo 0 'この行は挿入しなくても、飛ぶ箇所は同じなんですね。

On Error GoTo error3

Debug.Print "何かの命令処理。"

On Error GoTo 0 'この行は挿入しなくても、飛ぶ箇所は同じなんですね。

On Error GoTo error4

Debug.Print "何かの命令処理。"

On Error GoTo 0 'この行は挿入しなくても、飛ぶ箇所は同じなんですね。

On Error GoTo error5

'i = 1 / 0 'もしこの処理を実行すれば、ちゃんとerror5に飛んでくれる。

On Error GoTo 0 'この行は挿入しなくても、飛ぶ箇所は同じなんですね。

On Error GoTo error6

Debug.Print "何かの命令処理。"

On Error GoTo 0 'この行は挿入しなくても、飛ぶ箇所は同じなんですね。

On Error GoTo error7

Debug.Print "何かの命令処理。"

On Error GoTo 0 'この行は挿入しなくても、飛ぶ箇所は同じなんですね。

On Error GoTo error8

Debug.Print "何かの命令処理。"

On Error GoTo 0 'この行は挿入しなくても、飛ぶ箇所は同じなんですね。

On Error GoTo error9

Debug.Print "何かの命令処理。"

On Error GoTo 0 'この行は挿入しなくても、飛ぶ箇所は同じなんですね。

On Error GoTo error10

Debug.Print "何かの命令処理。"

On Error GoTo 0 'この行は挿入しなくても、飛ぶ箇所は同じなんですね。

On Error GoTo error11

Debug.Print "何かの命令処理。"

On Error GoTo 0 'この行は挿入しなくても、飛ぶ箇所は同じなんですね。

On Error GoTo error12

On Error GoTo 0 'この行は挿入しなくても、飛ぶ箇所は同じなんですね。

On Error GoTo error13

On Error GoTo 0 'この行は挿入しなくても、飛ぶ箇所は同じなんですね。

On Error GoTo error14

On Error GoTo 0 'この行は挿入しなくても、飛ぶ箇所は同じなんですね。

On Error GoTo error15

'i = 1 / 0 '【エラー再現できませんでした。】なぜかmyErrorに飛ぶことがある。しかも、コードをまったく変えずにF8で実行すると、ちゃんとerror15に飛ぶ。

On Error GoTo 0 'この行は挿入しなくても、飛ぶ箇所は同じなんですね。

On Error GoTo error16

i = 1 / 0 '【エラー再現できませんでした。】なぜか必ずmyErrorに飛ぶ。コードをまったく変えずにF8で実行しても、myErrorに飛ぶ。

error1:

Debug.Print

Exit Sub

error2:

Debug.Print

Exit Sub

error3:

Debug.Print

Exit Sub

error4:

Debug.Print

Exit Sub

error5:

Debug.Print

Exit Sub

error6:

Debug.Print

Exit Sub

error7:

Debug.Print

Exit Sub

error8:

Debug.Print

Exit Sub

error9:

Debug.Print

Exit Sub

error10:

Debug.Print

Exit Sub

error11:

Debug.Print

Exit Sub

error12:

Debug.Print

Exit Sub

error13:

Debug.Print

Exit Sub

error14:

Debug.Print

Exit Sub

error15:

Debug.Print "通常はここに飛びますが、条件によって飛びません。"

Exit Sub

error16:

Debug.Print "通常はここに飛びますが、飛んでくれません。"

End Sub

2010/11/19 15:14:44
id:taknt No.2

回答回数13539ベストアンサー獲得回数1198

ポイント27pt

http://www.red.oit-net.jp/tatsuya/vb/Err.htm

http://www.asahi-net.or.jp/~ef2o-inue/vba_k/sub04_140_02.html

一番目の回答にあるプログラムを一部修正して実行すると


計算ミスです。処理を続行します。

以下の処理は絶対に成功させなければならないので、ミスったら致命的エラーになります。

致命的エラーです。

という結果になります。

修正箇所は shori1()などを Call shori1と変えただけです。

あと このプログラムでは

shori1()
shori2()
fatalerror:
debug.print "致命的エラーです。"

となってますが

これだと shori1とshori2を呼んだ後に debug.print "致命的エラーです。"を実行してしまいます。

質問にあるのもそうです。

Sub test()
Dim i As Long
On Error GoTo fatalError
On Error GoTo normalError
i = 1 / 0 '!!
normalError:
fatalError:
End Sub

これだと normalError:の後 そのままfatalError:を実行してるのでは ないのでしょうか?

エラー処理で ちゃんと ジャンプさせるような処理は 入れてるのでしょうか?

Resume Nextとか。

id:ReoReo7

ありがとうございます。その通りです。

きちんと Exit Sub 処理を入れなければなりませんね。

初歩的なエラーの指摘をわざわざしていただく結果となり、たいへん申し訳ありませんでした。

2010/11/19 15:20:30
id:SALINGER No.3

回答回数3454ベストアンサー獲得回数969ここでベストアンサー

ポイント27pt

エラーを切り分ける場合、エラーがどのコードで起こったかで分けるか、エラーの種類で分けるかの2通りになります。

 

1 コードの場所の場合

on error goto 0 でエラー処理を停止させ該当の場所だけを違うエラー処理にする。

Sub test()
    Dim i As Long
    
    On Error GoTo normalError
    '処理
    On Error GoTo 0
    
    On Error GoTo fatalError
    i = 1 / 0 '!!
    On Error GoTo 0
    
    On Error GoTo normalError
    '処理
    Exit Sub
    
normalError:
    'エラー処理
    Exit Sub
fatalError:
    'エラー処理
End Sub

2 エラーの種類で分ける。

on error resume next でエラーが起きても処理を止めずに、err.numbarでエラーの種類を判断します。

Sub test2()
    Dim i As Long
    
    On Error Resume Next
    
    i = 1 / 0  '!!
    
    Select Case Err.Number
        Case 11
            GoTo normalError
        Case 13
            GoTo fatalError
    End Select
    
    On Error GoTo 0
    
    '処理
    Exit Sub
    
normalError:
    'エラー処理
    Exit Sub
fatalError:
    'エラー処理
End Sub

11というのは0の除算のエラーで、13は型の不一致です。

エラーの種類はこちらをみてください。

http://support.microsoft.com/kb/146864/ja

id:ReoReo7

ありがとうございます。

err.number

で分かるのですね。

On Error GoTo 0

の意味も初めて知りました。

コードの書き方として参考にさせて頂きました。ありがとうございます。

2010/11/19 15:21:29
  • id:Silvanus
    きっとtakntさんが既にお答えになっていらっしゃると思いますが、
    エラーをトラップする段階では、そのエラーが
    「fatalなもの(具体的にはどういう意味でしょう?)であるか否か」を
    区別することはできません。
    エラーをトラップして飛んだ先(エラー処理ルーチン)で、エラーの中身を
    Err.Number(ErrオブジェクトのNumberプロパティ)等を用いて調べることによって
    ReoReo7さんが仰せのところの「fatal or not」の切り分けを行ないます。
  • id:ReoReo7
    コメントありがとうございます。
    Err.Numberを見ることで切り分けができるというご指摘ありがとうございました。
    質問とは、「fatal or notを見分けるにはどうしたらよいのか?」
    という質問ではなく、むしろOn Error GoTo文のスコープに関する、ちょっとややこしい質問だと思います。

    エラーの構造は以下に示します。
    エラー再現できていないので、非常に答えにくいと思います。
    もしお心当たりのことがありましたらどなたかコメント頂けるとうれしいですが、こちらの思い違いの可能性もありますので思い当たることがなければ無視して頂いて結構です。
  • id:ReoReo7
    上記コメントでエラー再現できていないと書きましたが、
    エラー再現できました。
    以下の通りです。
    2回目のエラーでうまく飛ばないようです。
    原因を教えて頂ければうれしいです。

    Sub testParent()
    On Error GoTo myError
    Call testChild
    Exit Sub
    myError:
    Debug.Print "ここに飛ばせたく無い。"
    End Sub

    Sub testChild()
    Dim i As Long
    On Error GoTo error1
    i = 1 / 0
    Debug.Print "何かの命令処理。"
    error1:
    On Error GoTo 0 'この行は挿入しなくても、飛ぶ箇所は同じなんですね。
    On Error GoTo error2
    i = 1 / 0
    Debug.Print "何かの命令処理。"
    error2:
    Debug.Print "この処理を必ず実行させたい。"
    End Sub
  • id:ReoReo7
    何とか、自力でできました。

    http://hanatyan.sakura.ne.jp/dotnet/err01.htm#no3

    On Error GoTo -1
      現在のプロシージャで有効になっていた例外を無効にし、Nothing にリセットされます。

    を使えばよいんですね。

    Sub testParent()
    On Error GoTo myError
    Call testChild
    Exit Sub
    myError:
    Debug.Print "ここに飛ばせたく無い。"
    End Sub

    Sub testChild()
    Dim i As Long
    On Error GoTo error1
    i = 1 / 0
    Debug.Print "何かの命令処理。"
    error1:
    On Error GoTo -1 'この行を挿入しないと、myErrorに飛んでしまうのですね。
    On Error GoTo error2
    i = 1 / 0
    Debug.Print "何かの命令処理。"
    Exit Sub '一応、追加(大差ありませんが)
    error2:
    Debug.Print "この処理がやっと実行できました。"
    End Sub
  • id:Silvanus
    あと、エラー処理ルーチンから復帰する際には
    resumeステイトメントを使うのが本筋ですよ。
    "On Error GoTo -1"っていうのは初めて知りましたw。
  • id:taknt
    エラー処理の中でも エラー処理ですか。
    どこまでエラー処理するんでしょうね。

  • id:ReoReo7
    >resumeステイトメントを使うのが本筋ですよ。
    ありがとうございます。

    >エラー処理の中でも エラー処理ですか。
    >どこまでエラー処理するんでしょうね。
    objIE.Document.All.Item(i).nodeName
    を拾ってそれぞれ格納しています。
    エラーの場合、無視して次のパラメータを拾っています。
    phpで言うissetみたいな表現を使って、それで存在を調べて、エラーを回避するのが普通なんでしょうか・・・。よく分からないので、存在しないときは無視して次の処理、ということにしています。

この質問への反応(ブックマークコメント)

「あの人に答えてほしい」「この質問はあの人が答えられそう」というときに、回答リクエストを送ってみてましょう。

これ以上回答リクエストを送信することはできません。制限について

回答リクエストを送信したユーザーはいません