この記事でできること
「100件処理するマクロが38件目で止まった。残り62件は手作業でやり直し…」 こんな経験はないだろうか。この記事のエラー処理コードを追加すれば、エラーがあっても処理が最後まで走り、原因はログシートに自動記録される。On ErrorとErr.Numberの2つを覚えるだけなので、VBA初心者でもすぐ実装できる。
- VBAマクロがエラーで途中停止しなくなる(On Error Resume Next)
- エラーの内容(番号・説明・対象データ)をログシートに自動記録できる(On Error GoTo)
- 「止まらない」と「原因を追跡できる」を両立した実務向けマクロが作れる
対象: Excel 2016以降 / Microsoft 365、Windows 10/11
—
完成イメージ(Before / After)
Before(エラー処理なし):
- 100件のファイルを処理するマクロを実行
- 38件目でファイル名ミスのエラーが発生
- 「実行時エラー ’53’: ファイルが見つかりません」で停止
- 残り62件は未処理のまま
- 原因を直して1件目からやり直し(処理済み37件も再実行)
After(エラー処理あり):
- 100件のファイルを処理するマクロを実行
- 38件目でエラーが発生 → ログシートに自動記録
- 39件目から処理を継続
- 100件すべて完了後、「処理完了: 99件成功 / 1件エラー」と表示
- ログシートでエラー箇所を確認し、38件目だけ手動で対応
—
自分も以前、100件のファイルを処理するマクロを作ったことがある。テストでは問題なく動いた。だが本番で実行したら、38件目で止まった。ファイル名が1件だけ全角スペース入りだった。残り62件は未処理。しかも処理済みの37件をもう一度やり直す羽目になった。合計1時間のロス。
On Error GoToでエラーをログに記録し、処理を続行する仕組みにしてからは、100件中1件エラーがあっても残り99件は最後まで走る。翌朝ログを見て、エラーの1件だけ手動で直せばいい。「止まらないマクロ」は、自分だけでなく同僚にも安心して渡せる。
—
どんな場面で使う?
- 100件のファイルを処理するマクロで、1件のエラーで全体が止まるのを防ぎたい
- 同僚に渡すマクロが途中で止まって「壊れた?」と問い合わせが来るのをなくしたい
- エラーが起きたファイルだけログに記録して、残りは最後まで処理を続けたい
Application.ScreenUpdating = Falseのまま止まって画面が固まる事故を防ぎたい
—
マクロが途中で止まって、画面更新がオフのまま固まった経験がある。上司の前でフリーズして焦った。Application.ScreenUpdating = False を設定した後にエラーで止まると、画面が真っ白のまま操作不能になる(画面更新の制御については 画面更新・再計算を止めてマクロを高速化する方法 を参照)。On Errorを覚えてからは、エラーが出てもログを吐いて安全に止まるマクロが書けるようになった。
マクロが止まるたびに「VBAは怖い」と思っている人に、この記事で「止まらないマクロ」を体験してほしい。
エラー処理は「保険」。事故が起きてから入るのではなく、最初から組み込むもの。
なお、マクロをボタンに割り当てれば毎回Alt+F8を押す手間がなくなる。方法は マクロをボタン1つで実行する方法 を参照。ファイル処理系マクロを作る前には 指定フォルダのファイルを自動バックアップする方法 でバックアップを取っておくと安心。
—
実行前の準備
エラー処理の2つの方式を理解する
VBAのエラー処理には大きく2つの方式がある。
| 方式 | 書き方 | 用途 |
|---|---|---|
| スキップ方式 | On Error Resume Next |
1行だけエラーを無視したいとき |
| ジャンプ方式 | On Error GoTo ラベル |
エラー内容を記録・分岐したいとき |
この記事では、最小版で「スキップ方式」、実務版で「ジャンプ方式 + エラーログ記録」を紹介する。
Excelをマクロ有効ブック(.xlsm)で保存する
拡張子が .xlsx のままだとマクロが保存できない。
- 「ファイル」→「名前を付けて保存」
- ファイルの種類を「Excelマクロ有効ブック (*.xlsm)」に変更
- 保存
—
手順(コピペ → 実行まで約5分)
VBE(コードを書く画面)を開く
- Excelで
Alt + F11を押す - VBE(Visual Basic Editor)が開く
標準モジュールを挿入する
- VBEのメニュー →「挿入」→「標準モジュール」
- 白い画面(コードウィンドウ)が表示される
コードを貼り付けて実行する
- コードウィンドウに、下のコードをそのままコピペする
Alt + F8→ マクロ名を選んで「実行」
ボタンに割り当てれば毎回Alt+F8を押さなくて済む。方法は マクロをボタン1つで実行する方法 を参照。
—
コード(最小版)– On Error Resume Next で単一処理のエラーをスキップ
'============================================================
' ■ エラー処理(最小版)
' → On Error Resume Next で1行だけエラーをスキップ
' → 存在しないシートを安全に取得する例
'============================================================
Sub ErrorHandlingMinimal()
'--- ★書き換えポイント ---
Dim targetSheetName As String
targetSheetName = "集計" '← 取得したいシート名
'--- ★ここまで ---
Dim ws As Worksheet
'--- エラーを一時的にスキップする
On Error Resume Next
Set ws = ThisWorkbook.Worksheets(targetSheetName)
On Error GoTo 0 '← ★必ず解除する
'--- エラーが起きたかどうかを判定
If ws Is Nothing Then
MsgBox "シート「" & targetSheetName & "」が見つかりません。" & vbCrLf & _
"シート名を確認してください。", vbExclamation
Exit Sub
End If
'--- シートが見つかった場合の処理
MsgBox "シート「" & ws.Name & "」を取得しました。" & vbCrLf & _
"データ範囲: A1:" & ws.Cells(ws.Rows.Count, 1).End(xlUp).Address, vbInformation
End Sub
書き換えポイント
| 変数 | 説明 | 初期値 |
|---|---|---|
targetSheetName |
取得したいシート名 | "集計" |
コードの流れ
On Error Resume Nextでエラースキップを有効化Set ws = ThisWorkbook.Worksheets(targetSheetName)でシートを取得(存在しなければエラー → スキップされて ws は Nothing のまま)On Error GoTo 0でエラースキップを必ず解除If ws Is Nothingでシートが取得できたかを判定- 取得できなければメッセージを出して終了
重要: On Error Resume Next の後には必ず On Error GoTo 0 を書いて解除する。解除しないと、以降のすべてのエラーが無視されてしまう。この「解除忘れ」がResume Nextで一番多い事故の原因。
—
コード(実務版)– On Error GoTo + Err.Number + エラーログ記録
実務では「止まらない」だけでなく「なぜエラーが起きたかを後から追跡できる」ことが重要。エラーの内容をログシートに自動記録する実務版。
自分自身、以前はResume Nextをコード全体に入れて「止まらないマクロ」を作った気になっていた。だが翌月の集計で数値が合わない。調べてみると、Resume Nextでエラーが握りつぶされて、10件ほどデータが処理されていなかった。原因調査に丸1日かかった。それ以来、Resume Nextは「1行だけ」に限定し、実務では必ずOn Error GoTo + ログ記録を使うようにしている。
エラーログを仕込んでおけば、ファイル統合(複数Excelファイルを1つに統合)やPDF一括変換(ExcelファイルをPDFに一括変換)のようにファイル数が多い処理でも安心して実行できる。処理の進捗をステータスバーに表示する方法は ステータスバーで処理の進捗を表示する方法 も参考にしてほしい。
'============================================================
' ■ エラー処理(実務版)
' → On Error GoTo でエラーをキャッチし、ログシートに自動記録
' → 複数シートを一括処理し、エラーがあっても最後まで実行
'============================================================
Sub ErrorHandlingAdvanced()
'--- ★書き換えポイント ---
Dim logSheetName As String
logSheetName = "ErrorLog" '← エラーログを記録するシート名
'--- ★ここまで ---
'--- ログシートを準備(なければ自動作成)
Dim wsLog As Worksheet
On Error Resume Next
Set wsLog = ThisWorkbook.Worksheets(logSheetName)
On Error GoTo 0
If wsLog Is Nothing Then
Set wsLog = ThisWorkbook.Worksheets.Add(After:=ThisWorkbook.Worksheets(ThisWorkbook.Worksheets.Count))
wsLog.Name = logSheetName
'--- ヘッダー行を作成
wsLog.Range("A1").Value = "日時"
wsLog.Range("B1").Value = "マクロ名"
wsLog.Range("C1").Value = "エラー番号"
wsLog.Range("D1").Value = "エラー内容"
wsLog.Range("E1").Value = "対象データ"
wsLog.Rows(1).Font.Bold = True
End If
'--- 処理カウンター
Dim successCount As Long
Dim errorCount As Long
successCount = 0
errorCount = 0
'--- 全シートを一括処理(ErrorLogシートは除く)
Dim ws As Worksheet
For Each ws In ThisWorkbook.Worksheets
'--- ログシート自身はスキップ
If ws.Name = logSheetName Then GoTo NextSheet
'--- ★ここからエラーハンドリング開始 ---
On Error GoTo ErrHandler
'--- シートのA列最終行を取得
Dim lastRow As Long
lastRow = ws.Cells(ws.Rows.Count, 1).End(xlUp).Row
'--- B列に「処理済み」スタンプを押す(例)
Dim i As Long
For i = 2 To lastRow
'--- A列の値を数値に変換してB列に記録
ws.Cells(i, 2).Value = CDbl(ws.Cells(i, 1).Value) * 1.1
Next i
successCount = successCount + 1
GoTo NextSheet
ErrHandler:
'--- エラー情報をログシートに記録
Dim logRow As Long
logRow = wsLog.Cells(wsLog.Rows.Count, 1).End(xlUp).Row + 1
wsLog.Cells(logRow, 1).Value = Now '日時
wsLog.Cells(logRow, 2).Value = "ErrorHandlingAdvanced" ' マクロ名
wsLog.Cells(logRow, 3).Value = Err.Number 'エラー番号
wsLog.Cells(logRow, 4).Value = Err.Description 'エラー内容
wsLog.Cells(logRow, 5).Value = "シート: " & ws.Name & " / 行: " & i '対象データ
errorCount = errorCount + 1
Err.Clear
Resume NextSheet '← 次のシートに進む
NextSheet:
On Error GoTo 0 '← エラー処理をリセット
Next ws
'--- 完了メッセージ
Dim msg As String
msg = "処理完了" & vbCrLf & _
"成功: " & successCount & " シート" & vbCrLf & _
"エラー: " & errorCount & " シート"
If errorCount > 0 Then
msg = msg & vbCrLf & vbCrLf & _
"エラー詳細は「" & logSheetName & "」シートを確認してください。"
End If
MsgBox msg, vbInformation
End Sub
書き換えポイント
| 変数 | 説明 | 初期値 |
|---|---|---|
logSheetName |
エラーログを記録するシート名 | "ErrorLog" |
コードの流れ
- ログシート準備:
ErrorLogシートが存在しなければ自動作成し、ヘッダー行を追加 - 全シートをループ:
For Each ws In ThisWorkbook.Worksheetsで全シートを処理 - エラーハンドリング開始:
On Error GoTo ErrHandlerでエラー発生時にジャンプ先を指定 - 正常処理: A列の値を1.1倍にしてB列に記録(これは例。実務に合わせて書き換える)
- エラー時:
ErrHandlerラベルにジャンプし、Err.Number / Err.Description をログシートに記録 - 次のシートへ:
Resume NextSheetで次のシートの処理に進む - 完了メッセージ: 成功件数とエラー件数を表示
エラーログの記録があれば、翌朝出社して「何件エラーがあったか」「どのシートのどの行か」がすぐ分かる。複数シートの一括処理については 複数シートを一括処理する方法 を参照。
—
よくある落とし穴5選
1. On Error Resume Next を解除し忘れて全エラーが無視される
原因: On Error Resume Next の後に On Error GoTo 0 を書き忘れると、以降のコード全体でエラーが無視される。
自分もこれでハマった。Resume Nextを1行だけのつもりで書いたが、GoTo 0を入れ忘れた。その結果、シート名のスペルミスも、セル範囲の指定ミスも、全部スルーされた。データがおかしいことに気づいたのは3日後だった。
対策: On Error Resume Next を書いたら、すぐ次の行か数行後に On Error GoTo 0 を書く。この2つは必ずセットで使う。
2. Exit Sub を忘れてエラーハンドラが正常時も実行される
原因: On Error GoTo ErrHandler の構文で、エラーハンドラのラベル(ErrHandler:)の手前に Exit Sub がないと、正常終了時もエラーハンドラのコードが実行されてしまう。
対策: 以下の構文を必ず守る。
Sub Sample()
On Error GoTo ErrHandler
' 正常処理
Exit Sub '← ★これが必須
ErrHandler:
' エラー処理
End Sub
3. Resume Next の入れすぎでエラーが握りつぶされる
原因: コード全体を On Error Resume Next で囲むと、本来検知すべきエラーもすべてスキップされる。データが欠損しても気づけない。
自分の失敗談だが、以前100件のデータ処理でコード冒頭に On Error Resume Next を書いた。止まらなくなったのは良かったが、翌月の集計で数値が合わない。調べたら10件分のデータが処理されていなかった。Resume Nextでエラーがスキップされ、データが書き込まれていなかったのが原因。原因調査に丸1日かかった。
対策: Resume Nextは「1行だけ」に限定する。複数行の処理には On Error GoTo を使い、エラーをログに記録する。
4. Err.Clear を呼ばずにエラー情報が残ったまま次の処理に進む
原因: On Error Resume Next でエラーをスキップした後、Err.Number を確認せずに次の処理に進むと、前のエラー情報が残ったままになる。
対策: エラーチェック後は Err.Clear で明示的にクリアする。または On Error GoTo 0 でリセットする(GoTo 0 はErr情報もクリアされる)。
5. エラーハンドラ内でさらにエラーが発生して止まる
原因: On Error GoTo ErrHandler のエラーハンドラ内でエラーが発生すると、二重エラーで強制停止する。たとえば、ログシートへの書き込み自体がエラーになるケース。
自分もこれを経験した。ログシートが保護されていたのを忘れていて、エラーハンドラ内でさらにエラーが発生。「エラー処理を入れたのにエラーで止まる」という皮肉な状況になった。
対策: エラーハンドラ内の処理は極力シンプルにする。ログ書き込みの前に On Error Resume Next を入れる方法もあるが、エラーハンドラが複雑になるのは設計の問題。エラーの原因を効率よく特定するには VBAのデバッグ技術を使いこなす方法 のブレークポイントやウォッチ式も活用してほしい。
VBAのOn Error GoToでエラーハンドラに飛ばないときの対処法
「On Error GoToを書いたのにエラーでマクロが止まる」という場合、原因はエラーハンドラの中で再びエラーが発生する「二重エラー」だ。エラーハンドラ内の処理はログ書き込み程度に留め、複雑な処理は入れないこと。ログシートが保護されていないかも確認するとよい。
VBAでResume Nextを使ったらエラーが無視されすぎるときの対処法
「処理は最後まで走るが結果がおかしい」という場合、原因は On Error Resume Next がエラーを黙って無視し続けていることだ。Resume Nextは1行のチェック処理(ファイル存在確認など)だけに使い、すぐに On Error GoTo 0 でリセットすること。長い処理には On Error GoTo ラベル 方式を使うのが安全だ。
—
FAQ
Q1: On Error Resume Next と On Error GoTo はどう使い分ける?
| 場面 | 方式 | 理由 |
|---|---|---|
| ファイル・シートの存在確認(1行) | Resume Next |
結果をIf文で判定できる |
| ループ内の複数行処理 | GoTo ラベル |
エラー内容を記録して続行できる |
| 処理全体のセーフティネット | GoTo ラベル |
想定外エラーをキャッチできる |
Q2: Err.Number でよく使う番号は?
| 番号 | 説明 | よくある原因 |
|---|---|---|
| 9 | インデックスが有効範囲にない | 存在しないシート名 |
| 13 | 型が一致しない | 文字列を数値変換 |
| 53 | ファイルが見つからない | パスの間違い |
| 70 | 書き込みできない | ファイルが開かれている |
| 1004 | アプリケーション定義エラー | シート保護、範囲外 |
Q3: エラーログをファイルに出力したい
シートではなくテキストファイルに出力することも可能。
Dim f As Integer
f = FreeFile
Open "C:\log\error_log.txt" For Append As #f
Print #f, Now & vbTab & Err.Number & vbTab & Err.Description
Close #f
ファイル出力の基本は フォルダ内ファイル一覧を自動取得 でDir関数を使ったファイル操作を解説している。
Q4: マクロを人に渡すとき、エラー処理は必須?
必須ではないが、強く推奨する。エラー処理なしのマクロは、自分の環境でしかテストされていない。別の人のPCでは、ファイルパスが違う、シート名が違う、データ型が違うなど、想定外のエラーが頻発する。エラー処理を入れておけば「止まっても原因が分かる」マクロになる。渡す前に MsgBoxで確認ダイアログを出して処理を分岐する方法 で安全確認のダイアログを付けておくとさらに安心。
Q5: On Error GoTo -1 は何をするもの?
On Error GoTo -1 は、エラー処理状態をリセットする。通常は On Error GoTo 0 で十分だが、エラーハンドラ内でさらに別の On Error GoTo を使いたい場合に必要になる。初心者のうちは On Error GoTo 0 だけ覚えておけば問題ない。
—
まとめ
On Error Resume Nextは「1行だけ」のエラースキップに使う(最小版)On Error GoTo ラベル+Err.Number+ ログ記録で「止まらない+原因追跡」を両立(実務版)On Error GoTo 0での解除を忘れると、全エラーが握りつぶされる- エラー処理は「保険」。マクロを人に渡す前に必ず入れる
関連記事
- エラー処理の応用パターン(リトライ・ログ・通知)を実装する方法 — リトライや通知などエラー処理の発展形
- VBAのデバッグ技術を使いこなす方法 — エラーの原因を素早く特定するデバッグ技術
- 複数Excelファイルを1つに統合 — ファイル統合時にエラー処理を組み合わせると安心
- ExcelファイルをPDFに一括変換 — PDF変換で開けないファイルがあってもスキップ可能
- 古いファイルを自動削除 — 削除処理のエラー(ファイルが開かれている等)を安全に処理
—
次にやりたくなること
- エラー処理の応用パターン(リトライ・ログ・通知)を実装する方法 — リトライ処理やメール通知など、エラー処理をさらに実務レベルに引き上げたい場合に
- VBAのデバッグ技術を使いこなす方法 — エラーの原因特定を効率化するブレークポイント・ステップ実行・ウォッチ式の使い方
- 複数Excelファイルを1つに統合 — ファイル統合にエラー処理を組み合わせると、開けないファイルがあってもスキップして最後まで完了する
- ExcelファイルをPDFに一括変換 — PDF変換でもエラー処理は必須。壊れたファイルをスキップして残りを処理できる
- ステータスバーで処理の進捗を表示する方法 — エラー処理+進捗表示で「止まらない+今どこまで進んだか分かる」マクロの完成形
—
エラー処理を入れたマクロは、安心して人に渡せる。まずは最小版で「止まらないマクロ」を体験してみてほしい。


コメント