ms access form closing ask save yesnocancel - ms-access

I have put the VBA in Unload Form Event in ms access 2010
Private Sub Form_Unload(Cancel As Integer)
Dim strMsg As String
Dim iResponse As Integer
' Specify the message to display.
strMsg = "Do you wish to save the changes?" & Chr(10)
strMsg = strMsg & "Click Yes to Save or No to Discard changes."
' Display the message box.
iResponse = MsgBox(strMsg, vbQuestion + vbYesNoCancel, "Save Record?")
' Check the user's response.
If iResponse = vbYes Then
' Undo the change.
DoCmd.RunCommand acCmdSave
End If
If iResponse = vbNo Then
' Undo the change.
DoCmd.RunCommand acCmdUndo
End If
If iResponse = vbCancel Then
' Undo the change
Cancel = True
End If
End Sub
If data is changed then the above code is working fine, then yes to save & close, No to undo & close and cancel to cancel event and remain on the form
but when the data is unchanged then Yes button is working fine, but NO button do not close the form
Where I m mistaking ?

Your question is too vague because you simply state "NO button do not close the form."
You can do:
DoCmd.Close
See here:
Private Sub cmdCloseForm_Click()
On Error GoTo Err_cmdCloseForm_Click
DoCmd.RunCommand acCmdUndo 'OR Me.Undo - test which works best for your situation
DoCmd.Close
Exit_cmdCloseForm_Click:
Exit Sub
Err_cmdCloseForm_Click:
MsgBox Err.Description
Resume Exit_cmdCloseForm_Click
End Sub
On Me.Undo from Allen Browne:
Me.Undo cancels the edits in a specific form, so that it is no longer dirty.
Once the form is no longer dirty, no further undo is possible, because it
has reached the desired state. However, Me. represents the form that is in focus, so your form must have focus to perform the Me.Undo command.

Related

Access Form VBA: double record when saving

In my Access Form, I have a Save button whose aim is to add the new record to the table called Data Processing List.
The problem is that pushing the button, the record entered is saved into the table twice. I mean, two identical records.
I can't understand why, because the code is really simple:
Private Sub Save_Click()
On Error GoTo Save_Click_Err
Me.Today.SetFocus
On Error Resume Next
DoCmd.RunCommand acCmdSaveRecord
If (MacroError <> 0) Then
Beep
MsgBox MacroError.Description, vbOKOnly, ""
End If
With CurrentDb.OpenRecordset("Data Processing List")
.AddNew
!Department = Me.Department.Value
.Update
End With
Save_Click_Exit:
Exit Sub
Save_Click_Err:
MsgBox Error$
Resume Save_Click_Exit
End Sub
This is an example when I try to save the record with the word "prova".
You are saving twice:
DoCmd.RunCommand **acCmdSaveRecord**
...
With CurrentDb.OpenRecordset("Data Processing List")
.AddNew
!Department = Me.Department.Value
.**Update**
End With

Access VBA - prevent closing form

I have a code in Before_Update event, for saving changes. For this I use Msgbox with YesNoCancel prompt, but I cannot prevent closing form when I hit Cancel button. Here is a short sample of my code:
Option Compare Database
Public SomeVariable As Integer
Private Sub Form_BeforeUpdate(Cancel As Integer)
If MsgBox("There has been done some changes. You wish to save these changes ?", vbQuestion + vbYesNoCancel, "Save changes") = vbYes Then
'do nothing and Access saves automatically
ElseIf vbNo Then
DoCmd.RunCommand acCmdUndo
ElseIf vbCancel Then
SomeVariable = 1
End If
End Sub
Private Sub Form_Unload(Cancel As Integer)
If SomeVariable = 1 Then
SomeVariable=0
Cancel = True
End If
End Sub
Any way to fix this ?
You must save the return value from MsgBox, then proceeed accordingly:
Dim vbAnswer
vbAnswer= MsgBox("There has been done some changes. You wish to save these changes ?", vbQuestion + vbYesNoCancel, "Save changes")
if vbAnswer = vbYes Then
'do nothing and Access saves automatically
ElseIf vbAnswer= vbNo Then
....
ElseIf vbAnswer= vbCancel Then

How can I remove the pesky "The runCommand action was canceled" dialog box after a "cancel = true" statement

