Excel VBAのエラー91の対処法をお探しですね。

広告

Excel VBAの「エラー91」が出たときの直し方──原因別に分かりやすく解説

Excel VBAで「実行時エラー ’91’:オブジェクト変数またはWithブロック変数が設定されていません」と表示されると、どこを直せばいいのか分かりにくいですよね。

コード上では変数名も合っているし、シートやセルもちゃんと指定しているつもりなのに止まってしまうので、特に初心者の方ほど原因を見失いがちです。

この記事では、エラー91が起きる仕組みを整理しながら、Setの付け忘れ、Nothingの確認、Withブロック、Findの戻り値など、よくある原因別に直し方を紹介していきます。

エラー91は「オブジェクトが入っていない変数を使った」ときに起きる

Excel VBAのエラー91は、ひとことで言うと「オブジェクト変数に有効な参照が入っていないのに、その変数を使おうとした」ときに発生します。

ここでいうオブジェクトとは、Worksheet(シート)、Range(セル範囲)、Workbook(ブック)、Chart(グラフ)など、Excel上の部品を表すものです。

たとえば、`ws.Cells(1, 1).Value = “A”` のように書いた場合、`ws` にはどこかのワークシートが入っている必要があります。

もし `ws` が空っぽのままだと、VBAは「どのシートのCellsを操作すればいいの?」と判断できず、エラー91で処理を止めてしまうわけです。

このエラーを理解するうえで大事なのは、文字列や数値の変数と、シートやセルのようなオブジェクト変数では**代入の仕方が違う**という点です。

`String` や `Long` などの普通の値は `name = “田中”`、`count = 10` のように代入できますよね。

でも、`Worksheet` や `Range` などのオブジェクトを変数に入れる場合は、**原則として `Set` を使います**。

`Dim ws As Worksheet` と宣言しただけでは、箱を用意しただけで中身のシートはまだ入っていません。

つまり、宣言と代入は別物だと考えると分かりやすくなります。

エラー91が出たときは、まずエラーで黄色く止まった行を確認して、その行で使われているオブジェクト変数を見てみましょう。

`ws.Cells` で止まったなら `ws`、`rng.Address` で止まったなら `rng`、`With ws` の中の `.Range` で止まったなら `ws` やWithの対象が怪しいです。

原因を探すときは、止まった行そのものだけでなく、**その変数に値を入れているはずの行までさかのぼる**ことが大切です。

VBEのローカルウィンドウやウォッチ式で変数の値を確認すると、`Nothing`(空っぽ)になっているかどうかを判断しやすくなります。

Setの付け忘れと初期化漏れを確認する

一番よくある原因は、オブジェクト変数に代入するときの **`Set` の付け忘れ**です。

たとえば、`Dim ws As Worksheet` と宣言したあとに `ws = Worksheets(“Sheet1”)` と書くと、ワークシートというオブジェクトを正しく代入できません。

VBAでは、WorksheetやRangeのようなオブジェクトを変数に入れるとき、**`Set ws = Worksheets(“Sheet1”)` のように書く必要があります**。

Setは「この変数は、このオブジェクトを参照します」とVBAに伝えるためのものです。

“`vb
Sub Sample_Set()
Dim ws As Worksheet

Set ws = ThisWorkbook.Worksheets(“Sheet1”)
ws.Cells(1, 1).Value = “OK”
End Sub
“`

また、Setを正しく書いていても、**そもそも代入処理が実行されていなければ**エラー91になります。

たとえば、条件分岐の中だけで `Set ws = …` をしていて、その条件に入らなかった場合、`ws` は空のままです。

その後に `ws.Range(“A1”).Value` のような処理を実行すると、オブジェクト変数が設定されていない状態で参照するためエラーになります。

つまり、コードのどこかにSetがあるかどうかだけでなく、**エラー発生時の実行経路で本当にSetが通っているか**を確認する必要があります。

次のように、使う前に **`Is Nothing` で確認する**と原因を切り分けやすくなります。

`Nothing` は「オブジェクト変数が何も参照していない状態」を表すキーワードです。

`If Not ws Is Nothing Then` は「wsが空でなければ処理する」という意味になります。

毎回すべての行で確認する必要はありませんが、外部ファイル、シート名、検索結果など、状況によって取得できない可能性があるものには入れておくと安全です。

“`vb
Sub Sample_CheckNothing()
Dim ws As Worksheet

On Error Resume Next
Set ws = ThisWorkbook.Worksheets(“Sheet1”)
On Error GoTo 0

If Not ws Is Nothing Then
ws.Cells(1, 1).Value = “処理できます”
Else
MsgBox “対象のシートが見つかりません。


End If
End Sub
“`

WithブロックとGoToまわりのエラー91を直す

**`With…End With`** は、同じオブジェクトに対する処理を短く書ける便利な構文です。

