Listbox ItemsSelected returns NULL item on first call - but not if debugging - not a DoEvent problem (2 Viewers)

GregDataReno

Member
Local time
Tomorrow, 05:37
Joined
Jul 4, 2016
Messages
41
Weird.

Scenario:
  1. I have a multiselect ListBox on a form.
  2. I open the form and select one item in the list box and run code.
  3. The code iterates over the listbox to build a concatenated string of selected items
  4. The loop only looks at the collection of selected items ie. "for each variant item in the listbox.ItemsSelected"
Problem:
  1. Open the form and the first call of the, the code confirms one item is selected - it enters the loop but the list.ItemsSelected(varItem) returns NULL
  2. Keeping the form open and run the call again and the code works fine.
Solution:
  1. the second call to the code - with no change to the list - now enters the loop AND returns the selected item
If I debug the code, the problem does not occur. This is INFORMATIVE, but impossible to test. DoEvents has no effect.

I've tried variations on ListBox methods without success -- the same problem occurs if I step through all ListBox records and test only for selected items.

Each time I open the form, the first call fails, then all subsequent calls succeed.

Very annoying.

Advice most welcome

Greg
365/Access 64bit
 
UPDATE: With two ListBoxes on the form, the first time I select any item in any list, the code sees a selection but the loop into the selected items fails.

The only thing I can see that's different is, in the first time, the selected item's highlight is incomplete - the selected item has a dashed box around it. When returning from the first call to code, the selected items are now fully highlighted - no dashed box.
 
Can you post a demo file?
 
When you are confirming that an item (or more than one) was selected, did you test listbox.ItemsSelected.Count first? Is that how you determined that an item was selected? Just dotting the i's and crossing the t's with that question.
 
Yep... here's simplified version:

Code:
If ctlList.ItemsSelected.Count > 0 Then
    For Each <variant> In ctlList.ItemsSelected
         string = string & ctlList.ItemData(<variant>)
    Next varItem
End if

I can confirm that when the form is first opened and
  1. any one item selected in one list, the listbox (in code) does return the correct 'selected items' count =1 but the list.ItemData(item variant) returns NULL.
  2. select two items in the list on first opening, and the first selected item is ignored
  3. change nothing and run the same code a second time, and now the ItemData returns all selected values.
The problem seems to be that on first opening the form and selecting items, the ListBox doesn't update its ItemData collection. Only when focus returns to the Listbox does the count of selected items match the count of ItemData items.

Moving off and on the list on first opening makes no difference - first time the ITemData is NULL

UPDATE: Just noticed that on first opening, select two items then deselect the first, and the ItemData collection ONLY contains the deselected item

I'm pouring over my iterators - gotta be something wrong somewhere.
 
Any code related to the list box besides the items selected?

Bear in mind that a list boxes value can be set to anything in code, even values that are not in the list.

If you're setting the value on load with .itemdata(0) I believe you get a dotted outline
 
Here's a trivial demo - "ListTester.accdb". It uses VBA so will need to be trusted (the VBA is signed).

Open the single form and selecting a list item and then Run. An error is fired - the listbox reports at least one item has been selected, but iterating across the list Items using <list>.Selected(iterator) = TRUE returns nothing.

Dismiss the error dialog and repeat the Run and the error does NOT repeat.

I tested this same form first with only one ListBox and the error did not occur, suggesting it's a problem with cycling the collection of Controls on the form?

(PS: any reason why digitally signed ACCDC databases are not accepted for upload?)
 

Attachments

Change listbox loop to
Diff:
Dim varItem As Variant
...
                    For Each varItem In .ItemsSelected
                        If Not IsNull(varItem) Then
                        ' strFilter = strFilter & " " & i & ":" & .ItemData(i)
                        strIN = strIN & dblQuote(.ItemData(varItem)) & ","
                        End If
                    Next
Review http://allenbrowne.com/ser-50.html
 
Here's the truth test to prove that <listbox>.ItemData(i) is NULL yet a value is returned on a second call:

