VBAの実行時エラーとは、マクロを実行している途中で処理を続けられなくなったときに、番号とメッセージつきで表示されるエラーです。 番号ごとに原因の型が決まっているので、番号から原因と直し方を引けるようにしておくと、調べる時間をぐっと短くできます。

この記事は、エラー番号から引くためのリファレンスです。前半で頻出23番号の早見表と、特によく出る10番号の「発生するコード」と「修正後のコード」を対で示します。後半では、On Error と Resume の各形式の違い、Err オブジェクトを使ったエラー処理の定型とログ出力をまとめます。

確認環境:エラー番号とメッセージ、原因と解決策、On Error・Resume・Err オブジェクトの仕様、コードで使っているステートメント・関数・メソッドの構文は、2026年10月5日に Microsoft Learn の VBA リファレンス(日本語版)の各ページを開いて確認した内容です。コードはその構文に沿って書いたもので、Excel の画面出力は掲載していません。

VBA実行時エラーの番号別早見表(頻出23番号)

メッセージは Microsoft Learn「トラップできるエラー」の一覧にある日本語の表記です。

番号 メッセージ よくある原因 直し方
5 プロシージャ呼び出しが正しくありません 関数に渡した引数が、許可される範囲を超えている 関数のリファレンスで引数の範囲を確かめ、範囲内の値を渡す
6 オーバーフローしました 代入・計算・型変換の結果が、変数の型で扱える範囲を超えた より広い範囲を持てる型(Long、Double など)にする。計算式は CLng で変換してから掛ける
7 メモリが不足しています 開いているアプリケーションやドキュメントが多い。モジュールやプロシージャが大きすぎる 不要なものを閉じる。モジュールやプロシージャを小さく分ける
9 インデックスが有効範囲にありません 存在しない配列の要素や、コレクションに無いメンバー(シート名など)を指定した LBound・UBound で範囲を確かめる。コレクションは For Each でたどる
11 0 で除算しました 割る数として使っている式の値がゼロ 変数名のつづりを確かめる。割る前にゼロかどうかを判定する
13 型が一致しません 数値型の変数に、数値として読めない文字列を入れた。値が必要な場所にオブジェクトを渡した 互換性のある型どうしで代入する。IsNumeric で確かめてから変換する
20 エラーが発生していないときに Resume を実行することはできません エラー処理ルーチンの外で Resume が実行された ラベルの直前に Exit Sub を置き、通常の流れでエラー処理ルーチンに入らないようにする
28 スタック領域が不足しています プロシージャの入れ子が深い。再帰呼び出しが終わらない。イベントが連鎖している 再帰の終了条件を確かめる。呼び出し履歴でイベントの連鎖を調べる
52 ファイル名または番号が正しくありません Open していない(または閉じた)ファイル番号を使った。ファイル名に使えない文字がある 先に Open で開く。ファイル番号は 1〜511 の範囲にする。ファイル名を見直す
53 ファイルが見つかりません Kill・Name・Open などが、存在しないファイルを指している ファイル名とパスのつづりを確かめる。Dir で有無を調べてから操作する
55 ファイルは既に開かれています 開いているファイルを別のモードで Open した。開いているファイルに Kill や Name を実行した 先に Close で閉じてから操作する
58 既に同名のファイルが存在しています Name で指定した新しいファイル名が、既存のファイルと同じ 別の名前を指定する。または既存のファイルを先に削除する
62 ファイルにこれ以上データがありません Input # や Line Input # で、読み終えたファイルや空のファイルを読もうとした 読む直前に EOF でファイルの終わりを確かめる
70 アクセス許可が拒否されました 書き込み禁止のファイルを Output や Append で開いた。別のプロセスがロックしているファイルに書こうとした Input で開く、書き込み禁止の属性を変える、ほかのプロセスが解放するのを待つ
75 パス名/ファイル名が無効です パスの形式が正しくない。読み取り専用ファイルを上書き・出力モードで開こうとした ドライブ名から始まるパスか、正しい相対パスにする。別名で保存する
76 パスが見つかりません Open・MkDir・ChDir・RmDir などで、指定したパスが見つからない ドライブとフォルダーの指定を見直す
91 オブジェクト変数または With ブロック変数が設定されていません Set で代入していない、または Nothing になっているオブジェクト変数を使った Set で有効なオブジェクトを代入する。使う前に Nothing かどうかを確かめる
94 Null の使い方が正しくありません Null が入った Variant を、有効な値が必要な場所で使った 使う前に Null かどうかを確かめる。初期値を入れておく
424 オブジェクトが必要です オブジェクト名のつづり違い。Set を付けずにオブジェクトを代入した つづりを確かめる。オブジェクトの代入には Set を付ける
438 オブジェクトは、このプロパティまたはメソッドをサポートしていません そのオブジェクトに無いプロパティやメソッドを指定した オブジェクトのリファレンスで、プロパティ名・メソッド名のつづりを確かめる
450 引数の数が一致していません。または無効なプロパティを指定しています 呼び出しの引数の数が宣言と合っていない。読み取り専用プロパティに値を入れた 宣言と引数リストを見比べる
457 このキーは既にこのコレクションの要素に割り当てられています コレクションの Add で、すでに使われているキーを指定した 重複しないキーを使う
1004 アプリケーション定義またはオブジェクト定義のエラーです Excel など VBA の外側で起きたエラーが、VBA の番号に対応づけられずに伝わってきた エラーが出た行で操作しているオブジェクト(セル範囲・シート・ブック)の指定を見直す

