実行時エラー91「オブジェクト変数または With ブロック変数が設定されていません」の原因と直し方
実行時エラー91は、中身が空(Nothing)のオブジェクト変数を使おうとしたときに起きます。Set の書き忘れ、Find で見つからなかった場合など、よくある原因ごとに直し方を解説します。
どんなエラーか
実行時エラー91は、「オブジェクトを入れるための変数に、まだ何も入っていない(Nothing の)状態で、その変数のプロパティやメソッドを使おうとした」ときに表示されます。Worksheet 型や Range 型の変数は、宣言しただけでは中身が空で、Set で何かを入れて初めて使えるようになります。
エラーで止まった行には、たいてい「変数名.何か」という書き方があります。その変数に Set が実行されているか、Set した結果が Nothing になっていないかを確認するのが、原因を探す近道です。
原因1:Set を書き忘れている
最も多いのが、オブジェクト変数への代入に Set を付け忘れるケースです。数値や文字列の変数と同じ感覚で「ws = ...」と書くと、ws に中身が入らないままになり、エラー91になります。
' エラーになる書き方
Sub BadSample()
Dim ws As Worksheet
ws = ThisWorkbook.Worksheets("売上") ' Set がないのでエラー91
ws.Range("A1").Value = "集計日"
End Sub
' 正しい書き方
Sub GoodSample()
Dim ws As Worksheet
Set ws = ThisWorkbook.Worksheets("売上")
ws.Range("A1").Value = "集計日"
End Sub原因2:Find で見つからなかった
Range.Find は、探している値が見つからないと Nothing を返します。見つかる前提で「.Row」などを続けて書くと、データがない日にだけエラー91で止まる、という分かりにくい不具合になります。Find の結果は必ず変数に受け、Is Nothing で確認してから使います。
Sub FindCustomer()
Dim ws As Worksheet, hit As Range
Set ws = ThisWorkbook.Worksheets("顧客一覧")
Set hit = ws.Range("A:A").Find(What:="C1024", LookIn:=xlValues, LookAt:=xlWhole)
If hit Is Nothing Then
MsgBox "顧客コード C1024 は見つかりませんでした"
Exit Sub
End If
MsgBox "顧客コード C1024 は " & hit.Row & " 行目です"
End Subそのほかのよくある原因
ほかにも、次のような場面でエラー91が起きます。いずれも「変数に Set されないまま使われている」という点は共通です。
- If 文の中でだけ Set していて、条件に合わなかったときに Set されないまま使っている
- モジュールの先頭で宣言した変数を、別のマクロで Set してから使う設計になっていて、その準備のマクロを実行していない
- コードを編集したり「リセット」したりして、モジュール変数の中身が消えている
- With ブロックの外から GoTo で With の中の行へ飛び込んでいる
- On Error Resume Next を付けて Set した行が失敗し、変数が Nothing のまま次の行へ進んでいる
原因を見つける手順と予防策
エラーのダイアログで「デバッグ」を押すと、止まった行が黄色で表示されます。その行で使っているオブジェクト変数にマウスを重ねるか、イミディエイトウィンドウで「? 変数名 Is Nothing」と入力すると、中身が空かどうかを確認できます。True と表示されれば、その変数に Set されていないことが原因です。
予防策としては、オブジェクト変数を Set した直後に Is Nothing で確認する習慣を付けることです。特に Find、Dictionary から取り出したオブジェクト、On Error Resume Next を付けて取得したシートやブックは、取得に失敗しても次の行に進んでしまうため、確認を省略しないようにします。Find は前回の検索条件を引き継ぐ性質もあるので、LookIn や LookAt を毎回指定しておくと、見つかるはずの値が見つからないという事態も防げます。