you could unbind the form or handle many events, have you tried something?i don't want the data being entered to automatically save into table
Why?Reason is, i don't want the data being entered to automatically save into table
I understand your concerns, but I would certainly not discard unbound forms considering all the measures one must program against the save-that-record-no-matter-what default behavior of Access. You have gracefully described some of the things one must counter when using the bound form.I would never suggest an unbound form if there's some other way to do the same task, specially to someone who is new to Access.
I would set the Cycle property of the form to current record, add save and undo buttons and use OnClose event to undo before closing if the form is dirty.
User should either save the record or exit without saving.
That is correct, Pat, in the case of bound forms, you have to use the BeforeUpdate event and set its Cancel parameter to True to prevent the update programmatically. In the case of unbound forms, you do not require this event.I guess you haven't viewed any of my videos on the topic.
If you understand how forms work, there is one and only one event you have to work with and that is the form's BeforeUpdate event. That event is like the flapper on a funnel. It is the last event that fires before a record gets saved. Therefore, your validation code goes there - or is called from there if you prefer - and you cancel the event if an error is discovered.
How hard is?
Cancel = True
Private SavedOnPurpose As Boolean
Private Sub cmdCancel_Click()
If Not Me.Dirty Then
MsgBox "There are not updates to cancel.", vbInformation, "No Updates"
Else
MsgBox "Updates canceled.", vbInformation, "Updates Canceled."
End If
Me.Undo
End Sub
Private Sub cmdClose_Click()
DoCmd.Close acForm, Me.Name
End Sub
Private Sub cmdSave_Click()
SavedOnPurpose = True
Me.Dirty = False
MsgBox "Record Saved", vbInformation, "Saved"
End Sub
Private Sub Form_BeforeUpdate(Cancel As Integer)
Dim rtn As Long
If Not SavedOnPurpose Then
rtn = MsgBox("Do you want to Save this record?", vbYesNo, "Save Record?")
If rtn = vbNo Then
Cancel = True
Me.Undo
End If
End If
'Reset
SavedOnPurpose = False
End Sub
Dim tForm As clsTransactedForm
Private Sub Form_Close()
Set tForm = Nothing
End Sub
Private Sub Form_Open(Cancel As Integer)
Set tForm = New clsTransactedForm
tForm.Init Me, "select * from table1;", Me.cmdSaveAdd, Me.cmdSaveEdit, Me.cmdSaveClose, Me.cmdCloseNoSave
End Sub
Sure, but I am pretty sure if the OP is here asking for help to build a simple cancel/save, there is no way they are capable of building even a simple unbound form. The amount of code for load, edit, add, delete, and save would be orders of magnitude more code and more complex code that a simple undo and dirty = false. There are times and places for unbound forms but probably not when the OP statesIt's up to you to test them and make an informed decision about which one is better for you. I recommend the two, as you can see in the first reply to this thread
I am a beginner
Thank You @MajP@Gasman,
Better yet, I will provide the Class to show you can turn any form into a transactional form.
1. Import class into VBE using the File Import.
2. On any form add the following buttons
Save Add
Save Edit
Save Close
Close (No Save)
3. Code on form
Do not give the form a Recordsource, but pass it in instead. Pass in the buttons.
Code:Dim tForm As clsTransactedForm Private Sub Form_Close() Set tForm = Nothing End Sub Private Sub Form_Open(Cancel As Integer) Set tForm = New clsTransactedForm tForm.Init Me, "select * from table1;", Me.cmdSaveAdd, Me.cmdSaveEdit, Me.cmdSaveClose, Me.cmdCloseNoSave End Sub
Private SCF As New SaveCancelForm 'after the top of the module after options
Private Sub Form_Load()
SCF.Initialize Me, True, Me.cmdSave, Me.cmdSaveClose, Me.cmdSaveNew, Me.cmdCancel, Me.cmdCancelClose
End Sub
I simply love your example, is simple and works.. I am sort of not a beginner anymore, I do understand a lot, but one question.. you declare SavedOnPurpose as boolean so I believe at this momment is assumed TRUE; then if the user clicks the "X" asks " Do you want to Save this record? ", and here is my question... SavedOnPurpose is set to FALSE [last line of code], so I thought it SHOULD not save, so it should be be TRUE, I thought there was a mistake, but to my surprise, it doesn't matter if you change the value [False or True] the effect when you say Yes or NO is the same, the record is always saved..As @Pat Hartman says it is extremely simple to do this. For a simple form in single form view.
Code:Private SavedOnPurpose As Boolean Private Sub cmdCancel_Click() If Not Me.Dirty Then MsgBox "There are not updates to cancel.", vbInformation, "No Updates" Else MsgBox "Updates canceled.", vbInformation, "Updates Canceled." End If Me.Undo End Sub Private Sub cmdClose_Click() DoCmd.Close acForm, Me.Name End Sub Private Sub cmdSave_Click() SavedOnPurpose = True Me.Dirty = False MsgBox "Record Saved", vbInformation, "Saved" End Sub Private Sub Form_BeforeUpdate(Cancel As Integer) Dim rtn As Long If Not SavedOnPurpose Then rtn = MsgBox("Do you want to Save this record?", vbYesNo, "Save Record?") If rtn = vbNo Then Cancel = True Me.Undo End If End If 'Reset SavedOnPurpose = False End Sub
Where it gets tricky is when people want to do weird things like Create multiple records on a continuous form and then roll those back. Or Not create a parent record if you do not create child records.
Most of the time these are IMO just dumb user interface designs.
As @Edgar_ points out you have to account for all of the things that could make the form try to save (close, move to new record). That is why even though I have save / cancel buttons I still need to prompt to save/cancel in the before update.
If curious I included an example where you can add multiple records and roll them back in a transaction. Not something I would do, but it shows it can be done.