Move to next control in access form

G

Grimwadec

With CodeContextObject

If IsNull(CodeContextObject) = False Then
DoCmd.GoToControl (MyProblem)
End If

End With

see above code where (MyProblem) represents the next control in the Tab
Order that I want to go to when the current control is Not Null. I want to
call a function containing code in each control in a form. Please, what is
the code I need for (MyProblem)
 
G

Grimwadec

I haven't explained myself very well. (MyProblem) is a euphemism for simply
the next control in the Tab Order which obviously will have differing names
depending on which control (about 8 of them in this instance) is the current
CodeContextObject. What I am looking for is perhaps the capacity to move to
the next item in say a numbered controls collection if there is such a thing
 
D

Dirk Goldgar

Grimwadec said:
With CodeContextObject

If IsNull(CodeContextObject) = False Then
DoCmd.GoToControl (MyProblem)
End If

End With

see above code where (MyProblem) represents the next control in the Tab
Order that I want to go to when the current control is Not Null. I want to
call a function containing code in each control in a form. Please, what is
the code I need for (MyProblem)


I wrote the following function to return the name of the next control in the
tab order of the argument control's parent page or section:

'----- start of code ------
Function NextInTabOrder(StartCtl As Access.Control) As String

' Returns the name of the next active control in the tab order,
' if possible. Returns a null string if there isn't one.
'
' Copyright (c) 2005-2009, DataGnostics LLC
' Full license is granted to use this code in your application,
' so long as the copyright notice remains unchanged.

Dim astrControlNames() As String
Dim obj As Object
Dim ctl As Access.Control
Dim intI As Integer

On Error Resume Next
'to ignore errors we expect to raise

Set obj = StartCtl.Parent

ReDim astrControlNames(obj.Controls.Count)

' Build a list of available controls indexed by TabIndex.
' We aren't interested in controls that are invisible,
' disabled, not a tab stop, or not in the same section
' as StartCtl.
For Each ctl In obj.Controls
With ctl
If .Section = StartCtl.Section Then
If .Visible = True _
And .Enabled = True _
And .TabStop = True Then
astrControlNames(.TabIndex) = .Name
End If
End If
End With
Next ctl

Set obj = Nothing

' Loop forward through the list
For intI = StartCtl.TabIndex + 1 To UBound(astrControlNames)
If Len(astrControlNames(intI)) > 0 Then
NextInTabOrder = astrControlNames(intI)
Exit Function
End If
Next intI

' If we didn't find one, start at the beginning of the list.
For intI = 0 To StartCtl.TabIndex - 1
If Len(astrControlNames(intI)) > 0 Then
NextInTabOrder = astrControlNames(intI)
Exit Function
End If
Next intI

' If we get here, there's no available control.
Exit Function

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

You might modify your code like this:

With CodeContextObject

If IsNull(CodeContextObject) = False Then
Me.Controls(NextInTabOrder(ContextObject)).SetFocus
End If

End With
 
G

Grimwadec

OK, its all a bit vague and perhaps beyond me but this is what I did:
in the form's module I created:

Function NextInTabOrder(StartCtl As Access.Control) As String

by simply copying the code you provided, then I created a Function called

NextControl()

(which I call as the On Got Focus event of the First control in the Tab
order on which I wish to run the code; there are say 8 controls but I don't
want to run the Function until I get to the Third control)

with NextControl() containing the code you iterated:

With CodeContextObject

If IsNull(CodeContextObject) = False Then
Me.Controls(NextInTabOrder(ContextObject)).SetFocus
End If

End With

Issues arising:
before running any of it, on Debugging the code it doesn't like
"ContextObject" in "Me.Controls(NextInTabOrder(ContextObject)).SetFocus" but
its happy when I change it to "CodeContextObject" but then I get a run time
error "type mismatch"

if I leave it as "ContextObject" I of course get a run time error "By Ref
arguement type mismatch"

Help please, I am lost?
 
D

Dirk Goldgar

Grimwadec said:
OK, its all a bit vague and perhaps beyond me but this is what I did:
in the form's module I created:

Function NextInTabOrder(StartCtl As Access.Control) As String

by simply copying the code you provided, then I created a Function called

NextControl()

(which I call as the On Got Focus event of the First control in the Tab
order on which I wish to run the code; there are say 8 controls but I
don't
want to run the Function until I get to the Third control)

with NextControl() containing the code you iterated:

With CodeContextObject

If IsNull(CodeContextObject) = False Then
Me.Controls(NextInTabOrder(ContextObject)).SetFocus
End If

End With

Issues arising:
before running any of it, on Debugging the code it doesn't like
"ContextObject" in "Me.Controls(NextInTabOrder(ContextObject)).SetFocus"
but
its happy when I change it to "CodeContextObject" but then I get a run
time
error "type mismatch"

if I leave it as "ContextObject" I of course get a run time error "By Ref
arguement type mismatch"

Help please, I am lost?


The compile error was a typo on my part: it should have been
"Me.Controls(NextInTabOrder(CodeContextObject)).SetFocus".

However, I have since verified my original suspicion that CodeContextObject
is not what you want to use for this. The reason is that CodeContextObject
won't return a reference to the control, but rather to the form where the
code is running. I suggest you use Screen.ActiveControl instead:

'----- start of suggested (air) code -----
Function NextControl()

Dim ctl As Access.Control

