VBAマクロのエラー解決ガイド|実行時エラー13・1004・9など頻出エラー別の直し方

スポンサーリンク

VBAでマクロを書いていると、いきなり赤い画面で「実行時エラー」と表示されて慌てた経験、誰にでもあると思います。しかも番号だけ出て意味がわからない、英語で説明されても何を直せばいいか見当がつかない、というケースが多いですよね。

この記事では、VBAマクロで特に頻出する実行時エラーを 番号ごとに原因・発生パターン・修正コード の3点セットで整理しました。併せて、エラーが出たときの定番の調べ方(ステップ実行・イミディエイトウィンドウ)や、On Error 構文を使ったエラーハンドリングの基本もまとめています。

エラー番号で検索してたどり着いた方は、目次から該当箇所にジャンプしてください。「とりあえず一通り押さえたい」という方は、最初から順に読んでいただくとVBAの例外対処の勘所がつかめる内容になっています。

VBAの実行時エラーとは|まずは全体像を押さえる

VBAのエラーは大きく3種類あります。

  1. コンパイルエラー: マクロを実行する前、VBEが構文を解析した時点で出るエラー。「構文エラー」「変数が定義されていません」など。
  2. 実行時エラー: マクロを実行した途中で発生するエラー。この記事で主に扱う「実行時エラー 13」などがこれです。
  3. 論理エラー: エラーメッセージは出ないが結果が想定と違うバグ。

実行時エラーが厄介なのは、「コードの書き方」ではなく「実行時のデータ・環境」によって発生するため、書いたときには気づけないという点です。たとえば、開発中は問題なくても、他の人がシートを編集した瞬間に壊れることがあります。

実行時エラーが出たときは、黄色くハイライトされた行 が原因箇所です。「デバッグ」ボタンを押すとその行で一時停止するので、まずはその行で何が起きているかを確認するのが第一歩になります。

実行時エラー 13|型の不一致(Type mismatch)

VBAで最も頻繁に目にするエラーが、この「型の不一致」です。ある型を期待している場所に別の型の値を渡そうとしたときに発生します。

原因と典型パターン

Dim i As Long
i = Range("A1").Value  ' A1に "りんご" と入っているとエラー13

