VBA 中的通用结构列表

Generic List of Structs in VBA

我开始在 Excel 和 VBA 一起工作,想保存一些列表。

我的方法如下,但我担心我正在寻找完全错误的方向。

Public Type MyType
  ID As Integer
  Name As String
  MyInt As Integer
End Type

Public ListVar As New Collection

Public Sub MySub
  Dim MyVar As MyType
  MyVar.ID = 1
  MyVar.Name = "name"
  MyVar.MyInt = 2000

  ListVar.Add MyVar, MyVar.ID
End Sub

尝试执行时,出现编译错误:"Only user-defined types defined in public object modules can be coerced to or from a variant or passed to late-bound functions."

目标是拥有一个类似于 C# 的列表,我可以向其中添加 MyType 对象并以您可以在 C# 中执行的方式找到它们:ListVar.find(p => p.ID == 3). 此外,如果可行,该列表应该在文件中持久存在。这不是必需的,因为我可以在关闭时将其简单地写入工作表,反之亦然。

是否有其他对象class我可以使用更适合我的需要?

您可以使用数组列表吗?在您的子目录中:

Dim arrayList As Object
Set arrayList = CreateObject("System.Collections.ArrayList")

然后您可以使用 .NET 类型 ArrayList 的所有常用方法,例如 .Contains().Sort() 等...


编辑: (因为 OP 使用 Mac OS)

您可以自己创建一个 class,并在 collection 中使用它。首先创建一个新的 class 模块(Alt+I,然后是 C

在此模块中使用以下内容:

Private sID     As Integer
Private sName   As String
Private sInt    As Integer

Public Property Let ID(value As Integer)
    sID = value
End Property

Public Property Get ID() As Integer
    ID = sID
End Property

Public Property Let Name(value As String)
    sName = value
End Property

Public Property Get Name() As String
    Name = sName
End Property

Public Property Let MyInt(value As Integer)
    sInt = value
End Property

Public Property Get MyInt() As Integer
    MyInt = sInt
End Property

重要 - 将模块命名为 "MyType",这是您要在代码中使用的名称。

回到普通代码模块中的原始子模块:

Public ListVar As New Collection

Public Sub MySub()

  Dim MyVar As New MyType
  MyVar.ID = 1
  MyVar.Name = "name"
  MyVar.MyInt = 2000

  ListVar.Add MyVar, CStr(MyVar.ID)

End Sub

会很好用。

不确定是否可以在 mac 上执行此操作,但我使用了与此类似的 class,

Option Explicit

Implements Scripting.Dictionary

Private dic As Scripting.Dictionary

Private Sub Class_Initialize()
    Set dic = New Scripting.Dictionary
End Sub

Public Sub Add(Key As Variant, Item As Variant)
    dictionary_Add Key, Item
End Sub
Private Sub dictionary_Add(Key As Variant, Item As Variant)
    dic.Add Key, Item
End Sub
Public Sub Remove(Key As Variant)
    dictionary_Remove (Key)
End Sub
Private Sub dictionary_Remove(Key As Variant)
    dic.Remove (Key)
End Sub

Public Function TEST_LAMBDA(strLAMBDA As String) As Scripting.Dictionary

    Dim strSplit() As String
    Dim strCriteria As String

    Set TEST_LAMBDA = New Scripting.Dictionary

    strSplit = Split(strLAMBDA, "=>")
    strCriteria = strSplit(1)

    Dim intCounter As Integer
    strSplit = Split(strCriteria, "=")
    strCriteria = strSplit(1)

    For intCounter = 0 To dic.Count - 1
        If dic.Keys()(intCounter) = strCriteria Then
            TEST_LAMBDA.Add dic.Keys()(intCounter), dic.Items()(intCounter)
        End If
    Next intCounter

End Function
Private Property Get dictionary_CompareMode() As Scripting.CompareMethod
End Property
Private Property Let dictionary_CompareMode(ByVal RHS As Scripting.CompareMethod)
End Property
Private Property Get dictionary_Count() As Long
End Property
Private Function dictionary_Exists(Key As Variant) As Boolean
End Function
Private Property Get dictionary_HashVal(Key As Variant) As Variant
End Property
Private Property Get dictionary_Item(Key As Variant) As Variant
End Property
Private Property Let dictionary_Item(Key As Variant, RHS As Variant)
End Property
Private Property Set dictionary_Item(Key As Variant, RHS As Variant)
End Property
Private Function dictionary_Items() As Variant
End Function
Private Property Let dictionary_Key(Key As Variant, RHS As Variant)
End Property
Private Function dictionary_Keys() As Variant
End Function
Private Sub dictionary_RemoveAll()
End Sub

我是这样用的

Sub t()

Dim a As New clsDictionary

a.Add "9", "this out"
a.Add "10", "test"

Dim d As Scripting.Dictionary

Set d = a.TEST_LAMBDA("x=>x=9")

End Sub