Solved

Set focus, without calling the tab change event?

Posted on 2011-02-12
19
517 Views
Last Modified: 2012-05-11
I'm using Access 2003
I have a form with 8 tabs on it.
If a user tries to move to another tab I have code in the Private Sub TabCtl_Change() that calls a function to make sure all the fields were filled out correctly. The function checks the the form, if it finds a problem it displays an error message and then sets the focus to checkbox or text box in question.  The problem is when it does this (sets focus) it jumps to the TabCtl_Change() right then and there.  This causes the code to step through the function again which causes the error to display twice.  How can I get around this?

The "Print" button on my form calls the same function, however it works fine because I never changed tabs in the first place.

Hopefully that makes sense, you might have to ready it a couple of times.

TIA,
0
Comment
Question by:GWitek
  • 5
  • 4
  • 3
  • +3
19 Comments
 
LVL 14

Expert Comment

by:Bill Ross
Comment Utility
Hi  GW,

You cannot do that.  

As you've found the tab control change events fires once when the tab control is changed and again when it is changed back.  

Some ideas:
 1. Add your validation function to the first field in the tab order of each tab in the tab control to tet to see if the priorr tabe was filled out and then go to that tab.
 2. Change your function to only enable the other tabs when the data is correct.

Regards,

Bill
0
 
LVL 14

Expert Comment

by:Bill Ross
Comment Utility
control to tet to see if the priorr tabe was filled
S/B control to test to see if the prior tab was filled

0
 
LVL 37

Expert Comment

by:Neil Russell
Comment Utility
Have a module level variable declared, called say  AmIDirty and set to False by default.  When ever ANY field changes set AmIDirty to True.
Now in TabCtl_Change() first check if AmIDirty is False and if it is exit the function. If AmIDirty is TRUE then do your checks and then set AmIDirty to False before setting focus again to the field you want to.

Easy :D
0
 
LVL 57

Expert Comment

by:Jim Dettman (Microsoft MVP/ EE MVE)
Comment Utility
<<How can I get around this?>>

 Give this a go.  Think it will do the job:

 Use a form level variable to protect your validation code from executing multiple times for the same tab.

Dim intLastPage as Integer

In  OnChange of tab control:
      If Me.<tabControl>.page <> intLastPage
        ' User tried to move to a new page, check the fields.
        intRet = ValidateFunction()
        If intRet = True
          ' We are going to move to a new page, so intLastPage  
            intLastPage = Me.<tabControl>.Page
        Else
          ' We have moved back to the page because validation failed.
          ' Nothing to do
        End If
     End If

JimD.
0
 
LVL 57

Expert Comment

by:Jim Dettman (Microsoft MVP/ EE MVE)
Comment Utility
Slight correction:

      If Me.<tabControl>  <> intLastPage
        ' User tried to move to a new page, check the fields.
        intRet = ValidateFunction()
        If intRet = True
          ' We are going to move to a new page, so update intLastPage  
            intLastPage = Me.<tabControl>
        Else
          ' We have moved back to the page because validation failed.
          ' Nothing to do
        End If
     End If

  No "page" property, silly me.

JimD.
0
 
LVL 119

Assisted Solution

by:Rey Obrero
Rey Obrero earned 250 total points
Comment Utility
check this sample db, the tab change event fires once the first time  a page gets the focus, but not the second time, click the button "Click Me" to move thru the pages
TabCtlForm-Q-26817156.mdb
0
 
LVL 3

Author Comment

by:GWitek
Comment Utility
JDettman,
I think we're close. But I'm drawing a blank.

Through out the function I have "Exit Function", which is used when I find something that isn't right on the form because I don't want to continue checking.

How do I Exit Function and send a return code with it?
0
 
LVL 31

Expert Comment

by:Helen_Feddema
Comment Utility
I am not sure what function you are referring to (the Tab_Change event is a Sub), but it looks like you need to set your function to return a value.

Also, it is a good idea to set up an error handler and use GoTo ErrorHandlerExit instead of Exit Function, so any necessary closing actions can be taken before exiting.
0
How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

 
LVL 31

Expert Comment

by:Helen_Feddema
Comment Utility
If the function is checking for valid entries in the page controls, then set it to return (say) blnValid As Boolean.  Set blnValid to True if all checks are passed, or to False if one fails.  Then set the function itself to blnValid.
0
 
LVL 57

Expert Comment

by:Jim Dettman (Microsoft MVP/ EE MVE)
Comment Utility
<<How do I Exit Function and send a return code with it? >>

 As Helen has said, you need to structure it properly.   A well strucutred procedure should have only one exit point.  There are a couple of ways to do that, but it might look something like this:

Function ValidateFields() as Boolean

  Dim strUserMessage as string

  On Error Goto Error_ValidateFields

  ValidateFields = True

  'First check
  If Me.<some control> = "" then
      strUserMessage = strUserMessage & "Some control is required" & vbCrLF
  End If

  'Second check
  If Me.<some control2> = "" then
      strUserMessage = strUserMessage & "Some control2 is required" & vbCrLF
  End If

  ' All done with checks, tell user what went wrong if errors were found.
  If strUserMessage<>"" then
     strUserMessage = strUserMessage  & vbCrLf &  "You must correct these errors before proceeding".
     Msgbox strUserMessage, vbOKOnly + vbExclamation
     ValidateFields = False
  End If

Exit_ValidateFields:
   ' Clean up
   On Error Resume Next
   
    Exit Function

Error_ValidateFields:
     Msgbox "Unexpected error in ValidateFields"
     ValidateFields = False
     Resume Exit_ValidateFields

