「実行時エラー ’91’: オブジェクト変数または With ブロック変数が設定されていません。」
「実行時エラー ’13’: 型が一致しません。」
VBAを始めたばかりの頃、この2つのエラーに何度も悩まされました。
特にエラー91は「オブジェクト変数って何?」と理解するのに時間がかかり、エラー13は「数字なのになぜエラー?」と混乱しました。
しかし、エラーの原因を正しく理解し、適切なデバッグ手法を身につけてからは、エラーが出ても5分以内に解決できるようになりました。
この記事では、VBAで最も頻出する実行時エラー91・13の原因と解決方法を、実例コード付きで徹底解説します。
VBA実行時エラーの基礎知識
VBAのエラーは3種類ある
| エラー種類 | 発生タイミング | 代表例 |
|---|---|---|
| 構文エラー | コード入力時 | 「Sub」の綴りミス、カッコの閉じ忘れ |
| コンパイルエラー | 実行前(コンパイル時) | 「変数が定義されていません」 |
| 実行時エラー | マクロ実行中 | エラー91、エラー13、エラー9、エラー1004 |
この記事で扱うのは実行時エラーです。
実行時エラーが発生する理由
実行時エラーは、コードは正しいが、実行時の状況が想定外のときに発生します。
例えば:
- 存在しないシートを開こうとした(エラー9)
- 数値が入るべき変数に文字列を代入した(エラー13)
- オブジェクト変数にSetせずに値を代入した(エラー91)
- 範囲外のセルを参照した(エラー1004)
これらは構文的には正しいため、コンパイルは通過しますが、実行時に問題が起きます。
実行時エラー91「オブジェクト変数が設定されていません」の完全攻略
エラー91の正式メッセージ
実行時エラー '91':
オブジェクト変数または With ブロック変数が設定されていません。
エラー91が発生する5つの原因
原因①:Setを付け忘れた
最も頻出するパターンです。
❌ エラーが出るコード例
Sub Setを忘れた例()
Dim ws As Worksheet
ws = ThisWorkbook.Worksheets("Sheet1") ' ← Setが無い!
ws.Range("A1").Value = "テスト"
End Sub
エラー理由:
オブジェクト変数(Worksheet型、Range型など)に値を代入するときは、必ずSetが必要です。
✅ 正しいコード例
Sub Setを正しく使う()
Dim ws As Worksheet
Set ws = ThisWorkbook.Worksheets("Sheet1") ' ← Setを付ける
ws.Range("A1").Value = "テスト"
End Sub
原因②:Nothingに設定されたオブジェクトを使用
❌ エラーが出るコード例
Sub Nothingを参照()
Dim ws As Worksheet
Set ws = Nothing
ws.Range("A1").Value = "テスト" ' ← エラー91
End Sub
✅ 正しいコード例(Is Nothingでチェック)
Sub Nothing判定付き()
Dim ws As Worksheet
Set ws = Nothing
If ws Is Nothing Then
MsgBox "シートが設定されていません", vbExclamation
Exit Sub
End If
ws.Range("A1").Value = "テスト"
End Sub
原因③:Find/FindNextが見つからなかった
❌ エラーが出るコード例
Sub Findが見つからない()
Dim rng As Range
Set rng = Range("A:A").Find("存在しない文字列")
rng.Value = "更新" ' ← エラー91(rngがNothing)
End Sub
✅ 正しいコード例(Is Nothingでチェック)
Sub Find安全版()
Dim rng As Range
Set rng = Range("A:A").Find("存在しない文字列")
If rng Is Nothing Then
MsgBox "見つかりませんでした", vbInformation
Exit Sub
End If
rng.Value = "更新"
End Sub
原因④:Withブロック内で変数未設定
❌ エラーが出るコード例
Sub Withブロックエラー()
With Worksheets("存在しないシート") ' ← 存在しない
.Range("A1").Value = "テスト" ' ← エラー91
End With
End Sub
✅ 正しいコード例(事前にシート存在確認)
Sub With安全版()
Dim ws As Worksheet
On Error Resume Next
Set ws = Worksheets("存在しないシート")
On Error GoTo 0
If ws Is Nothing Then
MsgBox "シートが見つかりません", vbCritical
Exit Sub
End If
With ws
.Range("A1").Value = "テスト"
End With
End Sub
原因⑤:関数がNothingを返した
❌ エラーが出るコード例
Function シートを取得(sheetName As String) As Worksheet
On Error Resume Next
Set シートを取得 = Worksheets(sheetName)
On Error GoTo 0
End Function
Sub 関数からNothing()
Dim ws As Worksheet
Set ws = シートを取得("存在しないシート") ' ← Nothingが返る
ws.Range("A1").Value = "テスト" ' ← エラー91
End Sub
✅ 正しいコード例(関数の戻り値をチェック)
Sub 関数戻り値チェック()
Dim ws As Worksheet
Set ws = シートを取得("存在しないシート")
If ws Is Nothing Then
MsgBox "シートが取得できませんでした", vbCritical
Exit Sub
End If
ws.Range("A1").Value = "テスト"
End Sub
エラー91を防ぐ3つのベストプラクティス
- オブジェクト変数には必ずSetを付ける(最重要)
- Is Nothingで必ず存在チェック(Find、シート取得など)
- Option Explicitで変数宣言を強制(タイプミスを防ぐ)
実行時エラー13「型が一致しません」の完全攻略
エラー13の正式メッセージ
実行時エラー '13':
型が一致しません。
エラー13が発生する5つの原因
原因①:数値型の変数に文字列を代入
❌ エラーが出るコード例
Sub 型が一致しない()
Dim num As Long
num = "テスト" ' ← エラー13
End Sub
✅ 正しいコード例(IsNumericで事前チェック)
Sub 型チェック付き()
Dim num As Long
Dim inputValue As Variant
inputValue = InputBox("数値を入力してください")
If IsNumeric(inputValue) Then
num = CLng(inputValue)
MsgBox "入力値: " & num
Else
MsgBox "数値を入力してください", vbExclamation
End If
End Sub
原因②:空白セルをLong型に代入
❌ エラーが出るコード例
Sub 空白セルをLongに()
Dim num As Long
num = Range("A1").Value ' ← A1が空白の場合エラー13
MsgBox num
End Sub
✅ 正しいコード例(空白チェック付き)
Sub 空白チェック付き()
Dim num As Long
If Range("A1").Value = "" Then
MsgBox "A1が空白です", vbExclamation
Exit Sub
End If
If IsNumeric(Range("A1").Value) Then
num = CLng(Range("A1").Value)
MsgBox num
Else
MsgBox "A1に数値を入力してください", vbExclamation
End If
End Sub
原因③:日付型に不正な文字列を代入
❌ エラーが出るコード例
Sub 日付型エラー()
Dim dt As Date
dt = "テスト" ' ← エラー13
End Sub
✅ 正しいコード例(IsDateで事前チェック)
Sub 日付型チェック付き()
Dim dt As Date
Dim inputValue As String
inputValue = InputBox("日付を入力してください(例:2026/02/09)")
If IsDate(inputValue) Then
dt = CDate(inputValue)
MsgBox "入力日付: " & Format(dt, "yyyy/mm/dd")
Else
MsgBox "正しい日付形式で入力してください", vbExclamation
End If
End Sub
原因④:配列を単一値として扱う
❌ エラーが出るコード例
Sub 配列を単一値に()
Dim arr As Variant
arr = Array(1, 2, 3)
Dim num As Long
num = arr ' ← エラー13(配列を単一値に代入できない)
End Sub
✅ 正しいコード例(配列の要素を指定)
Sub 配列の要素を指定()
Dim arr As Variant
arr = Array(1, 2, 3)
Dim num As Long
num = arr(0) ' ← 配列の最初の要素
MsgBox num
End Sub
原因⑤:Range型を文字列に代入
❌ エラーが出るコード例
Sub Rangeを文字列に()
Dim str As String
str = Range("A1") ' ← エラー13(Range型を文字列に直接代入)
End Sub
✅ 正しいコード例(.Valueで値を取得)
Sub Rangeの値を取得()
Dim str As String
str = Range("A1").Value ' ← .Valueで値を取得
MsgBox str
End Sub
エラー13を防ぐ3つのベストプラクティス
- IsNumeric/IsDateで事前チェック(最重要)
- CInt/CLng/CDateで明示的に型変換(暗黙の型変換に頼らない)
- Option Strictを有効にする(VBA.NET環境の場合)
デバッグ手法の基本(F8・ブレークポイント・Debug.Print)
デバッグ手法①:F8キー(ステップ実行)
使い方:
- VBエディタを開く(Alt + F11)
- 実行したいマクロの最初の行にカーソルを置く
- F8キーを押す
- 1行ずつ実行され、黄色いハイライトが移動する
- 変数の中身を確認しながら進む
メリット:
- どの行でエラーが出るか特定できる
- 変数の値をリアルタイムで確認できる
デバッグ手法②:ブレークポイント(F9キー)
使い方:
- 一時停止したい行の左端をクリック(または行を選んでF9キー)
- 赤い●マークが表示される
- マクロを実行すると、その行で一時停止
- 変数の中身を確認できる
メリット:
- 特定の箇所だけチェックできる(F8より早い)
- 複数のブレークポイントを設定可能
デバッグ手法③:Debug.Print(イミディエイトウィンドウ)
使い方:
Sub Debug_Printを使う()
Dim num As Long
num = 100
Debug.Print "変数numの値: " & num
Dim ws As Worksheet
Set ws = ThisWorkbook.Worksheets("Sheet1")
Debug.Print "シート名: " & ws.Name
End Sub
イミディエイトウィンドウの表示方法:
- Ctrl + G
- または「表示」→「イミディエイトウィンドウ」
メリット:
- 変数の値をリアルタイムで確認できる
- マクロを止めずに確認可能
- ログとして残る
デバッグ手法の使い分け
| 手法 | 使うタイミング | メリット |
|---|---|---|
| F8(ステップ実行) | エラーが出る行が不明なとき | 全体の流れを確認できる |
| F9(ブレークポイント) | 特定の箇所だけチェックしたいとき | 高速にデバッグできる |
| Debug.Print | 変数の値を記録したいとき | ログとして残る |
エラーハンドリングの実践(On Error GoTo vs Resume Next)
エラーハンドリング①:On Error GoTo(推奨)
使い方:
Sub OnErrorGoTo例()
On Error GoTo ErrorHandler
' エラーが発生する可能性のある処理
Dim ws As Worksheet
Set ws = Worksheets("存在しないシート") ' ← エラー発生
ws.Range("A1").Value = "テスト"
' 正常終了時の処理
MsgBox "処理が完了しました", vbInformation
Exit Sub
ErrorHandler:
MsgBox "エラーが発生しました" & vbCrLf & _
"エラー番号: " & Err.Number & vbCrLf & _
"エラー内容: " & Err.Description, vbCritical
End Sub
メリット:
- エラーが発生しても安全に終了できる
- エラー番号とメッセージを取得できる
- エラー時の処理を自由に記述できる
エラーハンドリング②:On Error Resume Next(注意)
使い方:
Sub OnErrorResumeNext例()
On Error Resume Next
' エラーを無視して次の行に進む
Dim ws As Worksheet
Set ws = Worksheets("存在しないシート") ' ← エラー発生するが無視
' エラーチェック
If Err.Number <> 0 Then
MsgBox "シートが見つかりません", vbExclamation
On Error GoTo 0 ' ← エラー処理を解除
Exit Sub
End If
ws.Range("A1").Value = "テスト"
On Error GoTo 0 ' ← 必ず解除する
End Sub
⚠️ 注意点:
- エラーを無視するため、本当のエラー原因を見逃す危険性がある
- 必ずOn Error GoTo 0で解除する
- Err.Numberで毎回エラーチェックする
On Error GoTo vs Resume Nextの使い分け
| エラーハンドリング | 使うタイミング | 推奨度 |
|---|---|---|
| On Error GoTo | 基本的に常に使う | ⭐⭐⭐⭐⭐ |
| On Error Resume Next | シート存在チェックなど、エラーが想定内のとき | ⭐⭐⭐ |
実務で使える!汎用エラー対策テンプレート
テンプレート①:エラー91・13対策完全版
Sub 汎用エラー対策テンプレート()
' エラーハンドリング設定
On Error GoTo ErrorHandler
' ========== 処理1: オブジェクト変数の安全な取得 ==========
Dim ws As Worksheet
On Error Resume Next
Set ws = ThisWorkbook.Worksheets("売上")
On Error GoTo ErrorHandler
If ws Is Nothing Then
MsgBox "シート「売上」が見つかりません", vbCritical
Exit Sub
End If
' ========== 処理2: 数値型変数の安全な代入 ==========
Dim num As Long
Dim inputValue As Variant
inputValue = ws.Range("A1").Value
If inputValue = "" Then
MsgBox "A1が空白です", vbExclamation
Exit Sub
End If
If Not IsNumeric(inputValue) Then
MsgBox "A1に数値を入力してください", vbExclamation
Exit Sub
End If
num = CLng(inputValue)
' ========== 処理3: Findの安全な使用 ==========
Dim rng As Range
Set rng = ws.Range("A:A").Find("検索文字列")
If rng Is Nothing Then
MsgBox "検索文字列が見つかりませんでした", vbInformation
Exit Sub
End If
rng.Value = "更新"
' ========== 正常終了 ==========
MsgBox "処理が完了しました", vbInformation
Exit Sub
ErrorHandler:
MsgBox "エラーが発生しました" & vbCrLf & _
"エラー番号: " & Err.Number & vbCrLf & _
"エラー内容: " & Err.Description & vbCrLf & _
"エラー発生行: " & Erl, vbCritical
End Sub
テンプレート②:ログ出力機能付きエラーハンドリング
Sub ログ出力付きエラーハンドリング()
On Error GoTo ErrorHandler
Dim ws As Worksheet
Set ws = ThisWorkbook.Worksheets("Sheet1")
' Debug.Printでログ出力
Debug.Print "処理開始: " & Now
Debug.Print "対象シート: " & ws.Name
' 処理内容
ws.Range("A1").Value = "テスト"
Debug.Print "処理終了: " & Now
Exit Sub
ErrorHandler:
Debug.Print "エラー発生: " & Now
Debug.Print "エラー番号: " & Err.Number
Debug.Print "エラー内容: " & Err.Description
MsgBox "エラーが発生しました。イミディエイトウィンドウを確認してください。", vbCritical
End Sub
よくある質問(FAQ)
Q1. エラー91とエラー424の違いは?
A. エラー424は「オブジェクトが必要です」で、オブジェクト変数を使わずに直接メソッドを呼んだときに発生します。エラー91は「オブジェクト変数が設定されていません」で、Nothingまたは未初期化のオブジェクトを使ったときに発生します。
Q2. Option Explicitは必ず書くべき?
A. はい、必ず書くべきです。変数の宣言忘れによるエラーを防ぎ、タイプミスも検出できます。VBエディタの「ツール」→「オプション」→「変数の宣言を強制する」にチェックを入れると、自動的に挿入されます。
Q3. Debug.Printの結果はどこに表示される?
A. イミディエイトウィンドウに表示されます。Ctrl + G で表示できます。または「表示」→「イミディエイトウィンドウ」でも開けます。
Q4. エラー番号13と91、どちらが先に対策すべき?
A. エラー91を先に対策すべきです。エラー91が解決すると、エラー13も自然に減ります。理由は、オブジェクト変数が正しく設定されていれば、型不一致のエラーも減るからです。
Q5. On Error Resume Nextを使うと遅くなる?
A. わずかに遅くなりますが、体感できるレベルではありません。ただし、エラーを見逃すリスクの方が大きいため、基本的にはOn Error GoToを推奨します。
✅ まとめ
実行時エラー91と13は、VBAで最も頻繁に遭遇するエラーです。
エラー91対策:
- ✅ オブジェクト変数には必ずSetを付ける
- ✅ Is Nothingで存在チェック
- ✅ Findの戻り値は必ずチェック
エラー13対策:
- ✅ IsNumeric/IsDateで事前チェック
- ✅ 空白セルのチェックを忘れない
- ✅ .Valueで明示的に値を取得
デバッグ手法:
- ✅ F8キー(ステップ実行)でエラー箇所を特定
- ✅ F9キー(ブレークポイント)で高速デバッグ
- ✅ Debug.Printでログ出力
エラーハンドリング:
- ✅ 基本はOn Error GoToを使う
- ✅ On Error Resume Nextは最小限に
- ✅ 必ずOn Error GoTo 0で解除
この記事の汎用エラー対策テンプレートをコピーして、自分のコードに組み込んでください。
エラーが出たときは、まずF8キーでステップ実行してエラー箇所を特定し、Debug.Printで変数の値を確認しましょう。


コメント