たとえば `With ws` と書けば、その中では `.Range(“A1”)` のように先頭のオブジェクト名を省略できます。

でも、Withの対象である `ws` がNothingのままだと、ブロック内で `.Cells` や `.Range` を使った時点でエラー91が発生します。

見た目には `.Range` の行で止まるため、Range指定が間違っているように見えることがありますが、**実際にはWithの対象が設定されていないケース**が多いです。

“`vb
Sub Sample_With()
Dim ws As Worksheet
Set ws = ThisWorkbook.Worksheets(“Sheet1”)

With ws
.Range(“A1”).Value = “OK”
.Range(“A2”).Value = “Withブロック内の処理”
End With
End Sub
“`

Withブロックで特に注意したいのが、**`GoTo` によってWithの途中へジャンプするコード**です。

VBAでは、`With ActiveSheet` の行が実行されて初めて、ドットから始まる `.Range` や `.Cells` の対象が決まります。

ところが、`GoTo` でWithブロックの内側に直接飛び込むと、Withの初期化が行われていないため、`.Range` の対象が存在しません。

その結果、エラー91が発生します。

エラー処理でよく使われる `On Error GoTo ErrHandler` でも、ジャンプ先の位置によっては同じ問題が起きるため、**エラー処理ラベルをWithブロックの内側に置く書き方は避ける**のが安全です。

エラー処理を書く場合は、通常処理とエラー処理を分けて、**Withブロックの外側にラベルを置く**構成にすると読みやすくなります。

Withの中にジャンプさせるのではなく、エラーが起きたら後片付けやメッセージ表示に移る、という流れにするのが基本です。

また、GoToを通常の処理分岐に多用すると、どの変数が初期化済みなのか追いにくくなります。

エラー91を減らすという意味でも、条件分岐は `If` や `Select Case` を使い、GoToはエラーハンドリングなど必要最小限にとどめるといいでしょう。

Findの戻り値やNothing代入後の使用を安全に直す

Excel VBAでエラー91がよく起きる場面に、**`Find` メソッドの結果を使う処理**があります。

`Range.Find` は、検索値が見つかった場合は該当セルのRangeオブジェクトを返しますが、**見つからなかった場合は `Nothing` を返します**。

そのため、検索結果が必ず存在する前提で `rng.Address` や `rng.Value` を実行すると、検索に失敗したときにエラー91になります。

Findを使うときは「見つからない場合がある」ことを前提に、**必ずNothingチェックを挟む**のが基本です。

“`vb
Sub Sample_Find()
Dim rng As Range

Set rng = ThisWorkbook.Worksheets(“Sheet1”).Range(“A1:A10″).Find(What:=”検索値”, LookAt:=xlWhole)

If Not rng Is Nothing Then
MsgBox “見つかりました: ” & rng.Address
Else
MsgBox “検索値が見つかりませんでした。


End If
End Sub
“`

同じ考え方は、ユーザーフォームのコントロール、開いているブック、存在するか分からないシートなどを扱う場合にも当てはまります。

取得に失敗する可能性があるオブジェクトは、**使う前に存在確認を行う**ことでエラーを防げます。

また、一度 `Set ws = Nothing` のように変数を空にしたあと、その変数を再び使ってしまうケースにも注意が必要です。

処理の最後でNothingを代入すること自体は問題ありませんが、その後に追加したコードが同じ変数を参照するとエラー91になります。

後からマクロを修正したときに起きやすいので、Nothingを代入する位置は「本当にその変数をもう使わない場所」に置きましょう。

エラー91を直すときは、次の順番で確認すると効率的です。

1. **黄色く止まった行にあるオブジェクト変数を特定する**
2. **その変数が `Set` されているか、そして実行時にそのSet行を通っているかを確認する**
3. **Findなどの結果がNothingになる可能性や、Withブロックが正しく開始されているかを見る**

配列をオブジェクトのように扱っている場合や、型を省略して `Dim x` のように宣言している場合も原因の切り分けを難しくするため、変数にはできるだけ明確な型を指定するのがおすすめです。

実務で予防するなら、**`Option Explicit` をモジュール先頭に書き**、変数の宣言漏れを防ぐことから始めると効果的です。

さらに、`Dim ws As Worksheet`、`Dim rng As Range` のように型を明示し、オブジェクト変数にはSetを使う習慣を徹底します。

検索や取得に失敗する可能性がある処理では `If Not 変数 Is Nothing Then` を使い、存在しない場合のメッセージや処理分岐も用意しておきます。

Excel VBAの「オブジェクト変数またはWithブロック変数が設定されていません(エラー91)」は、原因さえ分かれば多くがケアレスミスや確認不足です。

止まった行だけを眺めるのではなく、**「そのオブジェクト変数には、いつ、何がSetされたのか」を追うこと**が、もっとも確実な直し方です。

広告