番号がわかったら、まず「どの行で止まったか」を確かめます。 エラーのダイアログで「デバッグ」を押すと、止まった行が黄色で示されます。その行に出てくる変数とオブジェクトを、上の表の原因と照らし合わせるのが近道です。

本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。

(記載例)出典:株式会社RJC「VBA実行時エラー一覧|1004・9・13・91の原因と対処」

よく出る10番号:発生するコードと修正後のコード

以降のコードは、標準モジュールに貼る前提です。シート名「注文」は架空の例です。

実行時エラー 1004:アプリケーション定義またはオブジェクト定義のエラー

Microsoft Learn では、このメッセージについて「ほかのアプリケーション(Microsoft Excel など)のオブジェクトにアクセスしたときに、VBA のエラーに対応づけられないエラーがプログラムに伝わることがある」と説明されています。つまり、Excel のオブジェクトに対する指定そのものを見直す番号です。代表例が、存在しないセル番地です。

発生するコード:

Sub Sample1004_Before()
    Dim r As Long
    r = 0
    ' 行番号 0 のセルは存在しないので、ここで 1004 になる
    Worksheets("注文").Range("A" & r).Value = "見出し"
End Sub

修正後のコード:

Sub Sample1004_After()
    Dim r As Long
    r = 0
    If r < 1 Then
        MsgBox "行番号が 1 未満です: " & r
        Exit Sub
    End If
    Worksheets("注文").Range("A" & r).Value = "見出し"
End Sub

1004 が出たときに確かめる点です。

確かめる点 見るところ
セル番地の文字列が正しいか "A" & r のように組み立てている場合は、変数の中身
対象のシートが意図したものか Worksheets("注文").Range(...) のようにシートを明示しているか
どのアプリケーションが出したエラーか Err.Source の値(Microsoft Learn で、発生元の確認方法として紹介)

実行時エラー 9:インデックスが有効範囲にありません

配列の範囲外の要素や、コレクションに無い名前を指定したときの番号です。Excel では、存在しないシート名の指定が典型です。

発生するコード:

Sub Sample9_Before()
    Dim items(1 To 3) As String
    ' 「集計」という名前のシートが無いと、ここで 9 になる
    Worksheets("集計").Range("A1").Value = "合計"
    ' 要素は 1〜3 なので、4 を指定すると 9 になる
    items(4) = "ノート"
End Sub

修正後のコード:

Sub Sample9_After()
    Dim items(1 To 3) As String
    Dim ws As Object
    Dim found As Boolean
    Dim i As Long

    ' コレクションは For Each でたどって有無を確かめる
    For Each ws In Worksheets
        If ws.Name = "集計" Then found = True
    Next ws
    If found Then
        Worksheets("集計").Range("A1").Value = "合計"
    Else
        MsgBox "「集計」シートがありません。"
    End If

    ' 配列は LBound と UBound の間だけを使う
    For i = LBound(items) To UBound(items)
        items(i) = "品名" & i
    Next i
