VBAのマクロを実行したら、突然コードが黄色くハイライトされて止まり、「実行時エラー ’91’: オブジェクト変数またはWithブロック変数が設定されていません」というメッセージが出た――。何を直せばいいのか分からず、画面の前で固まってしまった経験はありませんか。
結論から言うと、このエラーは「まだ何も入っていない空の箱(オブジェクト変数)を、中身があるものとして使おうとした」ときに起きます。多くの場合はSetの書き忘れか、参照先が見つからずに空になっているかのどちらかです。この記事では、実行時エラー91が出る7つの原因を症状別に整理し、コピペで直せる修正コードとあわせてご案内します。
- 症状別早見表:あなたの画面はどれ?
- そもそも「実行時エラー91」とは何が起きているのか
- 原因1:オブジェクト変数への代入で「Set」を書き忘れている(最多)
- 原因2:シート名の入力ミス・存在しないシートを参照している
- 原因3:Find・FindNextメソッドが見つからず、Nothingを返している
- 原因4:Withブロックの外で「.」から始まる書き方をしている
- 原因5:閉じた・削除されたオブジェクトを参照し続けている
- 原因6:For Eachループや条件分岐で、初期化前の変数を使っている
- 原因7:別のプロシージャに渡したオブジェクト変数が、途中で空になっている
- 迷ったときのチェックリスト+よくある質問
- まとめ:エラーメッセージは「敵」ではなく「道しるべ」です
症状別早見表:あなたの画面はどれ?
まずは黄色くハイライトされた行と、その手前で何をしていたかを見比べてください。
| 止まった行でしていたこと | 疑う原因 |
|---|---|
| オブジェクト型の変数に代入したはずの行の次で止まる | 原因1:Setキーワードの書き忘れ |
| シート名やセル範囲を指定した行で止まる | 原因2:シート名の入力ミス・存在しないシート参照 |
| Find・FindNextを使った直後の行で止まる | 原因3:Findが見つからずNothingを返している |
| Withブロックの外の行で「.」から始まる書き方をしている | 原因4:Withブロックの範囲外参照 |
| ブックやシートを閉じた後の行で止まる | 原因5:閉じた・削除されたオブジェクトへの参照 |
| For Eachループの1周目、または条件分岐の直後で止まる | 原因6:初期化前のオブジェクト変数の参照 |
| 別のプロシージャ(Sub/Function)を呼び出した後で止まる | 原因7:引数として渡したオブジェクト変数の受け渡しミス |

そもそも「実行時エラー91」とは何が起きているのか
直し方の前に、正体を知っておくと迷わなくなります。VBAでは、SheetやRange、Workbookのような「モノ」を扱う変数をオブジェクト変数と呼びます。数値や文字を入れる普通の変数と違い、オブジェクト変数は最初は必ず空(Nothing)の状態からスタートします。
この空の状態のまま「.Value」や「.Range」のように中身を使おうとすると、VBAは「その箱、まだ何も入っていませんよ」と教えてくれます。それがエラー91の正体です。データが壊れたのでも、パソコンの調子が悪いのでもありません。箱に中身を入れる一手間(Setによる代入)が、どこかで抜けているだけです。この挙動はMicrosoft公式のVBA言語リファレンスにも解説があります。