On the Form_beforeupdate() event of my form "Alias" I have this...
If IsNull(Me.txtFName) And IsNull(Me.txtLName) Then
MsgBox "You must enter a contact!", vbokayonly, "Contact"
Cancel = True
End If
Anytime this cancels a runCommand code such as...
DoCmd.RunCommand acCmdSaveRecord
a dialog appears telling me that it was canceled. Is there a way to suppress those dialogs?
You can add an error handler to trap and ignore error 2501, which is triggered when the form's Before Update event cancels DoCmd.RunCommand acCmdSaveRecord
The following example is from my form which has a command button to save the current record. It suppresses that "RunCommand action was canceled" message as I think you wish.
Since your form's code apparently calls DoCmd.RunCommand acCmdSaveRecord from multiple locations, replace each of those calls with SaveRecord as I did in cmdSave_Click().
Option Compare Database
Option Explicit ' <-- NEVER troubleshoot VBA code without this!!!
Private Sub cmdSave_Click()
'DoCmd.RunCommand acCmdSaveRecord
SaveRecord
End Sub
Private Sub SaveRecord()
Dim strMsg As String
On Error GoTo ErrorHandler
DoCmd.RunCommand acCmdSaveRecord
ExitHere:
Exit Sub
ErrorHandler:
Select Case Err.Number
Case 2501 ' The RunCommand action was canceled.
' do nothing --> just ignore the error
Case Else
' notify user about any other error
strMsg = "Error " & Err.Number & " (" & Err.Description _
& ") in procedure SaveRecord"
MsgBox strMsg
End Select
Resume ExitHere
End Sub
Private Sub Form_BeforeUpdate(Cancel As Integer)
If IsNull(Me.txtBlock_start.Value) Then
MsgBox "You must enter a start time!", vbOKOnly, "Start Time"
Cancel = True
End If
End Sub
I ended up doing this on a 'Save and Open the Receipts form' button.
Private Sub btnSaveOpenReceipts_Click()
'''''SaveRecord'''''
If (Me.Dirty) Then
SaveRecord
End If
'''''OpenReciepts'''''
If (Me.Dirty) Then 'unsure it saved
Exit Sub
Else
'blah blah blah
End If
End Sub

"No Current Record" error on acCmdSaveRecord when BeforeUpdate is cancelled

I'm using RunCommand acCmdSaveRecord to save a record, and I'm trying to use the form's BeforeUpdate event to validate certain fields that I don't want to be left blank before the record is saved.
I'm a bit new to using BeforeUpdate so I'm not sure if I'm using it correctly; here's my BeforeUpdate code:
Private Sub Form_BeforeUpdate(Cancel As Integer)
If IsNull(Me.[First Name]) Or IsNull(Me.LastName) Or IsNull(Me.DateOfBirth) Or IsNull(Me.CourseStartDate) Then
MsgBox "Before the enrolment can be saved, you must provide:" & vbCrLf & vbCrLf _
& "- First Name" & vbCrLf _
& "- Last Name" & vbCrLf _
& "- Date of Birth" & vbCrLf _
& "- Start Date" & vbCrLf & vbCrLf _
& "You must also attach a course. This can be done by selecting " _
& "the appropriate course in the Prospectus Search and clicking " _
& "the Use Prospectus Code button." & vbCrLf & vbCrLf _
& "If your course is not currently in the prospectus, you can " _
& "add it first by clicking the Add Course button.", vbOKOnly Or vbInformation
Cancel = True
Else
Me!EnrolmentID = "Enr" & Format(Me!ID, String(12 - Len("Enr"), "0"))
End If
End Sub
So this basically tests to see if certain fields have been left blank, if they have been left blank then a message box is displayed showing what fields need data and then the update is cancelled. Otherwise it assigns a custom primary key and allows the record to update.
It's throwing an error when cancelling the update though stating "No Current Record" and highlighting the RunCommand acCmdSaveRecord line of code.
What do I need to do to avoid the error? I've also tried Me.Dirty = False, but still get the same error.
#Johnny Bones:
Here's a simplified test I've tried on the answer you gave me:
Public ShouldRun As Boolean
Private Sub Command7_Click()
If ShouldRun = True Then
MsgBox ShouldRun
RunCommand acCmdSaveRecord
End If
End Sub
Private Sub Form_BeforeUpdate(Cancel As Integer)
If IsNull(Me.Field1) Or IsNull(Me.Field2) Then
MsgBox "This is the true"
ShouldRun = False
Else
MsgBox "This is the false"
ShouldRun = True
End If
End Sub
Basically none of the MsgBox functions are firing and the record is being saved regardless of whether a field is being left blank or not. I tried this as a test because the MsgBox in my real code was not firing in the BeforeUpdate event either. Can't see why though.. if a user leaves one of the fields blank this should trigger the true part of the if statement in the BeforeUpdate event, right?
The only thing I can think of is that the BeforeUpdate event is not being triggered by RunCommand acCmdSaveRecord, despite MSDN saying:
"if you then move to another record or save the record, the form's BeforeUpdate event does occur."
Not sure what the order is here... does VBA run the RunCommand acCmdSaveRecord then the BeforeUpdate event? If this is the case then the ShouldRun variable won't have any assignment at the first step (RunCommand acCmdSaveRecord) because it only gets that at the second (BeforeUpdate).
I would set a global variable like this:
Global ShouldRun as Bool
You throw that at the very top of the code page, up where you declare Options Explicit. Then, in the If/Then/Else statement you provided above, replace the line:
Cancel = True
with
ShouldRun = False
and in the Else part add the line
ShouldRun = True
Finally, your command button's OnClick event should look more like this:
If ShouldRun = True then
RunCommand acCmdSaveRecord
End If
By doing this, it will never even try to save the record if it shouldn't.
I know it's late, but have you tried to use DoCmd.RunCommand acCmdSaveRecord
instead?
Because for me it's firing the Before Update event well, when RunCommand acCmdSaveRecord wasn't!
But after cancelling the event you may get an execution error '2759', because the record can not be save anymore.
So you can handle it this way :
Private Sub Command7_Click()
On Error GoTo Command7_Click_Error
DoCmd.RunCommand acCmdSaveRecord
Command7_Click_Exit:
Exit Sub
Command7_Click_Error:
If Err.Number=2759 Then
'ignore the error
Else
MsgBox Err.Description
End If
Resume Exit_Here
End Sub
If you are using Me.Dirty = False instead, you can handle the error '2101'.
Hope it helps

