On Error Resume Nextを冒頭に1行書くだけで、関税計算マクロがデータを無言で上書きして復元不能になります。
VBAマクロを使い続けていると、避けられない壁にぶつかります。それが「実行時エラー」です。コードそのものに文法上の誤りがなくても、実行中に条件が合わなければマクロは突然止まります。
関税計算や輸入データの整理など、Excelマクロで業務自動化をしている場面を想像してみてください。何百行もある輸入品リストを処理している最中にマクロが止まると、どこまで処理が完了したのかも分からないまま作業が宙に浮いてしまいます。これが実務での大きなロスになります。
VBAのエラーは、大きく分けると3種類あります。
- コンパイルエラー:コードの文法が間違っている(例:変数名のスペルミス、End If の書き忘れ)。マクロを実行する前に検出されます。
- 実行時エラー:コードの文法は正しくても、実行中に処理できない状況が発生する(例:存在しないシートを参照する、数値以外の文字列を数値として計算しようとする)。マクロが動き出してから初めて発覚します。
- 論理エラー:エラーメッセージは出ないが、計算結果や処理内容が意図と異なる。もっとも発見しにくいタイプです。
実行時エラーが発生すると、VBAは処理をその行で停止し、「実行時エラー '11': ゼロ除算が行われました」のようなメッセージを表示します。エラー処理が必要なのは、主にこの「実行時エラー」への対応です。
エラーが発生しない完璧なコードを書ければ理想的ですが、実際の業務では「特定のシートが存在しない場合」「入力値が数値でない場合」「ファイルが開けない場合」など、想定外のケースが必ず生じます。そのような状況でもマクロを安全に動かし続けるために、エラー処理の構文を覚えることは必須です。
マクロがエラーで止まる原因は1000種類以上存在し、Microsoftの公式ドキュメントには実行時にトラップ可能なエラー番号が体系的に掲載されています。よく出会う番号としては、エラー番号9(インデックスが有効範囲にありません)、エラー番号13(型が一致しません)、エラー番号1004(RangeクラスのSelectメソッドが失敗しました)などが挙げられます。エラーが発生したときは番号をメモして調べる習慣をつけると、素早く原因にたどり着けます。
実行時にトラップ可能なエラー番号一覧と対処(エクセルの神髄)
VBAのエラー処理は、たった3つの構文で成り立っています。これが基本です。それぞれの役割を正確に理解することが、安定したマクロ作成の土台になります。
① On Error GoTo ラベル名
エラーが発生したとき、指定したラベルの行にジャンプして処理を続行する構文です。最も正統派のエラーハンドリングで、エラーの内容を確認しながら適切な対応ができます。
```vb
Sub ImportDataProcess()
On Error GoTo ErrorHandler
' 輸入データの処理
Dim ws As Worksheet
Set ws = Worksheets("輸入明細")
ws.Range("A1").Value = "処理完了"
Exit Sub ' ← 正常終了時はここで抜ける(必須)
ErrorHandler:
MsgBox "エラーが発生しました。" & vbCrLf & _
"エラー番号: " & Err.Number & vbCrLf & _
"内容: " & Err.Description
End Sub
```
`Exit Sub` を `ErrorHandler:` ラベルの直前に書くことが必須です。これを忘れると、正常終了のときでもエラーハンドラーが実行されてしまいます。意外と見落とされがちな落とし穴です。
② On Error Resume Next
エラーが発生しても、そのエラーを無視して次の行へ進む構文です。一見便利ですが、誤用すると「処理がスキップされたのに気づかない」という深刻な状態になります。詳しくは次の見出しで解説します。
③ On Error GoTo 0
エラー処理を「無効化」して、VBAの標準のエラー処理に戻すリセットスイッチです。`On Error Resume Next` や `On Error GoTo ラベル` を使った後に、その範囲限定で使いたい場面でよく登場します。
```vb
Sub SafeCheck()
On Error Resume Next
Set ws = Sheets("存在しないシート")
On Error GoTo 0 ' ← ここでエラー処理を無効化(リセット)
If ws Is Nothing Then
MsgBox "シートが見つかりません"
Exit Sub
End If
End Sub
```
この3つのルールは一度覚えれば一生使えます。構文を混在させるときは、`On Error GoTo 0` で都度リセットする習慣をつけると安全です。
On Errorステートメントの公式リファレンス(Microsoft Learn)
「On Error Resume Next をコードの冒頭に1行書けば、マクロが止まらなくなる」という認識は、実務では大きなリスクになります。これが最も危険な誤解です。
たとえば次のコードを見てください。
```vb
Sub BadExample()
On Error Resume Next ' ← ここで全エラー無視が有効になる
Dim ws As Worksheet
Set ws = Sheets("関税計算シート") ' シートが存在しない → ws = Nothing
ws.Range("A1").Value = "OK" ' Nothingに対して操作 → 何も起こらない
' 「関税計算シート」が存在しないのに、マクロは正常終了したように見える
End Sub
```
このマクロを実行すると、エラーメッセージは出ません。マクロは「正常終了」したように見えます。しかし実際には、`ws` が `Nothing` の状態で `ws.Range("A1").Value = "OK"` を実行しようとし、処理がスキップされています。データは書き込まれていません。
問題は「何も起きなかった」ではなく「何が起きたか分からない」という点です。ログにも記録されず、エラーダイアログも出ない。気づいたときには取り返しのつかない状態になっていることがあります。
正しい使い方は「特定の1処理だけを対象にして、直後にすぐ `On Error GoTo 0` でリセットする」形です。
```vb
Sub GoodExample()
Dim ws As Worksheet
' シートの存在確認のためだけにOn Error Resume Nextを使う
On Error Resume Next
Set ws = Sheets("関税計算シート")
On Error GoTo 0 ' ← 即リセット
' 存在チェックを行う
If ws Is Nothing Then
MsgBox "「関税計算シート」が見つかりません。処理を中断します。"
Exit Sub
End If
ws.Range("A1").Value = "OK"
MsgBox "書き込み完了しました。"
End Sub
```
この書き方なら、エラーを無視する範囲は `Set ws = Sheets("関税計算シート")` の1行だけです。その後は正常なエラー検知が働きます。これが原則です。
`On Error Resume Next` は「シートや変数が存在するかどうかを確認したいとき」など、エラーが起きることを事前に想定して許容する場面でのみ使うのが正しい使い方です。マクロ全体に使うのではなく、ピンポイントで使うと覚えておけば大丈夫です。
On Error Resume Nextの落とし穴と安全な使い方(jimove.biz)
エラーが発生したとき、「何のエラーか」を把握するための仕組みがErrオブジェクトです。VBAのエラー処理を実務レベルに持ち込むには、このオブジェクトの使い方が核心になります。
Errオブジェクトの主要なプロパティとメソッドは以下の通りです。
| プロパティ/メソッド | 内容 |
|---|---|
| `Err.Number` | エラーを識別する番号。正常時は0。エラー時は1以上の数値 |
| `Err.Description` | エラー内容の説明文(日本語で表示) |
| `Err.Source` | エラーが発生したオブジェクトやアプリケーションの名前 |
| `Err.Clear` | Errオブジェクトの情報を手動でリセット |
| `Err.Raise` | 意図的にエラーを発生させる(カスタムエラーの作成に使用) |
エラー番号ごとに処理を分けたい場合は、`Select Case` と組み合わせるのが定番のパターンです。たとえば、輸入データを処理するマクロで「シートが見つからない(エラー番号9)」「型が一致しない(エラー番号13)」を個別に対応するには次のように書きます。
```vb
Sub ImportProcess()
On Error GoTo ErrorHandler
Dim ws As Worksheet
Set ws = Worksheets("輸入データ")
Dim rate As Double
rate = ws.Range("B2").Value ' 数値でない値が入っていると型エラー
MsgBox "関税率: " & rate & "%"
Exit Sub
ErrorHandler:
Select Case Err.Number
Case 9
MsgBox "「輸入データ」シートが見つかりません。" & vbCrLf & _
"シート名を確認してください。"
Case 13
MsgBox "B2セルに数値以外の値が入っています。" & vbCrLf & _
"関税率を数値で入力し直してください。"
Case Else
MsgBox "予期しないエラーが発生しました。" & vbCrLf & _
"エラー番号: " & Err.Number & vbCrLf & _
Err.Description
End Select
Err.Clear ' エラー情報をリセット
End Sub
```
このように書くと、エラーが発生したときに「何が起きているのか」がユーザーに伝わるメッセージが表示されます。これは使えそうです。
`Err.Clear` は `On Error GoTo 0` を実行したり、次の `On Error` ステートメントを実行したりすると自動でリセットされますが、明示的に `Err.Clear` を書く習慣をつけると、コードの意図が読み取りやすくなります。特に複数のエラーチェックを連続して行う場面では必須です。
なお、`Err.Raise` を使うとカスタムエラーを意図的に発生させることもできます。システム定義のエラー番号(1〜65535)との衝突を避けるため、独自エラーには100000以上の番号を使うのが業界的な慣習です。管理が楽になります。
Errオブジェクトの公式リファレンス(Microsoft Learn)
一般的なVBAのエラー処理解説では語られない、実務視点のテクニックがあります。それが「エラーログをExcelシートに自動記録する」という手法です。
通常、エラーハンドラーでは `MsgBox` を使ってユーザーにメッセージを表示しますが、業務マクロでは「いつ」「どの処理で」「どんなエラーが起きたか」を記録しておくことが重要です。これはマクロを他の人が使う場面や、翌日以降に問題を振り返る場面で特に威力を発揮します。
```vb
Sub LogError(errNum As Long, errDesc As String, procName As String)
Dim logWs As Worksheet
Dim lastRow As Long
' ログシートが存在しない場合は作成
On Error Resume Next
Set logWs = Worksheets("エラーログ")
On Error GoTo 0
If logWs Is Nothing Then
Set logWs = Worksheets.Add
logWs.Name = "エラーログ"
logWs.Range("A1:D1").Value = Array("発生日時", "プロシージャ名", "エラー番号", "エラー内容")
End If
lastRow = logWs.Cells(Rows.Count, 1).End(xlUp).Row + 1
logWs.Cells(lastRow, 1).Value = Now()
logWs.Cells(lastRow, 2).Value = procName
logWs.Cells(lastRow, 3).Value = errNum
logWs.Cells(lastRow, 4).Value = errDesc
End Sub
```
このサブプロシージャを用意しておき、エラーハンドラーの中から呼び出す形にすれば、エラーが発生するたびに「エラーログ」シートに日時・場所・内容が自動記録されます。
呼び出し側はこのように書きます。
```vb
ErrorHandler:
Call LogError(Err.Number, Err.Description, "ImportProcess")
MsgBox "エラーが発生しました。エラーログシートを確認してください。"
Err.Clear
```
このアプローチのメリットは3点あります。まずエラーの再現性を追跡しやすくなる点、次に複数人でマクロを使う環境でも誰がどの場面でエラーに遭遇したかが分かる点、そして「エラーが出て止まった」という感覚的な記憶ではなく、具体的な番号と日時で振り返れる点です。
関税計算や輸入データ処理のようにデータの正確性が求められる業務では、「エラーが出たが何も記録されていない」という状況は致命的になりかねません。ログ記録は地味ですが、長期運用するマクロには欠かせない要素です。
また、Excelのシートに記録する代わりに、`Open` ステートメントを使ってテキストファイル(`.txt` や `.log`)にログを書き出す方法もあります。複数のExcelブックを横断して処理するマクロでは、単一のログファイルに記録する形が管理しやすくなります。
エラーログの仕組みを作ることそのものが、業務マクロの品質を一段上げるアプローチです。
VBAエラーハンドリングのベストプラクティス(cfxlog.com)