Collection object
2020-07-01 VBA programming 0 710
A collection is an object where you can store items of any datatype, and unlike arrays you don't have to set the size of how many items you want to store in the collection.
More information about array variables.
More information about the Dictionary object.
The collection object:
- Can store items of any datatype (e.g. string, long, worksheet, object, variant, arrays)
- Each item can optionally be associated with a unique key that must be a string
- The associated key for each item can not be retrieved, e.g. when looping through the collection items
- Usually you would only add items of the same datatype to the collection
- It is possible to add items of mixed datatypes to the collection
- Items can be added before or after existing items in the collection
- Looping through a collection is as fast as a dictionary when using For Each - Next
Below is some code examples on how to create a collection object, populate it with items and then retrieving one or more items:
Sub Example_Collection() ' updated 2020-06-26 by OPE Dim coll As Collection, i As Long, lngValue As Long, varItem As Variant, varArray() As Variant, objEmployee As clsEmployee ' collection object: ' can store items of any datatype (e.g. string, long, worksheet, object, variant, arrays) ' each item can optionally be associated with a unique key that must be a string ' the associated key for each item can not be retrieved, e.g. when looping through the collection items ' usually you would only add items of the same datatype to the collection ' it is possible to add items of mixed datatypes to the collection ' items can be added before or after existing items in the collection ' looping through a collection is as fast as a dictionary when using For Each - Next Set coll = New Collection ' create a new collection object ' add items to a collection For i = 1 To 10 coll.Add i * 100 ' add a new item without a key, items can only be retrieved by using their index numbers or a For Each - Next loop Next i ' add items to a collection For i = 1 To 10 coll.Add i * 100, CStr(i) ' add a new item with a key, the key must be a string, an error will occur if the key already exists Next i ' add items to a collection For i = 1 To 10 On Error Resume Next coll.Add i * 100, CStr(i) ' add a new item with a key, the key must be a string, ignore error if the key already exists On Error GoTo 0 Next i ' add items to the collection before or after any existing items coll.Add 111, CStr(111), Before:=2 ' add a new item with a key, the key must be a string, an error will occur if item already exists coll.Add 222, CStr(222), Before:="5" ' add a new item with a key, the key must be a string, an error will occur if item already exists coll.Add 333, "333", After:=2 ' add a new item with a key, the key must be a string, an error will occur if item already exists coll.Add 444, "444", After:="5" ' add a new item with a key, the key must be a string, an error will occur if item already exists ' remove items from the collection coll.Remove 10 ' remove item from collection using an index number between 1 to coll.Count coll.Remove "9" ' remove item from collection using a key identifier, the key must be a string coll.Remove coll.Count ' remove the last item from collection using an index number between 1 to coll.Count ' use items in the collection Debug.Print "Count of items in the collection: " & coll.Count Debug.Print "This is the value of the first item: " & coll(1) Debug.Print "This is the value of the last item: " & coll(coll.Count) Debug.Print "This is the value of the item for key ""333"": " & coll("333") ' update items in the collection 'coll(1) = coll(1) + 1 ' this will not work, you can't change the collection item ' if the collection item is an object you can change properties of the object (see example below) ' you can update an item by removing it and adding it again with an updated value lngValue = coll("itemkey") + 1 ' calculate the new value coll.Remove "itemkey" ' remove an existing item from the collection coll.Add lngValue, "itemkey", Before:=1 ' add the updated value to the collection, optionally at the desired position ' loop through the collection Debug.Print "Collection: " & coll.Count ' using a For Each - Next loop is the preferred and significantly fastest method for looping through all items in a collection if the collection has many items i = 0 For Each varItem In coll ' varItem must be a Variant, Object or specific object type (e.g. Worksheet or clsEmployee) i = i + 1 Debug.Print i, varItem ' the associated key for each item is not available Next varItem ' using a For Next loop can be extremely slow to loop through all items in a collection with many items (10000 or more) For i = 1 To coll.Count Debug.Print i, coll(i) ' the associated key for each item is not available Next i ' there is no easy way to write the collection content to a worksheet ' you would normally transfer the collection items to an array and write the array to the worksheet ' assumes that the items in the collection are normal datatypes, no objects or arrays If coll.Count > 0 Then ReDim varArray(1 To coll.Count, 1 To 1) i = 0 For Each varItem In coll i = i + 1 varArray(i, 1) = varItem ' populate the array with items from the collection Next varItem With Sheet1 On Error Resume Next .Range("A3:A" & .Rows.Count).Clear .Range("A3").Formula = "Items" .Range("A4").Resize(UBound(varArray, 1), 1).Formula = varArray With .Range("A3").CurrentRegion .Style = "Borders" .Rows(1).Style = "Tableheader" .EntireColumn.AutoFit End With On Error GoTo 0 End With End If ' remove all items in a collection (usually not necessary) ' this is slow and should be avoided: 'Do While coll.Count > 0 ' coll.Remove 1 ' remove item from collection 'Loop ' better alternatives: Set coll = Nothing ' delete the collection Set coll = New Collection ' create a new collection ' adding custom objects to a collection, properties for objects in the collection can be edited unless they are read-only Set objEmployee = New clsEmployee ' create a new object and add values to it With objEmployee .ID = 1 .Name = "Peder Aas" .Position = "Manager" .Salary = 100000 .StartDate = DateSerial(2000, 1, 1) End With coll.Add objEmployee, CStr(objEmployee.ID) ' add a new item with a key, an error will occur if the key already exists Set objEmployee = New clsEmployee ' create a new object and add values to it With objEmployee .ID = 2 .Name = "Lars Holm" .Position = "Supervisor" .Salary = 125000 .StartDate = DateSerial(2001, 1, 1) End With coll.Add objEmployee, CStr(objEmployee.ID) ' add a new item with a key, an error will occur if the key already exists ' loop through the collection Debug.Print "Collection: " & coll.Count For Each objEmployee In coll objEmployee.DebugPrint ' assumes that the object has a DebugPrint method With objEmployee ' update object in collection .Salary = .Salary * 1.05 .EndDate = DateSerial(Year(Date), 12, 31) End With Next objEmployee Debug.Print "After update:" For Each objEmployee In coll objEmployee.DebugPrint ' assumes that the object has a DebugPrint method Next objEmployee ' add some items of another datatype to the collection For i = 1 To 3 coll.Add i * 100 Next i ' loop through a collection with mixed data types Debug.Print "Collection with mixed datatypes: " & coll.Count i = 0 For Each varItem In coll i = i + 1 If TypeName(varItem) = "clsEmployee" Then varItem.DebugPrint Else Debug.Print "Not an employee: " & i, varItem, "TypeName: " & TypeName(varItem) End If Next varItem End Sub
If you need functionality to check if an item with a key has been added to a collection you can use the function below:
Function ExistsInColl(coll As Collection, strKey As String) As Boolean ' updated 2020-06-26 by OPE ' returns True if the collection contains an item associated with strKey (not case sensitive) ' example: If ExistsInColl(collEmployees, strEmployeeID) Then ' employee was found ExistsInColl = True On Error GoTo ErrorHandler TypeName coll(strKey) On Error GoTo 0 Exit Function ErrorHandler: ExistsInColl = False Resume Next End Function