使用vba中的自定义对象键访问字典中的项目

我有一个问题访问vba字典中的项目。

我有以下字典:

Dim CResults as dictionary 

我添加项目:

 CResults.add currentkey, result 

Currentkey是我从一个名为DCRkey的类创build的一个对象

 Private loadcase as long Private csystem as String Private node as long 

result是另一个类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

然后,我想也许是关键和我search哪里没有导入的项目,所以我决定在Excel工作表上显示我的整个字典:

 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 

我所看到的是:

  1. 我之前search的关键字存在于字典中:在表格上进行可视化检查
  2. 我之前search的密钥实际上存在于字典中: "This key is the same as the acceskey"被显示一次
  3. for each循环访问词典中的项目,因为C1和Fs正确显示在工作表上

然后我想也许是因为testkey被定义为一个变体而不是一个DCRKey ,所以我试着这样做:

 dim a as variant Set a = currentkey .Cells(i,1) = CResults(a).C1 

但它不起作用,我仍然有runtime error 424

我也做的是尝试:

 CResults.exists(accesskey) 

它返回false,并在字典中创build一个新的条目(顺便说一句,我讨厌什么时候这样做),与acceskey和空项目相同的密钥。

所以我的问题是:为什么使用自定义types键访问一个项目在for each循环中工作,而不是在独立的调用。 我错过了什么? 这段代码和我写的代码非常相似,但不完全一样(为了让你更好理解)。 告诉我,如果你认为真正的代码可以帮助。 谢谢你的帮助。

你需要记住一个类的两个实例是不一样的,即使它们的所有属性都被设置为相同的值。

我们来看下面的例子:

 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类的两个对象都将所有属性设置为相同的值。 但是,它们与下面的代码在最后运行Debug.Prints之后看到的不同。

在那些Debug.Print VBA内置函数ObjPtr 。 这个函数的目的是将指针返回给定的对象。 对象的每个实例都有自己的唯一指针,所以如果下面的代码打印两个不同的指针,则意味着这些对象是不一样的。


现在我们来看另一个例子:

 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 

在这里,我们为variableskey1分配了一个新的类DCRKey实例,然后我们将同一个对象分配给variableskey2 。 现在ObjPtr应该为key1key2返回相同的值,因为这是同一个对象,它只被分配给两个不同的variables。


现在,让我们回到字典。

字典searchObjecttypes的关键字的方式是通过它的指针。

所以如果你想在一个字典中添加一个对象作为关键字,你需要使用完全相同的对象(而不是具有相同属性的对象)。

例:

 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