🚀The world's best VBA AI has evolved. ExcelMaster is now an autonomous Agent.Read more →
Back to Blog

VBA の Err オブジェクトとは(Excel)— Number・Description と自前エラーの送出

|

VBA の Err オブジェクトとは(Excel)— Number・Description と自前エラーの送出

検証環境: Excel 365 v2509 · Excel 2021 · Excel 2019 · 最終確認 2026-06-08

要点 — 実行時エラーが起きると、VBA はただ一つのグローバルオブジェクト——Err——に、その「墜落」について知っているすべてを書き込みます。ハンドラーの中でこれを読んで対処を決めます。さらに Err.Raise で書き込めば、自前のエラーを送出することもできます。

Sub ReadPrice()
    On Error Resume Next
    Dim price As Double
    price = CDbl(Range("A1").Value)          ' A1 が数値でなければ失敗
    If Err.Number <> 0 Then
        MsgBox "エラー " & Err.Number & ": " & Err.Description
        Err.Clear                            ' 次の確認をきれいにするためリセット
    End If
    On Error GoTo 0
End Sub

オブジェクト全体を一か所にまとめると次のとおりです。

Err.Number        ' エラーコード ——0 は「エラーなし」
Err.Description   ' 人が読めるメッセージ
Err.Source        ' 誰が発生させたか(プロジェクト名/オブジェクト名)
Err.Raise 513     ' 自分でエラーを送出する
Err.Clear         ' Err をきれいな状態に戻す

メンタルモデル:Err は「直前の墜落」のブラックボックス

Err は、常に存在するただ一つのグローバルオブジェクトです。マクロの フライトレコーダー だと考えてください。実行時エラーが起きた瞬間、VBA は制御をハンドラーへ飛ばす前に、3 つの事実をここへ書き込みます。

  • Err.Number — 数値のコード(1004139…)。0 は「何も問題は起きていない」を意味します。
  • Err.Description — 赤いダイアログに出るのと同じ文言(「型が一致しません」「インデックスが有効範囲にありません」)。
  • Err.Source — どのプロジェクトまたはオブジェクトが発生させたか。

Err オブジェクトはセッション全体で 一つ だけで、保持するのは 直近の エラーです。だからこそ、何を 読むかと同じくらい いつ 読むかが重要で——そして自動でクリアされるのです(後述)。

たった一つのルール:Err.Number こそが「本当に失敗したか?」を知る唯一の確かな手段

On Error Resume Next の後、コードは行が成功してもしなくても走り続けます。どちらが起きたかを知る 唯一 の方法は、Err.Number を読むことです。

On Error Resume Next
Set wb = Workbooks("Budget.xlsx")     ' このブックはもう開いている?
If Err.Number = 0 Then
    MsgBox "すでに開いています。"
Else
    Err.Clear
    Set wb = Workbooks.Open("C:\Data\Budget.xlsx")
End If
On Error GoTo 0

Err.Number の確認が無い Resume Next は無駄です。VBA に失敗を無視せよと命じておきながら、失敗が起きたことに自分が気づけません。この確認こそが処理の本体 です。これは On Error Resume Next と対になるルールで——両者は二つで一組としてしか機能しません。

数値が違えば問題も違うので、特定の コードで分岐させることもできます。

Select Case Err.Number
    Case 0:    ' エラーなし
    Case 9:    MsgBox "そのシートまたはインデックスは存在しません。"   ' インデックスが有効範囲にない
    Case 13:   MsgBox "その値は正しい型ではありません。"             ' 型の不一致
    Case 1004: MsgBox "Excel がその操作を拒否しました。"             ' 一般的な自動化エラー
    Case Else: MsgBox "予期しないエラー " & Err.Number & ": " & Err.Description
End Select

落とし穴:Err は思いがけないタイミングで自分自身をクリアする

Err は、あなたが用済みになるまで値を保持してはくれません。VBA は次の いずれか が起きると、自動的に Number = 0 へリセットします。

  • 任意の On Error ステートメント(On Error GoTo 0 を含む)
  • Resume または Resume Next
  • Exit Sub / Exit Function
  • 次の実行時エラー(追記ではなく上書き)

したがって、これらの後で番号や説明が必要なら——記録する、後で表示する、上位へ渡す——ハンドラーが始まった瞬間に、自分の変数へ取り込んでおきましょう。

ErrHandler:
    Dim errNum As Long, errMsg As String
    errNum = Err.Number                     ' 今すぐ取り込む
    errMsg = Err.Description
    On Error Resume Next                     ' ← この行で Err は消える...
    Application.ScreenUpdating = True        ' ...だから後始末はもう Err を読めない
    LogToSheet errNum, errMsg                ' Err.* ではなく保存したコピーを使う

「エラーログにエラー 0 と出る」という不具合報告のほとんどは、このたった一つの罠が原因です。

Err.Raise で自前のエラーを送出する

