0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Excel VBAエラー逆引き② 【実行時エラー ‘91’: オブジェクト変数または With ブロック変数が設定されていません。】

Posted at

【実行時エラー ‘91’: オブジェクト変数または With ブロック変数が設定されていません。】の対処法です。

image.png

実行時エラー ‘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"

コンパイルエラーです。
image.png

チェック 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で調べてもよし、ウォッチで確認してもよし。

image.png

チェック 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’』を食らうかもしれません。

image.png

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 ・・・※補足』でも同様です。

image.png

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

コンパイルエラーです。
image.png

※補足

文頭に『On Error GoTo ・・・』を記入すると便利です。
ユーザに『実行時エラー』を見せるのは恥ずかしいですよね。
image.png

エラー処理を一点に集約してユーザフレンドリーなメッセージを表示させましょう。

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

image.png

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?