【実行時エラー ‘91’: オブジェクト変数または With ブロック変数が設定されていません。】の対処法です。
実行時エラー ‘91’:
オブジェクト変数または With ブロック変数が設定されていません。
チェック 1 - Level 0 -
Setを忘れてませんか?
VBAの変数にはSet不要なデータ型とSetが必要なデータ型(オブジェクト型)があります。
- Set不要なデータ型:String, Integer, Long, Float, Double, Booleanなど基本的なもの
- Setが必要なデータ型(オブジェクト型):上記以外
※ざっくりです。
Sub SampleError2_1()
Dim SomethingStr As String
SomethingStr = "Hello" 'Setはいらないので問題無し
Dim SomethingWs As Worksheet
SomethingWs = ActiveSheet 'Setが必要です!!ここでエラー
'Set SomethingWs = ActiveSheet 'こう書きます
End Sub
ちなみにSet不要なStringやInteger変数にSetを使用すると。。。
Dim SomethingStr As String
Set SomethingStr = "Hello"
チェック 2 - Level 1 -
Functionの戻り値は大丈夫ですか?
上の例では間違いが明白ですが、Functionの戻り値を受け取る場合、うっかりSetを忘れる場合があります。
特にFunctionの戻り値の方が"Variant"※1でぼかされている場合は、確認※2が必要です。
Sub SampleError2_2()
Dim SomethingStr As String
SomethingStr = ReturnStr 'Setはいらないので問題無し
Dim SomethingWs As Worksheet
SomethingWs = ReturnWs 'Setが必要です!!ここでエラー
'Set SomethingWs = ReturnWs 'こう書きます
Debug.Print TypeName(ReturnStr), TypeName(ReturnWs) '※2 戻り値の型を確認
End Sub
Function ReturnStr() As Variant
ReturnStr = "Hello"
End Function
Function ReturnWs() As Variant
Set ReturnWs = ActiveSheet
End Function
※1 Variant型:どんな型でも格納可能な万能型です。多用すると疎まれます。
※2 TypeNameで調べてもよし、ウォッチで確認してもよし。
チェック 3 - Level 1 -
Nothingだったりしませんか?
オブジェクト使用後にNothingを設定すると、メモリが解放されて何かとよろしいようです。
ただ、この『Nothing』にセットされたオブジェクトに対して何か操作しようとすると『実行時エラー ‘91’』が表示されます。
Sub SampleError2_3()
Dim SomethingWs As Worksheet
Set SomethingWs = ActiveSheet
'---
'SomethingWsに対していろいろ処理したとします。
'---
Set SomethingWs = Nothing '適切にNothing化します。
Debug.Print SomethingWs.Range("A1").Value 'SomethingWsはすでにNothingです!!ここでエラー
End Sub
チェック 4 - Level 2 -
Excelデータに対してFindしてませんか?
上の例では間違いが明白ですが、Excelシート上のデータを検索してヒットしなかった場合、Nothingが返ってきます。
『必ずヒットする!!』前提でコードを書いていると『実行時エラー ‘91’』を食らうかもしれません。
Sub SampleError2_4()
Dim HitRange As Range
Set HitRange = ActiveSheet.Range("A1:B1").Find("文字列") 'ヒットします
Dim NoHitRange As Range
Set NoHitRange = ActiveSheet.Range("A1:B1").Find(200) 'ヒットしません
Debug.Print HitRange.Value, NoHitRange.Value 'NoHitRangeはNothingです!!ここでエラー
End Sub
チェック 5 - Level 3 -
Withの中にダイブしてませんか?
VBAのコードを見やすくするためにWithを使うケースが多々あると思います。エレガントにWithを使いこなすVBAエンジニアはさぞかし尊敬の的であることでしょう。
ただ、GoTo文でWith外部からいきなりWith内部に飛び込むコードは『実行時エラー ‘91’』を食らうので注意が必要です。エラー処理で使用する『On Error GoTo ・・・※補足』でも同様です。
Sub SampleError2_5()
Dim HitInt As Integer
Dim HitStr As String
GoTo DIVE 'ここからWith内部へダイブ!
With ActiveSheet
HitInt = .Range("A1").Value
DIVE: 'ここへダイブ!
HitStr = .Range("B1").Value 'With ActiveSheet行を飛ばして実行される!!ここでエラー
End With
End Sub
ちなみにWithの外側で.Rangeを使用すると。。。
Sub SampleError2_5_x()
Dim HitInt As Integer
Dim HitStr As String
With ActiveSheet
HitInt = .Range("A1").Value
End With
HitStr = .Range("B1").Value
End Sub
※補足
文頭に『On Error GoTo ・・・』を記入すると便利です。
ユーザに『実行時エラー』を見せるのは恥ずかしいですよね。
エラー処理を一点に集約してユーザフレンドリーなメッセージを表示させましょう。
Sub SampleError2_5_y()
On Error GoTo ErrHandler '文頭に記入
'---
'ここでどんなエラーが発生してもErrHandlerに処理が移ります。
Dim x As Integer: x = 1 / 0 '例えば「0」で割ります
'---
ErrHandler:
MsgBox "下記のエラーが発生しました。担当者XXX(内線:XXXX)にご連絡ください。" & vbCrLf & vbCrLf & "Error(" & Err.Number & ") 『" & Err.Description & "』"
End Sub