Generic List of Structs in VBA

吃可爱长大的小学妹 提交于 2020-07-24 04:02:20

问题


I started working in Excel with VBA and would like to save some kind of List.

My approach is the following, but I fear that I am looking into the totally wrong direction.

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

When trying to execute, I get a compile error: "Only user-defined types defined in public object modules can be coerced to or from a variant or passed to late-bound functions."

The goal would be to have a C# like List to which I can add MyType-objects and find them in a way you can do it in C#: ListVar.find(p => p.ID == 3). Also if doable, the list should be persistent in the file. This is not needed because I could simply write it into a worksheet when closing and vice versa when opening.

Is there maybe a different object class I can use that fits my needs better?


回答1:


You could use an array list? Within your Sub:

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

You can then use all the usual methods of the .NET type ArrayList such as .Contains() or .Sort() etc...


Edit: (as OP is using Mac OS)

You can create a class yourself, and use this in the collection. Start by creating a new class module (Alt+I, then C)

Use the following in this module:

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

Important - name the module "MyType", this is the name you want to use in your code.

Back to your original sub in a normal code module:

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

Will work fine.




回答2:


Not sure if you can do this on a mac, but I used a class similar to this,

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

I used like so

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


来源:https://stackoverflow.com/questions/36151362/generic-list-of-structs-in-vba

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!