原因1:オブジェクト変数への代入で「Set」を書き忘れている(最多)
最も多いのがこのパターンです。VBAでは、数値や文字列を代入するときは=だけで済みますが、オブジェクト(SheetやRangeなど)を代入するときは先頭に必ず「Set」が必要です。これを忘れると、変数は空のまま次の行に進んでしまいます。
❌ つまずく書き方
Dim ws As Worksheet
ws = ThisWorkbook.Sheets("集計") ' Setがないため、wsは空のまま
ws.Range("A1").Value = "合計" ' ここで実行時エラー91
✅ こうすれば通る
Dim ws As Worksheet
Set ws = ThisWorkbook.Sheets("集計") ' Setを付けて代入
ws.Range("A1").Value = "合計" ' 正常に動作
見分け方は簡単です。Dimで宣言した型が「Worksheet」「Range」「Workbook」「Object」などモノの名前になっている変数には、代入のたびに必ずSetを付ける、と覚えてください。数値(Long、Integer)や文字列(String)にはSetは不要です。
原因2:シート名の入力ミス・存在しないシートを参照している
Sheets("集計")のようにシート名を直接書いている場合、そのシート名が1文字でも違うと、参照は失敗して変数はNothingのままになります。全角スペースが混じっている、シート名を後から変更した、コピーしたタブ名が「集計 (2)」になっている、といったケースが典型です。
直し方
- エラーが出た行のシート名を、実際のシートタブの表示と1文字ずつ見比べる
- タブ名をコピーして使う(手入力しない)
- シートが存在するかどうかを、事前にチェックする関数を挟む
存在確認は、次のような関数を用意しておくと毎回安心です。
Function シート存在確認(ByVal シート名 As String) As Boolean
Dim ws As Worksheet
On Error Resume Next
Set ws = ThisWorkbook.Sheets(シート名)
On Error GoTo 0
シート存在確認 = Not ws Is Nothing
End Function
❌ つまずく操作:シート名を見た目だけで判断し、末尾の半角スペースや全角スペースの混入に気づかない。
✅ こうすれば通る:上記の関数でFalseが返ってきたら、シート名を一度削除して再入力し、余計な空白が入っていないかを確認しましょう。
原因3:Find・FindNextメソッドが見つからず、Nothingを返している
Range.Findは、検索対象が見つからない場合にエラーを出さず、静かにNothingを返すという特徴があります。この性質を知らずに、見つかった前提ですぐ次の行を書いてしまうと、エラー91につながります。
❌ つまずく書き方
Dim 見つかったセル As Range
Set 見つかったセル = Range("A:A").Find("該当なしの文字列")
見つかったセル.Value = "OK" ' 見つからなければここで実行時エラー91
✅ こうすれば通る
Dim 見つかったセル As Range
Set 見つかったセル = Range("A:A").Find("該当なしの文字列")
If Not 見つかったセル Is Nothing Then
見つかったセル.Value = "OK"
Else
MsgBox "該当するデータが見つかりませんでした"
End If
このIf Not ○○ Is Nothing Thenという書き方は、Findに限らずオブジェクト変数を扱うVBAコード全体で頻出する「お守り」です。次に紹介するWithブロックや、原因7のプロシージャ間の受け渡しでも同じ考え方が使えます。

原因4:Withブロックの外で「.」から始まる書き方をしている
Withステートメントは、同じオブジェクトへの操作をまとめて短く書ける便利な機能ですが、Withブロックの外(End Withの後)で「.Range」のように「.」から書いてしまうと、何を指しているか分からずエラー91になります。
❌ つまずく書き方
With ThisWorkbook.Sheets("集計")
.Range("A1").Value = "合計"
End With
.Range("A2").Value = "件数" ' Withの外なので何を指すか不明→実行時エラー91
✅ こうすれば通る
With ThisWorkbook.Sheets("集計")
.Range("A1").Value = "合計"
.Range("A2").Value = "件数" ' Withブロックの内側に入れる
End With
コードを修正・追記しているうちに行がずれて、気づかないうちにEnd Withの外に「.」で始まる行がはみ出してしまう、というのはベテランでもよくやるミスです。エラーが出たら、まず止まった行がWithとEnd Withの間に収まっているかを確認しましょう。Withステートメントの正式な使い方は、Microsoft公式のこちらのページにまとまっています。

