機能と数式 | VBA | セミナー | オンラインソフト | お問い合わせ | その他
Top > Excel > VBA

VBAのエラー



プログラムのエラーは、原因や発生するタイミングなどで分類されます。分類の方法や考え方には様々ありますが、Excel VBAでマクロを開発中に発生するエラーを、ここでは次のように分類します。

  1. 構文エラー
  2. コンパイルエラー
  3. 実行時エラー

構文エラーは、いわゆる"打ち間違い"です。オブジェクト名やプロパティ名のスペルを間違えたり、括弧の数が合わなかったり、カンマ(,)を入力しなければいけない場所にコロン(.)を打ってしまったり…そうした原因によるエラーです。

コンパイルエラーは、マクロのコードがコンパイルされるときに発生するエラーです。ここでは、主に論理的なエラーがチェックされます。たとえば、変数の宣言を強制する設定をしたにも拘わらず、宣言しないで変数を使ったようなケースです。

実行時エラーは、マクロを実行して初めて露呈するエラーです。コンパイルエラーと同じように、論理的な間違いが多く、たとえば、ワークシートが3枚しか存在しないのに4枚目のワークシートを操作しようとしたり、存在しないブックを開こうとしたときなどに発生します。
実行時エラーには、それぞれ固有のエラー番号が割り当てられていて、Errオブジェクトを使えば、マクロのコード内で「どんなエラーが発生したか」を判定できます。On Errorステートメントなどを使うことで、あらかじめ想定したエラーに対する対処をプログラミングしておくことが可能です。これをエラートラップと呼びます。


VBAのコードは、いつコンパイルされるか



われわれがVBEのコードペインでマクロを作成するとき、裏でVBAが何をしているのかを解説します。


(1)まず、ユーザーが1行分の命令を入力して、行末でEnterキーを押します。



(2)するとVBAは、いま入力された行のスペルミスなど構文チェックをして
  問題がなければ、その行を中間コードにコンパイルします。この中間コードをPコードと呼びます。



(3)[F5]キーを押すなどして、このマクロを実行すると
  それまでコンパイルしてあった中間コード(Pコード)を
  VBAが理解できる最終的なコードにコンパイルしてから、実行します。




このように、VBAは2段階のコンパイルを行います。行末でEnterキーを押しただけでも「コンパイルエラー」が起こるのは、最初のコンパイルでエラーが発生するからです。
このことはヘルプにも記載されています。Excel 2007 VBEのヘルプ[Excel 2007 開発者用リファレンス ]-[Visual Basic 開発環境]-[構文チェックの設定と解除の切り替え]には、
Visual Basic には、次のような構文チェック機能があります。
  • キーワードの入力間違いや区切り記号の入力漏れなど、ステートメントが入力されるごとに、その構文エラーをチェックし、エラーがあるときにはそれを通知します。
  • 構文が正しいときはコードを内部形式に変換し、実行時の変換速度を向上させます。
と書かれています。この「ステートメントが入力されるごとに」のステートメントとは、IfステートメントやFor Nextステートメントなどを表すステートメントではなく、おそらく"ひとつの命令文"という意味のステートメントでしょう。VBAでは1行に1つの命令文を書くのがルールですから、「ステートメントが入力されるごとに」は「1行が入力されるごとに」という意味だと思います。

上の解説図のとおり、マクロを実行しようとすると、まずコンパイルが行われます。また、マクロを実行しなくても、VBEの[デバッグ]-[VBAProjectのコンパイル]を実行すれば、いつでもコンパイルできます。コンパイルが行われるとき、マクロのコード中に論理的な間違いがあればコンパイルエラーが発生します。主なコンパイルエラーについては、下記ページで解説します。


コンパイルが正常に完了するとマクロが実行されるわけですが、実行途中でしか発見できないエラーもあります。それが実行時エラーです。


実行時エラーへの対応


たとえば、ワークシートが3枚しか存在しないブックで、次のマクロを実行すると「インデックスが有効範囲にありません」という実行時エラーが発生します。

