Excel 在字典中用作键时范围的奇怪行为
我有以下代码:Excel 在字典中用作键时范围的奇怪行为,excel,vba,Excel,Vba,我有以下代码: Dim dicMyHash As Dictionary Dim rngMyRange As Range ' A1 is empty - although the outcome is the same in any case Set rngMyRange = Range("A1") Set dicMyHash = New Dictionary dicMyHash.Add Key:=rngMyRange(1), Item:=0 Debug.Print dicMyHash.Ex
Dim dicMyHash As Dictionary
Dim rngMyRange As Range
' A1 is empty - although the outcome is the same in any case
Set rngMyRange = Range("A1")
Set dicMyHash = New Dictionary
dicMyHash.Add Key:=rngMyRange(1), Item:=0
Debug.Print dicMyHash.Exists(rngMyRange(1).Value) ' returns False
Debug.Print rngMyRange(1) = rngMyRange(1).Value ' returns True
这种行为有些出乎意料。有什么类型的演员在幕后表演吗rngMyRange(1).Value
属性返回一个变量
,而rngMyRange(1)
是rngMyRange.项(1)
,它是一个范围
。但是,将rngMyRange(1)
转换为变量
会得到相同的结果
此外,添加键是按值进行的(因此rngMyRange(1)
的副本作为键传递)。但是我仍然不明白为什么存在没有找到密钥
提前谢谢你 我认为造成这种情况的原因是,rngMyRange
被认为是一个二维数组,两个数组维度都被传递到字典中
如果将向字典中添加元素的行更改为此行:
dicMyHash.Add Key:=rngMyRange(1).value, Item:=0
它开始像您期望的那样工作-两个检查点都返回true
调试代码时,您还可以在本地窗口中分析这种情况。我不确定您是如何使用它的,但这将返回True
:
Sub test()
Dim dicMyHash As Dictionary
Dim rngMyRange As Range
Set rngMyRange = Range("A1")
Set dicMyHash = New Dictionary
dicMyHash.Add Key:=rngMyRange(1).Value, Item:=0 ' assign it with Value
Debug.Print dicMyHash.Exists(rngMyRange(1).Value)
End Sub
这样你就有了一个项目,它的密钥是A1中的任何东西
我认为,如果没有值
,它将无法工作的原因是您正在为键
分配一个范围
。如果您将范围分配给字典的项,对我来说会更有意义。因此,在这里,我们传递了三个不同的值:
原始范围
范围.Value
,它是一个变量
词典内部的(1)的副本
如果你把这些和等号比较,它们都是一样的。但是根据字典的说法,它们都是不同的
为什么??对对象使用等号时,等号会强制对象调用其默认属性。Range
的默认属性是Range.Value
,这就是为什么r=r.Value
和r=r.Offset(0,0)
但对于一本字典来说,这并不聪明。想想看:每次调用Dictionary.Exists
都会导致用作键的每个对象调用其默认属性。这可能会非常昂贵,而且可能会引发很多副作用。因此,Dictionary.Exists
测试以下内容:
你在比较一个对象和一个非对象吗?自动失败
你在比较两个非项目吗?返回a=b
你在比较两个物体吗?返回a是b
因此r
与r.Value
不同,因为一个是对象,另一个是非对象。如果您复制了r
,就像r.Offset(0,0)
,它们也不相同,因为它们仍然指向两个不同的对象,即使对象具有相同的内容
另一方面,这将起作用,因为您将r
制作成与d.Keys(0)
相同的对象:
嗨,KazJew,谢谢-关于尺寸的观点很好。是的,传递值确实有效。。但是,将所有出现的rngMyRange(1)
替换为rngMyRange(1,1)
仍然像以前一样返回false
。好主意,重新设置Locals窗口
,将给它一个机会。因此,再次强调,传递rngMyRange(1,1)
仍然被识别为数组,但rngMyRange(1,1)。值
被识别为正确值,两个测试点的结果都是true
。哦,好的,我明白了。我还注意到,.exists(rngMyrange(1,1))
也给出了false
。这是因为rngMyrange(1,1)
作为二维数组复制到字典中吗?我宁愿说它没有正确地转换为从数组(1,1)维度获取值…嗨,道格,谢谢-我通常使用值,只是想知道为什么范围似乎不能作为键正常工作。还注意到,.Exists(rngMyRange(1))
在rngMyRange(1)
是键时返回false,并且想知道为什么会出现这种情况。。但是,是的,我会坚持使用value
。我投了赞成票,理由是上面的答案提供了一个解决办法。谢谢-因为Dictionary.Exists
可以像你上面描述的那样工作,其余的都是有意义的(并且在你的答案中设置r=d.Keys(0)
)。不过,我还是会使用更合理的键,绝对像r.Address
。在我的上下文中,我将自定义对象存储在该字典中,并使用它们的名称(字符串)作为键-我使用range.value
(使用.exists
检查重复项)从动态范围中获取。在某个时候,我引用了一个没有.value
部分的键,结果遇到了麻烦。感谢您的详细解释-非常有用!
Dim d As Scripting.Dictionary
Dim r As Range
Set r = [a1]
Set d = New Dictionary
d.Add r, 0
Set r = d.Keys(0)
Debug.Print d.Exists(r)