原因5:閉じた・削除されたオブジェクトを参照し続けている
Workbooks.CloseやSheets("○○").Deleteを実行した後も、以前にその中身を代入した変数はそのまま残っています。しかし参照先の実体はすでに存在しないため、その変数を使おうとするとエラー91になります。
典型パターン
Dim wb As Workbook
Set wb = Workbooks.Open("C:\data\売上.xlsx")
' ここで何か処理
wb.Close
wb.Sheets(1).Range("A1").Value = "済" ' 閉じた後なので実行時エラー91
✅ こうすれば通る:閉じる・削除する前に必要な値を読み取るか、変数へ入れておくところまでを終わらせてからCloseやDeleteを呼びましょう。処理の順番を「①必要な情報を取り出す → ②閉じる・削除する」の2段階に分けて書く癖をつけると、この種のミスを防げます。
原因6:For Eachループや条件分岐で、初期化前の変数を使っている
複数のオブジェクトから条件に合うものだけを探す処理でも、エラー91は起きやすいです。特に、ループの中で一度も条件に合わずループを抜けた後に、見つかった前提で変数を使ってしまうケースが典型です。
❌ つまずく書き方
Dim ws As Worksheet
Dim 対象 As Worksheet
For Each ws In ThisWorkbook.Worksheets
If ws.Name = "実績" Then
Set 対象 = ws
End If
Next ws
対象.Range("A1").Value = "完了" ' 「実績」シートが無ければ対象はNothingのまま
✅ こうすれば通る
Dim ws As Worksheet
Dim 対象 As Worksheet
For Each ws In ThisWorkbook.Worksheets
If ws.Name = "実績" Then
Set 対象 = ws
Exit For
End If
Next ws
If Not 対象 Is Nothing Then
対象.Range("A1").Value = "完了"
Else
MsgBox "「実績」という名前のシートが見つかりませんでした"
End If
ループの外に出た瞬間に「見つかったはず」と決めつけず、If Not 対象 Is Nothing Thenで一度確認する習慣が、エラー91を未然に防ぐ一番の近道です。
原因7:別のプロシージャに渡したオブジェクト変数が、途中で空になっている
Subプロシージャを分けて処理を整理していると、引数として渡したはずのオブジェクトが、呼び出し先で空(Nothing)のまま扱われることがあります。多くは、呼び出し元でSetを忘れたまま渡してしまうことが原因です。
Sub メイン処理()
Dim 対象シート As Worksheet
対象シート = ThisWorkbook.Sheets("集計") ' ここでSet忘れ
Call 書き込み処理(対象シート)
End Sub
Sub 書き込み処理(ByVal sh As Worksheet)
sh.Range("A1").Value = "処理済み" ' shが空のため実行時エラー91
End Sub
直し方は原因1と同じで、呼び出し元での代入にSetを付けるだけです。プロシージャをまたぐと原因の行から離れた場所でエラーが出るため気づきにくいので、エラーが出た行だけでなく、その変数がどこで最初に作られたかまで遡って確認するのがコツです。

迷ったときのチェックリスト+よくある質問
チェックリスト
- 止まった行の変数は、オブジェクト型(Worksheet/Range/Workbookなど)かを確認する
- その変数への代入行に「Set」が付いているかを確認する
- Find系メソッドを使っている場合は、直後に「Is Nothing」で判定を入れる
- Withブロックの中と外の境目(End With)がずれていないかを確認する
- 閉じた・削除したオブジェクトを、その後の行で使っていないかを確認する
- それでも直らなければ、変数名の上にカーソルを置いてローカルウィンドウで中身が「Nothing」になっていないか見る
Q. デバッグ画面が出たとき、まず何をすればいいですか?
あわてて「終了」を押さず、まず「デバッグ」ボタンで黄色くハイライトされた行を確認してください。そのうえで、Alt+F11でVBEを開き、止まった変数の上にマウスを乗せると現在の中身(Nothingかどうか)がポップアップで確認できます。
Q. On Error Resume Nextで回避してもいいですか?
一時的にエラーを黙らせることはできますが、根本原因が残ったまま次の処理に進んでしまい、後続の行で別のエラーや誤った結果につながることがあります。原因3で紹介したように、On Error Resume Nextは「存在確認」など目的が明確な場面に限定し、On Error GoTo 0で必ず元に戻す使い方が安全です。
Q. 実行時エラー1004とは何が違うのですか?
どちらも「思った通りに動かない」という点では似ていますが、エラー91は変数の中身が空(Nothing)であることが原因、エラー1004はExcel自体の操作(アプリケーション定義またはオブジェクト定義のエラー)が原因という違いがあります。エラー1004の7つの原因と直し方は、こちらの記事でコード例つきにまとめています。

まとめ:エラーメッセージは「敵」ではなく「道しるべ」です
「実行時エラー91」という表示を見ると、自分のコードがめちゃくちゃに壊れてしまったような気持ちになるかもしれません。でも実際には、VBAが「この箱、まだ空っぽですよ」と一箇所だけ丁寧に教えてくれているだけです。今日ご紹介した7つの原因のうち、まずは一番多い「Setの書き忘れ」から確認してみてください。
マクロがそもそも起動しない・ボタンを押しても反応しないという場合は、エラー91以前の入口の問題かもしれません。あわせてこちらもご覧ください。

エラーメッセージを1つずつ読み解けるようになるたびに、あなたの「VBAは難しそう」という苦手意識は少しずつ小さくなっていきます。焦らず、あなたのペースで大丈夫です。
あわせて読みたい記事はこちらです。






コメント