recursive setfocus. (1 Viewer)

John Sh

Member
Local time
Today, 20:54
Joined
Feb 8, 2021
Messages
410
when I run the code below with the first copy of cboBox_gotfocus the code flow is as follows;
from setfocus in collect afterupdate
to box gotfocus and call box_afterupdate.
runs the code in box_after which sets focus to another textbox
box-afterupdate ends and the code returns to box_gotfocus and exits .
the code now returns to collect_afterupdate and errors on cbobox_setfocus
The error message indicates it can't set focus to cbobox.

If I run the code with the second iteration of cbobox_gotfocus, i.e the code commented out, focus is set to cbobox as expected

I hope this is understandable as I can't think of another way to explain it.

Code:
Private Sub cboCollect_AfterUpdate()
   Me.cboBox.Requery
   Me.cboBox.SetFocus
   Me!cboBox.Dropdown
End Sub

Private Sub cboBox_GotFocus()
    Me.cboBox.BackColor = RGB(218, 255, 94)
    If Nz(Me.cboBox.ItemData(1), "") = "" Then
        Me.cboBox = Me.cboBox.ItemData(0)
        Call cboBox_AfterUpdate
   End If
End Sub

Private Sub cboBox_GotFocus()
    Me.cboBox.BackColor = RGB(218, 255, 94)
'    If Nz(Me.cboBox.ItemData(1), "") = "" Then
'        Me.cboBox = Me.cboBox.ItemData(0)
'        Call cboBox_AfterUpdate
'    End If
End Sub
 

Minty

AWF VIP
Local time
Today, 11:54
Joined
Jul 26, 2013
Messages
10,371
That's very confusing.
I think because you are setting the Itemdata in the cboBox, it is effectively trying to set the focus again to that control, which it can't do.

In this case, a rare ask, it might be better to describe what you are trying to achieve, rather than showing the code that doesn't work?
Why not do the cboBox itemdata process in the other controls after update event, then set focus to it?
 

cheekybuddha

AWF VIP
Local time
Today, 11:54
Joined
Jul 21, 2014
Messages
2,280
Why are you using the AfterUpdate at all?

What if you try removing the AfterUpdate code and just use:
Code:
Private Sub cboBox_GotFocus()
    With Me.cboBox
      .BackColor = RGB(218, 255, 94)
      If Nz(.cboBox.ItemData(1), "") = "" Then
        .cboBox = .cboBox.ItemData(0)
        .Dropdown
      End If
    End With
End Sub
?
 

John Sh

Member
Local time
Today, 20:54
Joined
Feb 8, 2021
Messages
410
What am I trying to do?
In the event that there is only one item in the query result, load that item and save a redundant click by the user.
If there is more than one result, let the user choose.

Why use afterupdate?
If there are multiple results to choose from, the afterupdate event needs to trigger after the user makes a choice.

Looking at your response, Cheekybuddha, I do not need the dropdown command if there is only one result.

Minty. Why didn't I think of that?
I'll work on both your ideas and let you know the result.

Thank you both for your time and suggestions. Much appreciated.
John
 

John Sh

Member
Local time
Today, 20:54
Joined
Feb 8, 2021
Messages
410
Code:
Private Sub cboBox_GotFocus()
    With Me.cboBox
      .BackColor = RGB(218, 255, 94)
      If Nz(.cboBox.ItemData(1), "") = "" Then
        .cboBox = .cboBox.ItemData(0)
        .Dropdown
      End If
    End With
End Sub
?
Just a point to clear up.
If I use "With me.cbobox" do I then need to repeat ".cbobox" or could I just use ".itmedata(1)"
or could I say "with me" and then use ".cbobox...."
just curious.
John
 

cheekybuddha

AWF VIP
Local time
Today, 11:54
Joined
Jul 21, 2014
Messages
2,280
If I use "With me.cbobox" do I then need to repeat ".cbobox" or could I just use ".itmedata(1)"
Sorry, the .cbobox within the With ... End With was left behind in error - you should remove it.
 

cheekybuddha

AWF VIP
Local time
Today, 11:54
Joined
Jul 21, 2014
Messages
2,280
or could I say "with me" and then use ".cbobox...."
Actually, that would probably be a better strategy since you need to refer to .cbobox.

