PR
アフィリエイト広告を利用しています
アフィリエイト広告を利用しています

【止まらない】VBA「実行時エラー91」の原因7つと直し方|オブジェクト変数またはWithブロック変数が設定されていません

親しみやすいIT講師がVBAのコードを指し示して説明している様子 EXCEL VBA講座
スポンサーリンク

VBAのマクロを実行したら、突然コードが黄色くハイライトされて止まり、「実行時エラー ’91’: オブジェクト変数またはWithブロック変数が設定されていません」というメッセージが出た――。何を直せばいいのか分からず、画面の前で固まってしまった経験はありませんか。

結論から言うと、このエラーは「まだ何も入っていない空の箱(オブジェクト変数)を、中身があるものとして使おうとした」ときに起きます。多くの場合はSetの書き忘れか、参照先が見つからずに空になっているかのどちらかです。この記事では、実行時エラー91が出る7つの原因を症状別に整理し、コピペで直せる修正コードとあわせてご案内します。

スポンサーリンク

症状別早見表:あなたの画面はどれ?

まずは黄色くハイライトされた行と、その手前で何をしていたかを見比べてください。

止まった行でしていたこと 疑う原因
オブジェクト型の変数に代入したはずの行の次で止まる 原因1:Setキーワードの書き忘れ
シート名やセル範囲を指定した行で止まる 原因2:シート名の入力ミス・存在しないシート参照
Find・FindNextを使った直後の行で止まる 原因3:Findが見つからずNothingを返している
Withブロックの外の行で「.」から始まる書き方をしている 原因4:Withブロックの範囲外参照
ブックやシートを閉じた後の行で止まる 原因5:閉じた・削除されたオブジェクトへの参照
For Eachループの1周目、または条件分岐の直後で止まる 原因6:初期化前のオブジェクト変数の参照
別のプロシージャ(Sub/Function)を呼び出した後で止まる 原因7:引数として渡したオブジェクト変数の受け渡しミス
ノートPCの前で困った表情の40代男性に、講師が優しく画面を指さして説明している様子

そもそも「実行時エラー91」とは何が起きているのか

直し方の前に、正体を知っておくと迷わなくなります。VBAでは、SheetやRange、Workbookのような「モノ」を扱う変数をオブジェクト変数と呼びます。数値や文字を入れる普通の変数と違い、オブジェクト変数は最初は必ず空(Nothing)の状態からスタートします。

この空の状態のまま「.Value」や「.Range」のように中身を使おうとすると、VBAは「その箱、まだ何も入っていませんよ」と教えてくれます。それがエラー91の正体です。データが壊れたのでも、パソコンの調子が悪いのでもありません。箱に中身を入れる一手間(Setによる代入)が、どこかで抜けているだけです。この挙動はMicrosoft公式のVBA言語リファレンスにも解説があります。

Object variable not set (Error 91)
VBA language reference

原因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. エラーが出た行のシート名を、実際のシートタブの表示と1文字ずつ見比べる
  2. タブ名をコピーして使う(手入力しない)
  3. シートが存在するかどうかを、事前にチェックする関数を挟む

存在確認は、次のような関数を用意しておくと毎回安心です。

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のプロシージャ間の受け渡しでも同じ考え方が使えます。

ホワイトボードにSetと書いて丸をつけながら真剣に説明する先生

原因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公式のこちらのページにまとまっています。

Using With statements (VBA)
VBA language reference

原因5:閉じた・削除されたオブジェクトを参照し続けている

Workbooks.CloseSheets("○○").Deleteを実行した後も、以前にその中身を代入した変数はそのまま残っています。しかし参照先の実体はすでに存在しないため、その変数を使おうとするとエラー91になります。

典型パターン

Dim wb As Workbook
Set wb = Workbooks.Open("C:\data\売上.xlsx")
' ここで何か処理
wb.Close
wb.Sheets(1).Range("A1").Value = "済"   ' 閉じた後なので実行時エラー91

✅ こうすれば通る:閉じる・削除する前に必要な値を読み取るか、変数へ入れておくところまでを終わらせてからCloseDeleteを呼びましょう。処理の順番を「①必要な情報を取り出す → ②閉じる・削除する」の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を付けるだけです。プロシージャをまたぐと原因の行から離れた場所でエラーが出るため気づきにくいので、エラーが出た行だけでなく、その変数がどこで最初に作られたかまで遡って確認するのがコツです。

