VBAで新たにマクロを作成する場合、テストを何度も行ない正しく動作することを検証してから配布します。しかし、実際に運用が開始されたところ「エラーになった!」ということが結構あります。
テストでは想定していなかった環境で運用されたりすることもあるため、エラーが発生することをあらかじめ想定して対処しておく必要があります。このエラーへの対処方法について基本的な部分をいくつか紹介したいと思います。
【この記事でわかることは】
・On Error ステートメントの使い方
はじめに
「実行時エラー」は主にVBA(マクロ)が外部とのデータ取得・参照や書き込みなどのやりとりを行なう時に発生します。
エラーに対する対策を何もしていない場合は、次のようなVBAのエラーダイアログが表示されます。
ここで「終了」を選択すると、エラーが発生して箇所で処理が中断されてそのまま終了します。
「デバッグ」を選択すれば、VBEが開き中断されている部分が黄色く表示されて編集状態になりますが、VBAがわからない人にとっては余計に混乱させてしまうことでしょう。また、VBAコードを触られたくない場合はVBAのエラーダイアログは表示しない方が良いでしょう。
On Errorステートメントを使ってエラーをトラップすることでエラーダイアログを表示しないようにできます。操作者にエラー発生事象や内容など独自のメッセージを通知して処理を打ち切るようにもできます。
On Errorステートメント
On Error は、実行時エラーが発生したらどうするかを指定するステートメントです。
発生したエラーをトラップしてプロシージャ内のエラー処理ルーチンの場所へジャンプさせたり、エラー処理ルーチンを無効にしたりすることができます。
On Error ステートメントの構文は、次の形式を使用できます。
ステートメント | 説明 |
---|---|
On Error GoTo line | 同じプロシージャ内の line の指定行からの処理を実行します。 ※ line 引数は、任意の行ラベルまたは行番号です。 |
On Error Resume Next | エラーは捉えますが、そのまま次のステートメントを実行します。 |
On Error GoTo 0 | プロシージャ内の有効なすべてのエラーハンドラーを無効にします。 |
On Error GoTo line
On Error に GoToステートメントを使うことで、エラー発生時にエラー処理ルーチンの場所へジャンプさせることができます。
※ GoToステートメンについて、詳しくはこちらを参照ください。
line には「行ラベル」又は「行番号」を指定します。「行ラベル」は任意の文字列で指定できます。
ジャンプ先の「行ラベル」はインデントせずに1列目から入力し末尾にコロン (:)を付けます。大文字と小文字は区別しません。
前回記事で使ったサンプルに基本的なエラー処理を加えてみるとこんな感じです。
Sub Sample03()
Dim arr As Variant
Dim i As Long
On Error GoTo ErrorHandler 'エラー処理用
arr = Array(1, 2, 3, 4, 5)
For i = 1 To 5
Cells(i, 1) = arr(i) 'i = 5 でエラー発生
Next i
Exit Sub
ErrorHandler: '「行ラベル」
With Err 'Errオブジェクト
MsgBox .Source & "内でエラーが発生しました!" & _
vbCrLf & "エラー番号" & .Number & ":" & .Description _
, vbCritical, "エラー通知"
End With
End Sub
・4行目に On Error GoToステートメントを入れ行ラベル ErrorHandler を指定
・9行目に Exit Sub を追加して正常の場合はここで処理を終了させます。
これを忘れると正常なのに次のエラー処理のコードが実行されてしまいます。
・10行目の行ラベル ErrorHandler: からがエラー発生後の処理です。
・11行目、Errオブジェクトを複数使うので With プロパティを使っています。
・12~14行目でメッセージボックスの表示内容を設定しています。
・エラーが発生すると、エラーの情報が Errオブジェクトに格納されます。
ここでは、その情報の中から「.Source」「.Number」「.Description」を使っています。
・14行目「, vbCritical, “エラー通知”」はアイコンとタイトルの設定です。
MsgBox のアイコン変更はvb定数で指定します。ここでは「停止(×)」を示す赤いアイコン「vbCritical」を使っています。
その他、黄色の「注意(!)」アイコン「vbExclamation」、青色の「案内(i)」アイコン「vbInformation」などもあります。必要に応じて使い分けましょう。
On Error Resume Next
Resumeステートメントの構文は次のような形式を使用できます。
ステートメント | 説明 |
---|---|
Resume [0] | エラー発生ステートメントから実行を再開します。 |
Resume Next | エラー発生ステートメントを無視して次のステートメント から実行が再開されます。 |
Resum line | エラーハンドラーと同じプロシージャ内の line で指定された行から実行が再開されます。 ※line は行ラベル又は行番号を指定できます。 |
On Error に Resumeステートメントを使うことで、エラー発生時に指定した行からの処理を実行したり、エラー発生個所をスルーして次の処理を実行させることが可能です。
エラーをスルーさせたい場合は On Error Resume Next を使います。
Sub Sample03_2()
Dim arr As Variant
Dim i As Long
On Error Resume Next '実行時エラーを無視する
arr = Array(1, 2, 3, 4, 5)
For i = 1 To 5
Cells(i, 1) = arr(i) 'i = 5 でエラー発生
Next i
End Sub
先ほどのサンプルに On Error Resume Next を使うと、i = 5 で実行時エラーが発生しますがエラーメッセージは表示されずにそのまま終了します。
でもこの使い方では、セルに誤った結果が書き出されてしまいます。不用意に On Error Resume Next を使ってはダメだということがわかる事例です。エラーを無視しても正常な処理(結果)になる場合にだけ利用しましょう。
次の例は、セルのデータを一旦配列に入れて違うセルに2倍して書き出す処理です。
Sub ResumeNextSample()
Dim arr(5) As Long 'Variant
Dim i As Long
On Error Resume Next '実行時エラーを無視する
'セルのデータを配列に格納
For i = 1 To 5
arr(i) = Cells(i, 1) 'データ型がLongならエラー
Next
'配列のデータを2倍してセルに書き込む
For i = 1 To 5
Cells(i, 2) = arr(i) * 2 'Variantならここでエラー
Next
End Sub
・4行目に On Error Resume Next を入れています。
・Resume Next 無しでは取得するセルに #N/A や #VALUE! のエラー表示や文字列があった場合、実行時エラー’13’が発生します。
・配列のデータ型が Long の場合は、7行目のループでエラーが発生します。
データ型が Variant の場合は、11行目のループでエラーとなります。
このように On Error Resume Next でエラーを無視することで、データが「0」になるので問題は発生しなくなります。むしろ、エラーのデータを事前に処理する手間が省けるというわけです。
On Error GoTo 0
現在のプロシージャで有効なすべてのエラーハンドラーを無効にするステートメントです。
先ほどの例でいえば、データ型が Long の場合は、配列にセルのデータを書き込む際のループでエラーが発生しますが、セルに書き込む際にはエラーは発生しませんので次のようにしても問題ありません。
Sub GoTo_0_Sample()
Dim arr(5) As Long 'Variant
Dim i As Long
On Error Resume Next '実行時エラーを無視する
'セルのデータを配列に格納
For i = 1 To 5
arr(i) = Cells(i, 1) 'データ型がLongならエラー
Next
On Error GoTo 0 'エラー処理を無効にする
'配列のデータを2倍してセルに書き込む
For i = 1 To 5
Cells(i, 2) = arr(i) * 2 'Variantならここでエラー
Next
End Sub
・配列のデータ型を Variant に変更して実行してみてください。
11行目のループでエラーが発生します。
・エラーハンドラーが無効になっていることが確認できます。
まとめ(おわりに)
今回の内容はいかがでしたか? お役に立てたなら幸いです(^^;
想定できるエラーに対して、エラー処理を設置する方法についての基本的なことは解説できたのではないでしょうか。
今回紹介したものはプロシージャだけでしたが、プロシージャを跨ぐ場合のエラー処理についても理解しておく必要があります。次回以降でエラー処理についてさらに詳しく見ていくようにしたいと思います。
★★★ ブログランキング参加中! クリックしてね(^^)/ ★★★
過去記事のサンプルファイルをダウンロードできます
この記事で使用したサンプルの登録はありません。
過去の記事で使用したサンプルファイルをダウンロードできるようにページを設置していますので、こちら(このリンク先)からご利用ください