【问题标题】:Referencing an object within a collection of collections by key通过键引用集合集合中的对象
【发布时间】:2014-11-16 08:27:21
【问题描述】:

首先,抱歉,这是我的第一篇文章,因此我可能没有使用最佳实践。

我正在使用 VBA for Excel 编写应用程序。

我创建了一个类,然后将该类的几个对象实例化并将它们添加到一个集合中。然后我将该集合添加到另一个集合中,并重复该过程,以便最终得到同一类对象的集合集合,就像我想的层次结构一样。

每当我添加到集合中时,我都会创建一个键来唯一标识我正在添加的内容。我现在想使用键来引用“层次结构”中的特定对象。

下面的伪代码希望解释了实例化对象、添加到新集合、然后将集合添加到新集合的过程(注意,为简单起见,我只添加了一个对象,从而产生了一个分支层次结构,而我的实际代码将多个对象添加到多个集合中)。

Public Element As CElement
Public InsideCollection As Collection
Public OutsideCollection As Collection

Sub Main()

    Set Element = New CElement
    Set InsideCollection = New Collection
    Set OutsideCollection = New Collection

    Element.Field1 = "blah1"
    Element.Field2 = "blah2"

    InsideCollection.Add Element, Element.Field1

    OutsideCollection.Add InsideCollection, "ABCD"

End Sub

既然我已经将这些数据加载到一种层次结构中,那么如何在不遍历所有元素搜索正确元素的情况下访问最低级别的特定元素?我本以为我可以按照以下方式做一些事情:

OutsideCollection("ABCD").InsideCollection("blah1").Field2

OutsideCollection.InsideCollection("blah1").Field2  

但他们给出了这个错误:

运行时错误“438”:对象不支持此属性或方法

我也尝试过上述方法,例如通过整数值引用元素。

OutsideCollection(1).InsideCollection(1).Field2

但得到同样的错误。

有什么想法吗?

干杯,克里斯

【问题讨论】:

    标签: vba


    【解决方案1】:

    任重道远。让我们定义两个额外的变量innerColinnerEl

    Dim innerCol As Collection
    Dim innerEl As CElement
    

    然后通过key获取OutsideCollection集合的值:

    Set innerCol = OutsideCollection("ABCD")
    

    现在innerCol 包含CElements 的集合。让我们按键获取单个元素:

    Set innerEl = innerCol("blah1")
    

    变量innerEl包含CElement类型的对象,我们可以得到它的属性:

    MsgBox innerEl.Field1 ' returns "blah1"
    MsgBox innerEl.Field2 ' returns "blah2"
    

    捷径,没有额外的变量我们可以使用这个:

    MsgBox OutsideCollection("ABCD")("blah1").Field1 ' returns "blah1"
    MsgBox OutsideCollection("ABCD")("blah1").Field2 ' returns "blah2"
    

    【讨论】:

      【解决方案2】:

      要通过文字访问对象,有“!”运营商:

      Sub test_collection_intf()
        Dim v_a As New Collection
        v_a.Add Item:=New Collection, Key:="first"
        v_a!first.Add Item:=CreateObject("Scripting.Dictionary"), Key:="red"
        v_a!first!red!Type = "color"
      
        v_a.Add Item:=New Collection, Key:="second"
        v_a!Second.Add Item:=CreateObject("Scripting.Dictionary"), Key:="green"
        v_a!Second!green!scheme = "RGBA"
      
        Debug.Print "Access by literals"
        Debug.Print "v_a!first!red.Count:"; v_a!first!red.Count; "v_a!first!red!type: "; v_a!first!red!Type
        Debug.Print "v_a!Second!green.Count"; v_a!Second!green.Count; "v_a!Second!green!RGBA: "; v_a!first!red!RGBA
        Debug.Print "v_a!Second!green!scheme: "; v_a!Second!green!scheme
      ' But it is impossiable to use a variable to acces field of object as in Perl
      '  Dim v_key_l1 As String, v_key_l2 As String
      '  v_key_l1 = "first": v_key_l2 = "red"
      '  Debug.Print "v_a!v_key_l1!v_key_l2:"; v_a; !v_key_l1; !v_key_l2
      '  v_key_l1 = "second": v_key_l2 = "green"
      '  Debug.Print "v_a!v_key_l1!v_key_l2:"; v_a!v_key_l1!v_key_l2
      End Sub
      

      在即时窗口中输出:

      Access by literals
      v_a!first!red.Count: 1 v_a!first!red!type: color
      v_a!Second!green.Count 1 v_a!Second!green!RGBA: 
      v_a!Second!green!scheme: RGBA
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-05-19
        • 1970-01-01
        相关资源
        最近更新 更多