エラー処理を知っておこう。

プロシージャを実行していると、時として、こちらが予期してない事に出くわします。
つまり、想定外のデータ入力があったりするわけです。
そうすると、たいていの場合、マクロはエラーを表示して、停止してしまいます。
そのときに対応するのが、エラー処理です。

1.エラー時の行き先を記述する。(On Error Goto 〜)

マクロがエラーになった時、処理がどこに行くのか記述する方法です。
エラーが起きると、ラベルが付いている行に処理が移ります。
エラー処理がしてあるので、マクロ自体は正常に動作して終わります。
次のマクロは、わり算をして、商と余りを求めるものです。

  このプロシージャは、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: ラベルのあとに : が付いています)

2.エラーになっても、無視して次の行から処理を続ける。(On Error Resume Next)

エラー処理は、エラーが出たとき、ラベルのある行に進み、メッセージを表示したりするのが本来の役目ですが、
場合によっては、エラーを無視して次の処理をして欲しいときがあります。
そこで紹介するのが、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行目以降を処理していきます。

3.エラー処理をやめる。(On Error Goto 0)

エラー処理は、行頭で宣言すると、その先ずっと宣言した通りになります。
しかし、実際は、エラーの処理はある部分だけに必要で、全体には関係のないことの方が多いものです。
そこで、関係のないところにきたら、エラー処理をやめるのが、このステートメントです。

  このプロシージャは、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なので、エラーになります。
 エラー処理がキャンセルされているので、マクロがエラーメッセージを出して停止しました。

4.エラー番号や内容を表示する。

  このプロシージャは、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)と意味は同じです。

5.使い勝手の面から考えると・・・

今までエラー処理のことでいろいろと書いてきましたが、本当はエラーが出そうな場面では、その都度エラー対策をしておいた方がいいです。
今回は、サンプルとして短いプロシージャを書いていますが、実際に作るとかなり長くなってきます。
となると、エラーが発生する可能性のある部分がたくさんあるわけで、そのエラーをひとくくりにして処理すると、非常に煩雑になるからです。
エラーが出そうな場所で個別に細かく対応した方が、ユーザーにとってもどう修正したらいいのかがわかりやすくなります。

   このプロシージャは、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でそれぞれ判断することで、返すメッセージもそれに対応したメッセージを返しているので、ユーザーはどう修正していいのかわかりやすくなります。