Move multiple items in a listbox

Zakraket

Registered User.
Local time
Today, 13:37
Joined
Feb 19, 2013
Messages
92
I have a form with a listbox in which users should be able to move the items up and down. The listbox has 4 columns and multiple selection is enabled.

For a NON multiselect box I have it working, and also for a multiple selection box but in that case it works only for one row at a time.

For a NON multiselect listbox:
Code:
cmdDown_Click()
Dim i As Integer
Dim t1 As String, t2 As String, t3 As String, t4 As String

i = selectie.ListIndex

t1 = Nz(selectie.Column(0, i))
t2 = Nz(selectie.Column(1, i))
t3 = Nz(selectie.Column(2, i))
t4 = Nz(selectie.Column(3, i))
t1 = t1 & Chr(59) & t2 & Chr(59) & t3 & Chr(59) & t4

If i < selectie.ListCount - 1 Then
    Me.selectie.RemoveItem (i)
    Me.selectie.AddItem t1, i + 1
    Me.selectie.Selected(i + 1) = True
Else

End If
You can select an item and then press "Down" as many times as you want to put the items as "down" in the list as you want it to be.

Multiselect listbox
This code also works for a multipleselection listbox when one item is selected, however, after you press "down" the item is still selected (highlighted) as the code reselects is (last line) BUT the value of selectie.listindex apparently is set to "-1".

Pressing "Down" again generates an error (i = -1). I can evade the error by adding "if selectie.listindex <=0 then exit sub", but that doens't fix the problem that the only way I can manage to reset the listindex to the new "position" of the item is to click on it again and THEN press "Down".

To fix this and be able to press "down" multiple times listindex should be set to the new value. Adding a "me.selectie.listindex = i -1" doens't work (error), it seems like this value is readonly despite what the helppage seems to say.
I can't find a way to "simulate" a mousepressed selection and really set the listindex.

The other problem is of course that this code doens't support moving multiple items at once: listindex points to the last selected item, but only one.

So, I tried another piece of code to move multiple items, not using listindex (since that resets to -1), but I run into another problem

Code:
Private Sub cmdDown_Click()
Dim var As Variant
Dim i As Integer
Dim n As Integer

Dim t1 As String, t2 As String, t3 As String, t4 As String

n = Me.selectie.ItemsSelected.Count

For i = Me.selectie.ListCount - 1 To 0 Step -1

    If Me.selectie.Selected(i) = True Then
    
        t1 = Nz(selectie.Column(0, i))
        t2 = Nz(selectie.Column(1, i))
        t3 = Nz(selectie.Column(2, i))
        t4 = Nz(selectie.Column(3, i))
        t1 = t1 & Chr(59) & t2 & Chr(59) & t3 & Chr(59) & t4
        
        If i < selectie.ListCount - 1 Then
            Me.selectie.RemoveItem (i)
            Me.selectie.AddItem t1, i + 1
            'Me.selectie.Selected(i + 1) = True
        Else
        
        End If
    End If
Next i

The problem with this is: I can select multiple items and press "Down", but the problem now is that the selection is lost as soon as the code removes the first item, and the 2nd loop skips the if selected(i) = true (nothing is selected anymore).
The me.selectie.selected(i+1) = true doens't work since that would only reselect the first item after moving it.

The code "forgets" which items were selected and moves only one item...So I guess I need to put the indexnumbers in memory while moving the items.

I have been searching a lot, but can only find VB-solutions. In VB it's a lot simpeler using f.e. the .list property of a listbox, which is not available in MSAccess

The solution I'm thinking about is:
- set an array with the numbers of selected items
- put indexnumbers of the selected items in the array (f.e. 3 and 4)
- move items based on the indexnumers in the array
- when moving an item update the indexnumber in the array (3>4, 4>5)
- after moving all items reset the selection based on the array

But maybe someone has another /better solution

edit: it occured to me then if I'm going to use an array anyway, I might as well load all items in an array, do the "resorting" and the reload the items in the list from the array. Might be more straightforward?

Btw...It seems VB has a simple solution to moving items: listbox.list(i) = listbox.list(i+1) or something like that moves an item. Even Excel seems to have this property but not MSaccess!
 
Last edited:
One part of the problem is solved: I CAN set listindex, but only if the listbox has focus :confused:

So:
Code:
Me.selectie.RemoveItem (i)
    Me.selectie.AddItem t1, i + 1
    Me.selectie.Selected(i + 1) = True
This part removes the selection, the third line "highlights" the line that was removed and added. However, listindex is still -1

If I add
Code:
    me.selectie.setfocus
    Me.selectie.listindex = i + 1
This sets the listindex to the corresponding line, but this works only after the setfocus. Without setfocus, you get an error stating that the listindex can't be updated.

This solves one part of the problem, being the fact that - in a multiselect listbox - I can highlight a row and then repeat the function as often as I want without actually reselecting the row.

However, listindex wasn't the real problem anymore since I can't use that when multiple items are selected

So, now for the actual problem: the problem that the selection is lost when trying to move multiple rows
 
Last edited:

Users who are viewing this thread

Back
Top Bottom