プロシージャを実行していると、時として、こちらが予期してない事に出くわします。
つまり、想定外のデータ入力があったりするわけです。
そうすると、たいていの場合、マクロはエラーを表示して、停止してしまいます。
そのときに対応するのが、エラー処理です。
マクロがエラーになった時、処理がどこに行くのか記述する方法です。
エラーが起きると、ラベルが付いている行に処理が移ります。
エラー処理がしてあるので、マクロ自体は正常に動作して終わります。
次のマクロは、わり算をして、商と余りを求めるものです。
このプロシージャは、A列をB列で割った商をC列に、余りをD列に書き込んでいきます。 6行目の割る数が0なのでエラーになり、Trapというラベルに処理が飛びました。 |
|
Sub わり算() On Error GoTo Trap ←@ Dim R As Integer For R = 2 To 11 Cells(R, 3) = Cells(R, 1) \ Cells(R, 2) ←A Cells(R, 4) = Cells(R, 1) Mod Cells(R, 2) ←B Next R Exit Sub ←C Trap: ←D MsgBox R & "行目: 割る数が0なので、計算できません。" End Sub |
@ エラーが起きたら、Trapというラベルから処理をします。 A ¥ は、わり算をした商を求めます。 6行目は、割る数が0なので、エラーになります。 B MOD は、わり算をした余りを求めます。 6行目は、割る数が0なので、エラーになります。 C通常の処理をしたとき、ここで終わりにします。 Dエラーを起こしたとき、このラベルに飛びます。(Trap: ラベルのあとに : が付いています) |
エラー処理は、エラーが出たとき、ラベルのある行に進み、メッセージを表示したりするのが本来の役目ですが、
場合によっては、エラーを無視して次の処理をして欲しいときがあります。
そこで紹介するのが、On Error Resume Next です。
このステートメントは、エラーを無視して次の行から処理を継続します。
このプロシージャは、A列をB列で割った商をC列に、余りをD列に書き込んでいきます。 6行目が割る数が0で商も余りもエラーになりますが、そのエラーを無視して7行目からの処理を続けています。 |
|
Sub わり算2() On Error Resume Next ←@ Dim R As Integer For R = 2 To 11 Cells(R, 3) = Cells(R, 1) \ Cells(R, 2) ←A Cells(R, 4) = Cells(R, 1) Mod Cells(R, 2) ←B Next R End Sub |
@ エラーが起きたら、無視して次の行から処理を続けます。 A ¥ は、わり算をした商を求めます。 6行目は、割る数が0なので、エラーになります。 B MOD は、わり算をした余りを求めます。 6行目は、割る数が0なので、エラーになります。 しかし、On Error Resume Next ステートメントがあるので、 6行目の処理は飛ばして、7行目以降を処理していきます。 |
エラー処理は、行頭で宣言すると、その先ずっと宣言した通りになります。
しかし、実際は、エラーの処理はある部分だけに必要で、全体には関係のないことの方が多いものです。
そこで、関係のないところにきたら、エラー処理をやめるのが、このステートメントです。
このプロシージャは、A列をB列で割った商をC列に、余りをD列に書き込んでいきます。 同じ処理を2回続けていますが、2回目はエラー処理をキャンセルしているので、マクロのエラー画面が表示されました。 |
|
Sub わり算3() On Error GoTo Trap ←@ Dim R As Integer '(1回目) Range("C2:D11") = "" MsgBox "1回目 スタート" For R = 2 To 11 Cells(R, 3) = Cells(R, 1) \ Cells(R, 2) ←A Cells(R, 4) = Cells(R, 1) Mod Cells(R, 2) ←B Next R '(2回目) Trap: ←C MsgBox "1回目 終わり" On Error GoTo 0 ←D MsgBox "2回目 スタート" Range("C2:D11") = "" For R = 2 To 11 Cells(R, 3) = Cells(R, 1) \ Cells(R, 2) ←E Cells(R, 4) = Cells(R, 1) Mod Cells(R, 2) Next R End Sub |
@ エラーが起きたら、Trapというラベルから処理をします。 A ¥ は、わり算をした商を求めます。 6行目は、割る数が0なので、エラーになります。 B MOD は、わり算をした余りを求めます。 6行目は、割る数が0なので、エラーになります。 COn Erro Goto Trap ステートメントがあったので、、このラベル(Trap:)に処理が飛びます。 Dここで、エラー処理をキャンセルしています。 E ¥ は、わり算をした商を求めます。 6行目は、割る数が0なので、エラーになります。 エラー処理がキャンセルされているので、マクロがエラーメッセージを出して停止しました。 |
このプロシージャは、A列をB列で割った商をC列に、余りをD列に書き込んでいきます。 6行目の割る数が0なのでエラーになり、Trapというラベルに処理が飛びました。 |
|
Sub わり算4() On Error GoTo Trap ←@ Dim R As Integer For R = 2 To 11 Cells(R, 3) = Cells(R, 1) \ Cells(R, 2) ←A Cells(R, 4) = Cells(R, 1) Mod Cells(R, 2) ←B Next R Exit Sub Trap: ←C MsgBox "エラー番号:" & Err.Number & vbCr & "エラー内容:" & Err.Description ←D End Sub |
@ エラーが起きたら、Trapというラベルから処理をします。 A ¥ は、わり算をした商を求めます。 6行目は、割る数が0なので、エラーになります。 B MOD は、わり算をした余りを求めます。 6行目は、割る数が0なので、エラーになります。 Cエラーを起こしたとき、このラベルに飛びます。(Trap: ラベルのあとに : が付いています) D次のことを返します。 Err.Number → エラー番号 Err.Description → エラーの内容 Select Case文と組み合わせると、エラー番号によって、処理を変えることもできます。 vbCr は、改行させたい時に使います。 Chr(13)と意味は同じです。 |
今までエラー処理のことでいろいろと書いてきましたが、本当はエラーが出そうな場面では、その都度エラー対策をしておいた方がいいです。
今回は、サンプルとして短いプロシージャを書いていますが、実際に作るとかなり長くなってきます。
となると、エラーが発生する可能性のある部分がたくさんあるわけで、そのエラーをひとくくりにして処理すると、非常に煩雑になるからです。
エラーが出そうな場所で個別に細かく対応した方が、ユーザーにとってもどう修正したらいいのかがわかりやすくなります。
このプロシージャは、A列をB列で割った商をC列に、余りをD列に書き込んでいきます。 | |
Sub わり算5() Dim R As Integer For R = 2 To 11 If IsNumeric(Cells(R, 2)) = False Then ←@ MsgBox R & "行目: 文字が入力されています。" Exit Sub ElseIf Cells(R, 2) = 0 Then ←A MsgBox R & "行目: 0が入力されています。" Exit Sub End If Cells(R, 3) = Cells(R, 1) \ Cells(R, 2) ←A Cells(R, 4) = Cells(R, 1) Mod Cells(R, 2) ←B Next R End Sub |
この場合は、AやBでエラーにならないように、事前にIF文で判断しています。 @ IsNumeric関数は、値が数値かどうかを返します。 数値であればTrueを、数値でなければFalseを返します。 ACells(R, 2) = 0 で、値が0かどうか調べています。 @やAでそれぞれ判断することで、返すメッセージもそれに対応したメッセージを返しているので、ユーザーはどう修正していいのかわかりやすくなります。 |