End Sub

Microsoft Learn には、Dim MyArray() As Integer のように要素数を指定せずに宣言した配列へ、そのまま MyArray(8) = 234 と代入した場合もこの番号になる、と書かれています。Dim か ReDim で要素数を決めてから使います。

実行時エラー 13:型が一致しません

数値型の変数に、数値として読めない文字列を入れようとしたときの番号です。セルに「未定」のような文字が入っている表で起きやすくなります。

発生するコード:

Sub Sample13_Before()
    Dim amount As Long
    ' A2 に「未定」のような文字が入っていると、ここで 13 になる
    amount = Worksheets("注文").Range("A2").Value
    MsgBox amount * 2
End Sub

修正後のコード:

Sub Sample13_After()
    Dim amount As Long
    Dim v As Variant
    v = Worksheets("注文").Range("A2").Value
    If IsNumeric(v) Then
        amount = CLng(v)
        MsgBox amount * 2
    Else
        MsgBox "A2 が数値ではありません: " & v
    End If
End Sub

IsNumeric は、式が数値として評価できるときに True を返す関数です。セルの値はいったん Variant で受け、確かめてから型を変換すると、この番号を避けられます。

実行時エラー 91:オブジェクト変数または With ブロック変数が設定されていません

オブジェクト変数に有効なオブジェクトが入っていない(Nothing の)状態で、プロパティやメソッドを使ったときの番号です。Range.Find は、一致するデータが見つからなかった場合に Nothing を返すので、検索結果をそのまま使うコードでよく起きます。

発生するコード:

Sub Sample91_Before()
    Dim hit As Range
    Set hit = Worksheets("注文").Range("A:A").Find(What:="モニター")
    ' 見つからないと hit は Nothing なので、ここで 91 になる
    MsgBox hit.Row
End Sub

修正後のコード:

Sub Sample91_After()
    Dim hit As Range
    Set hit = Worksheets("注文").Range("A:A").Find(What:="モニター")
    If hit Is Nothing Then
        MsgBox "「モニター」は見つかりませんでした。"
    Else
        MsgBox hit.Row
    End If
End Sub

Dim で宣言しただけで Set していないオブジェクト変数も Nothing です。オブジェクト変数は「Set したか」「Nothing ではないか」の2点を確かめます。

実行時エラー 424:オブジェクトが必要です

オブジェクトではないものに対して、プロパティやメソッドを使おうとしたときの番号です。変数名のつづり違いと、Set の付け忘れが代表的な原因です。

発生するコード:

' モジュールの先頭に Option Explicit が無い場合
Sub Sample424_Before()
    Dim ws As Worksheet
    Set ws = Worksheets("注文")
    ' wss はつづり違い。宣言のない別の変数として扱われ、ここで 424 になる
    wss.Range("A1").Value = "見出し"
End Sub

修正後のコード:

Option Explicit

Sub Sample424_After()
    Dim ws As Worksheet
    Set ws = Worksheets("注文")
    ws.Range("A1").Value = "見出し"
End Sub

モジュールの先頭に Option Explicit を書いておくと、宣言していない変数名は実行前のコンパイルの段階で知らせてもらえます。

Set の付け忘れについては、Microsoft Learn に次の対の例が載っています。

' 発生するコード
Dim RetVal ' Implicitly a Variant.
RetVal = CreateObject("Excel.Application")
RetVal.Visible = True ' Error occurs here.

' 修正後のコード
Dim RetVal As Object
Set RetVal = CreateObject("Excel.Application")
RetVal.Visible = True

実行時エラー 438:オブジェクトは、このプロパティまたはメソッドをサポートしていません

オブジェクト自体は有効でも、そのオブジェクトに無いプロパティやメソッドを指定したときの番号です。

発生するコード:

Sub Sample438_Before()
    ' ワークシートに Value プロパティは無いので、ここで 438 になる
    Worksheets("注文").Value = "見出し"
End Sub

修正後のコード:

Sub Sample438_After()
    ' 値を持つのはセル範囲(Range)
    Worksheets("注文").Range("A1").Value = "見出し"
End Sub