So either:
Code:
Private Sub cboBox_GotFocus()
    With Me.cboBox
      .BackColor = RGB(218, 255, 94)
      If Nz(.ItemData(1), "") = "" Then
        .Value = .ItemData(0)
        .Dropdown
      End If
    End With
End Sub
or:
Code:
Private Sub cboBox_GotFocus()
    With Me
      .cboBox.BackColor = RGB(218, 255, 94)
      If Nz(.cboBox.ItemData(1), "") = "" Then
        .cboBox = .cboBox.ItemData(0)
        .cboBox.Dropdown
      End If
    End With
End Sub
(with your necessary logic adjustments as well!)
 

John Sh

Member
Local time
Today, 20:54
Joined
Feb 8, 2021
Messages
410
Puting the relevant code in the "Collect_afterupdate" did the trick.
If there is only one response from the query then that is entered into cbobox and the afterupdate event does it's thing, otherwise the cbobox dropdown is triggered.

Code:
Private Sub cboBox_GotFocus()
    Me.cboBox.BackColor = RGB(218, 255, 94)
End Sub


Private Sub cboCollect_AfterUpdate()
    Me.cboBox.Requery
    If Nz(Me.cboBox.ItemData(1), "") = "" Then
        Me.cboBox = Me.cboBox.ItemData(0)
        Call cboBox_AfterUpdate
    Else
        Me.cboBox.SetFocus
        Me!cboBox.Dropdown
    End If
End Sub

Apart from a bit less typing, is there any real advantage to using the "With... End With" construct?

Once again I thank you both.
John
 

The_Doc_Man

Immoderate Moderator
Staff member
Local time
Today, 05:54
Joined
Feb 28, 2001
Messages
27,186
Just a couple of side comments:

FIrst, in cboCollect_AfterUpdate() you have a call to cboBox_AfterUpdate, but in the thread title you mention recursion. If that was supposed to be recursive, it is not because the called and calling names are different. In fact, it is possible to perform recursion and I have done so for my home genealogy project. But recursion is not for the squeamish because of what it does to system memory if your recursion termination code has any weaknesses.

Second, whatever you planned to do, remember this: Access is normally single-threaded and linearized. Mechanically, an event routine is called when something in Access detects that you declared a routine for the event. It is NOT the result of an interrupt. It is a SCHEDULED action based on the internal sequence of Access operations (that are a black box to us on the outside.) But that means that normally, only one event routine at a time can be running for a given form's class module. Events cannot interrupt each other because there IS no interrupt. Though it IS possible to explicitly call an event routine through its entry point such as your CALL instruction to cboBox_AfterUpdate. In that case, you have one active event routine and one pending on the call stack waiting for the active routine's End Sub/Exit Sub.

Third, just as a clarification, you showed us code in post #1, but if you tried to activate that code, you had TWO definitions of cboBox_GotFocus. Only one of those can be valid, and I believe the 2nd definition "wins" ... in this case, the one with most of its lines "ticked" out. Both sets of code might be compiled - but one of them is unreachable. The event entry point linkage in the control's event property list will only point to one of them. A direct call will only get one of them. The other one's definition has been overridden.
 

John Sh

Member
Local time
Today, 20:54
Joined
Feb 8, 2021
Messages
410
Thanks docman.
Your information is good but I think you have misread my OP.
The second iteration of cbobox_Gotfocus is a demo of what works in my problem, not that I have two iterations defined at the same time.
The demo code was never meant to run.
My calling the problem "recursive"was possibly a bit misleading. I am fully aware of recursion and it's traps but in this case the setfocus event was being activated and the reactivating after the ensuing code was completed.
As always I appreciate your input.
John
 

John Sh

Member
Local time
Today, 20:54
Joined
Feb 8, 2021
Messages
410
Another update.
By adding a .requery to the code, the unwanted dropdown is cleared, making the form cleaner.

Code:
If Nz(Me.cboBox.ItemData(1), "") = "" Then
        Me!cboBox = Me.cboBox.ItemData(0)
        Me.cboBox.Requery
        Call cboBox_afterupdate
    Else
        Me.cboBox.SetFocus
        Me!cboBox.Dropdown
End If
 

Users who are viewing this thread

Top Bottom