Sub Sample1()
    Dim i As Long
    For i = 1 To 4
        Cells(i, 1) = Worksheets(i).Name
    Next i
End Sub



ワークシートが3枚しかないということは、Worksheets(1)・Worksheets(2)・Worksheets(3)しか操作できないということです。Worksheetsコレクションにはメンバーが3つしかありません。なのに上のコードは「For i = 1 To 4」と、存在しない4枚目のワークシートを操作しようとしています。だからエラーです。マクロは、プログラミングされたことしかできません。プログラミングされたら、たとえそれが間違った命令だったとしても、馬鹿正直に実行しようとします。その結果、エラーになります。「だってぇ…やれって言われたから」みたいな。ビジネスの現場では、こんなヤツ使い物になりませんね。「お前な、言われなくたって、ちょっと考えればわかるだろ?」と苦言のひとつも言いたくなります。まぁ、とにかく。エラーの原因と責任は、エラーになるコードを書いたプログラマにあります。

エラーが起こってもマクロを停止させないためには、エラーの発生を予想して、先手を打たなければなりません。そこで使うのがOn Errorステートメントです。On Errorステートメントは「もしエラーが起こったら○○しろ」という"ルールを決める"ためのステートメントです。On Errorステートメントでよく使うやり方は次の2つです。

  1. On Error Goto ラベル
  2. On Error Resume Next

「On Error Goto ラベル」は、「もしエラーが起こったら'ラベル'の行にジャンプしろ」という命令です。たとえば次のように使います。

Sub Sample2()
    Dim i As Long
    On Error GoTo ErrorRoutine
    For i = 1 To 4
        Cells(i, 1) = Worksheets(i).Name
    Next i
    Exit Sub
ErrorRoutine:
    MsgBox "エラーが発生しました"
End Sub

ラベルは「ラベル名:」と入力します。
上のコードは「もしエラーが起こったらErrorRoutineの行へジャンプしろ」と指示しました。忘れてならないのは、ラベルErrorRoutineの直前にあるExit Subです。ラベルは、コード内の単なる印に過ぎません。On Errorステートメントで指定したとはいえ、その他の行と何ら変わりません。なので、もしエラーが起こらなかったときには実行させないように、正常なときは、その直前でマクロを終了させなければなりません。それがExit Subです。

もうひとつの「On Error Resume Next」は、「もしエラーが起こっても、そのエラーを無視して、次の命令から先を実行しろ」という命令です。次のように使います。

Sub Sample3()
    Dim i As Long
    On Error Resume Next
    For i = 1 To 4
        Cells(i, 1) = Worksheets(i).Name
    Next i
End Sub

実行してみるとわかりますが、Worksheets(4)を操作することによって起こる実行時エラーは無視されます。
エラーが無視されるということは、マクロがエラーで止まらないということです。これはこれで便利なケースも多いのですが、止まらないからといって"エラーが起きていない"とは断言できません。エラーを無視したときは、実際にはエラーが起きていたのかどうかを確かめなければなりません。そこで使うのがErrオブジェクトです。

Errオブジェクトは、マクロ実行中に発生したエラーが格納されるオブジェクトです。つまり、Errオブジェクトを調べれば、実際にはエラーが起きていたのかどうかを判定することができるのです。

Errオブジェクトにはいくつかのプロパティがありますが、その中のNumberプロパティには、発生したエラーの"エラー番号"が格納されます。Numberプロパティが0でないということは、何らかのエラーが発生したということです。

Sub Sample4()
    Dim i As Long
    On Error Resume Next
    For i = 1 To 4
        Cells(i, 1) = Worksheets(i).Name
    Next i
    If Err.Number <> 0 Then
        MsgBox "エラーが発生しました"
    End If
End Sub


このへんがエラー対策の基本です。On ErrorステートメントやErrオブジェクトを使って、できうる限りのエラーに対して先手を打ち、エラーで止まらない頑強なマクロを心がけてください。なお、実行時エラーの一覧と解説は、下記ページをご覧ください。




このエントリーをはてなブックマークに追加