424 との違いは次のとおりです。

番号 対象そのもの プロパティ・メソッド 見直す場所
424 オブジェクトではない ― ドットの左側(変数名、Set の有無)
438 有効なオブジェクト そのオブジェクトに無い ドットの右側(プロパティ名・メソッド名)

実行時エラー 6:オーバーフローしました

計算や代入の結果が、型の扱える範囲を超えたときの番号です。Microsoft Learn には、代入先が Long でも、計算に使う数値が整数として扱われて途中の結果があふれる例が載っています。

発生するコード(Microsoft Learn の例):

Dim x As Long
x = 2000 * 365   ' Error: Overflow

修正後のコード(Microsoft Learn の例):

Dim x As Long
x = CLng(2000) * 365

行番号や件数を入れる変数は、最初から Long で宣言しておくと安心です。

Sub Sample6_After()
    Dim rowCount As Long   ' Integer ではなく Long にする
    rowCount = 40000
    MsgBox rowCount
End Sub

実行時エラー 11:0 で除算しました

割る数がゼロのときの番号です。Microsoft Learn では、変数名のつづり違いによってゼロで初期化された別の変数が使われていないか、も確認点に挙げられています。

発生するコード:

Sub Sample11_Before()
    Dim total As Double
    Dim cnt As Long
    total = 12000
    cnt = 0
    ' cnt が 0 なので、ここで 11 になる
    MsgBox total / cnt
End Sub

修正後のコード:

Sub Sample11_After()
    Dim total As Double
    Dim cnt As Long
    total = 12000
    cnt = 0
    If cnt = 0 Then
        MsgBox "件数が 0 のため、平均は計算しません。"
    Else
        MsgBox total / cnt
    End If
End Sub

実行時エラー 53:ファイルが見つかりません

Kill・Name・Open などが、存在しないファイルを指しているときの番号です。

発生するコード:

Sub Sample53_Before()
    ' ファイルが無いと、ここで 53 になる
    Kill "C:\work\temp.csv"
End Sub

修正後のコード:

Sub Sample53_After()
    Dim filePath As String
    filePath = "C:\work\temp.csv"
    ' Dir は、見つからないとき長さ 0 の文字列を返す
    If Dir(filePath) <> "" Then
        Kill filePath
    Else
        MsgBox "ファイルがありません: " & filePath
    End If
End Sub

フォルダーごと見つからない場合は、76(パスが見つかりません)になります。

実行時エラー 70:アクセス許可が拒否されました

書き込み禁止のファイルを Output や Append で開こうとしたとき、または別のプロセスがロックしているファイルに書こうとしたときの番号です。事前の判定だけでは避けにくいので、エラー処理で受けて案内する形にします。

発生するコード:

Sub Sample70_Before()
    Dim fileNo As Integer
    fileNo = FreeFile
    ' 書き込み禁止のファイルや、ほかで開かれているファイルだと、ここで 70 になる
    Open "C:\work\report.txt" For Append As #fileNo
    Print #fileNo, "完了"
    Close #fileNo
End Sub

修正後のコード:

Sub Sample70_After()
    Dim fileNo As Integer
    On Error GoTo ErrHandler
    fileNo = FreeFile
    Open "C:\work\report.txt" For Append As #fileNo
    Print #fileNo, "完了"
    Close #fileNo
    Exit Sub
ErrHandler:
    Select Case Err.Number
        Case 70
            MsgBox "ファイルに書き込めません。読み取り専用になっていないか、ほかで開かれていないかを確かめてください。"
        Case Else
            MsgBox "番号: " & Err.Number & " " & Err.Description
    End Select
End Sub

読むだけでよい場合は、For Input で開けばこの番号を避けられます(Microsoft Learn の解決策)。

On Errorの3形式の違い

On Error は、エラーが起きたときの進み先を決めるステートメントです。Microsoft Learn には、On Error を使わない場合、発生する実行時エラーはすべて致命的となり、エラーメッセージが表示されて実行が停止する、と書かれています。

