|
Eine Sammlung (Collection) von Objekten können Sie nach einem bestimmten Objekt-Typ durchsuchen, wenn Sie den Objekt-Typ jedes einzelnen Objekts in der Sammlung mit dem gesuchten Objekt-Typ vergleichen. Alle CommandButtons in der Controls-Collection eines Forms finden Sie etwa so:
Dim nControl As Control
For Each nControl In Me.Controls
If TypeOf nControl Is CommandButton Then
' Gefunden...
End If
Next
Falls Sie jedoch den zu suchenden Objekt-Typ nicht vorher festlegen können, sondern flexibel mal den einen, mal einen anderen Objekt-Typ suchen wollen, ist eine universelle Funktion hilfreich, der Sie die zu durchsuchende Sammlung und den zu suchenden Objekt-Typ übergeben. Naheliegend wäre dazu eine Funktion wie folgende:
Public Function FindObjectType(Collection As Object, _
ObjType As Object) As Collection
Dim nItems As Collection
Dim nItem As Object
Set nItems = New Collection
With nItems
For Each nItem in Collection
If TypeOf nItem Is ObjType Then
.Add nItem
End If
Next
End With
Set FindObjectType = nItems
End Function
Dieser Ansatz funktioniert jedoch nicht. Das TypeOf-Statements erwartet nämlich, dass Sie den Vergleichs-Typ namentlich festlegen - Sie können hier kein anderes Objekt zum Vergleich angeben. Die Übergabe als Funktionsparameter scheint nicht der richtige Ansatz zu sein.
Glücklicherweise bietet Visual Basic noch eine weitere Möglichkeit, Objekte abstrakt zu vergleichen - mit der TypeName-Funktion. Diese Funktion liefert den Namen eines Objekts. Sie können daher den Namen eines Objekts in einer Sammlung mit dem Namen eines gesuchten Objekt-Typs vergleichen:
Public Function FindObjectType(Collection As Object, _
ObjType As Object) As Collection
Dim nItems As Collection
Dim nItem As Object
Dim nTypeName As String
Set nItems = New Collection
With nItems
nTypeName = TypeName(ObjType)
For Each nItem in Collection
If TypeName(nItem) = TypeName(ObjType) Then
.Add nItem
End If
Next
End With
Set FindObjectType = nItems
End Function
Dieser Ansatz hat jedoch wiederum einen Haken: Sie brauchen ein instanziertes Objekt des zu suchenden Objekt-Typs, um ihn an die Funktion übergeben zu können. Praktischer ist es, wenn Sie den Objekt-Typ als Name, also als String übergeben können:
Public Function FindObjectType(Collection As Object, _
ObjType As String) As Collection
Dim nItems As Collection
Dim nItem As Object
Set nItems = New Collection
With nItems
For Each nItem in Collection
If TypeName(nItem) = ObjType Then
.Add nItem
End If
Next
End With
Set FindObjectType = nItems
End Function
Wenn Sie nun die Funktion in ein Modul packen, in dem die Vergleichsmethode "Option Compare Text" gesetzt ist, können Sie zum einen den Vergleich mittels des Like-Operators tolerant bezüglich der Groß-/Kleinschreibung werden lassen. Zum anderen können Sie auch eine Suchmaske verwenden, um beispielsweise Objekte ähnlich benannter Typen zu finden - etwa von unterschiedlichen Klassen mit einer allen gemeinsamen Schnittstelle. Die geänderte Zeile für den Vergleich sähe dann so aus:
If TypeName(nItem) Like ObjType Then
Nun ist es ein Leichtes, eine Funktion zu erstellen, die beide Varianten der Vorgaben für zu suchende Objekte bietet - ein vorhandenes, instanziertes Objekt als "Modell" oder einen Namen bzw. eine Suchmaske:
Option Compare Text
Public Enum cfoErrConstants
cfoErrInvalidObjectTypeParam = vbObjectError + 10001
cfoErrInvalidStartParam = vbObjectError + 10002
End Enum
Public Function CollectionFilterObjectsByType(Collection As Object, _
ObjType As Variant) As Collection
Dim nItems As Collection
Dim nItem As Object
Dim nTypeName As String
Set nItems = New Collection
If IsObject(ObjType) Then
nTypeName = TypeName(ObjType)
ElseIf VarType(ObjType) = vbString Then
nTypeName = ObjType
Else
Err.Raise cfoErrInvalidObjectTypeParam, _
"CollectionFilterObjectsByType"
End If
With nItems
For Each nItem In Collection
If TypeName(nItem) Like nTypeName Then
.Add nItem
End If
Next
End With
Set CollectionFilterObjectsByType = nItems
End Function
Wenn Sie nicht alle der Suchvorgabe entsprechenden Objekte in einer Sammlung benötigen, sondern nur das erste ab einer bestimmten Index-Position in der Sammlung, können Sie folgende Variante der vorangegangenen Funktion verwenden:
Public Function CollectionFindObjectsByType(Collection As Object, _
ObjType As Variant, Optional Start As Long = 1) As Long
Dim nItem As Object
Dim nTypeName As String
Dim l As Long
If IsObject(ObjType) Then
nTypeName = TypeName(ObjType)
ElseIf VarType(ObjType) = vbString Then
nTypeName = ObjType
Else
Err.Raise cfoErrInvalidObjectTypeParam, _
"CollectionFindObjectsByType"
End If
With Collection
Select Case Start
Case 1 To .Count
For l = Start To .Count
If TypeName(nItem) Like nTypeName Then
CollectionFindObjectsByType = l
Exit Function
End If
Next
Case Else
Err.Raise cfoErrInvalidStartParam, _
"CollectionFindObjectsByType"
End Select
End With
End Function
|