I have a collection with several elements in VBA, each of these elements has a key assigned.
I would like to know the position of a given element in the collection u
I liked Sil's answer above. I think he short changed himself by saying 'Its not pretty but it works'. In my experience it is way faster when doing a large number of lookups. Here is another example
Sub UseCollectionWithKey()
Dim Col As New Collection
Dim I As Integer
' create a new collection that is keyed
For I = 1 To ActiveWorkbook.Styles.Count
Col.Add I, ActiveWorkbook.Styles(I) ' where "ActiveWorkbook.Styles(I)" is the key
Next I
MsgBox Col(ActiveCell.Style) ' this gives the index of the style for the active cell
End Sub
See also "Adding Items Using a Key" at this link https://excelmacromastery.com/excel-vba-collections/
Essentially, no. There's not a faster way. Not using a collection at least. Here's the fastest way I know to find the index of an item in a collection.
' returns index of item if found, returns 0 if not found
Public Function IndexOf(ByVal coll As Collection, ByVal item As Variant) As Long
Dim i As Long
For i = 1 To coll.Count
If coll(i) = item Then
IndexOf = i
Exit Function
End If
Next
End Function
Note that we exit the function as soon as we've found the first matching item. This algorithm has an average and worst case of O(n) where n is the number of items in the collection.
I think there may be another reason you want to be able to find the index though, so I'm going to suggest also taking a look at the Scripting.Dictionary in the Microsoft Scripting Runtime library. While, there is also no way to get an item's index via it's key value (other than looping), you can actually retrieve the key values from the dictionary, not just it's items. I suspect that you may be asking this question because of the lack of this ability in the built in Collection
object.
I recently had the same "issue" and used this workaround:
Create two collections: one containing the actual strings of interest and one containing numbers from 1 to n with the actuals strings as keys. This way you can retrieve the index since it's a value in the second collection.
Sub example()
'imagine we are reading out following excel column
'one
'two
'three
Dim textcol, numcol As New Collection
Dim i, index As Integer
Dim str As String
For i = 1 To Range.Rows.Count
textcol.Add Range.Cells(i, 1) 'value, no key
numcol.Add i, Range.Cells(i, 1) 'i, value as key
Next i
'textcol: "one", "two", "three"
'numcol: 1 ["one"], 2 ["two"], 3 ["three"]
str = "two"
index = numcol(str) '~> 2
End Sub
It's not pretty but it worked for me.
There is no way that I have found to return the index, however if you have a collection of user defined objects that will only be stored in a single collection you can add an index property to the object and set it when the object is added to the collection.