形式 動き 使いどころ
On Error GoTo ラベル 実行時エラーが起きると、指定した行ラベル(または行番号)のエラー処理ルーチンへ進む。ラベルは同じプロシージャ内に置く 基本形。後始末とメッセージ表示をまとめる
On Error Resume Next エラーが起きたステートメントの直後のステートメントから実行を続ける 「あるかどうか試す」短い区間。直後に Err.Number を確かめる
On Error GoTo 0 現在のプロシージャで有効になっているエラー処理を無効にする Resume Next の区間を終えるとき

On Error GoTo ラベルの基本形

Sub BasicHandler()
    On Error GoTo ErrHandler

    ' ここに本体の処理を書く
    Worksheets("注文").Range("A1").Value = "見出し"

    Exit Sub   ' 正常に終わったときは、ここで抜ける
ErrHandler:
    MsgBox "番号: " & Err.Number & " " & Err.Description
End Sub

ラベルの直前に Exit Sub(関数なら Exit Function)を置くのが決まりです。置かないと、エラーが起きていないときにもエラー処理ルーチンの行が実行されます。

On Error Resume Next は短い区間だけで使う

Function SheetExists(ByVal sheetName As String) As Boolean
    Dim ws As Object
    On Error Resume Next          ' ここから「試す」区間
    Set ws = ThisWorkbook.Worksheets(sheetName)
    On Error GoTo 0               ' 区間を終える
    SheetExists = Not ws Is Nothing
End Function

On Error Resume Next を書いたままにすると、そのあとのエラーもすべて素通りして、どこで問題が起きたかを追いにくくなります。試したい1〜2行を挟んで、すぐ On Error GoTo 0 で閉じる形にします。

知っておきたい On Error の決まり

Microsoft Learn の On Error ステートメントのページに書かれている内容です。

場面 動き
プロシージャが終了したとき On Error GoTo 0 を書いていなくても、エラー処理は自動的に無効になる
呼び出し先のプロシージャでエラーが起き、そこにエラー処理が無いとき 呼び出し元に有効なエラー処理があれば、それが使われる
エラー処理ルーチンの実行中に、さらにエラーが起きたとき そのプロシージャのエラー処理では受けられず、呼び出し元へ制御が渡る
On Error Resume Next のあとで別のプロシージャを呼んだとき 呼び出し先では効かない。呼び出し先でも必要なら、そこで改めて書く

Resumeの3形式の違い

Resume は、エラー処理ルーチンの中から本体の処理へ戻るためのステートメントです。On Error Resume Next と名前が似ていますが、役割が違います。

形式 戻る場所 使いどころ
Resume(Resume 0) エラーが起きたステートメント。同じ行をもう一度実行する 原因をエラー処理ルーチンの中で取り除けるとき(開いていたファイルを閉じる、など)
Resume Next エラーが起きたステートメントの直後のステートメント その行を飛ばして先へ進めてよいとき
Resume ラベル 指定した行ラベル(または行番号)。同じプロシージャ内に置く 後始末の処理へ進めて終わりたいとき

呼び出し先のプロシージャで起きたエラーを呼び出し元で受けた場合、Resume は「呼び出しを行ったステートメント」から、Resume Next は「その直後のステートメント」から再開します。

エラー処理ルーチン以外の場所で Resume を実行するとエラーになります(番号 20)。また、Resume は原因を取り除かないまま使うと同じ行でまたエラーになり、処理が繰り返されます。 再試行の回数に上限を付けておくと安心です。

Sub ResumeWithRetry()
    Dim fileNo As Integer
    Dim retryCount As Long
    On Error GoTo ErrHandler

    fileNo = FreeFile
    Open "C:\work\report.txt" For Append As #fileNo
    Print #fileNo, "完了"
    Close #fileNo
    Exit Sub

ErrHandler:
    If Err.Number = 70 And retryCount < 3 Then
        retryCount = retryCount + 1
        MsgBox "ファイルを閉じてから OK を押してください。(" & retryCount & " 回目)"
        Resume            ' Open の行をもう一度実行する
    End If
    MsgBox "番号: " & Err.Number & " " & Err.Description
End Sub

On Error と Resume の対応

