使用 vba 中的自定义对象键访问字典中的项目
Acces an item in a dictionary with a custom object key in vba
我在 vba.
中访问字典中的项目时遇到问题
我有以下字典:
Dim CResults as dictionary
我添加项目:
CResults.add currentkey, result
Currentkey
是我自己从一个名为 DCRkey
的 class 创建的对象
Private loadcase as long
Private csystem as String
Private node as long
和 result
是来自 class 的另一个对象 DCR
:
Private Fs as double
Private C1 as double
Private C2 as double
...
然后我尝试使用
访问一个项目
Dim accesskey as DCRKey
accesskey.loadcase=10
accesskey.node = 2000
accesskey.csystem="Global"
Sheets("Results").cells(i,1).value= CResults(accesskey).C1
这就是我遇到错误的地方:runtime error 424 object required
然后我想也许我搜索的键和项目没有导入,所以我决定在 excel 作品sheet:
上显示我的整个词典
Dim testkey as variant
dim i as integer
i=1
with worksheet("Test")
For each testkey in CResults.keys
.cells(i,1)=test.node
.cells(i,2)=test.loadcase
.cells(i,3)=test.csystem
.cells(i,4)=Cresults(testkey).C1
.cells(i,5)=Cresults(testkey).Fs
if accesskey.loadcase=testkey.loadcase and accesskey.node=testkey.node and accesskey.csystem=testkey.csystem then
Msgbox "This key is the same as the accesskey"
End if
i=i+1
Next
End with
我看到的是:
- 我之前搜索的关键字存在于字典中:视觉检查 sheet
- 我之前搜索的关键字确实存在于字典中:
"This key is the same as the acceskey"
显示一次
- 从
for each
循环访问字典中的项目是有效的,因为 C1 和 Fs 在作品上正确显示sheet
然后我想可能是因为 testkey
被定义为变体而不是 DCRKey
,所以我试了一下:
dim a as variant
Set a = currentkey
.Cells(i,1) = CResults(a).C1
但它不起作用,我仍然得到 runtime error 424
。
我也试过:
CResults.exists(accesskey)
它 returns 错误并在字典中创建一个新条目(顺便说一句,我讨厌这样做),使用与 acceskey 相同的键和一个空项目。
所以我的问题是:为什么使用自定义类型键访问项目在 for each
循环中起作用,而不是在独立调用中起作用。我错过了什么?这段代码与我编写的代码非常相似但不完全相同(为了让您更好地理解)。告诉我您是否认为真正的代码可以提供帮助。
感谢您的帮助。
您需要记住,class 的两个实例不是同一个实例,即使它们的所有属性都设置为相同的值。
让我们考虑以下示例:
Sub compareSimilarObjects()
Dim key1 As DCRKey
Dim key2 As DCRKey
Set key1 = New DCRKey
With key1
.loadcase = 10
.node = 2000
.csystem = "Global"
End With
Set key2 = New DCRKey
With key1
.loadcase = 10
.node = 2000
.csystem = "Global"
End With
'Debug.Print to check pointer assigne to those variables.
Debug.Print "Key1: " & ObjPtr(key1)
Debug.Print "Key2: " & ObjPtr(key2)
End Sub
在此示例中,DCRKey
class 的两个对象都将所有属性设置为相同的值。但是,它们与您在下面的代码 运行 Debug.Prints
最后看到的不是同一个对象。
在那些Debug.Print
VBA中使用了内置函数ObjPtr
。这个函数的目的是将return指针指向给定的对象。每个对象实例都有自己唯一的指针,因此如果下面的代码打印出两个不同的指针,则表示这些对象不相同。
现在,让我们考虑另一个例子:
Sub compareSimilarObjects()
Dim key1 As DCRKey
Dim key2 As DCRKey
Set key1 = New DCRKey
With key1
.loadcase = 10
.node = 2000
.csystem = "Global"
End With
Set key2 = key1
'Debug.Print to check pointer assigned to those variables.
Debug.Print "Key1: " & ObjPtr(key1)
Debug.Print "Key2: " & ObjPtr(key2)
'Now those pointers should be the same.
End Sub
在这里,我们将 class DCRKey
的新实例分配给变量 key1
,然后我们将相同的对象分配给变量 key2
。现在 ObjPtr
应该 return key1
和 key2
的值相同,因为这是同一个对象,它只是分配给两个不同的变量。
现在,让我们回到字典。
字典查找 Object
类型的键的方式是通过它的指针。
所以如果你想在字典中查找以对象为键添加的条目,你需要使用完全相同的对象(而不是具有相同属性的对象)。
示例:
Sub objectsToDictionaryTest()
Dim CResults As Dictionary
Dim accessKey As DCRKey
Dim key As DCRKey
Dim value As DCR
'--------------------------------------------------------------------------------
Set CResults = New Scripting.Dictionary
'Let's create an object of [DCRKey] class (it will be used as a key when adding to
'the dictionary) and an object of [DCR] class (it will be used as a value).
Set accessKey = New DCRKey
With accessKey
.loadcase = 10
.node = 2000
.csystem = "Global"
End With
Set value = New DCR
With value
.C1 = 10
.C2 = 20
.Fs = 3
End With
'Now, let's add a new entry to the dictionary [CResults]
CResults.Add accessKey, value
'Let's create the other object of [DCRKey] that have exactly the same properties
'as object assigned to the variable [accessKey].
Set key = New DCRKey
With key
.loadcase = 10
.node = 2000
.csystem = "Global"
End With
'Now, let's check how dictionary is acting when we try to find an entry by [accesKey] and [key].
Debug.Print "[accessKey] exists: " & CResults.Exists(accessKey) 'it should return True.
Debug.Print "[key] exists: " & CResults.Exists(key) 'it should return False.
Debug.Print "[Value for accessKey]: " & CResults.Item(accessKey).Fs 'it should print 3
'The line below should cause an run-time error 424: Object required.
Debug.Print "[Value for key]: " & CResults.Item(key).Fs
End Sub
我在 vba.
中访问字典中的项目时遇到问题我有以下字典:
Dim CResults as dictionary
我添加项目:
CResults.add currentkey, result
Currentkey
是我自己从一个名为 DCRkey
Private loadcase as long
Private csystem as String
Private node as long
和 result
是来自 class 的另一个对象 DCR
:
Private Fs as double
Private C1 as double
Private C2 as double
...
然后我尝试使用
访问一个项目Dim accesskey as DCRKey
accesskey.loadcase=10
accesskey.node = 2000
accesskey.csystem="Global"
Sheets("Results").cells(i,1).value= CResults(accesskey).C1
这就是我遇到错误的地方:runtime error 424 object required
然后我想也许我搜索的键和项目没有导入,所以我决定在 excel 作品sheet:
上显示我的整个词典Dim testkey as variant
dim i as integer
i=1
with worksheet("Test")
For each testkey in CResults.keys
.cells(i,1)=test.node
.cells(i,2)=test.loadcase
.cells(i,3)=test.csystem
.cells(i,4)=Cresults(testkey).C1
.cells(i,5)=Cresults(testkey).Fs
if accesskey.loadcase=testkey.loadcase and accesskey.node=testkey.node and accesskey.csystem=testkey.csystem then
Msgbox "This key is the same as the accesskey"
End if
i=i+1
Next
End with
我看到的是:
- 我之前搜索的关键字存在于字典中:视觉检查 sheet
- 我之前搜索的关键字确实存在于字典中:
"This key is the same as the acceskey"
显示一次 - 从
for each
循环访问字典中的项目是有效的,因为 C1 和 Fs 在作品上正确显示sheet
然后我想可能是因为 testkey
被定义为变体而不是 DCRKey
,所以我试了一下:
dim a as variant
Set a = currentkey
.Cells(i,1) = CResults(a).C1
但它不起作用,我仍然得到 runtime error 424
。
我也试过:
CResults.exists(accesskey)
它 returns 错误并在字典中创建一个新条目(顺便说一句,我讨厌这样做),使用与 acceskey 相同的键和一个空项目。
所以我的问题是:为什么使用自定义类型键访问项目在 for each
循环中起作用,而不是在独立调用中起作用。我错过了什么?这段代码与我编写的代码非常相似但不完全相同(为了让您更好地理解)。告诉我您是否认为真正的代码可以提供帮助。
感谢您的帮助。
您需要记住,class 的两个实例不是同一个实例,即使它们的所有属性都设置为相同的值。
让我们考虑以下示例:
Sub compareSimilarObjects()
Dim key1 As DCRKey
Dim key2 As DCRKey
Set key1 = New DCRKey
With key1
.loadcase = 10
.node = 2000
.csystem = "Global"
End With
Set key2 = New DCRKey
With key1
.loadcase = 10
.node = 2000
.csystem = "Global"
End With
'Debug.Print to check pointer assigne to those variables.
Debug.Print "Key1: " & ObjPtr(key1)
Debug.Print "Key2: " & ObjPtr(key2)
End Sub
在此示例中,DCRKey
class 的两个对象都将所有属性设置为相同的值。但是,它们与您在下面的代码 运行 Debug.Prints
最后看到的不是同一个对象。
在那些Debug.Print
VBA中使用了内置函数ObjPtr
。这个函数的目的是将return指针指向给定的对象。每个对象实例都有自己唯一的指针,因此如果下面的代码打印出两个不同的指针,则表示这些对象不相同。
现在,让我们考虑另一个例子:
Sub compareSimilarObjects()
Dim key1 As DCRKey
Dim key2 As DCRKey
Set key1 = New DCRKey
With key1
.loadcase = 10
.node = 2000
.csystem = "Global"
End With
Set key2 = key1
'Debug.Print to check pointer assigned to those variables.
Debug.Print "Key1: " & ObjPtr(key1)
Debug.Print "Key2: " & ObjPtr(key2)
'Now those pointers should be the same.
End Sub
在这里,我们将 class DCRKey
的新实例分配给变量 key1
,然后我们将相同的对象分配给变量 key2
。现在 ObjPtr
应该 return key1
和 key2
的值相同,因为这是同一个对象,它只是分配给两个不同的变量。
现在,让我们回到字典。
字典查找 Object
类型的键的方式是通过它的指针。
所以如果你想在字典中查找以对象为键添加的条目,你需要使用完全相同的对象(而不是具有相同属性的对象)。
示例:
Sub objectsToDictionaryTest()
Dim CResults As Dictionary
Dim accessKey As DCRKey
Dim key As DCRKey
Dim value As DCR
'--------------------------------------------------------------------------------
Set CResults = New Scripting.Dictionary
'Let's create an object of [DCRKey] class (it will be used as a key when adding to
'the dictionary) and an object of [DCR] class (it will be used as a value).
Set accessKey = New DCRKey
With accessKey
.loadcase = 10
.node = 2000
.csystem = "Global"
End With
Set value = New DCR
With value
.C1 = 10
.C2 = 20
.Fs = 3
End With
'Now, let's add a new entry to the dictionary [CResults]
CResults.Add accessKey, value
'Let's create the other object of [DCRKey] that have exactly the same properties
'as object assigned to the variable [accessKey].
Set key = New DCRKey
With key
.loadcase = 10
.node = 2000
.csystem = "Global"
End With
'Now, let's check how dictionary is acting when we try to find an entry by [accesKey] and [key].
Debug.Print "[accessKey] exists: " & CResults.Exists(accessKey) 'it should return True.
Debug.Print "[key] exists: " & CResults.Exists(key) 'it should return False.
Debug.Print "[Value for accessKey]: " & CResults.Item(accessKey).Fs 'it should print 3
'The line below should cause an run-time error 424: Object required.
Debug.Print "[Value for key]: " & CResults.Item(key).Fs
End Sub