在字典中用作键时范围的奇怪行为

时间:2013-05-24 20:02:26

标签: excel-vba vba excel

我有以下代码:

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属性返回variant,而rngMyRange(1)rngMyRange.item(1),这是range。但是,将rngMyRange(1)投射到Variant会得到相同的结果。

此外,按键添加键(因此rngMyRange(1)的副本作为键传递)。但我仍然无法理解为什么.Exists找不到钥匙..

提前谢谢!

3 个答案:

答案 0 :(得分:3)

所以在这里,我们传递了三个不同的值:

  1. 原始范围。
  2. Range.Value,这是一种变体。
  3. 字典内部的(1)副本。
  4. 如果将它们与等号相比较,它们都是一样的。但根据Dictionary.Exists,他们所有不同。

    为什么呢?对象使用等号时,等号会强制对象调用其默认属性。 Range的默认属性为Range.Value,这就是r = r.Valuer = r.Offset(0, 0)的原因。

    但对于字典来说,这并不是那么聪明。考虑一下:Dictionary.Exists的每次调用都会导致用作密钥的每个对象调用其默认属性。这可能会变得非常昂贵,并且可能会引发很多副作用。因此,Dictionary.Exists测试以下内容:

    1. 您是在将对象与非对象进行比较吗?自动失败。
    2. 你在比较两个非对象吗?返回a = b
    3. 你在比较两个物体吗?返回a Is b
    4. 所以rr.Value不同,因为一个是对象而另一个是非对象。如果您创建r副本,与r.Offset(0, 0)一样,那些也不一样,因为它们仍指向两个不同的对象,即使这些对象具有相同的内容

      另一方面,工作,因为您将r变为d.Keys(0)相同的对象

      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)
      

答案 1 :(得分:1)

我认为你的情况的原因是rngMyRange被识别为二​​维数组,并且两个数组维都被传递到你的字典。

如果您将将元素添加到Dictionary中的行更改为:

dicMyHash.Add Key:=rngMyRange(1).value, Item:=0

它开始按预期工作 - 两个检查点都返回true

您可以在调试代码的同时在Locals Window中分析这种情况。

答案 2 :(得分:0)

我不确定你如何使用它,但这将返回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它无效的原因是您要为Range分配Key。如果你将范围分配给字典的项目,那对我来说会更有意义。