マクロのエラーが直り、男性がガッツポーズで喜び講師も一緒に笑顔になっている様子

迷ったときのチェックリスト+よくある質問

チェックリスト

  1. 止まった行の変数は、オブジェクト型(Worksheet/Range/Workbookなど)かを確認する
  2. その変数への代入行に「Set」が付いているかを確認する
  3. Find系メソッドを使っている場合は、直後に「Is Nothing」で判定を入れる
  4. Withブロックの中と外の境目(End With)がずれていないかを確認する
  5. 閉じた・削除したオブジェクトを、その後の行で使っていないかを確認する
  6. それでも直らなければ、変数名の上にカーソルを置いてローカルウィンドウで中身が「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つの原因と直し方は、こちらの記事でコード例つきにまとめています。

VBA「実行時エラー 1004」の原因7つと直し方|アプリケーション定義またはオブジェクト定義のエラー
VBAの「実行時エラー 1004(アプリケーション定義またはオブジェクト定義のエラー)」は、[デバッグ]で黄色く光る行を見れば原因が特定できます。シート名の指定ミス、閉じたブック、Range範囲、Select、保護、PasteSpecial、結合セルの7原因を、❌ダメな書き方→✅直した書き方のコピペ可VBAコード付きで解説します。

まとめ:エラーメッセージは「敵」ではなく「道しるべ」です

「実行時エラー91」という表示を見ると、自分のコードがめちゃくちゃに壊れてしまったような気持ちになるかもしれません。でも実際には、VBAが「この箱、まだ空っぽですよ」と一箇所だけ丁寧に教えてくれているだけです。今日ご紹介した7つの原因のうち、まずは一番多い「Setの書き忘れ」から確認してみてください。

マクロがそもそも起動しない・ボタンを押しても反応しないという場合は、エラー91以前の入口の問題かもしれません。あわせてこちらもご覧ください。

【動かない人へ】エクセルのマクロが実行できない原因7つと直し方|有効化・ブロック解除・xlsm保存
エクセルのマクロが実行できない原因は、ほとんど3つ。黄色いバーの「コンテンツの有効化」、赤いバー「セキュリティ リスク」のブロック解除、.xlsmでの保存です。症状別の早見表から、開発タブ・ボタン無反応・トラストセンター設定まで、7つの原因を手順つきで直します。

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

あわせて読みたい記事はこちらです。

【動かない人へ】エクセルのマクロが実行できない原因7つと直し方|有効化・ブロック解除・xlsm保存
エクセルのマクロが実行できない原因は、ほとんど3つ。黄色いバーの「コンテンツの有効化」、赤いバー「セキュリティ リスク」のブロック解除、.xlsmでの保存です。症状別の早見表から、開発タブ・ボタン無反応・トラストセンター設定まで、7つの原因を手順つきで直します。
VBA「実行時エラー 1004」の原因7つと直し方|アプリケーション定義またはオブジェクト定義のエラー
VBAの「実行時エラー 1004(アプリケーション定義またはオブジェクト定義のエラー)」は、[デバッグ]で黄色く光る行を見れば原因が特定できます。シート名の指定ミス、閉じたブック、Range範囲、Select、保護、PasteSpecial、結合セルの7原因を、❌ダメな書き方→✅直した書き方のコピペ可VBAコード付きで解説します。
【コピペで解決】エクセルで数値が「文字列」になって合計できない!直し方まとめ
数字を入れたのに合計できないのは「文字列」化が原因。緑の三角マークや区切り位置での一括変換、VALUE関数など、コピペで使える直し方を初心者にもやさしく解説します。
【コピペOK】エクセルで行挿入しても合計がずれない5つの方法|SUM範囲を自動で広げる設定
「行を追加したのに合計が増えない」を今日で終わりに。結論はテーブル化(Ctrl+T)です。テーブルが使えない場合の範囲指定・列全体・SUBTOTAL・OFFSETまで、コピペできる数式つきで5つの方法を解説します。

コメント

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