【问题标题】:Return array of class properties from dictionary从字典返回类属性数组
【发布时间】:2020-03-09 08:18:00
【问题描述】:

背景:

在最近尝试回答 question 时,我自己在想是否可以直接从字典项返回一个类对象属性数组。

代码:

TstClass想象成一个类模块,代码如下:

Public val1 As Variant
Public val2 As Variant
Public val3 As Variant

然后这段代码来测试:

Sub Test()

Dim dict As Object: Set dict = CreateObject("Scripting.Dictionary")
Dim lst As TstClass, key As Variant, arr As Variant

For x = 1 To 3
    Set lst = New TstClass
    lst.val1 = "A" & x
    lst.val2 = "B" & x
    lst.val3 = "C" & x
    dict.Add x, lst
Next x

For Each key In dict
    arr = Array(dict(key).val1, dict(key).val2, dict(key).val3)
Next key

End Sub

问题:

在上述情况下,Array(dict(key).val1, dict(key).val2, dict(key).val3) 将返回数组就好了,但如果我们想象val4-val50 它将变成更多的代码。使用Array(...) 或逐行写出Debug.Print Dict(key).Valx

问题:

是否可以直接从字典键的类对象属性中返回一个数组?对我来说最明显的尝试是arr = Dict(key),希望它能以某种方式识别我需要该项目的所有属性。除此之外,不允许将常量、数组、用户定义类型声明为 Public,所以像 Public Vals(0 to 2) 这样的东西也不起作用。

谢谢你, 合资公司

【问题讨论】:

    标签: arrays excel vba class dictionary


    【解决方案1】:

    从@RyanWildry 的答案中获得灵感,我发现尽管无法使用Public 变体数组,但我们可以使用Private 变体数组。因此,我使Property Let 将值分配给数组中的特定索引。

    创建一个Public Function 以返回Private 数组变量将一次性返回该数组。


    类模块,名为TstClass

    Private vals(0 To 2) As Variant
    
    Public Property Let val(ByVal x As Long, ByVal NewVal As Variant)
        vals(x) = NewVal
    End Property
    
    Public Function GetArray() As Variant
        GetArray = vals
    End Function
    

    Module1 下的代码

    Sub Test()
    
    Dim dict As Object: Set dict = CreateObject("Scripting.Dictionary")
    Dim lst As TstClass, key As Variant, arr As Variant
    
    For x = 1 To 3
        Set lst = New TstClass
        lst.val(0) = "A" & x
        lst.val(1) = "B" & x
        lst.val(2) = "C" & x
        dict.Add x, lst
    Next x
    
    For Each key In dict
        arr = dict(key).GetArray
    Next key
    
    End Sub
    

    另一种方法是不考虑 Class 模块的想法,而使用(例如)ArrayList 对象:

    Sub Test()
    
    Dim dict As Object: Set dict = CreateObject("Scripting.Dictionary")
    Dim lst As Object: Set lst = CreateObject("System.Collections.ArrayList")
    Dim arr As Variant
    
    For x = 1 To 3
        lst.Add "A" & x
        lst.Add "B" & x
        lst.Add "C" & x
        dict.Add x, lst.Toarray
        lst.Clear
    Next x
    
    For Each key In dict
        arr = dict(key)
    Next key
    
    End Sub
    

    但是,后一种方法会超出这个问题的目的。

    这与直接从字典项返回数组一样接近。我很高兴收到建设性的反馈或其他/更好的方式,因为 Class 模块对我来说相当新,这仍然不能回答关于如何直接返回属性数组的问题的本质。

    【讨论】:

      【解决方案2】:

      不确定这是否正是您所追求的,但是可以在您的类中创建一个方法来构建您想要的属性数组。然后,您可以在该类的每个实例上调用它以获取数组详细信息。

      类 - 命名为“示例”:

      Public val1 As Variant
      Public val2 As Variant
      Public val3 As Variant
      
      Public Function GetArray() As Variant
          GetArray = Array(Me.val1, Me.val2, Me.val3)
      End Function
      

      客户端代码 - 在标准模块中:

      Sub SOExample()
      
          Dim dict As Object: Set dict = CreateObject("Scripting.Dictionary")
          Dim lst As Example, arr As Variant, key As Variant
      
          For x = 1 To 3
              Set lst = New Example
              lst.val1 = "A" & x
              lst.val2 = "B" & x
              lst.val3 = "C" & x
              dict.Add x, lst
          Next
      
          For Each key In dict.keys
              arr = dict(key).GetArray
              Debug.Print Join(arr, ",")
          Next
      
      End Sub
      

      输出:

      A1,B1,C1
      A2,B2,C2
      A3,B3,C3
      

      【讨论】:

      • 感谢您的建议。在类中创建一个方法似乎是在模块的幕后完成所有工作(构建一个数组)。这不是我所追求的(甚至可能不存在)。
      • 我采用了创建Public Function 来返回数组的想法,但使用了另一种方法来使用Property Let 构建Private 数组。我已经发布了答案。欢迎提供有关如何改进的反馈/想法。再次感谢您的意见。
      • 是的,我听到了。这种方法的优点是您只需要定义一次。
      • 听起来您正在尝试将类中的属性表示为数组,我不知道这样做的直接方法。我不认为类像这样构造他们的数据,尽管很高兴错了。如果您想动态引用类中的属性,也许 CallByName 函数 (docs.microsoft.com/en-us/dotnet/visual-basic/programming-guide/…) 会有所帮助?
      • 不是真的,因为我对Class 模块还很陌生,我一直在寻找一种以更动态的方式引用它们的属性的方法。而你的GetArray 想法让我更进一步理解了它的结构,这导致了我在帖子中的尝试=)
      猜你喜欢
      • 2014-12-06
      • 1970-01-01
      • 2020-05-22
      • 1970-01-01
      • 2020-07-20
      • 1970-01-01
      • 2011-08-02
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多