やりたいこと エラーの受け方 戻り方
エラーをまとめて受け、メッセージを出して終わる On Error GoTo ラベル 戻らずに終了(End Sub へ進む)
後始末を必ず通してから終わる On Error GoTo ラベル Resume 後始末のラベル
原因を取り除いて同じ行をやり直す On Error GoTo ラベル Resume
その行だけ飛ばして続ける On Error GoTo ラベル Resume Next
試して、結果を自分で判定する On Error Resume Next Err.Number を確かめ、On Error GoTo 0 で閉じる

Errオブジェクトの使い方(Number・Description・Raise)

Err は、実行時エラーの情報を持つ組み込みのオブジェクトです。宣言や生成をせずにそのまま使えます。

メンバー 種類 内容
Err.Number プロパティ エラー番号(既定のプロパティ)。エラーが無いときは 0
Err.Description プロパティ エラーの説明文
Err.Source プロパティ エラーの発生元
Err.HelpFile・Err.HelpContext プロパティ ヘルプファイルのパスとトピックの番号
Err.Clear メソッド Err の内容を明示的にリセットする
Err.Raise メソッド 実行時エラーを発生させる

Err の内容がリセットされるタイミング

Microsoft Learn によると、Err のプロパティは、Exit Sub・Exit Function・Exit Property・Resume Next・エラー処理ルーチン内の Resume のあとで、ゼロまたは長さ 0 の文字列にリセットされます。

そのため、エラー処理ルーチンに入ったら、最初に番号と説明を変数へ写しておくと、あとの処理で値が変わる心配がなくなります。次の定型でもこの形にしています。

Err.Raise で独自のエラーを発生させる

構文は次のとおりです。number 以外は省略できます。

Err.Raise number, [source], [description], [helpfile], [helpcontext]

Microsoft Learn には、番号の範囲について次の説明があります。

範囲 用途
0〜512 システムエラー用に予約
513〜65535 ユーザー定義のエラーに使える
クラスモジュール内 vbObjectError に自分のエラー番号を足した値を使う

入力の確認で、独自のエラーを発生させる例です。

Option Explicit

Public Const ERR_NO_DATA As Long = vbObjectError + 513

Sub CheckInput()
    If Worksheets("注文").Range("A2").Value = "" Then
        Err.Raise Number:=ERR_NO_DATA, _
                  Source:="CheckInput", _
                  Description:="A2 が空です。データを貼り付けてから実行してください。"
    End If
End Sub

呼び出し元では、Err.Number で独自の番号かどうかを見分けられます。

Sub RunCheck()
    On Error GoTo ErrHandler
    CheckInput
    MsgBox "入力の確認が終わりました。"
    Exit Sub
ErrHandler:
    Select Case Err.Number
        Case ERR_NO_DATA
            MsgBox Err.Description
        Case Else
            MsgBox "番号: " & Err.Number & " " & Err.Description
    End Select
End Sub

エラー処理の定型とログ出力

ここまでの要素を1つにまとめた、コピーして使える形です。「後始末を必ず通す」「Err の内容を先に変数へ写す」「ログに残す」の3点を入れています。

本体側の定型

Option Explicit

Public Sub RunMonthlyReport()
    Const PROC_NAME As String = "RunMonthlyReport"
    Dim errNo As Long
    Dim errMsg As String
    Dim errSrc As String

    On Error GoTo ErrHandler
    Application.ScreenUpdating = False

    ' ここに本体の処理を書く
    Worksheets("注文").Range("A1").Value = "見出し"

CleanUp:
    ' 正常時もエラー時も必ず通る後始末
    Application.ScreenUpdating = True
    Exit Sub

ErrHandler:
    ' 1. Err の内容を先に変数へ写す
    errNo = Err.Number
    errMsg = Err.Description
    errSrc = Err.Source
    ' 2. ログに残す
    WriteErrorLog PROC_NAME, errNo, errMsg, errSrc
    ' 3. 利用者に知らせる
    MsgBox "処理を中断しました。" & vbCrLf & _
           "番号: " & errNo & vbCrLf & errMsg
    ' 4. 後始末へ進む
    Resume CleanUp
End Sub

Application.ScreenUpdating を False にしたマクロは、終わるときに True へ戻すよう Microsoft Learn に書かれています。エラーで途中終了した場合も戻るように、設定を戻す行は CleanUp ラベルの下に集め、Resume CleanUp で必ず通す形にしています。

