Generic Form with "Save", "Cancel" buttons

moi

Member
Local time
Tomorrow, 05:04
Joined
Jan 10, 2024
Messages
273
I am a beginner. and i am searching a demo form with 2 buttons (Save, Cancel). Reason is, i don't want the data being entered to automatically save into table.. can someone please help me.. thank you in advance..
 
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.
 
Last edited:
moi,
Welcome to AWF.
What exactly do you mean by "automatically"? You wouldn't Save bad data, so you validate the entered data, then either reject or save the data based on your validation. As Gasman says-- use the BeforeUpdate event of the form to do your validation. See this post for similar information.

Since you are a self-identified beginner, I suggest you describe your proposed application to readers and get some feedback. Do some research on various topics -reading posts, watching videos, analyzing sample databases...

Access does many things for you behind the scenes; better to learn and use these features than try to struggle with additional work.
 
Last edited:
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.
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.

Since an unbound form can be as simple or as complicated as:
if edit: load the data into the form
if new: load empty form
if save: validate and save

I would advice OP to consider the two approaches and explore what it's like to develop with the two possibilities.
 
you can use ADO disconnected recordsets which is fine for adding new data, but a real pain if the user can edit existing data as you will need routines to check whether someone else has edited or deleted the record before updating.

Advantage - you can bind the form to the ado recordset., particularly useful for a continuous form.

Disadvantage - some form functionality does not work with ADO, primarily sort and filter, although you can write your own alternatives to overcome this.
 
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
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.
 
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.
 

Attachments

@MajP
Any chance of getting the Transacted DB in the same format as the SimpleSave DB please?
I can open the latter, but not the first, unrecognized DB, as I am on 2007. :(
 
@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
 

Attachments

@Pat Hartman
If you don't use the suitable events, properties and states for each feature, you're going to have a poor development experience. If a bound form solves your problems neatly, use them. If the flexibility of an unbound form does not meet your particular expectations, it's not mandatory to use it, but you have the right to know that the two possibilities exist in the context of Access.

It'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.
 
It'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
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 states
I am a beginner

I could just give them my transaction class module and that would be way easier than to implement an unbound form. It only requires a single line of code to instantiate. However, they would be absolutely clueless of what is going on.
 
As stated, you have the right to know there are two main ways to program your form and it's up to you to test how you feel more comfortable developing an app.

Beginners here are being taught about bang notation, event driven programming, they're using COM and byproducts of OOP and you're expressing sensitivity about a simple unbound form? Let's be serious.
 
@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
Thank You @MajP
 
Hey folks. An interesting discussion with lots of good advice and some sample databases. Hopefully the OP will return and take advantage of it.
 
If you where going to do this more than once then might as well build a class module to make this simple, flexible, and re-usable.

To use on any form simply add the buttons you want. All are optional. In the demo I choose all the buttons, but you can pick whatever ones you want.

Save
Save and Close
Save and Add New
Cancel
Cancel and Close

When you instantiate you can pick to show messages or turn them off.

This is all it takes to make any form into a Simple Save and Cancel
Code:
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


One thing important in the Demo is that the class traps the Before update event. However if you want to do additional actions such as validation in the Before udpate you can still write a Before update event method in the form. The order is the Before update in the form is trapped before the Before update in the class. This has to be accounted for. Because you can cancel the before update in the form before the class traps the already canceled event. This required some error trapping in the class. To demo this I do validation in the forms before update.
 

Attachments

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.
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..
 
No, if you say no, the cancel is set to true.
Walk the code. What is the value of saved on purpose after being dimmed?
 

Users who are viewing this thread

Back
Top Bottom