Err を読むのは、このオブジェクトの半分にすぎません。もう半分は 書き込む こと——VBA のルール違反だけでなく、あなたの ルールが破られたときに、意図的にエラーを送出することです。

Function NetPrice(gross As Double, taxRate As Double) As Double
    If taxRate < 0 Or taxRate > 1 Then
        Err.Raise vbObjectError + 513, "NetPrice", _
                  "taxRate は 0 から 1 の間でなければなりません。指定値: " & taxRate
    End If
    NetPrice = gross / (1 + taxRate)
End Function

Err.Raise Number, Source, Description は本物の実行時エラーを発生させます——呼び出し側の On Error ハンドラーは、組み込みエラーとまったく同じように捕まえます。カスタムエラーには vbObjectError + nn は 513 から 65535)を使いましょう。この定数は、VBA がシステムコード用に予約している 0〜512 の範囲から十分に外してくれるので、本物のコードと衝突しません。

踏み込んだ判断:エラーコードを返すのは「願い」、エラーを送出するのは「強制」

多くの VBA は、番兵値を返すことで「検証」したつもりになります——-1False、空文字列を返し、すべての呼び出し側がそれを確認してくれると信じる。確認しません。半年後、誰かがあなたの関数を呼び、-1 を無視し、それで割り算します。

Err.Raise は、その選択肢ごと奪います。送出されたエラーは静かに無視できません——ハンドラーに当たるか、マクロを止めるかのどちらかです。それこそが要点です。Err.Number を読めるようになればエラー処理が「できる人」になりますが、不正な 入力やビジネスルール に対して自前のエラーを送出することこそが、あなたのコードを「礼儀正しいだけ」から「守りが堅い」へ変えます。下流で結果を壊しかねない値なら、フラグを返して祈るのではなく——送出しましょう。

よくある Err の誤り(と直し方)

症状 原因 直し方
ログがいつも「エラー 0」 ResumeOn Error/後始末が消した後で Err を読んだ 先に Err.Number / Err.Description を変数へ保存する
Resume Next が「何も捕まえない」 リスクのある行の後で Err.Number を確認していない If Err.Number <> 0 Then … を追加
カスタムエラーがシステムエラーと衝突 Err.Raise 5 のような小さな生の数値を使った Err.Raise vbObjectError + 513 以上を使う
2 回目の確認が古いエラーで発火 1 件目を処理した後に Err.Clear を忘れた 対処し終えたら一度 Err.Clear を呼ぶ
Err.Description が空 Err.Clear やリセットの後で読んだ クリアする に説明を読む

エラー配管を手書きするのはやめて ——ルールを言葉で伝えるだけでいい

堅牢な VBA の半分はこれです。Err.Number を読み、説明を保存し、不正なデータには自前のエラーを送出し、クリアし、また繰り返す。必要ではあるけれど、退屈です。ExcelMaster Agent なら、「税率が 0 から 1 の間にあるか検証して、外れていたら分かりやすいメッセージで止めて」 と自然な日本語で言うだけ——生成された Python が、ファイルを先にバックアップしたうえで、エラーを送出して報告してくれます。無料で試す →

関連記事

よくある質問

VBA の Err オブジェクトとは何ですか? Err は、直近の実行時エラーに関する情報を保持するグローバルオブジェクトです。主なメンバーは Err.Number(エラーコード、0 = エラーなし)、Err.Description(メッセージ)、Err.Source(発生元)です。エラーハンドラーの中でこれを読み、どう対処するかを決めます。

VBA でエラー番号を確認するには? Err.Number を読みます。On Error Resume Next の後で If Err.Number <> 0 Then を判定すれば、直前の行が失敗したかどうかが分かります。値が 0 ならエラーは起きていません。Select Case Err.Number で、9(インデックスが有効範囲にない)や 13(型の不一致)など特定のコードごとに違う対応をすることもできます。

Err オブジェクトはいつリセットされますか? 任意の On Error ステートメント、ResumeResume NextExit SubExit Function、そして次のエラーによる上書きで、自動的にリセットされます。後で値が必要なら、Err.NumberErr.Description を直ちに自分の変数へコピーしてください。Err.Clear で手動リセットすることもできます。

VBA でカスタムエラーを発生させるには? Err.Raise Number, Source, Description を使います。カスタムエラーには vbObjectError + nn は 513〜65535)を使います。例:Err.Raise vbObjectError + 513, "MyFunc", "入力が不正です"。こうするとシステムエラー用に予約された 0〜512 の範囲を避けられ、呼び出し側のハンドラーが組み込みエラーと同じように捕まえられます。

Err.Clear と On Error GoTo 0 の違いは何ですか? Err.Clear は Err オブジェクトのプロパティをきれいな状態に戻しますが、エラートラップのモードは変えません。On Error GoTo 0トラップのモード を既定(エラーで止まる)に戻し——その副作用として Err もクリアします。同じハンドラー内で Err を再利用するには Err.Clear を、エラーの無視をやめるには On Error GoTo 0 を使います。