VBAを使ってプログラミングをしていると、「エラー」は避けて通れません。
適切にエラー処理(エラーハンドリング)しておかないと、次のような困ったことが起こります。
- プログラムが途中で止まってしまう
- 意図しない結果を返す
- エラーの原因がわからない
本記事では知っておきたいエラーハンドリングの方法と、知っておくと便利な付随知識をご紹介します。
VBAにおけるエラーを理解しよう
VBAのエラーを扱うための基礎知識を解説します。
最初の段階では以下の内容を把握しておけば十分戦えます。
エラー処理が必要な理由
VBAはユーザ操作や外部ファイルとの連携が多いため、実行中に想定外の事態が発生しやすい言語です。
- 存在しないファイルを開こうとした
- 数値の
0
で割り算をした - 存在しないシート名を参照した
こうした場合、エラー処理を組み込んでいないとプログラムは強制終了してしまいます。
VBAで発生するエラーの種類
VBAのエラーは次の2種類に分けられます。
- コンパイルエラー
- 実行時エラー
エラーハンドリングの対象は②の「実行時エラー」です。
順番に解説します。
① コンパイルエラー
コードの実行前に発生するエラーです。
明らかにコードの書き方が間違っている場合に、VBE(VBAのエディタ)が教えてくれます。
開発時に直せばいいので、本番での影響は少なエラーです。
② 実行時エラー
プログラムを実行している最中に発生するエラーです。
例えば存在しないファイルを開こうとする場合などは、これに当たります。
エラーハンドリングの具体的な方法
VBAで実行時エラーを制御するには On Error
文を使います。
いくつか使い方があるので、適切な方法で使い分けましょう。
1. On Error GoTo [ラベル]
エラーがあった場合に、ラベルとして設定した箇所にジャンプします。
以下の場合は、エラー時にErrorHandler
にジャンプすることになります。
On Error GoTo ErrorHandler
Dim x As Integer
x = 10 / 0 ' エラー発生
Exit Sub
ErrorHandler:
MsgBox "エラーが発生しました: " & Err.Description
2. Resumeステートメント
Resume
ステートメントはエラー発生時の挙動を制御するもので、On Error GoTo
と組み合わせて使います。
種類は以下の3つがあります。
ステートメント | 効果 |
---|---|
Resume | エラーが出た行を再実行する |
Resume Next | エラーが出た次の行から再開 |
Resume [ラベル] | 指定ラベルにジャンプして再開 |
例えばResume Next
を使う場合は以下のようになります。
On Error GoTo ErrorHandler
Dim x As Integer
x = 10 / 0
Exit Sub
ErrorHandler:
MsgBox "エラー: " & Err.Description
Resume Next ' ← ここで挙動を制御
上記の場合には4行目でエラーが出るので、MsgBox
を表示した後に6行目が実行されます。
3. On Error Resume Next
エラー行があっても無視する方法です。
On Error Resume Next
x = 10 / 0 ' ← 本来はエラーだが、次の行へ進む
Debug.Print "処理継続"
この方法ではエラーに気づくことができないので、あまり使う機会はありません。
ある行からエラー無視を解除したい場合には、On Error GoTo 0
を書きます。
On Error Resume Next
x = 10 / 0 ' エラー無視
On Error GoTo 0
y = 10 / 0 ' ここでは通常通りエラーで停止
エラーハンドリングに関する追加の知識
エラーハンドリングの具体的な方法でご紹介した3つの方法だけでもエラーハンドリングはできますが、より高度な操作をするなら他の機能も組み合わせることが必要です。
順番に解説していきます。
1. Errオブジェクトのプロパティ
例えば以下のような形でプロパティを指定すると、Err
オブジェクトの情報を取得できます。
On Error GoTo ErrorHandler
Dim x As Integer
x = 10 / 0
Exit Sub
ErrorHandler:
MsgBox "番号: " & Err.Number & vbCrLf & _
"内容: " & Err.Description
その他のプロパティについては、以下のようなものがあります。
プロパティ名 | 内容 |
---|---|
Number | エラー番号(整数値)。0はエラーなし |
Description | エラー内容(文字列)。人間が理解できるメッセージ |
Source | エラーの発生元(モジュール名やオブジェクト名)。Err.Raise で設定可能 |
HelpFile | エラーに関連付けられたヘルプファイルのパス |
HelpContext | ヘルプファイル内のトピックID(整数) |
LastDllError | 外部DLL呼び出しでのエラーコード |
Number
とDescription
はよく使うので、この二つを覚えておけば問題ありません。
2. Errオブジェクトのメソッド
Errオブジェクトを操作することもでき、以下のようなメソッドを使います。
メソッド | 説明 |
---|---|
Clear | Err.Number や Err.Description をリセットする |
Raise | 任意のエラーを発生させる(番号・発生元・メッセージを指定可能) |
使用例も掲載します。
On Error Resume Next
x = 10 / 0
If Err.Number <> 0 Then
Debug.Print "エラー発生: "; Err.Description
Err.Clear
End If
5行目の段階でErr
オブジェクトはリセットされることになります。
3. エラー処理のスコープ
On Error
の効力は、同じプロシージャ内のみ有効です。
つまり、あるSub
プロシージャを抜けるとErr
がリセットされます。
4. エラーハンドリングのベストプラクティス
以下の内容に気をつけると良いです。
- 必要な範囲でのみエラーハンドリングを使う
・Resume Next
の使用は最小限にすること。
・意図しない挙動を見逃す。 - エラー後はリソースを解放する
・開いたファイルは閉じる
・DB接続を開いたら閉じる - ユーザーに分かりやすいメッセージを提示する
・例:「売上データのファイルが見つかりません。フォルダを確認してください。」
5. そもそもエラーハンドリングをしないようにする
「存在しません」系のエラーは、そもそも存在確認をしておけばエラーハンドリングは不要です。
Sub ファイルを開く()
Dim fPath As String
fPath = "C:\Test\data.xlsx"
' 存在確認
If Dir(fPath) = "" Then
MsgBox "ファイルが存在しません: " & fPath
Exit Sub
End If
' 存在するので開く
Workbooks.Open fPath
End Sub
上記はファイルの例ですが、シートの存在確認などでも使えます。
まとめ
本記事ではエラーハンドリングの基本を解説してきました。
実務で使う内容としては本記事で大体網羅できているので、ぜひ全て使いこなせるように頑張ってみてください!
次回は「デバッグ術:ブレークポイント設定・ウォッチウインドウ活用法」で、実際にエラー箇所を効率的に特定するテクニックを解説予定です。
コメント