Weder eine direkte Lieferung der in einer ListBox mit Mehrfachauswahl ausgewählten Elemente ist in Visual Basic vorgesehen, noch allein deren Anzahl. Sie können natürlich beides mit einfachem Visual Basic-Code in einer Schleife ermitteln.
Die Anzahl der ausgewählten Elemente:
Dim nSelCount As Long
Dim l As Long
With List1
For l = 1 To .ListCount - 1
If .Selected(l) Then
nSelCount = nSelCount + 1
End If
Next 'l
End With
Debug.Print nSelCount & "Elemente ausgewählt."
Die ausgewählten Elemente, mit ItemData-Wert und Index:
Dim l As Long
With List1
For l = 1 To .ListCount - 1
If .Selected(l) Then
Debug.Print .List(l), . ItemData(l), l
End If
Next 'l
End With
Sonderlich effizient ist beides nicht - vor allem dann nicht, wenn nur wenige Elemente ausgewählt sind und wenn Sie die ausgewählten Elemente dazu auch noch in einer Liste zur weiteren Verarbeitung festhalten wollen.
Die reine Anzahl der ausgewählten Elemente können Sie statt dessen über die API-Funktion SendMessage mit der Nachricht LB_GETSELCOUNT erheblich einfacher erhalten (der Einfachheit halber in die Hilfs-Funktion LBGetSelCount verpackt):
Private Declare Function SendMessage Lib "user32" _
Alias "SendMessageA" (ByVal hwnd As Long, ByVal wMsg As Long, _
ByVal wParam As Long, lParam As Any) As Long
Private Const LB_GETSELITEMS = &H191
Public Function LBGetSelCount(ListBox As ListBox) As Long
LBGetSelCount = SendMessage(ListBox.hwnd, LB_GETSELCOUNT, 0, 0)
End Function
Ein ähnlicher API-Aufruf liefert ihnen die Indices der ausgewählten Elemente in einem Array. Bei der folgenden Hilfs-Funktion LBGetSelIndices können Sie im optionalen Parameter angeben, ob das zurückgegebene Array mit dem Index 0 (Standardwert) oder einem anderen Index (beispielsweise 1) beginnen soll.
Private Const LB_GETSELCOUNT = &H190
Public Function LBGetSelIndices(ListBox As ListBox, _
Indices() As Long, Optional ByVal OptionBase As Long) As Long
Dim nCount As Long
Dim l As Long
With ListBox
nCount = SendMessage(.hwnd, LB_GETSELCOUNT, 0, 0)
If nCount Then
ReDim Indices(OptionBase To OptionBase + nCount - 1)
SendMessage .hwnd, LB_GETSELITEMS, nCount, _
Indices(OptionBase)
End If
End With
LBGetSelIndices = nCount
End Function
Mit der Liste der Indices können Sie nun schon einiges mehr anfangen. Sie können Sie aufbewahren und jederzeit auf die ausgewählten Elemente über die List-Eigenschaft der ListBox zugreifen. Und auch die jeweiligen ItemData-Werte können Sie anhand der Indices jederzeit erhalten.
Wenn Sie es bequemer haben möchten, können Sie anhand der Indices-Liste eigene Listen der Elemente erstellen, etwa ebenfalls als Array oder auch als Collection.
Public Function LBGetSelItemsArray(ListBox As ListBox, _
Items() As String, Optional ByVal OptionBase As Long) As Long
Dim nIndices() As Long
Dim nCount As Long
Dim l As Long
nCount = LBGetSelIndices(ListBox, nIndices, OptionBase)
If nCount Then
ReDim Items(LBound(nIndices) To UBound(nIndices))
With ListBox
For l = LBound(nIndices) To UBound(nIndices)
Items(l) = .List(nIndices(l))
Next 'l
End With
End If
LBGetSelItemsArray = nCount
End Function
Public Function LBGetSelItems(ListBox As ListBox) As Collection
Dim nItems As Collection
Dim nIndices() As Long
Dim nCount As Long
Dim l As Long
nCount = LBGetSelIndices(ListBox, nIndices)
Set nItems = New Collection
If nCount Then
With ListBox
For l = 0 To UBound(nIndices)
nItems.Add .List(nIndices(l))
Next 'l
End With
End If
Set LBGetSelItems = nItems
End Function
Sind Sie lediglich an den ItemData-Werten interessiert, können Sie auch diese in eigene Listen (Array oder Collection) stecken:
Public Function LBGetSelItemDataArray(ListBox As ListBox, _
ItemData() As Long, Optional ByVal OptionBase As Long) As Long
Dim nIndices() As Long
Dim nCount As Long
Dim l As Long
nCount = LBGetSelIndices(ListBox, nIndices, OptionBase)
If nCount Then
ReDim ItemData(LBound(nIndices) To UBound(nIndices))
With ListBox
For l = LBound(nIndices) To UBound(nIndices)
ItemData(l) = .ItemData(nIndices(l))
Next 'l
End With
End If
LBGetSelItemDataArray = nCount
End Function
Public Function LBGetSelItemData(ListBox As ListBox) As Collection
Dim nItemData As Collection
Dim nIndices() As Long
Dim nCount As Long
Dim l As Long
nCount = LBGetSelIndices(ListBox, nIndices)
Set nItemData = New Collection
If nCount Then
With ListBox
For l = 0 To UBound(nIndices)
nItemData.Add .ItemData(nIndices(l))
Next 'l
End With
End If
Set LBGetSelItemData = nItemData
End Function
Sollten Sie am "kompletten" Satz der Daten eines Elements interessiert sein und Ihre eigene Liste sowohl das Element und den ItemData-Wert als auch noch den Index enthalten, lässt sich das ebenfalls bewerkstelligen.
Die Funktion LBGetSelItemsExArray liefert ein zweidimensionales Array. Die erste Dimension enthält die "Datensätze", die zweite Dimension enthält die jeweiligen Bestandteile (so zu sagen die "Felder"). Für beide Dimensionen können Sie den Basis-Index (Standard-Werte sind wieder 0) angeben.
Public Function LBGetSelItemsExArray(ListBox As ListBox, _
Items() As Variant, Optional ByVal OptionBaseIndices As Long, _
Optional ByVal OptionBaseData As Long) As Long
Dim nIndices() As Long
Dim nCount As Long
Dim l As Long
Dim n As Long
nCount = LBGetSelIndices(ListBox, nIndices, _
OptionBaseIndices)
If nCount Then
ReDim Items(LBound(nIndices) To UBound(nIndices), _
OptionBaseData To OptionBaseData + 2)
With ListBox
For l = LBound(nIndices) To UBound(nIndices)
n = nIndices(l)
Items(l, OptionBaseData) = .List(n)
Items(l, OptionBaseData + 1) = .ItemData(n)
Items(l, OptionBaseData + 2) = n
Next 'l
End With
End If
LBGetSelItemsExArray = nCount
End Function
Die Funktion LBGetSelItemsExDataArray gibt eine Collection zurück, die den "Datensatz" zu jedem Element in Form eines einfachen Variant-Arrays (hier ist der Basis-Index unveränderbar 0) enthält.
Public Function LBGetSelItemsExDataArray(ListBox As ListBox) _
As Collection
Dim nItems As Collection
Dim nIndices() As Long
Dim nCount As Long
Dim l As Long
Dim n As Long
nCount = LBGetSelIndices(ListBox, nIndices)
Set nItems = New Collection
If nCount Then
With ListBox
For l = 0 To UBound(nIndices)
n = nIndices(l)
nItems.Add Array(.List(n), .ItemData(n), n)
Next 'l
End With
End If
Set LBGetSelItemsExDataArray = nItems
End Function
Und schließlich bietet Ihnen die Funktion LBGetSelItemsEx eine Collection, in der jedes Element in einer Mini-Collection abgelegt ist, die nun jeweils die drei Felder mit den Schlüsseln "Item", "ItemData" und "Index" versehen enthält.
Public Function LBGetSelItemsEx(ListBox As ListBox) As Collection
Dim nItems As Collection
Dim nData As Collection
Dim nIndices() As Long
Dim nCount As Long
Dim l As Long
nCount = LBGetSelIndices(ListBox, nIndices)
Set nItems = New Collection
If nCount Then
With ListBox
For l = 0 To UBound(nIndices)
Set nData = New Collection
nData.Add .List(nIndices(l)), "Item"
nData.Add .ItemData(nIndices(l)), "ItemData"
nData.Add nIndices(l), "Index"
nItems.Add nData
Next 'l
End With
End If
Set LBGetSelItemsEx = nItems
End Function
|