End Function


   This checks all conditions and then reports to the user.   Some procedures do it the other way; stop on each error found and set focus to the control that caused the error.    This works well when there are few errors, but generally I find most like to see all errors so they can fix them in one shot.

HTH,
JimD.
0
 
LVL 3

Author Comment

by:GWitek
Comment Utility
Examples are looking good and helping. However, no where do I see any of the code setting focus to the tab in error.

The problem is that as soon as the code in the ValidateTabs() function sets the focus to something on the form, the code jumps back to the Private Sub TabCtl0_Change () and reruns the function.
0
 
LVL 3

Author Comment

by:GWitek
Comment Utility
<< This checks all conditions and then reports to the user.   Some procedures do it the other way; stop on each error found and set focus to the control that caused the error.    This works well when there are few errors, but generally I find most like to see all errors so they can fix them in one shot. >>

Sadly enough, my users need quite a bit of hand holding and I'd like to use this method, but can't for the non-intuitive users.
0
 
LVL 57

Accepted Solution

by:
Jim Dettman (Microsoft MVP/ EE MVE) earned 250 total points
Comment Utility
So twist it around a bit:

Function ValidateFields() as Boolean

  Dim strUserMessage as string

  On Error Goto Error_ValidateFields

  ValidateFields = True

  'First check
  If Me.<some control> = "" then
      strUserMessage = strUserMessage & "Some control is required" & vbCrLF
      Me.<some control>.SetFocus
  Else
     'Second check
     If Me.<some control2> = "" then
        strUserMessage = strUserMessage & "Some control2 is required" & vbCrLF
        Me.<some control>.SetFocus
     End If
   End If

  ' All done with checks, tell user what went wrong if errors were found.
  If strUserMessage<>"" then
     strUserMessage = strUserMessage  & vbCrLf &  "You must correct this error before proceeding".
     Msgbox strUserMessage, vbOKOnly + vbExclamation
     ValidateFields = False
  End If

Exit_ValidateFields:
   ' Clean up
   On Error Resume Next
   
    Exit Function

Error_ValidateFields:
     Msgbox "Unexpected error in ValidateFields"
     ValidateFields = False
     Resume Exit_ValidateFields

End Function

which would message them on the first error encountered.  Or if you wanted to message them on all errors, but set focus to the first:

Function ValidateFields() as Boolean

  Dim strUserMessage as string
  Dim strSetFocusTo as string

  On Error Goto Error_ValidateFields

  ValidateFields = True

  'First check
  If Me.<some control> = "" then
      strUserMessage = strUserMessage & "Some control is required" & vbCrLF
      If strSetFocusTo="" then strSetFocusTo = "<some control name>"
  End If

   'Second check
   If Me.<some control2> = "" then
      strUserMessage = strUserMessage & "Some control2 is required" & vbCrLF
      If strSetFocusTo="" then strSetFocusTo = "<some control2 name>"
   End If

  ' All done with checks, tell user what went wrong if errors were found.
  If strUserMessage<>"" then
     strUserMessage = strUserMessage  & vbCrLf &  "You must correct these error(s) before proceeding".
     Msgbox strUserMessage, vbOKOnly + vbExclamation
    Forms("<myform>")(strSetFocusTo).SetFocus
     ValidateFields = False
  End If

Exit_ValidateFields:
   ' Clean up
   On Error Resume Next
   
    Exit Function

Error_ValidateFields:
     Msgbox "Unexpected error in ValidateFields"
     ValidateFields = False
     Resume Exit_ValidateFields

End Function

  as I said, lots of ways to structure this.  You could leave it the way it is and use Goto to move to a single exit point, etc.

  and to note, some may have issue with me saying you can use a goto in a procedure, but one can use Goto's and still have a well structured procedure.  It's a matter of style in coding.  Of course some would argure that as well, but that's a whole different topic.

JimD.

0
 
LVL 119

Expert Comment

by:Rey Obrero
Comment Utility
GWitek,

did you test the sample db at http:#a34879343
0
 
LVL 14

Expert Comment

by:Bill Ross
Comment Utility
Hi again GW,

There are some good solutions here but as I said early on, you should probably review what you are trying to do and change where the test fires.  Perhaps just move the data test to the before update event of the record.  That way it will always check the data before it is saved and you're sure the data is correct regardless of which tab the mistake is on.

Regards,

Bill
0
 
LVL 3

Author Comment

by:GWitek
Comment Utility
I'm going to test out some of these options and get back to you guys.
0
 
LVL 3

Author Comment

by:GWitek
Comment Utility
Just FYI the hyperlink above that says "Standard Comment Box" is dead. IE8
Additionally, I'd like to give some points aways. I was able to get this to work using a few solutions above.
0

Featured Post

How to improve team productivity

Quip adds documents, spreadsheets, and tasklists to your Slack experience
- Elevate ideas to Quip docs
- Share Quip docs in Slack
- Get notified of changes to your docs
- Available on iOS/Android/Desktop/Web
- Online/Offline

Join & Write a Comment

A short article about a problem I had getting the GPS LocationListener working.
If you’re thinking to yourself “That description sounds a lot like two people doing the work that one could accomplish,” you’re not alone.
In Microsoft Access, learn different ways of passing a string value within a string argument. Also learn what a “Type Mis-match” error is about.
In this seventh video of the Xpdf series, we discuss and demonstrate the PDFfonts utility, which lists all the fonts used in a PDF file. It does this via a command line interface, making it suitable for use in programs, scripts, batch files — any pl…

772 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

15 Experts available now in Live!

Get 1:1 Help Now