Setting ListIndex

B

BruceS

Hi, all!

I have noticed that when I use cbo.ListIndex = x to set the value of a combo
box, the AfterUpdate event fires twice, sucessively. Is there any way to
prevent this? I have a lengthy routine that runs in AfterUpdate and really
don't want it to run twice.

Thanks,
Bruce
 
R

ruralguy via AccessMonster.com

The ListIndex property of a ComboBox is read only. You should be throwing
error 7777 - You've used the ListIndex Property incorrectly.
 
R

ruralguy via AccessMonster.com

Hi Bruce,
I stand corrected. Thank you. I get 2 AfterUpdate events as well. What are
you trying to accomplish and maybe there is another way to do it. I know you
are running the cbo with code, but why?
RuralGuy,

Nope, it's read-write. (See MSDN listing,
http://msdn.microsoft.com/library/d...us/vbaac11/html/acproListIndex_HV05187422.asp)

Only thing is that you have to set focus on it before you assign it a value.
If you don't you will get the 7777.

Bruce
The ListIndex property of a ComboBox is read only. You should be throwing
error 7777 - You've used the ListIndex Property incorrectly.
[quoted text clipped - 8 lines]
 
R

ruralguy via AccessMonster.com

Thanks for the explaination Bruce. It makes sense and I can't think of a
better way right now other than just using a RecordSet directly. Sorry I
couldn't come up with something. Maybe someone else will drop by with a
useful suggestion.
This part of the app is for a manufacturing control system and is used with
a touch screen, so I have to use a large text box for the displayed value and
finger-size "up" and "down" buttons to change the value.

The cbo is actually "hidden", but has 6 columns that provide data for other
items on the form. Just seemed a lot easier to use it than to do a bunch of
DLookUps every time the user hit or up or down. The recordsource is a
standard one that is used all through the app, so it also gave me some
consistency in variable naming.

Best I've been able to figure out is to use a global flag that I set just
before changing the index, then test at the top of the AfterUpdate. I use it
to bypass the logic the second time through. It's not pretty, but it works.

Bruce
Hi Bruce,
I stand corrected. Thank you. I get 2 AfterUpdate events as well. What are
[quoted text clipped - 16 lines]
 
D

Dirk Goldgar

BruceS said:
Hi, all!

I have noticed that when I use cbo.ListIndex = x to set the value of
a combo box, the AfterUpdate event fires twice, sucessively. Is
there any way to prevent this? I have a lengthy routine that runs in
AfterUpdate and really don't want it to run twice.

Why are you using the ListIndex to set the combo's value? Why not just
set the value directly in your code, and then call the combo's
AfterUpdate event procedure?
 
B

BruceS

Dirk,
See 2:02 PM PST post, above.
Bruce

Dirk Goldgar said:
Why are you using the ListIndex to set the combo's value? Why not just
set the value directly in your code, and then call the combo's
AfterUpdate event procedure?

--
Dirk Goldgar, MS Access MVP
www.datagnostics.com

(please reply to the newsgroup)
 
D

Dirk Goldgar

BruceS said:
Dirk,
See 2:02 PM PST post, above.
Bruce

I read that, Bruce, but it doesn't answer my question. If what you want
to do is set the value of a combo box, why are you using the ListIndex
property to do it? Why not just set the combo box's Value property?
That's simple, easily understood, and relieves you of the need to set
the focus to the combo box. If you do it in code, that won't fire the
AfterUpdate event, but you can always simply call that event procedure
in your code after you assign the value.
 
B

BruceS

Dirk,

Maybe I am doing it the hard way...

There is a list of production machines with various specs stored in a table.
I use a query to select specific ones compatible with the task being done,
and load that result as the RowSource for the combo, sorted by the "common
name". (One of them is "Matilda", believe it or not.) The terminal on which
the form runs has a mouse, but the operators vastly perfer to use the
touchscreen, so I need a way for the operator to scroll up or down the list
by touching a button until they reach the machine they want to use. The
"show list" button on the combo box control is not big enough to use on the
touchscreen and, even if it was, it'd be difficult for them to touch the
proper line entry in the list.

Current logic reads the up/down button click then increments/decrements the
index to change the values shown on the screen and stored in variables. I
pull the values from .Column(2), .Column(3), etc. to use in controlling the
selected machine.

I can't just assign the value of the next item because I don't know what it
is. The MachID field (value for the combo box) is not sequential. I guess I
could open a recordset and move up or down through it, but that seemed like a
lot more coding effort than just dropping the combo box on the form.

