Vba 为什么可以';字典键不能变成单元格吗?
我在处理更复杂的代码时遇到了麻烦,而且我还没有完全理解字典,所以我构建了一个非常基本、简单的测试表来了解它们是如何工作的。a-c列顶部只有三个条目,分别是“first”、“do”和“alpha”(目标是最终确保我理解嵌套字典,尽管这个问题并没有涉及到这一点) 代码是:Vba 为什么可以';字典键不能变成单元格吗?,vba,excel,Vba,Excel,我在处理更复杂的代码时遇到了麻烦,而且我还没有完全理解字典,所以我构建了一个非常基本、简单的测试表来了解它们是如何工作的。a-c列顶部只有三个条目,分别是“first”、“do”和“alpha”(目标是最终确保我理解嵌套字典,尽管这个问题并没有涉及到这一点) 代码是: Sub testing() Dim dict As New Scripting.Dictionary dict.Add Key:=Cells(1, 1), Item:=Cells(1, 2) MsgBox dict(Cells
Sub testing()
Dim dict As New Scripting.Dictionary
dict.Add Key:=Cells(1, 1), Item:=Cells(1, 2)
MsgBox dict(Cells(1, 1))
End Sub
这不起作用。但是当我添加一个变量temp=Cells(1,1)
并用它代替Cells(1,1)
时,无论它出现在哪里,它都能工作
为什么钥匙不能是一个细胞?有人能帮我理解两者之间的区别吗
dict.Add Key:=Cells(1, 1), Item:=(1, 2)
及
是吗?项目可以是单元格,而不是键 您可以使用对象作为键和值(包括.Cells
返回的范围),如下代码所示:
Public Sub Example()
Dim dict As New Scripting.Dictionary
dict.Add Sheet1.Cells(1, 1), Sheet1.Cells(1, 1)
dict.Add Sheet1.Cells(1, 2), Sheet1.Cells(1, 1)
Dim x As Variant
For Each x In dict.Keys
Debug.Print TypeName(x) 'Prints Range
Next
For Each x In dict.Items
Debug.Print TypeName(x) 'Prints Range
Next
End Sub
事实上,您上面的代码“有效”-您只是没有在MsgBox
中看到您期望的内容。在这行代码中
MsgBox dict(Cells(1, 1))
…MsgBox的第一个参数是变量
,但它最终需要能够显示字符串
。如果它接收一个对象作为参数,它将调用其默认成员(.Value
)。这意味着您的代码相当于:
MsgBox dict(Cells(1, 1).Value)
Dim temp As Variant
temp = Cells(1, 1).Value
dict.Add temp, Cells(1, 2) '<--- temp is whatever the type of Cells(1, 1).Value is.
对于使用temp
的第二个示例,我假设它要么是未声明的(并且隐式地是Variant
),要么是其他一些强类型的值。在这种情况下,赋值隐式调用单元格(1,1)
的默认成员,因此赋值等价于:
MsgBox dict(Cells(1, 1).Value)
Dim temp As Variant
temp = Cells(1, 1).Value
dict.Add temp, Cells(1, 2) '<--- temp is whatever the type of Cells(1, 1).Value is.
请记住,唯一单元值与唯一单元对象不同:
Public子示例2()
Dim dict作为新的脚本编写字典
单元格(1,1)。Value=“Foo”
单元格(1,2)。Value=“Foo”
'这很好-键是唯一的单元格引用:
添加单元格(1,1),空
dict.添加单元格(1,2),在两个单元格(1,1)的末尾清空“put。value
”。是的,字典在存储数据时非常方便。没有Value
its存储范围对象。噢!我没听说过这个功能。因此,.value
返回一个字符串,其中包含.value
附加到的任何内容?因此,如果我理解正确-因为我在字典(单元格)中保存键时将其作为一种数据类型使用,但在调用msgbox(variant)时它默认为另一种数据类型,因此它不会显示,因为即使文本相同,数据类型也不同?因此,使用temp是一种无意的桥梁,无意中将其作为不同的数据类型保存在字典中,而msgbox默认为?@grandrilly-No的数据类型恰好是相同的类型(Range
)。您不能MsgBox
对象,因此它调用其默认成员-.Value
。分配给temp
做了完全相同的事情,因为您没有在它前面使用Set
。没有Set
关键字的Variant
的赋值是值赋值,而不是引用赋值。我想我现在更糊涂了<代码>单元格(1,1)
是范围对象。temp是一个(n个未声明的)变量,因此它隐式地将自身设置为等于单元格(1,1).Value
。而range是一个对象(?),因此msgbox试图通过添加.value
,生成单元格(1,1).value
,来解决这个问题。我的意思是,显然不是这样,否则它会起作用,因为这是相同的结果,但是…@Grabundry-这几乎就是发生的事情。从技术上讲,它调用单元格(1,1)。[\u默认值]
,但这与单元格(1,1)是一样的。这(不是我的)可能有助于澄清工作中的概念。
Public Sub Example2()
Dim dict As New Scripting.Dictionary
Cells(1, 1).Value = "Foo"
Cells(1, 2).Value = "Foo"
'This is fine - the keys are unique cell references:
dict.Add Cells(1, 1), Empty
dict.Add Cells(1, 2), Empty '<-- No runtime error
Set dict = New Scripting.Dictionary
'This is an error - the keys are identical values:
dict.Add Cells(1, 1).Value, Empty
dict.Add Cells(1, 2).Value, Empty '<-- Runtime error 457, key already exists.
End Sub