|
Eine ListBox mit Mehrfachauswahl liefert Ihnen zwar in der
Eigenschaft SelCount
die Anzahl der ausgewählten Elemente. Die tatsächlich gewählten
Elemente müssen Sie jedoch selbst herausfinden. Dazu könnten Sie
zum Beispiel in einer Schleife alle Elemente in der ListBox
durchlaufen und jeweils anhand der Selected-Eigenschaft
für jedes Element feststellen, ob es ausgewählt ist:
Dim l As Long
With ListBox
For l = 0 To .ListCount -1
If .Selected(l) Then
' gewählt...
End If
Next ' l
End With
Enthält die ListBox viele Elemente, und sind nur wenige davon
ausgewählt, ist der Zeitaufwand zur Ermittlung der gewählten
Elemente unverhältnismäßig hoch. Sie können jedoch über die
API-Funktion SendMessage
die Nachricht LB_GETSELITEMS
an die ListBox senden und eine Liste in Form eines Arrays mit den
Indices der gewählten Elemente erhalten. Der Funktion SendMessage
übergeben Sie neben dem Fenster-Handle (hWnd-Eigenschaft) der
ListBox die Nachrichten-Konstanten, die Anzahl der gewählten
Elemente und das erste Element eines Arrays des Datentyps Long, das
bereits entsprechend der Anzahl dimensioniert ist. Die
Hilfs-Funktion SelectedItemsIndexes vereinfacht den API-Aufruf für
eine beliebige ListBox.
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 SelectedItemsIndexes(ListBox As ListBox) _
As Variant
Dim nIndexes() As Long
Dim nSelCount As Long
With ListBox
nSelCount = .SelCount
If nSelCount Then
ReDim nIndexes(nSelCount - 1)
SendMessage .hwnd, LB_GETSELITEMS, nSelCount, nIndexes(0)
SelectedItemsIndexes = nIndexes
End If
End With
End Function
Nun haben Sie immerhin schon eine Liste der ausgewählten
Elemente. Diese Elemente müssen Sie allerdings nach wie vor selbst
aus der Liste auslesen. Die Funktion SelectedItemsArray liefert
Ihnen die Elemente in einem Array. Geben Sie im optionalen Parameter
IncItemData True an, erhalten Sie ein Variant-Array, in dessen
Elementen der jeweilige gewählte Eintrag in der ListBox und der
dazugehörende ItemData-Wert wiederum in einem Array abgelegt sind.
Lassen Sie IncItemData weg oder übergeben Sie ausdrücklch False,
erhalten Sie ein einfaches String-Array mit den gewählten
ListBox-Einträgen. Im optionalen Parameter OptionBase legen Sie
fest, ob das zurückgegebene Arrays mit dem Index 0
oder mit dem Index 1 beginnt. Im letzten optionalen
Parameter RemoveItems legen Sie schließlich noch fest, ob die
ausgelesenen Elemente gleich aus der ListBox entfernt werden sollen.
Public Enum OptionBaseConstants
OptionBase0
OptionBase1
End Enum
Public Function SelectedItemsArray(ListBox As ListBox, _
Optional ByVal IncItemData As Boolean, _
Optional ByVal OptionBase As OptionBaseConstants, _
Optional ByVal RemoveItems As Boolean) As Variant
Dim nIndexes As Variant
Dim l As Long
Dim nItems() As String
Dim nItemsUBound As Long
Dim nOptionBase As OptionBaseConstants
Dim nItems2() As Variant
nIndexes = SelectedItemsIndexes(ListBox)
If Not IsEmpty(nIndexes) Then
Select Case OptionBase
Case Is <= 0
nOptionBase = OptionBase0
Case Is >= 1
nOptionBase = OptionBase1
End Select
nItemsUBound = UBound(nIndexes)
With ListBox
If IncItemData Then
ReDim nItems2(nOptionBase To nItemsUBound + nOptionBase)
If RemoveItems Then
For l = nItemsUBound To 0 Step -1
nItems2(l + nOptionBase) = _
Array(.List(nIndexes(l)), .ItemData(nIndexes(l)))
.RemoveItem nIndexes(l)
Next 'l
Else
For l = 0 To nItemsUBound
nItems2(l + nOptionBase) = _
Array(.List(nIndexes(l)), .ItemData(nIndexes(l)))
Next 'l
End If
SelectedItemsArray = nItems2
Else
ReDim nItems(nOptionBase To nItemsUBound + nOptionBase)
If RemoveItems Then
For l = nItemsUBound To 0 Step -1
nItems(l + nOptionBase) = .List(nIndexes(l))
.RemoveItem nIndexes(l)
Next 'l
Else
For l = 0 To nItemsUBound
nItems(l + nOptionBase) = .List(nIndexes(l))
Next 'l
End If
SelectedItemsArray = nItems
End If
End With
End If
End Function
Die Funktion SelectedItemsCollection gibt Ihnen die gewählten
Elemente einer ListBox in einer Collection zurück. Setzen Sie den
optionalen Parameter IncItemData auf True, erhalten Sie auch hier
wieder als Elemente der Collection jeweils kleine Arrays mit den
eigentlichen ListBox-Einträgen und den dazugehörenden
ItemData-Werten. Im ptionalen Parameter ItemKeys geben Sie an, ob
die Elemente der Collection mit dem jeweiligen ListBox-Eintrag als
Schlüssel versehen werden sollen. Die Übergabe von True im
optionalen Parameter RemoveItems entfernt wieder die gewählten
Elemente nach dem Auslesen.
Public Function SelectedItemsCollection(ListBox As ListBox, _
Optional ByVal IncItemData As Boolean, _
Optional ByVal ItemKeys As Boolean, _
Optional ByVal RemoveItems As Boolean) As Collection
Dim nIndexes As Variant
Dim l As Long
Dim nItems As Collection
Dim nItemsUBound As Long
Dim nItem As String
nIndexes = SelectedItemsIndexes(ListBox)
If Not IsEmpty(nIndexes) Then
nItemsUBound = UBound(nIndexes)
Set nItems = New Collection
With ListBox
If IncItemData Then
If ItemKeys Then
If RemoveItems Then
nItem = .List(nIndexes(nItemsUBound))
nItems.Add Array(nItem, .ItemData(nItemsUBound)), nItem
.RemoveItem nIndexes(nItemsUBound)
For l = nItemsUBound - 1 To 0 Step -1
nItem = .List(nIndexes(l))
nItems.Add Array(nItem, .ItemData(nIndexes(l))), nItem, 1
.RemoveItem nIndexes(l)
Next 'l
Else
For l = 0 To nItemsUBound
nItem = .List(nIndexes(l))
nItems.Add Array(nItem, .ItemData(nIndexes(l))), nItem
Next 'l
End If
Else
If RemoveItems Then
nItems.Add Array(.List(nIndexes(nItemsUBound)), _
.ItemData(nIndexes(nItemsUBound)))
.RemoveItem nIndexes(nItemsUBound)
For l = nItemsUBound - 1 To 0 Step -1
nItems.Add Array(.List(nIndexes(l)), _
.ItemData(nIndexes(l))), , 1
.RemoveItem nIndexes(l)
Next 'l
Else
For l = 0 To nItemsUBound
nItems.Add Array(.List(nIndexes(l)), _
.ItemData(nIndexes(l)))
Next 'l
End If
End If
Else
If ItemKeys Then
If RemoveItems Then
nItem = .List(nIndexes(nItemsUBound))
nItems.Add nItem, nItem
.RemoveItem nIndexes(nItemsUBound)
For l = nItemsUBound - 1 To 0 Step -1
nItem = .List(nIndexes(l))
nItems.Add nItem, nItem, 1
.RemoveItem nIndexes(l)
Next 'l
Else
For l = 0 To nItemsUBound
nItem = .List(nIndexes(l))
nItems.Add nItem, nItem
Next 'l
End If
Else
If RemoveItems Then
nItems.Add .List(nIndexes(nItemsUBound))
.RemoveItem nIndexes(nItemsUBound)
For l = nItemsUBound - 1 To 0 Step -1
nItems.Add .List(nIndexes(l)), , 1
.RemoveItem nIndexes(l)
Next 'l
Else
For l = 0 To nItemsUBound
nItems.Add .List(nIndexes(l))
Next 'l
End If
End If
End If
End With
Set SelectedItemsCollection = nItems
End If
End Function
Schließlich können Sie die gewählten Elemente von der Funktion
SelectedItemsString auch in einem einzigen String zusammengefasst
erhalten, jeweils getrennt durch den im optionalen Parameter
Separator angegebenen Trenn-String (voreingestellt ist vbCrLf als
Zeilenschaltung). Diesen String können Sie beispielsweise gleich
komplett in eine Datei schreiben. Übergeben Sie im optionalen
Parameter EndSeparator False, wird der Trenn-String nach dem letzten
Element weggelassen. Auch hier entfernt wieder die Angabe von
RemoveItems gleich True die ausgelesenen Elemente aus der ListBox.
Public Function SelectedItemsString(ListBox As ListBox, _
Optional Separator As String = vbCrLf, _
Optional ByVal EndSeparator As Boolean = True, _
Optional ByVal RemoveItems As Boolean) As String
Dim nIndexes As Variant
Dim l As Long
Dim nItems As String
Dim nItemsUBound As Long
nIndexes = SelectedItemsIndexes(ListBox)
If Not IsEmpty(nIndexes) Then
nItemsUBound = UBound(nIndexes)
With ListBox
If RemoveItems Then
If EndSeparator Then
nItems = .List(nIndexes(nItemsUBound)) & Separator
Else
nItems = .List(nIndexes(nItemsUBound))
End If
.RemoveItem nIndexes(nItemsUBound)
For l = nItemsUBound - 1 To 0 Step -1
nItems = .List(nIndexes(l)) & Separator & nItems
.RemoveItem nIndexes(l)
Next 'l
Else
For l = 0 To nItemsUBound - 1
nItems = nItems & .List(nIndexes(l)) & Separator
Next 'l
If EndSeparator Then
nItems = nItems & .List(nIndexes(l)) & Separator
Else
nItems = nItems & .List(nIndexes(l))
End If
End If
End With
SelectedItemsString = nItems
End If
End Function
Falls Sie die von der ersten Funktion SelectedItemsIndexes
zurückgegebene Liste der Elemente selbst bearbeiten und auswerten
und trotzdem irgendwann danach die gewählten Elemente aus der
ListBox entfernen möchten, erledigt dies die Funktion RemoveItems:
Public Sub RemoveItems(ListBox As ListBox, Indexes() As Long)
Dim l As Long
With ListBox
For l = UBound(Indexes) To 0 Step -1
.RemoveItem Indexes(l)
Next 'l
End With
End Sub
|