You've been doing VBA a lot longer than me so, if you have a suggestion for
accomplishing the same thing a better way, I'd love to hear it. Always
willing to learn!

BTW, I know you MVPs don't hear this often, but you're a tremendous
resource. Thanks for being there.

Bruce
 
R

ruralguy via AccessMonster.com

BTW, I know you MVPs don't hear this often, but you're a tremendous
resource. Thanks for being there.

Ditto for me Dirk. Thanks!

Dirk said:
Dirk,
See 2:02 PM PST post, above.
[quoted text clipped - 10 lines]
I read that, Bruce, but it doesn't answer my question. If what you want
to do is set the value of a combo box, why are you using the ListIndex
property to do it? Why not just set the combo box's Value property?
That's simple, easily understood, and relieves you of the need to set
the focus to the combo box. If you do it in code, that won't fire the
AfterUpdate event, but you can always simply call that event procedure
in your code after you assign the value.
 
M

Marshall Barton

BruceS said:
I have noticed that when I use cbo.ListIndex = x to set the value of a combo
box, the AfterUpdate event fires twice, sucessively. Is there any way to
prevent this? I have a lengthy routine that runs in AfterUpdate and really
don't want it to run twice.


Have you tried just setting the combo box's Value?

Me.combo = Me.combo.Column(bc, ndx)

where bc is the combo box's bound column less one and ndx is
the value you were setting Listindex to (less one?)

This way the AfterUpdate event will not be triggered at all.
You can call the AfterUpdate event right after the line
above line of of code:
Me.combo_AfterUpdate
 
D

Dirk Goldgar

BruceS said:
Dirk,

Maybe I am doing it the hard way...

There is a list of production machines with various specs stored in a
table. I use a query to select specific ones compatible with the
task being done, and load that result as the RowSource for the combo,
sorted by the "common name". (One of them is "Matilda", believe it
or not.) The terminal on which the form runs has a mouse, but the
operators vastly perfer to use the touchscreen, so I need a way for
the operator to scroll up or down the list by touching a button until
they reach the machine they want to use. The "show list" button on
the combo box control is not big enough to use on the touchscreen
and, even if it was, it'd be difficult for them to touch the proper
line entry in the list.

Current logic reads the up/down button click then
increments/decrements the index to change the values shown on the
screen and stored in variables. I pull the values from .Column(2),
.Column(3), etc. to use in controlling the selected machine.

I can't just assign the value of the next item because I don't know
what it is. The MachID field (value for the combo box) is not
sequential. I guess I could open a recordset and move up or down
through it, but that seemed like a lot more coding effort than just
dropping the combo box on the form.

You've been doing VBA a lot longer than me so, if you have a
suggestion for accomplishing the same thing a better way, I'd love to
hear it. Always willing to learn!

How about using functions like these?

'----- start of code -----
Public Function AdvanceCombo(cbo As Access.ComboBox) As Long

' Advances the argument combo box to the next entry in its list,
' and returns the ListIndex value of that entry. If the combo box
' is already at the last entry, the value and ListIndex of the combo
' remain unchanged.

Dim lngNext As Long

With cbo
lngNext = .ListIndex + 1
If lngNext < .ListCount Then
.Value = .ItemData(lngNext)
AdvanceCombo = lngNext
Else
AdvanceCombo = .ListIndex
End If
End With

End Function

Public Function RetreatCombo(cbo As Access.ComboBox) As Long

' Retreats the argument combo box to the previous entry in its list,
' and returns the ListIndex value of that entry. If the combo box
' is already at the first entry -- or is not set to any entry -- the
' value and ListIndex of the combo remain unchanged.

Dim lngPrevious As Long

With cbo
lngPrevious = .ListIndex - 1
If lngPrevious >= 0 Then
.Value = .ItemData(lngPrevious)
RetreatCombo = lngPrevious
Else
RetreatCombo = .ListIndex
End If
End With

End Function
'----- end of code -----

Note -- I just wrote those functions, so they've only been lightly
tested, and obviously any error-handling is left as an exercise for the
reader. <g>

With those functions in a standard module, you could code the event
procedures for your "up" and "down" buttons as simply as this:

'----- start of code -----
Private Sub cmdComboUp_Click()

AdvanceCombo Me.cboMachine

End Sub

Private Sub cmdComboDown_Click()

RetreatCombo Me.cboMachine

