イントロダクション
第16回から続けてきたエラー処理編も、今回が最終回である。これまでの3回では、エラーが「起きた後」にどう対処するかを学んできた。
- 第16回:
On Error GoToで捕まえ、Errオブジェクトで原因を知る - 第17回:
On Error Resume Nextで無視し、Resumeでやり直す - 第18回:
Err.Raiseで伝え、後始末を1か所にまとめる
今回はその一歩手前、「そもそもエラーを起こさない」ための事前チェックを取り上げる。エラー処理と事前チェックは対になる考え方であり、両方を使い分けられるようになると、マクロがぐっと安定する。
事前チェックとエラー処理、どちらを使うか
まず、この2つの違いを整理しておこう。
- 事前チェック:処理を実行する前に、条件を
Ifで確認し、問題があれば手前で止める - エラー処理:処理を実行してみて、失敗したら
On Errorで対処する
「入力された値が数値かどうか」のように、チェックする方法が用意されている場合は、事前チェックのほうが分かりやすい。一方、「ファイルを開けるかどうか」のように、実際にやってみないとわからない場合は、エラー処理に頼ることになる。
IsNumericで数値かどうかを事前に確認する
第16回では、InputBox に文字列を入れるとエラーになり、それをOn Errorで受け止めていた。これを、IsNumeric 関数を使った事前チェックに書き直してみよう。
Sub 割り算の計算_事前チェック版()
Dim 入力A As String
Dim 入力B As String
入力A = InputBox("割られる数を入力してください")
If Not IsNumeric(入力A) Then
MsgBox "数値を入力してください。", vbExclamation
Exit Sub
End If
入力B = InputBox("割る数を入力してください")
If Not IsNumeric(入力B) Then
MsgBox "数値を入力してください。", vbExclamation
Exit Sub
End If
If CDbl(入力B) = 0 Then
MsgBox "0で割ることはできません。", vbExclamation
Exit Sub
End If
MsgBox 入力A & " ÷ " & 入力B & " = " & CDbl(入力A) / CDbl(入力B)
End SubIsNumeric で文字列かどうかを判定し、= 0 で0かどうかを判定することで、On Error を使わずにエラーを未然に防いでいる。第16回のコードと見比べると、どちらも同じ場面に対応できることがわかるだろう。
事前チェック版のほうが、何を確認しているのかがコードを読むだけでわかるという利点がある。一方で、確認する項目が増えるほどIfが増えてしまうという面もある。
シート存在確認を事前チェックの形で書く
第17回では、On Error Resume Next を使ってシートの存在を確認した。実はこれは、For Each でシート一覧を調べることでも実現できる。
Function シートが存在する2(シート名 As String) As Boolean
Dim ws As Worksheet
For Each ws In ThisWorkbook.Worksheets
If ws.Name = シート名 Then
シートが存在する2 = True
Exit Function
End If
Next ws
シートが存在する2 = False
End FunctionこちらはOn Errorを一切使わず、シート名を順番に比較しているだけである。
動作は第17回の版と同じだが、仕組みがわかりやすいという良さがある。
シートの数が多い場合などは、実際の処理内容によって速度差が生じることもある。どちらが優れているというより、仕組みを理解しやすい書き方と、実務でよく使われる書き方の両方を知っておくことに意味がある。
事前チェックでは防ぎきれない場面
事前チェックは万能ではない。たとえば、次のようにファイルの存在をDir関数で確認してから開く場合を考えてみよう。
Sub ブックを開く_事前チェック版()
Dim パス As String
パス = "C:\test\データ.xlsx"
If Dir(パス) = "" Then
MsgBox "ファイルが見つかりません。", vbExclamation
Exit Sub
End If
Dim wb As Workbook
Set wb = Workbooks.Open(パス)
MsgBox wb.Name & " を開きました。"
End SubDirでファイルの存在を確認しても、その直後に他の人がファイルを削除したり、ファイルが壊れていたりすれば、Workbooks.Openは失敗しうる。事前チェックをすり抜けてくる失敗に備えて、事前チェックとエラー処理を組み合わせるのが、実務では現実的な選択になる。
Sub ブックを開く_組み合わせ版()
Dim パス As String
パス = "C:\test\データ.xlsx"
If Dir(パス) = "" Then
MsgBox "ファイルが見つかりません。", vbExclamation
Exit Sub
End If
On Error GoTo エラー処理
Dim wb As Workbook
Set wb = Workbooks.Open(パス)
MsgBox wb.Name & " を開きました。"
Exit Sub
エラー処理:
MsgBox "ファイルを開けませんでした。" & vbCrLf & Err.Description, vbExclamation
End Sub事前チェックで防げる失敗は手前で防ぎ、それでも起こりうる失敗はエラー処理で受け止める。
この二段構えが、安定したマクロの基本形である。
エラー処理編のまとめ
第16回から今回まで、4回にわたってエラー処理を学んできた。最後に、全体を振り返っておこう。
| 回 | テーマ | 主な内容 |
|---|---|---|
| 第16回 | 基本 | On Error GoTo、Err.Number、Err.Description |
| 第17回 | 無視とやり直し | On Error Resume Next、On Error GoTo 0、Err.Clear、Resume |
| 第18回 | 伝達と後始末 | Err.Raise、Resume ラベル名による後始末の一本化 |
| 第19回 | 事前チェック | IsNumeric、Dir、事前チェックとエラー処理の組み合わせ |
エラー処理は、覚えることが多く感じられるかもしれない。しかし考え方はシンプルで、「防げる失敗は事前チェックで防ぎ、防げない失敗はエラー処理で受け止め、後始末を忘れない」という一言に集約される。
これで、第12回から続いた「Function・引数・エラー処理」編がひと区切りとなる。
次回からは新しいテーマで、このシリーズを続けていく予定である。お楽しみに。


コメント