数値型の変数に文字列を入れようとした、というのがもっとも典型的なパターンです。他にも次のような状況で発生します。

  • セルにエラー値(#N/A#VALUE! など)が入っている状態で、そのセルを数値変数に代入した
  • CInt / CLng / CDbl に変換不可能な文字列を渡した(例: CInt("abc")
  • 配列が必要な場所にスカラー値を渡した

直し方

セルの値を数値として扱いたい場合は、事前に IsNumeric で検査 してから代入するのが定石です。

Dim v As Variant
v = Range("A1").Value
If IsNumeric(v) Then
    Dim i As Long
    i = CLng(v)
Else
    MsgBox "A1が数値ではありません: " & v
End If

また、エラー値が混ざる可能性があるセルは IsError で事前チェックしましょう。

If Not IsError(Range("A1").Value) Then
    i = Range("A1").Value
End If

ポイントは、Variantでいったん受けてから判定 → 変換 という流れです。直接 Long 型に代入しようとすると、そこで処理が止まってしまいます。

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

エラー1004は「Excelに何かを頼んだけど、その頼み方が正しくない」ときに出ます。メッセージが曖昧なので原因の特定が難しい、VBAでもトップクラスに悩まされるエラーです。

典型パターン 1: シート名が間違っている

Worksheets("売上").Range("A1").Value = 100  ' "売上"シートが存在しないとエラー1004

シートをリネームしたのにコード側を直し忘れた、というよくあるパターンです。Worksheets("名前") は該当シートがないと即座に1004になります。

直し方: シート存在チェックを関数化しておくと安全です。

Function SheetExists(name As String) As Boolean
    Dim ws As Worksheet
    On Error Resume Next
    Set ws = ThisWorkbook.Worksheets(name)
    On Error GoTo 0
    SheetExists = Not ws Is Nothing
End Function

典型パターン 2: Range の引数が不正

Range("A1:Z0").Select  ' 行番号 0 は存在しない → 1004
Range("").Value = 1    ' 空文字 → 1004

Range に渡す文字列が不正(存在しないアドレス・空文字)だと1004になります。変数から動的に組み立てた文字列を Range に渡す場合は要注意です。

典型パターン 3: 保護されたシートに書き込み

ActiveSheet.Range("A1").Value = 100  ' シートが保護されているとエラー1004

直し方: 保護を一時的に解除してから書き込み、終わったら戻します。

ActiveSheet.Unprotect
ActiveSheet.Range("A1").Value = 100
ActiveSheet.Protect

典型パターン 4: Cells の引数が範囲外

Cells(1048577, 1).Value = 1  ' Excel 2007以降でも行の上限は 1048576

Excelの行列の上限を超えた値を CellsRange に渡すと1004です。ループで i を増やしていく処理でありがちなミスです。

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

配列やコレクションの範囲外にアクセスしたときに出るエラーです。

典型パターン

Dim arr(1 To 3) As String
arr(4) = "aaa"  ' エラー9

Workbooks("存在しないブック.xlsx").Activate  ' エラー9
Worksheets(5).Select  ' シートが4枚しかなければエラー9

配列の添字、ブック名、シート名・シート番号の指定ミスで発生します。1004 と混同しがちですが、「コレクションに対するアクセス」がキーワードです。

直し方

配列の場合LBoundUBound で範囲を確認します。

Dim i As Long
For i = LBound(arr) To UBound(arr)
    Debug.Print arr(i)
Next i

ブック・シートの場合 は名前で存在チェックしてからアクセスします。先ほどの SheetExists 関数のように、On Error Resume Next で一時的にエラーを抑制して判定する方法が定番です。

動的配列で ReDim を忘れた場合もエラー9になります。ReDim Preserve arr(1 To n) を先に実行してから添字に代入しましょう。

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

「Nothing が入っているオブジェクト変数を使おうとした」というエラーです。Set を書き忘れたときに出ます。

典型パターン

Dim ws As Worksheet
ws.Range("A1").Value = 1  ' Set していない → エラー91

Dim r As Range
Set r = Range("A:A").Find("検索語")
MsgBox r.Address  ' Find で見つからないと Nothing → エラー91

特に Find メソッドは「見つからないとき Nothing を返す」 ので、そのまま r.Address などにアクセスすると91になります。Findは実務で多用するので、ここは鉄則として覚えておきましょう。

直し方

Set が必要なオブジェクト(WorksheetRangeWorkbook など)は、必ず Set で代入してから使う。Find などの結果は Nothing 判定を挟む

Dim r As Range
Set r = Range("A:A").Find("検索語")
If r Is Nothing Then
    MsgBox "見つかりませんでした"
    Exit Sub
End If
MsgBox r.Address

Is Nothing は VBA における null チェックの作法です。Findと組み合わせて使う流れは必ず身につけてください。

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

そのオブジェクトに存在しないプロパティやメソッドを呼び出したときのエラーです。

典型パターン

Dim ws As Worksheet
Set ws = ActiveSheet
ws.Rows.Count  ' OK
ws.Count       ' Worksheet に Count プロパティはない → エラー438

よくあるのは、変数の型を間違えている ケースです。「Range と思って書いていたけど実際は Worksheet だった」など、オブジェクト型の取り違えで発生します。

直し方

まずは Dim で型をきちんと宣言すること。VariantObject 型で受けてしまうと、VBEの入力補完が効かず、存在しないメソッドを気づかずに書けてしまいます。

Dim ws As Worksheet   ' OK: 入力補完が効く
Dim obj As Object     ' NG: 何でも書けてしまう

また . を打ったときに候補が出ないメンバは存在しないので、入力補完に頼る のも有効な予防策です。

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

オブジェクトを要求する場所に、オブジェクトではない値を渡したときのエラーです。

Dim ws As Worksheet
ws = Worksheets("Sheet1")      ' Set を忘れた → エラー424
Set ws = Worksheets("Sheet1")  ' 正解

Set キーワードを忘れたパターンがほぼ全てです。オブジェクト変数への代入には必ず Set を付ける、というルールを徹底しましょう。VBAは他言語にない独特な作法なので、初学者ほどハマりやすいポイントです。

実行時エラー 6|オーバーフロー

変数の型の最大値を超えたときに発生します。

Dim i As Integer
i = 40000  ' Integer の上限は 32767 → エラー6

Integer(-32768〜32767)の上限を超えると即座にオーバーフローします。行数をカウンタにするなど、大きな値が入る可能性のある変数は必ず Long にしましょう。

Dim lastRow As Long
lastRow = Cells(Rows.Count, 1).End(xlUp).Row

VBAでは Integer を使うメリットはほぼないため、整数は基本 Long と覚えてしまって構いません。

エラーが出たときのデバッグ手順

エラー番号を検索しても原因がわからないときは、次の手順で調査します。

1. ステップ実行(F8キー)

VBEで調査したいプロシージャの先頭にカーソルを置き、F8 キーを押すと 1行ずつ実行 できます。1行進めるたびに変数の中身を確認できるので、「どの行でおかしくなったか」を特定できます。

2. イミディエイトウィンドウ(Ctrl + G)

イミディエイトウィンドウは、VBEで Ctrl + G を押すと開く対話的な実行窓です。ここに次のように打ち込むと、その場で値を確認できます。

? Range("A1").Value
? TypeName(Range("A1").Value)
? ActiveSheet.Name

TypeName は変数やセルの値の型を調べられる関数で、エラー13(型の不一致)のデバッグに絶大な効果を発揮します。

コードの途中に Debug.Print を仕込むのも定番です。

Debug.Print "i=" & i, "値=" & arr(i)

3. ブレークポイント(F9キー)

気になる行を選択して F9 を押すと、その行に赤い丸(ブレークポイント)が付きます。実行するとその行で自動的に一時停止するので、ステップ実行と組み合わせて原因箇所を絞り込めます。

ステップ実行・イミディエイト・ブレークポイントの3つを使いこなせると、VBAのデバッグ効率は劇的に上がります。VBEの使い方を体系的に押さえたい方は Excel VBAのVBE(Visual Basic Editor)のメニュー解説 も併せてご覧ください。

On Error 構文によるエラーハンドリング

想定外のエラーでマクロが止まるのを防ぐには、On Error 構文でハンドリングを書きます。

On Error GoTo ラベル

エラー発生時に指定したラベルへジャンプする、もっとも基本的な形です。

Sub Sample()
    On Error GoTo ErrHandler

    ' 本体処理
    Range("A1").Value = 1 / 0

    Exit Sub  ' ← エラーなく終わったらここで抜ける(重要)

ErrHandler:
    MsgBox "エラー番号: " & Err.Number & vbCrLf & _
           "内容: " & Err.Description
End Sub

ポイントは、エラーがなく正常終了した場合にラベルの下に処理が流れ込まないよう Exit Sub を置く ことです。これを忘れると、正常終了時にもエラーメッセージが表示されてしまいます。

Err.Number でエラー番号、Err.Description でメッセージを取得できるので、ログ出力やユーザー向けメッセージに活用しましょう。

On Error Resume Next

エラーが起きても止めずに次の行へ進む、というモードです。前述のシート存在チェックのように、「エラーが出ること自体を期待している」局面で使います。

On Error Resume Next
Set ws = ThisWorkbook.Worksheets("売上")
On Error GoTo 0  ' エラー抑制を解除

If ws Is Nothing Then
    MsgBox "売上シートがありません"
End If

使い終わったら必ず On Error GoTo 0 で解除 してください。付けっぱなしにすると、本来気づくべきエラーまで無視されてしまい、バグの発見が遅れます。

On Error Resume Next は強力な一方で、乱用するとエラーが全部握りつぶされる危険な構文 でもあります。「ここで発生するエラーは想定内だ」と言い切れる狭い範囲に限定して使いましょう。

エラーを減らすための予防策

そもそもエラーを出さないコードを書く、というのが最も効率的な対策です。VBAで押さえておきたい基本作法をまとめておきます。

  • Option Explicit を必ず宣言する: 変数の宣言漏れを防ぎ、タイプミスをコンパイル時に検出できます。詳しくは Excel VBA の Option Explicit とは を参照してください。
  • 適切な型で宣言する: VariantObject の乱用を避け、Long / String / Worksheet など具体的な型を指定する。入力補完が効き、エラー438・424の予防になります。型の基本は Excel VBA の変数について でまとめています。
  • シート・ブックは名前ではなく変数で保持: Worksheets("売上") を何度も書かず、先頭で Set ws = Worksheets("売上") しておく。リネーム時の修正箇所も減ります。
  • マジックナンバーを避ける: Cells(Rows.Count, 1).End(xlUp).Row のように、最終行を動的に取る。固定で Range("A1:A1000") と書くと、1000行を超えたときに破綻します。最終行取得の定石は Excel VBAで最終行を取得する方法 を参照してください。
  • Find の結果は必ず Nothing チェック: 前述の通りエラー91の温床です。

こうした基本を押さえたうえで、On Error で想定外だけ拾う、という二段構えが理想です。VBAマクロの基礎から学び直したい方は Excel VBAマクロ入門ガイドExcel VBA自動化ガイド に体系的にまとめていますので、併せてどうぞ。

まとめ

VBAの実行時エラーは、番号ごとに原因のパターンがかなり決まっています。

  • エラー13(型の不一致): 数値変数に文字列やエラー値を入れていないか。IsNumeric / IsError で事前チェック。
  • エラー1004: シート名・Range引数・シート保護・セル範囲超過のいずれか。シート存在チェック関数を用意しておく。
  • エラー9(インデックス範囲外): 配列・ブック・シートへのアクセスを確認。LBound / UBound や名前検査で防ぐ。
  • エラー91(オブジェクト未設定): Set の書き忘れ、Findの結果 Nothing。Is Nothing 判定を徹底。
  • エラー438: 存在しないメソッド呼び出し。型を正しく宣言する。
  • エラー424: Set 忘れ。
  • エラー6(オーバーフロー): Integer ではなく Long を使う。

そして、エラーが出たときは慌てずに ステップ実行 → イミディエイトで型を確認 → Debug.Print でログを仕込む という順番で追いかけましょう。ハンドリングが必要な場面では On Error GoToOn Error Resume Next を適切に使い分け、使ったら必ず On Error GoTo 0 で解除する ことも忘れずに。

エラーと上手に付き合えるようになると、VBAの開発スピードは一段階上がります。この記事をブックマークしておいて、エラーが出たときに番号で逆引きしていただければ幸いです。

タイトルとURLをコピーしました