ログ出力のプロシージャ

マクロのブックと同じフォルダーの error.log に、1件を1行で追記します。

Public Sub WriteErrorLog(ByVal procName As String, ByVal errNo As Long, _
                         ByVal errMsg As String, ByVal errSrc As String)
    Dim fileNo As Integer
    Dim logPath As String

    ' ログ出力そのものでマクロが止まらないようにする
    On Error Resume Next

    logPath = ThisWorkbook.Path & "\error.log"
    fileNo = FreeFile
    Open logPath For Append As #fileNo
    Print #fileNo, Format(Now, "yyyy-mm-dd hh:nn:ss") & vbTab & _
                   procName & vbTab & errNo & vbTab & errSrc & vbTab & errMsg
    Close #fileNo

    On Error GoTo 0
End Sub

使っている要素は次のとおりです。

要素 役割(Microsoft Learn の説明)
FreeFile Open で使える、次の空きファイル番号を返す
Open … For Append 追記モードで開く。ファイルが無い場合は作成される
Print # 表示形式のデータをシーケンシャルファイルに書き込む
Format(Now, "yyyy-mm-dd hh:nn:ss") 現在の日時を、年-月-日 時:分:秒 の文字列にする(分は nn)
ThisWorkbook.Path マクロのコードが入っているブックの保存先フォルダーのパス

ログの1行は、日時・プロシージャ名・番号・発生元・説明の5項目をタブで区切った形になります。表計算ソフトにそのまま貼り付けて、番号ごとに並べ替えられます。

呼び出し元へエラーを伝え直す

下位のプロシージャではログだけ残し、利用者への表示は最上位のプロシージャに任せたい場合は、変数に写した内容で Err.Raise を実行して、呼び出し元へ伝え直します。

ErrHandler:
    errNo = Err.Number
    errMsg = Err.Description
    errSrc = Err.Source
    WriteErrorLog PROC_NAME, errNo, errMsg, errSrc
    Application.ScreenUpdating = True
    Err.Raise errNo, errSrc, errMsg

エラー処理ルーチンの中で起きたエラーは呼び出し元へ制御が渡る、という On Error の決まりを利用した書き方です。

エラー処理を書くときのチェックリスト

確認すること 理由
モジュールの先頭に Option Explicit があるか 変数名のつづり違いを、実行前に見つけられる
ラベルの直前に Exit Sub/Exit Function があるか 正常時にエラー処理ルーチンへ入らないようにする
On Error Resume Next を On Error GoTo 0 で閉じているか 意図しないエラーまで素通りさせない
エラー処理ルーチンの先頭で Err.Number・Err.Description を変数に写しているか あとの処理で内容がリセットされても使える
画面更新などの設定を、後始末のラベルで元に戻しているか エラーで終わったときも設定が残らない
Resume で再試行する箇所に、回数の上限があるか 同じ行の繰り返しを止められる
オブジェクト変数を使う前に、Nothing かどうかを確かめているか 91 を事前に避けられる

よくある質問

Q. 実行時エラーとコンパイルエラーは何が違いますか? A. コンパイルエラーは、実行を始める前に文法や宣言の問題として知らされるものです。実行時エラーは、文法は正しくても、実行した時点の値や状態(シートが無い、セルが文字列、ファイルが無いなど)によって起きます。この記事の番号はすべて実行時エラーです。

Q. On Error Resume Next をマクロの先頭に書いておけば安心ですか? A. エラーのダイアログは出なくなりますが、問題が起きた行も素通りして先へ進むため、結果が途中から意図と違っていても気づきにくくなります。試したい行だけを挟み、直後に Err.Number を確かめて On Error GoTo 0 で閉じる使い方が向いています。

Q. 1004 はメッセージが漠然としていて原因がわかりません。 A. VBA の外側(Excel など)から伝わってきたエラーに付く番号なので、止まった行で操作しているセル範囲・シート・ブックの指定を順に見直します。Err.Description と Err.Source をログに残しておくと、発生元の切り分けに役立ちます。

Q. 自分で決めたエラー番号は何番を使えばよいですか? A. Microsoft Learn では、0〜512 はシステムエラー用に予約され、513〜65535 がユーザー定義に使える範囲とされています。クラスモジュールでは vbObjectError に番号を足した値を使います。定数に名前を付けておくと、Select Case で見分けやすくなります。