Set ctl = Screen.ActiveControl

If IsNull(ctl.Value) = False Then
Screen.ActiveForm.Controls(NextInTabOrder(ctl)).SetFocus
End If

Set ctl = Nothing

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

I used Screen.ActiveForm and Screen.ActiveControl in the above function so
that the function could be stored in a standard module (as opposed to the
form's module) and still work. If you intend to put the code in the form's
module, you can write it using "Me" references:

'----- start of alternative, form-restricted code -----
Function NextControl()

Dim ctl As Access.Control

Set ctl = Me.ActiveControl

If IsNull(ctl.Value) = False Then
Me.Controls(NextInTabOrder(ctl)).SetFocus
End If

Set ctl = Nothing

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

Grimwadec

OK and thanks, and whilst it runs it doesn't seem to want to loop. I set the
function to run On Got Focus but it only takes you to the next control
whereupon it should recognise its not null status and move along until it
finds a control that is null... I guess I can just run the function on On Got
Focus for each control but thats' giving up easy isn't it!
 
D

Dirk Goldgar

Grimwadec said:
OK and thanks, and whilst it runs it doesn't seem to want to loop. I set
the
function to run On Got Focus but it only takes you to the next control
whereupon it should recognise its not null status and move along until it
finds a control that is null...

Why should it? There is nothing in anything you've posted so far that would
make it loop. If you don't call the function in the GotFocus event of every
control, there's no reason it should run the code for more than the very
first control.
I guess I can just run the function on On Got Focus for each control but
thats' giving up easy isn't it!

What exactly are you trying to do here? I think we have pretty much solved
the specific question you asked, but I don't think we're any nearer to doing
what you actually *want*. How do you want the form to behave, and under
what circumstances? How is it supposed to look to the user?
 
G

Grimwadec

Once a user populates the first control in the Form's Tab order, some
subsequent controls are automatically populated and others aren't depending
on what is populated in the first control. I then want to go to the next
control in the tab order, if that is control has been automatically
populated then go the next control etc. etc. until it finds a control that
has not been automatically populated and stop there so the user can then
enter data. In that way the user doesn't have to bother with the form
stopping at controls that are already populated.
As I said, I can simply run individual code On Got Focus in each control
which would then tell it to go to the next control if the control with the
focus is populated but I was trying to get by with just the one looping
function but I guess I can just run the NextControl Function on Got Focus on
each control
 
D

Dirk Goldgar

Grimwadec said:
Once a user populates the first control in the Form's Tab order, some
subsequent controls are automatically populated and others aren't
depending
on what is populated in the first control. I then want to go to the next
control in the tab order, if that is control has been automatically
populated then go the next control etc. etc. until it finds a control that
has not been automatically populated and stop there so the user can then
enter data. In that way the user doesn't have to bother with the form
stopping at controls that are already populated.
As I said, I can simply run individual code On Got Focus in each control
which would then tell it to go to the next control if the control with the
focus is populated but I was trying to get by with just the one looping
function but I guess I can just run the NextControl Function on Got Focus
on
each control

I would certainly not do it that way. I'd use the first control's
AfterUpdate event to do whatever it is that populates the other controls,
and then call a function like this:

'------ start of code ------
Function GoToNextNullControl()

' Set the focus to the next Null control in the tab order.
' Ignore all non-data controls (which don't have a Value
' property).
'
' Copyright (c) 2009, DataGnostics LLC
' License is granted to use this code in your application,
' provided the copyright notice remains intact.

Dim objParent As Object
Dim ctl As Access.Control
Dim strStartControl As String
Dim strNextControl As String
Dim blnControlIsNull As Boolean
Dim lngControlCount As Long

Set ctl = Screen.ActiveControl
Set objParent = ctl.Parent
strStartControl = ctl.Name
strNextControl = NextInTabOrder(ctl)

' Loop through the controls in tab order, looking
' for one that has a Null value.

Do Until strNextControl = strStartControl

' Check to see if we've gotten into an infinite
' loop, which could happen if the starting control
' is not in the tab order.
lngControlCount = lngControlCount + 1
If lngControlCount > objParent.Controls.Count Then
Exit Function
End If

' Point ctl to the next control.
Set ctl = objParent.Controls(strNextControl)

' Check to see if this control has a Null value.
' If it doesn't have a Value property at all,
' treat that as "not null".
blnControlIsNull = False
On Error Resume Next ' Suspend normal error-handling
blnControlIsNull = IsNull(ctl.Value)
On Error GoTo 0 ' Resume normal error-handling

' If the control has a Null value, exit the loop.
If blnControlIsNull Then
Exit Do
End If

' Locate the next control in the tab order.
strNextControl = NextInTabOrder(ctl)

Loop

' If we found a non-null control, set the focus to it.
If blnControlIsNull Then
ctl.SetFocus
End If

Set ctl = Nothing
Set objParent = Nothing

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

That hasn't really been tested, but it may work.
 
G

Grimwadec

what, no Aussies in NJ?, its an Australianism for when something has gone
very well!
 
D

Dirk Goldgar

Grimwadec said:
what, no Aussies in NJ?, its an Australianism for when something has gone
very well!


Actually, we do have some Aussies around here -- one of my daughter's
schoolmates even had a big Australia Day party a couple of years ago -- but
somehow I never heard this particular idiom. So now I've learned something
new.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top