Asked by:
Exiting from a form when there are pending updates with validation errors.

Question
-
I'm modifying an existing application which I did not design or code. Access 2010.
The main form is a bound form consisting of a tab control with three tabs. Navigation is by the standard MS Access navigation buttons. Every time the form is opened, the entire table of 28,000 records is read in.
All the data is in one table. It should really be in three different tables since each tabs data is distinct and is validated separately from the other tabs.
However, I think all that is irrelevant to my question. And I don't have time to redesign or rewrite this application.
There is a 'return' button on the form that returns to the previous menu. The Before Update event has lots of validations. When the 'return' button is pressed, if the user has made changes, the Before Update event is triggered along with the validations. If there are validation errors, a message box pops up describing all the errors. However, when ok is clicked on this message box, control exits from the form and saves the invalid record.
My question is how do I prevent the invalid record being saved? I guess I would like to give the user the option to save or discard an invalid record when the 'return' button is pressed. There is currently some code in the Before Update event that displays a message box informing the user when a record has been changed and prompting the user to save or discard the change. This happens only after all the validations have passed.
Thursday, May 18, 2017 1:15 AM
All replies
-
It would help to see the code in the Before Update event. What is most likely happening is there is a MsgBox command displaying the errors. Following that command, a Cancel = True line is probably needed as well as an Exit Sub to stop processing.
Hope this helps, Scott<> P.S. Please post a response to let us know whether our answer helped or not. Microsoft Access MVP 2009 Author: Microsoft Office Access 2007 VBA Technical Editor for: Special Edition Using Microsoft Access 2007 and Access 2007 Forms, Reports and Queries
Thursday, May 18, 2017 12:11 PM -
I think that this question is some how related with question below which is also asked by you.
The setting you entered isn't valid for this property - error message
as other user already mentioned to use "Cancel=True".
you had mentioned that,"I guess I would like to give the user the option to save or discard an invalid record when the 'return' button is pressed."
I think that if record is invalid then you should not allow it to Save.
why need to save invalid data? it will ruin your data and creates lots of issues in the future.
if you allow to save invalid data then why need to check so many validation? just for asking the user choice.
I think that you need to spend some time to redesign this saving data approach to save valid data in database.
it is not good that you have some valid and some invalid data in database. because it can affect you when you try to implement any new functionality to this database in future. also data are not accurate so you will not able to reports properly.
overall I do not recommend you to save any invalid data to your database.
if data are invalid then you can warn the user to correct it or cancel it if he don't want to correct it.
Regards
Deepak
MSDN Community Support
Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.Friday, May 19, 2017 2:45 AM -
Firstly you should as far as possible include validation rules in the table definition. You might also be able to apply CHECK CONSTRAINTs to the table for conditions which cannot be covered by a validation rule.
For validation at form level you not only need to set the return value of the form's BeforeUpdate event procedure's Cancel argument to True, but also that of the Unload event procedure to True to prevent the form closing without the user having the opportunity to correct the validation infringements. To do this you need to use a Boolean module level variable whose value allows the form to close, and assign a value to this variable which prevents the form closing wherever a validation infringement is encountered elsewhere in the code. The variable's value needs to be reassigned when the validation infringements have been corrected of course, in order to allow the form to close.
You might like to take a look at SaveDemo.zip in my public databases folder at:
https://onedrive.live.com/?cid=44CC60D7FEA42912&id=44CC60D7FEA42912!169
Note that if you are using an earlier version of Access you might find that the colour of some form objects such as buttons shows incorrectly and you will need to amend the form design accordingly.
If you have difficulty opening the link copy its text (NB, not the link location) and paste it into your browser's address bar.
In this simple little demo file code in the form's module does as described above. It also ensures that the form can only be closed via a Close button (equivalent to your Return button, but without moving to another form) by enabling/disabling the relevant buttons on the basis of the form's current state. The form also includes validation at control level. The full code for the form's module is:
Option Compare Database
Option Explicit
Dim blnSaved As Boolean
Dim blnAllowClose As Boolean
Dim blnAllowUndo As Boolean
Private Sub cboFindContact_AfterUpdate()
Const CANNOT_MOVE_TO_RECORD = 3709
Const MESSAGE_TEXT = "Cannot move to record. Save or undo current record first."
Dim ctrl As Control
Set ctrl = Me.ActiveControl
If Not IsNull(ctrl) Then
If ctrl = 0 Then
Me.FilterOn = False
Else
On Error Resume Next
Me.Filter = "ContactID = " & ctrl
Select Case Err.Number
Case CANNOT_MOVE_TO_RECORD
'iinform user and set combo box to current contact
MsgBox MESSAGE_TEXT, vbInformation, "Warning"
ctrl = Me.ContactID
Case 0
' no error
Me.FilterOn = True
Case Else
' unknown error - inform user
MsgBox Err.Description, vbExclamation, "Error"
End Select
End If
End If
End Sub
Private Sub cmdClose_Click()
' set variable to allow form to close
blnAllowClose = True
DoCmd.Close acForm, Me.Name
End Sub
Private Sub cmdSave_Click()
Const MESSAGETEXT = "Save record?"
If Me.Dirty Then
' if user confirms set variable to True and attempt to save record
If MsgBox(MESSAGETEXT, vbQuestion + vbYesNo, "Confirm") = vbYes Then
blnSaved = True
On Error Resume Next
RunCommand acCmdSaveRecord
' if record cannot be saved set variable to False
If Err <> 0 Then
blnSaved = False
Else
' disable buttons
' move focus to another control first
Me.FirstName.SetFocus
Me.cmdSave.Enabled = False
Me.cmdUndo.Enabled = False
Me.cmdClose.Enabled = True
End If
Else
blnSaved = False
End If
End If
End Sub
Private Sub cmdUndo_Click()
blnAllowUndo = True
' undo edits
Me.Undo
blnAllowUndo = False
' disable buttons
' move focus to another control first
Me.FirstName.SetFocus
Me.cmdSave.Enabled = False
Me.cmdUndo.Enabled = False
Me.cmdClose.Enabled = True
End Sub
Private Sub DoB_GotFocus()
If IsNull(Me.FirstName) Then
MsgBox "First name must be entered", vbExclamation, "Invalid Operation"
Me.FirstName.SetFocus
ElseIf IsNull(Me.Lastname) Then
MsgBox "Last name must be entered", vbExclamation, "Invalid Operation"
Me.Lastname.SetFocus
End If
End Sub
Private Sub FirstName_BeforeUpdate(Cancel As Integer)
If IsNull(Me.FirstName) Then
MsgBox "First name must be entered", vbExclamation, "Invalid Operation"
End If
End Sub
Private Sub Form_AfterUpdate()
' reset variable to False
blnSaved = False
End Sub
Private Sub Form_BeforeUpdate(Cancel As Integer)
Dim strMessage As String
Dim strCriteria As String
' cancel update if variable is False,
' i.e. save button has not been clicked
If Not blnSaved Then
Cancel = True
Exit Sub
End If
' ensure first and last names have been entered
If IsNull(Me.FirstName) Then
MsgBox "First name must be entered", vbExclamation, "Invalid Operation"
Cancel = True
Me.FirstName.SetFocus
Exit Sub
End If
If IsNull(Me.Lastname) Then
MsgBox "Last name must be entered", vbExclamation, "Invalid Operation"
Cancel = True
Me.Lastname.SetFocus
Exit Sub
End If
' ensure names not duplicated
strCriteria = "FirstName = """ & Me.FirstName & _
""" And LastName = """ & Me.Lastname & _
""" And ContactID <> " & Me.ContactID
If Not IsNull(DLookup("ContactID", "Contacts", strCriteria)) Then
strMessage = Me.FirstName & " " & Me.Lastname & _
" already exists in database."
MsgBox strMessage, vbExclamation, "Invalid Opeartion"
Cancel = True
End If
End Sub
Private Sub Form_Current()
' reset variable to False
blnSaved = False
' disable buttons
' move focus to another control first
Me.FirstName.SetFocus
Me.cmdSave.Enabled = False
Me.cmdUndo.Enabled = False
Me.cmdClose.Enabled = True
End Sub
Private Sub Form_Dirty(Cancel As Integer)
' enable buttons
Me.cmdSave.Enabled = True
Me.cmdUndo.Enabled = True
Me.cmdClose.Enabled = False
End Sub
Private Sub Form_Error(DataErr As Integer, Response As Integer)
Const IS_DIRTY = 2169
Const MESSAGETEXT = "Record will not be saved."
' suppress system error message if form
' is closed while record is unsaved,
' NB: changes to current record will be lost
If DataErr = IS_DIRTY Then
MsgBox MESSAGETEXT, vbExclamation, "Warning"
Response = acDataErrContinue
End If
End Sub
Private Sub Form_Undo(Cancel As Integer)
' only allow record to be undone via Undo button
Cancel = Not blnAllowUndo
End Sub
Private Sub Form_Unload(Cancel As Integer)
' prevent closure if not via button
Cancel = Not blnAllowClose
End Sub
Private Sub Lastname_BeforeUpdate(Cancel As Integer)
If IsNull(Me.Lastname) Then
MsgBox "Last name must be entered", vbExclamation, "Invalid Operation"
End If
End Sub
Private Sub Lastname_GotFocus()
If IsNull(Me.FirstName) Then
MsgBox "First name must be entered", vbExclamation, "Invalid Operation"
Me.FirstName.SetFocus
End If
End Sub
Ken Sheridan, Stafford, England
- Edited by Ken Sheridan Friday, May 19, 2017 11:18 AM Hyperlink added.
Friday, May 19, 2017 11:17 AM