I'm generating a query and report through VBA. I have an option of asking the user if they want to output the report as a snapshot. I first ask them if they want to make a snap shot. If they say no, nothing happens. If they say yes, they get a prompt asking where they want to save it.
Everything works great except if they say yes and then click Cancel on the prompt, it raises a runtime error 2501 saying the report action was cancelled. Here is the code.
DoCmd.OpenReport "CONCERNS", acViewPreview, lstFee.Value & " DETAILS"
If MsgBox("Do you wish to create a snapshot of this report?", vbQuestion + vbYesNo) = vbYes Then
DoCmd.OutputTo acReport, "CONCERNS", "SnapshotFormat(*.snp)", ""
End If
This is also the end of my procedure so I don't really care if an error happens here since all the important stuff happened already. I just know some monkey somewhere will flip if they ever see it. Is there a way to handle this error? On Error Resume Next is not an option because that would make debugging a nightmare in the future. It sounds like I'm looking for something like a Try/Catch but I don't think VBA supports that.
On Error GoTo errHandler
....
Exit Sub
errHandler:
If (Err.Number = 2501) Then
Resume Next
End If
End Sub
All you need is to handle the error ie:
On Error Goto HandleErr
DoCmd.OpenReport "CONCERNS", acViewPreview, lstFee.Value & " DETAILS"
If MsgBox("Do you wish to create a snapshot of this report?" _
, vbQuestion + vbYesNo) = vbYes Then
DoCmd.OutputTo acReport, "CONCERNS", "SnapshotFormat(*.snp)", ""
End If
ExitHere:
Exit Sub 'or Function
HandleError:
Select Case Err.Number
Case 2501 'Report Was Cancelled
If MsgBox ("Did you really want to cancel saving the report?", _
vbYesNo + vbDefaultButton2 ,"Please Confirm") = vbNo then
Resume
Else
Resume ExitHere
End if
Case Else
Msgbox "An Unexpected error Occurred " & Err.Description, _
vbExclamation,"Error"
Resume ExitHere
End Select
This will give the user the option to undo the cancel and let them know what they did.
There are (at least) two ways to handle this.
1> get the filename and handle possible cancellation in a step before sending the report snapshot. I haven't done this recently but there's another way to generate the snapshot report than the DoCmd.OutputTo command, or some variation that doesn't require the command itself to use a file dialog. I generated report snapshots in an old application and didn't have to ask the user for a filename. I'll try to find the code and show an example.
2> use On Error Resume Next, but only right before the DoCmd.OutputTo routine, then see if there's an error, then turn it back off:
If MsgBox("Do you wish to create a snapshot of this report?", _
vbQuestion + vbYesNo) = vbYes Then
On Error Resume Next
DoCmd.OutputTo acReport, "CONCERNS", "SnapshotFormat(*.snp)", ""
if Err.Number = 2501 Then
'' log or ignore error
Else
'' log or warn other unexpected errors
End If
On Error Goto 0
End If
Related
I have a button on a Continuous subform with the below VBA attached -
Private Sub del_Click()
On Error GoTo del_Click_Err
Dim LResponse As Integer
On Error Resume Next
DoCmd.GoToControl Screen.PreviousControl.Name
Err.Clear
If (Not Form.NewRecord) Then
LResponse = Eval("MsgBox('You are about to delete a record.'" & _
"'#If you click yes, you won't be able to undo this delete operation.' & Chr(13) & Chr(10) & " & _
"'Are you sure you want to delete this record?##', 276, 'Are you sure?')")
If LResponse = vbYes Then
DoCmd.SetWarnings False
DoCmd.OpenQuery "qry_DeleteSpecific"
DoCmd.RunCommand acCmdDeleteRecord
DoCmd.SetWarnings True
Else
End If
End If
If (Form.NewRecord And Not Form.Dirty) Then
Beep
End If
If (Form.NewRecord And Form.Dirty) Then
DoCmd.RunCommand acCmdUndo
End If
If (MacroError <> 0) Then
Beep
MsgBox MacroError.Description, vbOKOnly, ""
End If
del_Click_Exit:
DoCmd.SetWarnings True
Exit Sub
del_Click_Err:
MsgBox Error$
Resume del_Click_Exit
End Sub
The button was originally the auto-generated 'Delete Record' button and I have since modified it to include the query activation as well as my own msgBox.
The 'delete' button obviously worked fine before modification. The query also works as intended and I tested a button on a seperate form that just included the MsgBox code, which also worked.
But bringing it all together has failed somehow. When I click the button I don't get the MsgBox and it doesn't delete a record or run the query.
DoCmd.GoToControl Screen.PreviousControl.Name
This line appears to have fired correctly though.
Could anybody explain what may be going wrong with this?
---Edit---
Replaced
Error Clear
With
On Error GoTo del_Click_Err
I now get the error message -
The expression you entered contains invalid syntax
So it turns out it was all in the Quotes. The quotation issue is still a bit of a mystery to me, but I managed to get my code working.
Here's the change -
LResponse = Eval("MsgBox(""You are about to delete a record."" & " & _
"""#If you click yes, you won't be able to undo this delete operation."" & Chr(13) & Chr(10) & " & _
"""Are you sure you want to delete this record?##"", 276, ""Are you sure?"")")
Single quotes seemed to work when it was just the msgBox code by itself but not in the extended code. Anyway, I'll know to look out for this again.
#Andre your comment helped me debug this. I initially left 'Error Clear' as that was what the wizard put in for the delete button.
Others have had issues with the MSACCESS.EXE process not closing (from Task Manager) when exiting their databases. Each of the posts I've read have had something to do with not properly closing recordset variables.
When I exit the database I'm working on, I notice the MSACCESS.EXE process moves from the "Apps" section to "Background Processes" in Win 10 Task Manager. This hung process continues to utilize RAM. I'm certain that I'm closing all recordset variables properly.
Through a lot of debugging, I figured out a simple way to replicate the problem:
Create two forms in a new Access database. Set the PopUp property to True for one of them and False for the other. Save the forms "PopUp" and "NoPopUp" and close the database.
Open Task Manager to view the processes running on your screen.
Open your Access database and open the NoPopUp form. Note the MSACCESS.EXE process under Apps.
Close your database. Note that MSACCESS.EXE is removed from your list of Processes (both under "Apps" and "Background Processes").
Now reopen your Access database and open form PopUp. Then close the database.
Note that the MSACCESS.EXE process moves from the "Apps" section to "Background Processes" and is still utilizing system memory.
Additional MSACCESS.EXE processes hang in Task Manager each time the database is closed after opening a form with its Pop-up property set to True.
My database uses a ton of Pop-up forms. How should I be closing my database so that these hung processes aren't stacking up? (I'm using Access 2013 in Windows 10.)
Thanks,
Sam
How are you closing your database now?
Can you change the command to call a function.
Then in that function call a routine that closes all open forms
You may have to add parameter to close without saving - depending on your results.
Function CloseAllOpenFrms()
On Error GoTo Error_Handler
Dim DbF As Access.Form
Dim DbO As Object
Set DbO = Application.Forms 'Collection of all the open forms
For Each DbF In DbO 'Loop all the forms
DoCmd.Close acForm, DbF.Name, acSaveNo
Next DbF
Error_Handler_Exit:
On Error Resume Next
Set DbF = Nothing
Set DbO = Nothing
Exit Function
Error_Handler:
MsgBox "The following error has occured." & vbCrLf & vbCrLf & _
"Error Number: " & Err.Number & vbCrLf & _
"Error Source: CloseAllOpenFrms" & vbCrLf & _
"Error Description: " & Err.Description, _
vbCritical, "An Error has Occured!"
Resume Error_Handler_Exit
End Function
From http://www.devhut.net/2015/02/17/ms-access-vba-close-all-open-forms/
Try this very basic example in a new sample database.
EDIT: Add a Sleep and DoEvents after every close form in case of caching/fast cpu getting ahead of code? Last attempt to fix weird issue.
In Module 1
Option Compare Database
Option Explicit
Private Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
Function CloseAllOpenFrms()
On Error GoTo Error_Handler
Dim DbF As Access.Form
Dim DbO As Object
Set DbO = Application.Forms 'Collection of all the open forms
' Close all popups first
For Each DbF In DbO 'Loop all the forms
If DbF.PopUp Then
DoCmd.Close acForm, DbF.Name, acSaveNo
DoEvents
Sleep 1000
End If
Next DbF
' Close remaining forms
For Each DbF In DbO 'Loop all the forms
DoCmd.Close acForm, DbF.Name, acSaveNo
DoEvents
Sleep 1000
Next DbF
Application.Quit acQuitSaveNone
Error_Handler_Exit:
On Error Resume Next
Set DbF = Nothing
Set DbO = Nothing
Exit Function
Error_Handler:
MsgBox "Error closing : " & DbF.Name & vbCrLf & _
"Error Description: " & Err.Description, _
vbCritical, "Error closing form"
Resume Error_Handler_Exit
End Function
Create basic Form1 with two command buttons:
Command button Command1 (Caption= Open Popup Form)
Command button Command0 (Caption = Exit DB)
In Form1's form module paste text
'------------------------------------------------------------
' Command1_Click
'
'------------------------------------------------------------
Private Sub Command1_Click()
On Error GoTo Command1_Click_Err
CloseAllOpenFrms
Command1_Click_Exit:
Exit Sub
Command1_Click_Err:
MsgBox Error$
Resume Command1_Click_Exit
End Sub
'------------------------------------------------------------
' Command0_Click
'
'------------------------------------------------------------
Private Sub Command0_Click()
On Error GoTo Command0_Click_Err
DoCmd.OpenForm "Form2-popup", acNormal, "", "", , acWindowNormal
Command0_Click_Exit:
Exit Sub
Command0_Click_Err:
MsgBox Error$
Resume Command0_Click_Exit
End Sub
Create another form Form2-popup and set Popup property to true
Add command button Command1 with caption "Exit Form"
'------------------------------------------------------------
' Command1_Click
'
'------------------------------------------------------------
Private Sub Command1_Click()
On Error GoTo Command1_Click_Err
DoCmd.Close , ""
Command1_Click_Exit:
Exit Sub
Command1_Click_Err:
MsgBox Error$
Resume Command1_Click_Exit
End Sub
I have a function that has been in use for a number of months that checks to see if the form that is going to be opened will actually have records to be viewed before opening it. Recently I decided to change from ACCDB to ACCDE for security purposes. After making the change over the function started throwing error 2450 "Microsoft Access cannot find the referenced form..." I can't seem to find anything of use online that could tell me what the cause of this error is and why it only happens with ACCDE.
On a side note I realize the inefficiency of the logic in this function, it's on my list.
Public Function ValidateFormToOpen(strFormName As String, strFilter As String, strFieldName As String) As Boolean
On Error GoTo Err_Handler
Dim intNumberOfRecords As Integer
'If the form is currently open count how many results will be shown
If CheckFormState(strFormName) Then
intNumberOfRecords = DCount(strFieldName, Access.Forms(strFormName).RecordSource, strFilter)
'If it is closed open it in a hidden state and then count how many records would be shown
Else
DoCmd.OpenForm strFormName, acDesign, "", strFilter, , acHidden
intNumberOfRecords = DCount(strFieldName, Access.Forms(strFormName).RecordSource, strFilter)
DoCmd.Close acForm, strFormName
End If
'If there were records that will be shown return true
If intNumberOfRecords > 0 Then
ValidateFormToOpen = True
Else
ValidateFormToOpen = False
End If
Exit_Handler:
Exit Function
Err_Handler:
Call LogError(Err.Number, Err.Description, strMODULE_NAME & ".ValidateFormToOpen on " & strFormName)
Resume Exit_Handler
End Function
This is the CheckFormState Code
Public Function CheckFormState(sFormName As String) As Boolean
On Error GoTo Err_Handler
If Access.Forms(sFormName).Visible = True Then
CheckFormState = True
End If
Exit_Handler:
Exit Function
Err_Handler:
CheckFormState = False
Resume Exit_Handler
End Function
An ACCDE format database restricts design capabilities in general. I think that may be why you get an error with this line:
DoCmd.OpenForm strFormName, acDesign, "", strFilter, , acHidden
However I'm not positive that is the complete explanation because when I attempt to open a form in Design View (DoCmd.OpenForm "Form1", acDesign) in my ACCDE database, Access gives me a different error message:
"The command you specified is not available in an .mde, .accde, or .ade database."
So I don't know what the solution is for your goal, but I believe it can not be based on opening a form in Design View.
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
I'm seeing an error code like this in my Access 2000 VBA:
-2147352567-Record in '[SomeTable]' was deleted by another user.
So, 2 questions:
1) How do I handle/avoid an error code like this?
2) Can anyone explain why I'm getting an error code that doesn't seem to exist in MS documentation? And is there some way to decipher this code? Is it a combination of several codes? Any guidance on this topic would be appreciated.
Public Sub Form_Open(Cancel As Integer)
' Check for unposted record / regardless of Date / Shift
' If there is an unposeted record goto it
Dim lCheck
Dim sPress As String
On Error GoTo Form_Open_Err
GotoRecord:
If bPressConsumptionOpenRan = True Then
lCheck = DLookup("PressConsumptionID", "spI_GetUnPostedRecord")
If Not IsNothing(lCheck) Then
Me.txtPressConsumptionID.SetFocus
DoCmd.FindRecord lCheck
Else
DoCmd.SetWarnings False
DoCmd.OpenQuery ("spI_InsertNewPressConsumption")
Me.Requery
DoCmd.SetWarnings True
End If
End If
Form_Open_Exit:
Exit Sub
Form_Open_Err:
sErrMsg = Err.Number & "-" & Err.Description
MsgBox sErrMsg, vbCritical + vbOKOnly + vbInformation, "Program Error"
So I just commented out the
On Error GoTo
lines in Form_Open(), Form_Load(), and Form_Activate(), and still no debugger call. This error is shown when the db is opened, so I have no idea where else the error could be in the code.
And here is the code for IsNothing:
Public Function IsNothing(vCheck As Variant) As Boolean
On Error GoTo IsNothing_Err
If IsNull(vCheck) Then IsNothing = True: Exit Function
If IsEmpty(vCheck) Then IsNothing = True: Exit Function
If Trim(vCheck) = "" Then IsNothing = True: Exit Function
IsNothing_Err:
IsNothing = False
End Function
Now I'm getting a similar error in Form_Current():
Private Sub Form_Current()
Dim sUser As String
On Error GoTo Form_Current_Err
If IsNothing(Me.dtpUsageDate) Then
Me.dtpUsageDate = Date 'This line throws error.
End If
...Ommitted to save space. Not relevant...
Form_Current_Err:
sErrMsg = Err.Number & "-" & Err.Description
MsgBox sErrMsg, vbCritical + vbOKOnly + vbInformation, "Program Error"
Resume Form_Current_Log
Form_Current_Log:
On Error Resume Next
Call LogError(sErrMsg, "PressConsumptions_Form_Current")
GoTo Form_Current_Exit
End Sub
Error Message:
-2417352567-There is no object in this control.
Is this message related to the other one we've been seeing? Any thoughts on correcting?
The error number and message suggest to me that this is a problem from outside of Access. The fact that you're executing a saved query that has a name suggesting that it runs an SPROC on a database server suggests to me that the back end is SQL Server or some other back end.
It's a very common error in Access when you don't have both a primary key and a timestamp field in your back end table. It's caused by the fact that Access can't tell exactly which record is involved and can't refresh the display appropriately. Having a PK and a timestamp field usually gets rid of the problem.
But it may be caused by something else, of course.