まとめ

  • 実行時エラーは番号で原因の型が決まる。まず止まった行を確かめ、早見表の原因と照らし合わせる
  • 1004 は Excel 側のオブジェクトの指定、9 は範囲外や存在しない名前、13 は型、91 は Nothing を見直す
  • 424 はドットの左側(オブジェクトではない)、438 はドットの右側(そのメンバーが無い) と覚える
  • On Error は GoTo ラベル・Resume Next・GoTo 0 の3形式。ラベルの前に Exit Sub を置き、Resume Next は短い区間で閉じる
  • Resume は「同じ行」「次の行」「ラベル」の3つの戻り方。後始末は Resume ラベル で必ず通す
  • エラー処理ルーチンでは、Err.Number と Err.Description を先に変数へ写す
  • 独自のエラーは Err.Raise で 513 以降の番号を使い、ログには日時・プロシージャ名・番号・発生元・説明を残す

参考・出典

  • Microsoft Learn「トラップできるエラー」 https://learn.microsoft.com/ja-jp/office/vba/language/reference/user-interface-help/trappable-errors
  • Microsoft Learn「On Error ステートメント」 https://learn.microsoft.com/ja-jp/office/vba/language/reference/user-interface-help/on-error-statement
  • Microsoft Learn「Resume ステートメント」 https://learn.microsoft.com/ja-jp/office/vba/language/reference/user-interface-help/resume-statement
  • Microsoft Learn「Err オブジェクト」 https://learn.microsoft.com/ja-jp/office/vba/language/reference/user-interface-help/err-object
  • Microsoft Learn「Raise メソッド」 https://learn.microsoft.com/ja-jp/office/vba/language/reference/user-interface-help/raise-method
  • Microsoft Learn「アプリケーション定義またはオブジェクト定義のエラー」 https://learn.microsoft.com/ja-jp/office/vba/language/reference/user-interface-help/application-defined-or-object-defined-error
  • Microsoft Learn エラー 9 の解説ページ https://learn.microsoft.com/ja-jp/office/vba/language/reference/user-interface-help/subscript-out-of-range-error-9
  • Microsoft Learn エラー 13 の解説ページ https://learn.microsoft.com/ja-jp/office/vba/language/reference/user-interface-help/type-mismatch-error-13
  • Microsoft Learn エラー 91 の解説ページ https://learn.microsoft.com/ja-jp/office/vba/language/reference/user-interface-help/object-variable-not-set-error-91
  • Microsoft Learn「Range.Find メソッド (Excel)」 https://learn.microsoft.com/ja-jp/office/vba/api/excel.range.find

本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。

(記載例)出典:株式会社RJC「VBA実行時エラー一覧|1004・9・13・91の原因と対処」

株式会社RJC ― SI事業・SES事業・AI駆動開発。RJCは一緒に成長を楽しめる会社です。

WE ARE HIRING

RJCで一緒に開発しながら、
成長を楽しみませんか?

RJCは、Web・モバイル・AIを活用した開発プロジェクトで、テックリードやPM・PMOも活躍するシステム開発会社です。会社を知る、待遇を確かめる、話を聞いてみる。気になるところ見てみてください!

  • 127日年間休日
  • 12時間平均残業時間
  • 毎日ガチャ遊びココロも大切にする福利厚生。アマギフなどの賞品ラインナップ!

ほかにも、チケットレストラン、書籍読み放題、2年ごとの慰労報奨(休暇 or 金一封)、11期連続の黒字決算。

ABOUT RJC RJCがどんな会社か知る 考え方、研修、働き方、福利厚生、社員の前職まで。RJCのことが丸わかり! RJC丸わかりページへ JOB DESCRIPTION 仕事内容・待遇を見てみる 仕事内容、給与・待遇、選考の流れ。経験者も未経験も!応募前に知りたいこと、まとめました! 募集要項を見る ENTRY エントリーする エントリーは1〜2分・履歴書不要です。まずは話を聞いてみたい、という方でも歓迎です! エントリーフォームへ

RJCで一緒に開発しながら、 成長を楽しみませんか?