ここから本文です

□[Excel VBA]Dictionaryのアイテムに格納されたオブジェクト変数の有り無しを判定...

yasukiyonetさん

2010/4/2402:00:08

□[Excel VBA]Dictionaryのアイテムに格納されたオブジェクト変数の有り無しを判定する方法
--------

Dictionaryのアイテムに格納されたオブジェクト変数の有り無しを判定する方法について質問とさせていただきたいことがあります。

'------
Sub Sample1()
Dim rng As Range
''''Set rng = Range("A1")

If rng Is Nothing Then
Debug.Print "Sample1/T"
Else
Debug.Print "Sample1/F"
End If

End Sub


上と同じ要領で、キー(A)のアイテムにオブジェクト変数が格納されるか判定するマクロを作成しました↓。


'-------
Sub Sample2()
Dim Dic1 As Object

Set Dic1 = CreateObject("Scripting.Dictionary")
''''Set Dic1.Item("A") = Range("A1")


Debug.Print Dic1.Item("A") '''★回避策
If Dic1.Item("A") Is Nothing Then '''「オブジェクトが必要です」のエラー。
'''If IsEmpty(Dic1.Item("A")) Then←だと別の問題が発生する。※1
Debug.Print "Sample1/T"
Else
Debug.Print "Sample1/F"
End If

End Sub


If Dic1.Item("A") Is Nothing Thenでエラーになります。If Dic1.Item("A") Is Nothing Thenの場合Dic1.Item("A")に戻り値や「=」で設定しないからキーが作成されず、エラーになってしまうのだろうと考え、Sample2に「Debug.Print Dic1.Item("A") '''★回避策」を追加しましたが改善されませんでした。
※1:IsEmptyも格納したオブジェクト(セルの値)が空欄だとTrueを返してしまうため使えない。

別の回避策として、以下で判定出来ることを確認しました↓。


'-----
Sub Sample3()
Dim Dic1 As Object

Set Dic1 = CreateObject("Scripting.Dictionary")
''''Set Dic1.Item("A") = Range("A1")

MsgBox "If前" & Dic1.Count ''''この時点では0

If TypeName(Dic1.Item("A")) = "Empty" Then
Debug.Print "Sample1/T"
Else
Debug.Print "Sample1/F"
End If

MsgBox "If後" & Dic1.Count ''''この時点では1

End Sub
'------

Sample2と3の結果からEmptyキーワードやDicのItemプロパティをヘルプを確認し以下の見解に至りました。
「設定されていないキーを取得しようとしたとき関連付けられる項目は"バリアント型"の空欄を格納している。」

上の見解は正しいのでしょうか?またTypeName関数以外でオブジェクト変数の有り無しを判定する方法はないものでしょうか?

閲覧数:
5,498
回答数:
3
お礼:
50枚

違反報告

ベストアンサーに選ばれた回答

fortunecityさん

2010/4/2610:56:21

>TypeName関数以外でオブジェクト変数の有り無しを判定する方法はないものでしょうか?

If VarType(Dic1.Item("A")) = vbEmpty Then
でも判定できると思います。

質問した人からのコメント

2010/4/27 11:32:49

降参 みなさま回答ありがとうございました。上でも本件はクリアすることを確認しました。繰り返しの処理をした場合等未検証ですが、おそらく問題ないだろうと思いこちらをBAにさせていただきます。

ベストアンサー以外の回答

1〜2件/2件中

並び替え:回答日時の
新しい順
|古い順

neko8nosukeさん

編集あり2010/4/2405:32:16

まず、検索をしませんか?

大抵のサンプルは、いきなりアイテムにアクセスせず
辞書内の有無を確認してから、アクセスしています。

Sub Sample3() ’☆要参照設定。
Dim Dic1 As Scripting.Dictionary

Set Dic1 = New Scripting.Dictionary
'Set Dic1.Item("A") = Range("A1")

If Dic1.Exists("A") Then
Debug.Print "Aあり" 'この時点では存在しないので、ここには入らない。
If TypeOf Dic1.Item("A") Is Object Then
Debug.Print "Is Object" ''ここまで入ってくるのは、Objectのみ。
End If
End If

If TypeName(Dic1.Item("A")) = "Empty" Then 'アクセスしたので、自動作成される。
Debug.Print "Sample1/T"
Else
Debug.Print "Sample1/F"
End If

If Dic1.Exists("A") Then
Debug.Print "Aあり" 'この時点では存在するので、ここに入る。
End If
End Sub

これはきっと、アイテムにアクセスすると
自動で作られてしまうからなのでしょうね^^;

編集あり2010/4/2403:55:06

>「設定されていないキーを取得~"バリアント型"の空欄を格納している。」
その通りだと思います。

DictionaryやCollectionのItemに登録する型は不特定の為
Variant型になっています。
そしてVariant型は他の型(※)と異なり、型宣言から値(型)が代入されるまで
Emptyという特殊な値を取ります。
※他の型:Stringは、長さ0の文字列("")を
__________:Integer等数値型は、0を
__________:オブジェクト変数等は、Nothingを
__________VBAコンパイラが型宣言から判断して自動的に代入する
__________そのため、Long型の変数lngRow = Emptyとしても0に変換される

>TypeName関数以外でオブジェクト変数の有り無しを判定~
上記の場合、TypeNameの式もIsEmptyの式も同値かと思います。
冗長ですが、オブジェクト変数の有無を判定するとしたらこんな感じでは?

Sub Sample4()
Dim Dic1 As Object
Dim rngDummy As Range '/初期値:Nothing
Set Dic1 = CreateObject("Scripting.Dictionary")
Set Dic1.Item("A") = rngDummy
If IsEmpty(Dic1.Item("A")) = True Then
Debug.Print "値(型):未代入"
Else
Debug.Print "値(型):代入済"
If Dic1.Item("A") Is Nothing Then
Debug.Print "オブジェクト変数:Nothing" '←今回はこれが表示
Else
Debug.Print "オブジェクト変数:Nothing以外"
End If
End If
End Sub

※ちょっと分かりづらかったかもスミマセン。。

あわせて知りたい

みんなで作る知恵袋 悩みや疑問、なんでも気軽にきいちゃおう!

Q&Aをキーワードで検索:

Yahoo! JAPANは、回答に記載された内容の信ぴょう性、正確性を保証しておりません。
お客様自身の責任と判断で、ご利用ください。
本文はここまでです このページの先頭へ

「追加する」ボタンを押してください。

閉じる

※知恵コレクションに追加された質問や知恵ノートは選択されたID/ニックネームのMy知恵袋で確認できます。