(I'll test storing the ItemData value before using it - see if it forces the ListBox to read .ItemData)

For i = 0 To .ListCount - 1
If .Selected(i) = True Then
If IsNull(.ItemData(i)) Then
' test failed
Beep
MsgBox ".ItemData(" & i & ") tested NULL; but value returned is " & dblQuote(.ItemData(i))
End If
' strFilter = strFilter & " " & i & ":" & .ItemData(i)
strIN = strIN & dblQuote(.ItemData(i)) & ","
End If
Next i
2025-04-19_13-43-03.png
 
1745049220629.png



Thanks. This will prevent the error but won't fix the bug where first call to ItemData(i) fails but succeeds on subsequent calls.

It does seem to me that when first selecting an item in the list, the item 'looks' selected, but is surrounded by a marque-style border and not a solid border - it's as if the item is marked for selection, but not actually written to ItemData.

Then when focus comes back to the form after the first run, the selected item's border is now solid - as if it's been stored to ItemData - and subsequent calls to ItemData succeed.
 
What event are you using to run the code? Form open? Load? Current? Listbox afterupdate? Something else?
 
What event are you using to run the code? Form open? Load? Current? Listbox afterupdate? Something else?
Just hit the Run Query button to load an existing query that then filters on the contents of the lists (there's a demo accdb in this thread - signed). The issue remains - the count of selected items > 0, but the actual ItemData is NULL - but only the first time the query is called.
 
Just had a quick glance because I'm rushing at the moment, but the problem appears to be:
Code:
' ...
                    For i = 0 To .ListCount - 1
                        If .Selected(i) = True Then        ' <--- Problem here
                            ' strFilter = strFilter & " " & i & ":" & .ItemData(i)
                            strIN = strIN & dblQuote(.ItemData(i)) & ","
                        End If
                    Next i
' ...

.Selected(i) gives you the index of the selected item, not whether an item is selected or not.

The first index = 0, so coerces to False.

Why aren't you iterating the .ItemsSelected collection instead?


Actually, I think it's because you have listbox headers, and row 0 is actually the header.

Try changing your code to:
Code:
' ...

                    For i = (0 - .ColumHeads) To .ListCount - 1
' ...
 
Last edited:
Just had a quick glance because I'm rushing at the moment, but the problem appears to be:
Code:
' ...
                    For i = 0 To .ListCount - 1
                        If .Selected(i) = True Then        ' <--- Problem here
                            ' strFilter = strFilter & " " & i & ":" & .ItemData(i)
                            strIN = strIN & dblQuote(.ItemData(i)) & ","
                        End If
                    Next i
' ...

.Selected(i) gives you the index of the selected item, not whether an item is selected or not.

The first index = 0, so coerces to False.

Why aren't you iterating the .ItemsSelected collection instead?


Actually, I think it's because you have listbox headers, and row 0 is actually the header.

Try changing your code to:
Code:
' ...

                    For i = (0 - .ColumHeads) To .ListCount - 1
' ...
Yeeees, tried with and without Headers. The numbering is tricky in any case, but the ItemData(i) still returns a NULL on first call, even though .Selected > 0 - remains weird.

I think it still comes down to the 'selected' status of the ListBox - first call is a marquee border, later calls are solid borders, which I think hints at the ItemData property is incomplete on first call because .Selected is greater than zero, hence 'weird'
 
I think I need to do some deeper forensics, try some 'LostFocus' code on the listbox or Form (yuck, I hate kludges). I'll post any discoveries.
 
Did you try what I suggested, so that you avoid i = 0 if you have columnheads?
Yep - thanks for following up.

I tested with ColumnHeads active - it requires changing the iterators since the ListCount is base ONE, but the ItemData array is base ZERO (I'm not changing OPTION BASE for purity). The result is the same - first pass ItemData = NULL, second pass ItemData = selected value.

AND NOTE: if we step through the code, the NULL does NOT occur - the ItemData array returns the selected value - hence my comment about it not being a DoEvents (I tried it) because I thought perhaps there's a delay in the ListBox saving the selection array.
 

Users who are viewing this thread

Back
Top Bottom