2

I'm trying to do something in VBA that I've previously done something similar to in C# with a list of class (not that I'm any expert in C# either). Simplified idea version...

Public Class ResultLine
{
  public string VariableThing1 {get:set}
  public string VariableThing2 {get:set}
}
Public void Main
{
  List<ResultLine> AllTheResults = new List<ResultLine>();
  Do while *LogicStuff*
     Mode = *Current Mode Found*
     Result1 = *ThingFoundLogic*
     Result2 = *OtherThingFoundLogic*
     If *a ResultLine exists in AllTheResults for that Mode (using
                              AlltheResults.Find or AlltheResults.Contains)*
     {
        *Add something to that pre-existing ResultLine - not defo sure 
         how to do this in C# either, but should be able to google that 
         and I want VBA anyway*
     } 
     else
     {
           AllTheResults.Add(NewResultLine() {VariableThing1 = 
                                       Result1, VariableThing2 = Result2});
     }
  Loop

What's the best way to do that in VBA though as there's no List function? An array I don't know what size it'll be until I'm finished. How about a collection? Is that closest to List? As noted I want to be able to "find" within it as sometimes I want to sometimes add stuff to a pre-existing "ResultLine" in "AllTheResults", other times I want to create the new ResultLine.

I'm a pretty inexperienced programmer so hopefully this isn't too dumb a question! Googling didn't seem to help much though. Thanks!

2 Answers 2

1

Would an ArrayList borrowed from System.Collections (requires .Net framework) work?

Option Explicit
Public Sub test()
    Dim aList As Object
    Set aList = CreateObject("System.Collections.ArrayList")
    aList.Add "SomeValue"
    If aList.contains("SomeValue") Then Debug.Print "found"
End Sub

Implements the IList interface using an array whose size is dynamically increased as required. Provides methods to search, sort, and manipulate lists.

Example.

Sign up to request clarification or add additional context in comments.

2 Comments

Thanks, that's useful to know. Yes, the PC has .NET installed. Do I need to add a VBA reference to use .NET stuff in VBA though? Or does it "just work"? I have 'system' as an available .NET reference in VBA but it doesn't seem to have systems.collections anything off that. Also how would I make the entry added to it defined as my class and add various parts like the list example I made?
Sorry I didn't see this message. It just works. It is late bound and so no intellisense. It is only for certain members of System.Collections AFAIK. Whether you can hijack some of the other interface classes I am not sure. For your last part "how would I make the entry added to it defined as my class and add various parts like the list example I made" - could you explain a little more perhaps as I didn't quite follow.
0

I'm not sure whether you want all the other functionality of a C# List object (such as sorting), but if you purely want a collection of objects that you can index via some form of key then VBA's Collection object should suit you just fine.

It's perfectly possible to add class objects to a collection, like so:

myCollection.Add myClassObject, key

and to retrieve it like so:

Set myClassObject = myCollection(key)

Either by good design or chance, you've come across one of the great features of a Collection in that properties of a class object held by a collection can simply be changed using standard syntax (whereas primitive data types cannot be changed; you'd have to remove and then add the variable each time):

Set myClassObject = myCollection(key)
myClassObject.Property = "a"

If you wanted to, you could add some kind of test routine to check that the object you're adding is indeed your desired class object. In the code below, you'd have a compile error if the type were incorrect similar in spirit to that of Visual Studio. Your pseudo C# code, would therefore look something like this in VBA:

Your class object (called 'ResultLine')

Option Explicit

Public VariableThing1 As String
Public VariableThing2 As String

Your module code

Option Explicit

Private mAllTheResults As Collection

Public Sub RunMe()
    Dim mode As String
    Dim res As ResultLine
    Dim i As Long
    Dim result1 As String
    Dim result2 As String

    Set mAllTheResults = New Collection

    'Just add some dummy data for testing.
    Set res = New ResultLine
    With res
        .VariableThing1 = "1"
        .VariableThing2 = "2"
    End With
    mode = "key1"
    AddObject res, mode

    Set res = New ResultLine
    With res
        .VariableThing1 = "10"
        .VariableThing2 = "20"
    End With
    mode = "key2"
    AddObject res, mode

    Set res = New ResultLine
    With res
        .VariableThing1 = "100"
        .VariableThing2 = "200"
    End With
    mode = "key3"
    AddObject res, mode

    i = 1
    Do While i <= 4

        mode = "key" & i 'your mode.
        result1 = CStr(i) 'your found data.
        result2 = CStr(i * 10) 'your other found data.

        Set res = GetObjectIfExists(mode)
        If Not res Is Nothing Then 'it exists
            'Change the values in your object.
            With res
                .VariableThing1 = "changed"
                .VariableThing2 = "changed"
            End With
        Else
            Set res = New ResultLine
            With res
                .VariableThing1 = result1
                .VariableThing2 = result2
            End With
            AddObject res, mode
        End If

        i = i + 1
    Loop

End Sub

Private Sub AddObject(obj As ResultLine, Optional key As String)
    If key = vbNullString Then
        mAllTheResults.Add obj
    Else
        mAllTheResults.Add obj, key
    End If
End Sub

Private Function GetObjectIfExists(key As String) As ResultLine
    On Error Resume Next
    Set GetObjectIfExists = mAllTheResults(key)
    On Error GoTo 0
End Function

If you wanted to create a kind of generic CollectionT object in which you could specify the type of 'T' as part of your code, then you could create your own Collection class. Skeleton code for that might be:

 Option Explicit

Private mTestObject As Object
Private mCollection As Collection

Public Property Set TestObject(RHS As Object)
    Set mTestObject = RHS
End Property

Public Sub AddObject(obj As Object, key As String)

    If mTestObject Is Nothing Then
        MsgBox "Type not assigned."
        Exit Sub
    End If

    If TypeName(obj) = TypeName(mTestObject) Then
        mCollection.Add obj, key
    Else
        MsgBox "Incorrect object"
    End If
End Sub

Public Function GetObjectIfExists(key As String)
    On Error Resume Next
    Set GetObjectIfExists = mCollection(key)
    On Error GoTo 0
End Function

Private Sub Class_Initialize()
    Set mCollection = New Collection
End Sub

So, some sample module could could look like this:

Option Explicit

Private mAllTheResults As Collection_T

Public Sub RunMe()
    Dim mode As String
    Dim goodObject As ResultLine
    Dim wrongObject As Range
    Dim i As Long
    Dim result1 As String
    Dim result2 As String

    Set mAllTheResults = New Collection_T
    Set mAllTheResults.TestObject = New ResultLine


    'Add a correct type.
    Set goodObject = New ResultLine
    With goodObject
        .VariableThing1 = "a"
        .VariableThing2 = "b"
    End With
    mAllTheResults.AddObject goodObject, "yep"

    'Add an incorrect type.
    Set wrongObject = Sheet1.Range("A1")
    mAllTheResults.AddObject wrongObject, "nope"

    'Retrieve an item
    Set goodObject = mAllTheResults.GetObjectIfExists("yep")
    If Not goodObject Is Nothing Then
        With goodObject
            .VariableThing1 = "c"
            .VariableThing2 = "d"
        End With
    End If

    'Demonstrate the collection has retained the property change.
    MsgBox "VariableThing1 = " & mAllTheResults.GetObjectIfExists("yep").VariableThing1

End Sub

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.