End Sub
'----- end of code -----

Or you could even forego the event procedures entirely, and set the
buttons' OnClick event properties to simple function expressions:

=AdvanceCombo([cboMachine])

=RetreatCombo([cboMachine])
BTW, I know you MVPs don't hear this often, but you're a tremendous
resource. Thanks for being there.

You're very welcome, Bruce. Thank you for the kind word.
 
D

David F Cox

My guess is that there are not that many machines involved, and never will
be. If that is true I would make the app generate an array of buttons and
have the operator "push" one. To preserve screen real estate I would have
these on a popup form, so it would be click popup, click button, job done.
 
B

BruceS

Great GUI suggestion, David. Thanks!
Bruce

David F Cox said:
My guess is that there are not that many machines involved, and never will
be. If that is true I would make the app generate an array of buttons and
have the operator "push" one. To preserve screen real estate I would have
these on a popup form, so it would be click popup, click button, job done.
 
B

BruceS

Dirk,
Thanks for the time and effort! Looks like Marsh bested us both.
Bruce

Dirk Goldgar said:
BruceS said:
Dirk,

Maybe I am doing it the hard way...

There is a list of production machines with various specs stored in a
table. I use a query to select specific ones compatible with the
task being done, and load that result as the RowSource for the combo,
sorted by the "common name". (One of them is "Matilda", believe it
or not.) The terminal on which the form runs has a mouse, but the
operators vastly perfer to use the touchscreen, so I need a way for
the operator to scroll up or down the list by touching a button until
they reach the machine they want to use. The "show list" button on
the combo box control is not big enough to use on the touchscreen
and, even if it was, it'd be difficult for them to touch the proper
line entry in the list.

Current logic reads the up/down button click then
increments/decrements the index to change the values shown on the
screen and stored in variables. I pull the values from .Column(2),
.Column(3), etc. to use in controlling the selected machine.

I can't just assign the value of the next item because I don't know
what it is. The MachID field (value for the combo box) is not
sequential. I guess I could open a recordset and move up or down
through it, but that seemed like a lot more coding effort than just
dropping the combo box on the form.

You've been doing VBA a lot longer than me so, if you have a
suggestion for accomplishing the same thing a better way, I'd love to
hear it. Always willing to learn!

How about using functions like these?

'----- start of code -----
Public Function AdvanceCombo(cbo As Access.ComboBox) As Long

' Advances the argument combo box to the next entry in its list,
' and returns the ListIndex value of that entry. If the combo box
' is already at the last entry, the value and ListIndex of the combo
' remain unchanged.

Dim lngNext As Long

With cbo
lngNext = .ListIndex + 1
If lngNext < .ListCount Then
.Value = .ItemData(lngNext)
AdvanceCombo = lngNext
Else
AdvanceCombo = .ListIndex
End If
End With

End Function

Public Function RetreatCombo(cbo As Access.ComboBox) As Long

' Retreats the argument combo box to the previous entry in its list,
' and returns the ListIndex value of that entry. If the combo box
' is already at the first entry -- or is not set to any entry -- the
' value and ListIndex of the combo remain unchanged.

Dim lngPrevious As Long

With cbo
lngPrevious = .ListIndex - 1
If lngPrevious >= 0 Then
.Value = .ItemData(lngPrevious)
RetreatCombo = lngPrevious
Else
RetreatCombo = .ListIndex
End If
End With

End Function
'----- end of code -----

Note -- I just wrote those functions, so they've only been lightly
tested, and obviously any error-handling is left as an exercise for the
reader. <g>

With those functions in a standard module, you could code the event
procedures for your "up" and "down" buttons as simply as this:

'----- start of code -----
Private Sub cmdComboUp_Click()

AdvanceCombo Me.cboMachine

End Sub

Private Sub cmdComboDown_Click()

RetreatCombo Me.cboMachine

End Sub
'----- end of code -----

Or you could even forego the event procedures entirely, and set the
buttons' OnClick event properties to simple function expressions:

=AdvanceCombo([cboMachine])

=RetreatCombo([cboMachine])
BTW, I know you MVPs don't hear this often, but you're a tremendous
resource. Thanks for being there.

You're very welcome, Bruce. Thank you for the kind word.

--
Dirk Goldgar, MS Access MVP
www.datagnostics.com

(please reply to the newsgroup)
 
M

Marshall Barton

Thanks for the nice words, but, now that I can see Dirk's
posts, I think he was leading up to the same conclusion.
 
Top