こんにちは。ECF Tech担当
Michiharu.Tです。
Excel VBA入門の第11回です。
今回はエラーとその対応方法に関する内容です。エラーとは、プログラムの予期せぬ動作のことを指します。エラーを適切に処理するプログラムを書くことで、利用者にとって使いやすいプログラムを書くことができます。
本連載の目次は下記よりご覧頂けます。

コンパイルエラーと実行時エラー
Excel VBAにはコンパイルエラーと実行時エラーの大きく2種類があります。
コンパイルエラー
コンパイルは、コンピュータがプログラムを解釈する作業のことです。コンパイルエラーはその際に発生するエラーで、文法の誤りが主な原因です。プログラムを修正することで、エラーが発生しないようにすることができます。
上図のエラーは、値を代入しようとしている変数Nameが宣言されていないため、エラーとなっています。
実行時エラー
実行時エラーはプログラムの記述はあっているものの、実行中に発生してしまうエラーのことです。次のようなシンプルなマクロで確認してみましょう。
Sub tashizan() Dim val1 As Integer Dim val2 As Integer 'A1とC1の値を取得 val1 = Range("A1").Value val2 = Range("C1").Value '足し算の結果をE1に出力 Range("E1").Value = val1 + val2 End Sub
上のマクロは下図のようなExcelシートにおいて、A1とC1のセルに数値を入力したら、その加算結果をE1に出力してくれるというものです。
利用者がA1とC1のセルに正しく数値を入力すれば、プログラムは正常に動作しますが、数値以外(下図では「A」)の値を入力すると次のような結果となります。
実行時エラーが表示されています。このエラーは整数(Integer)型の変数val2にC1セルの値を代入する際、C1セルの値が数値では無いために発生しています。実行時エラーは実際に動作させてみて、その状況に応じて発生するエラーです。この実行時エラーも適切に対処することで、より利便性が高く利用者に優しいプログラムを作成することができます。
実行時エラーに対する考え方
実行時エラーが起こりうる状況に対し、どのように対応すべきか。については大きく2つの考え方があります。足し算マクロを例に、それぞれの考え方でプログラムを修正してみましょう。
実行時エラーの発生を防ぐ
1つ目の考え方は、実行時エラーが発生しないようにプログラムを記述することです。先ほどの足し算プログラムにおける実行時エラーの原因は、val1 = Range("A1").Value
のような処理で、セルの値を無条件に変数に代入しようとしていることです。セルに入力される値が数値とみなせるかわからない点が問題です。
そこで対応策として、A1セルの値の内容を事前にチェックしたいと思います。VBAには値の種類を事前にチェックできる次のような関数が用意されています。
関数名 | 説明 |
---|---|
IsEmpty | 指定された値が空ならTrueを返す |
IsNumeric | 指定された値が数値ならTrueを返す |
IsDate | 指定された値が日付形式ならTrueを返す |
これらの関数はいずれも引数を1つとり、その引数の値を対象に判定を行います。簡単なプログラム例でみてみましょう。
Sub isSample() If IsNumeric(5) Then MsgBox "数値です" End If End Sub
このプログラムではIsNumeric関数を使って、引数に指定した値が数値かどうかを判定しています。引数には5
が指定されています。5
は数値とみなせるので、IsNumeric(5)
の結果はTrueとなります。If文は条件式に指定した式がTrueならIf文内の処理に入りますので、MsgBox "数値です"
が実行されることになります。実行結果は次のとおりです。
一方、下のプログラムではIsNumeric関数の引数に文字が入っており、数値と判定されないためFalseとなります。したがってIf文の処理に入らず、実行しても何も表示されません。
Sub isSample2() If IsNumeric("A") Then MsgBox "数値です" End If End Sub
では次に、このIsNumeric関数を使って、最初の足し算プログラムを改良してみましょう。
Sub tashizan() Dim val1 As Integer Dim val2 As Integer 'A1が数値でないなら処理を終了 If Not IsNumeric(Range("A1").Value) Then Exit Sub End If 'C1が数値でないなら処理を終了 If Not IsNumeric(Range("C1").Value) Then Exit Sub End If 'A1とC1の値を取得 val1 = Range("A1").Value val2 = Range("C1").Value '足し算の結果をE1に出力 Range("E1").Value = val1 + val2 End Sub
A1セルとC1セルに対する下のような処理が追加されています。
If Not IsNumeric(Range("A1").Value) Then Exit Sub End If
上の例では、IsNumeric関数を使ってA1セルの値が数値かどうかを判定しています。Not
演算子は条件式などの前に置かれ、「TrueをFalse、FalseをTrueにする」演算子です。今回のIf文では「A1セルの値が数値でない場合」、つまりIsNumeric(Range("A1").Value)
がFalseの場合にIf文に入りたいので、Not
を付けることでIsNumeric関数の結果がFalseの場合に条件式がTrueとなるようにし、If文に入るようにしています。
If文内のExit Sub
は、Subプロシージャの処理を途中終了させる役割があります。つまり、A1セルの値が数値でない場合は以降の処理はしない。というプログラムになります。その後C1セルについても下記のように同様の処理を行っています。
If Not IsNumeric(Range("C1").Value) Then Exit Sub End If
これらの追加処理によって、2つのセルが数値であることを確認できたら、足し算処理のつづきを行っています。これで実行時エラーの発生を防ぐことができます。
If Not IsNumeric(Range("A1").Value) Then
は、実は「A1が数値である」の判定として十分とは言えません。理由は、IsNumeric関数が空の値に対し、Trueを返してしまうからです。したがってA1セルが空の状態で実行すると、If文に入らずに実行時エラーを発生させる恐れがあります。そのため、If文の条件式は「A1セルが空である または A1セルが数値でない」のいずれかに該当する場合にTrueとなるようにする必要があります。そのため、正確にはIsEmpty(Range("A1").Value Or Not IsNumeric(Range("A1").Value))
とする必要があります。式が複雑だと感じる方は、次の実行時エラー発生時に対処する方法を検討しても良いでしょう。実行時エラー発生時に対処する
実行時エラーに対するもう1つの考え方は、実行時エラーが発生したときに対処する方法です。On Errorステートメントを使用することで実現できます。
On Errorステートメントの基本的な文法は次のようになります。
On Error GoTo ラベル名 : ラベル名: 'ここに実行時エラーの時の処理を書く
簡単に説明すると、On Error GoTo ラベル名
以降の処理で実行時エラーが発生した場合は、ラベル名:
の部分に処理がジャンプします。足し算マクロの例で具体的に確認します。
Sub tashizan() Dim val1 As Integer Dim val2 As Integer On Error GoTo DispMsg 'A1とC1の値を取得 val1 = Range("A1").Value val2 = Range("C1").Value '足し算の結果をE1に出力 Range("E1").Value = val1 + val2 Exit Sub DispMsg: MsgBox "A1とC1には数値を入れてください" End Sub
On Error GoTo DispMsg
の部分と下記の処理が追加されています。ラベル名は自由に設定できるので、今回はDispMsg
としました。
DispMsg: MsgBox "A1とC1には数値を入れてください"
どのような動作をするかは、下の図でイメージして頂くと良いでしょう。
On Error GoTo DispMsg
より後の処理、つまり図の①に示す範囲で実行時エラーが発生すると、②の矢印が指すDispMsg
のラベルに処理がジャンプし、「A1とC1には数値を入れてください」のメッセージを表示します。
実行時エラーが発生しない場合は、図の③に示すExit Sub
でSubプロシージャが終了します。このExit Sub
が無いと、実行時エラーが発生しない場合でもMsgBox "A1とC1には数値を入れてください"
が実行されてしまうので注意が必要です。
Exit Sub
をつけておかないと、処理がひたすら下に進み、MsgBox "A1とC1には数値を入れてください"
まで実行されてしまいます。複数の実行時エラーの処理
次にOn Errorステートメントを使って、複数の実行時エラーを処理するプログラムをご紹介します。
足し算プログラムと同様に、上図のようなシートで割り算を行うプログラム例です。A1とC1のセルに値を入れると割り算を行い、結果をE1セルに代入します。割り算を伴うプログラムの場合、0で割ってしまう処理にならないよう注意が必要です。割る数を0にして割り算をしてしまうと、下のような実行時エラーが発生します。
したがって、割り算プログラムを作るにあたっては
- 整数型の変数に数値でない値を代入する実行時エラー(以降、型不一致エラーと記載)
- 0で割り算をする実行時エラー(以降、0割りエラーと記載)
の2つに対応する必要があります。
それでは、プログラムを示します。
Sub warizan() Dim val1 As Integer Dim val2 As Integer On Error GoTo TypeError 'A1とC1の値を取得 val1 = Range("A1").Value val2 = Range("C1").Value On Error GoTo Div0Error '割り算の結果をE1に出力 Range("E1").Value = val1 / val2 Exit Sub TypeError: MsgBox "A1とC1には数値を入れてください" Exit Sub Div0Error: MsgBox "割る数に0は使えません" End Sub
2つのOn Errorステートメントを使って、複数の実行時エラーを処理しています。こちらも下図で処理イメージを確認して頂くと良いでしょう。
型不一致エラーに関連する処理はオレンジ、0割りエラーに関する処理は水色で示しています。
①で示す範囲で起こりうるのは型不一致エラーになりますので、その場合はTypeError:
ラベルにジャンプ(図中②)し、「A1とC1には数値を入れてください」を表示します。
③で示す範囲で起こりうるのは型不一致エラーになりますので、その場合はDiv0Error:
ラベルにジャンプ(図中④)し、「割る数に0は使えません」を表示します。
このようにすることで、複数の実行時エラーに対応した処理を記述することができます。
本日はここまでとさせて頂きます。最後までお読みいただきありがとうございました。エラー処理の方法を身につけて、利用者に優しいプログラムの作成を目指しましょう。