runtime error 2448 you cant assign a value to this object

I am using David-W-Fenton's answer to this question to try to allow users to print a report when they click on a control, but I am getting the following error message:
runtime error 2448: you cannot assign a value to this object.
The line of code triggering the error is:
Me.txtPageTo.Value = numPages
Here is the full code of the OnLoad event handler for the form:
Private Sub Form_Load()
Dim varPrinter As Printer
Dim strRowsource As String
Dim strReport As String
If Len(Me.OpenArgs) > 0 Then
strReport = Me.OpenArgs
Me.Tag = strReport
For Each varPrinter In Application.Printers
strRowsource = strRowsource & "; " & varPrinter.DeviceName
Next varPrinter
Me!cmbPrinter.RowSource = Mid(strRowsource, 3)
' first check to see that the report is still open
If (1 = SysCmd(acSysCmdGetObjectState, acReport, strReport)) Then
With Reports(strReport).Printer
Me!cmbPrinter = .DeviceName
Me!optLayout = .Orientation
End With
Dim numPages As String
numPages = Reports(strReport).Pages
Debug.Print "numPages = " & numPages
TypeName(Me.txtPageTo) 'added this line as a test after
Me.txtPageTo.Value = numPages
End If
End If
End Sub
numPages prints out to equal 0 just before the error is thrown, even though the report should have at least one page. Also, the error does not get thrown when the form is already open. The error only gets thrown when the form has to be opened. (Probably because the offending code is in the onload event.)
When I added TypeName(Me.txtPageTo) , it triggered runtime error 2424: The expression you entered has a field, control, or property name that mydatabasename cant find.
I think the problem is that I need to set the control source for txtPageFrom and txtPageTo. But how do I do that? This form will only be loaded by a vba method that is trying to print a report, so the values for txtPageFrom and txtPageTo will come from the calling method, not from some underlying data table. (there is no underlying data table for this dialog form.)
cmbPrinter and optLayout seem to be populating correctly using the code above.
Can anyone show me how to get past the error messages so that the form loads properly?
CORRECT, COMPLETE ANSWER:
The answer to this problem was to greatly simplify the code. The code in the link at the top of this posting is WAY TOO COMPLEX, and tries to reinvent things that are already done well by the tools built into Access and VBA. I was able to print reports without any of the complicated solutions by simply using the following code in the on-click event of a control on a form associated with the report:
Private Sub txtPrintReport_Click()
On Error GoTo Error_Handler
Dim commNum As Long
commNum = Me.CommunicationNumber
Dim strReport As String
Dim strVarName As String
strReport = "rptCommunicationFormForPrinting"
strVarName = "CommunicationNumber"
DoCmd.OpenReport strReport, acViewPreview, , strVarName & " = " & commNum, acWindowNormal, acHidden
DoCmd.RunCommand acCmdPrint
DoCmd.Close acReport, strReport
Exit_Point:
Exit Sub
Error_Handler: 'this handles the case where user clicks cancel button
If Err.Number <> 2501 Then
MsgBox Err.Description, _
vbExclamation, "Error " & Err.Number
End If
DoCmd.Close acReport, strReport
End Sub
That is all the code that was required. Much less than the link at the start of this question. And also much less than the answer below. I am marking John Bingham's answer as the accepted answer because he clearly worked a lot on this, and I am very grateful for that. But I ended up solving the problem with A LOT LESS CODE. My solution does not require the custom dialog form because it uses the Windows print dialog form. As such, the on load event code in my posting (taken from the link above), is not necessary.
The code posted cannot work, because when a form is opened as a dialog:
DoCmd.OpenForm "dlgPrinter", , , , , acDialog, strReport
no other logic after this line is executed until the form has been closed, at which point control returns to the next line after this one, and logic continues on - except of course you can no longer reference anything in that form, because it is now closed.
Ok, now there is a question, where is the button the user clicks to print a report?
What I'm thinking is to split the logic in PrintReport into two methods, one that launches it, and tells the form to configure itself (doing the stuff suggested in the comment), but the rest of PrintReport then needs to happen after the user clicks OK (or Cancel);
So if I assume that you've got a form which can launch one or more reports, and the button is on this form, what I would suggest is this:
In the click event for that button - no changes to what you've got.
In that buttons form, add this:
Public Sub DialogAccept()
With Forms!dlgPrinter
If .Tag <> "Cancel" Then
Set Reports(strReport).Printer = Application.Printers((!cmbPrinter))
Reports(strReport).Printer.Orientation = !optLayout
Application.Echo False
DoCmd.SelectObject acReport, strReport
DoCmd.PrintOut acPages, !txtPageFrom, !txtPageTo
PrintReport = True
End If
End With
DoCmd.Close acForm, "dlgPrinter"
DoCmd.Close acReport, strReport
Application.Echo True
End Sub
Change PrintReport to:
Public Function PrintReport(strReport As String, strVarName As String, numVal As Long) As Boolean
' open report in PREVIEW mode but HIDDEN
DoCmd.OpenReport strReport, acViewPreview, , strVarName & " = " & numVal, acHidden
'DoCmd.OpenReport strReport, acViewPreview, , , acHidden
' open the dialog form to let the user choose printing options
DoCmd.OpenForm "dlgPrinter", , , , , , strReport
Forms!dlgPrinter.Configure
End Function
In the OK/Cancel button click events on dlgPrinter put (after existing code, but removing any instances of "Docmd.close"):
Forms!Calling_Form_Name.DialogAccept
This then calls that method, to do the stuff that is meant to happen after the user says "I'm done with the dialog".
Finally add the configure method to dlgPrinter:
Public Sub Configure()
With Reports(Me.Tag).Printer
Me!cmbPrinter = .DeviceName
Me!optLayout = .Orientation
End With
Dim numPages As String
numPages = Reports(Me.Tag).Pages
Debug.Print "numPages = " & numPages
TypeName(Me.txtPageTo) 'added this line as a test after
Me.txtPageTo.Value = numPages
End Sub
And remove this code section from Form_Load.
Hoep this helps.
Lastly, if the form on which the button launching dlgPrinter can vary, change this line:
DoCmd.OpenForm "dlgPrinter", , , , , acDialog, strReport
to:
DoCmd.OpenForm "dlgPrinter", , , , , acDialog, strReport & ";" & me.Name
In form_load of dlgPrinter, break up me.Openargs using left() & mid() with instr(), and save me.Name into the tag of something on the form (which you're not already using the tag of).
In the OK/Cancel button click events, change the code above to:
Forms(Object.Tag).DialogAccept