The expression On Click you entered as the event property setting produced the following error: Sorry, an unexpected error occurred - vba

The error message continues with:
"*The expression may not result in the name of a macro, the name of a user-defined function, or [Event Procedure]."
"*There may have been an error evaluating the function, event, or macro."
This database was written by an employee who retired years ago and unfortunately I am now stuck with it. It was working last week and of course when it stopped working today. I am not sure where to even start looking or how to debug in VBA. When a user enter data in the fields and click on Print button, I believe the data gets populated in the data source and then it will print a report/receipt. The print button call the cmdPrintReceipt_Click() procedure. Can someone give me some pointers or how to debug in VBA? Much appreciated and happy holidays!
Pasting the code here:
Option Compare Database
Option Explicit
Dim OkPass As Integer, message As String, Response As Integer
Dim nAmount As Integer
Dim Conn As New ADODB.Connection
Dim RS2 As ADODB.Recordset
Dim Total As Long 'Hold receiptNumber for ReceiptLine
Private Sub cmdNoAdd_Click() 'close window without adding a new reacord
'Use the msgbox function to see if user wants to exit this form w/o adding new receipt
Dim Msg, Style, Title, respons
Msg = "Close this window without saving this receipt?"
Style = vbYesNo + vbQuestion + vbDefaultButton2 'Define buttons of message box
Title = "Exit without adding a receipt?" 'Title of the message box
respons = MsgBox(Msg, Style, Title)
If respons = vbYes Then 'User chose Yes DO NOT ADD the Record
DoCmd.Close
Else 'User chose No close the message box and leave frmReceipt Open
End If
End Sub
Private Sub Form_Load()
'Clear Total
Total = 0
End Sub
'****************************************************************************************
' Main procedure for the form, check first all required fields filled in
' then Add new records and print receipts.
'****************************************************************************************
Private Sub cmdPrintReceipt_Click()
'Check if all filled in, then
'Just call the AddReceipt Function
DoNotClose 'function
If OkPass <> 9 Then
Response = MsgBox(message, vbOKOnly, "Information Missing")
'return focus to the frmReceipt
txtFirstName.SetFocus
Exit Sub
Else
' Add the new Receipt record
Me.lblNoAdd.Visible = False
Me.cmdNoAdd.Visible = False 'you can't escape after printing receipt.
AddAReceipt ' call AddReceipt function
MsgBox "Please confirm the information you entered is correct", vbOKOnly
ShowPrint3Button
'cmdPrint3Button print 3 copies of receipt
End If
Exit Sub
End Sub

If it worked for years without errors before, I doubt debugging will help.
The db might be corrupted. Try the following steps:
see if VBA compiles
compact and repair the db
if not successfull, create a new blank db, and imort all objects from the old one.
Also, when you get the error message, you can press Ctrl+Break and arrive on the exact line that causes the error. Good luck ;-)

Related

How to close current Word document and stop all VBA code running

I am creating a Word template that performs a bunch of actions when Document_New is initialised. For example, I am pulling in and applying Custom Document Properties from an XML file in one sub, and referring to them in a second.
I'm trying to add some error handling to close the document with an error message and prevent the rest of the VBA from running, and I can get to the point where the document closes, but the rest of the VBA code continues to execute. Ideally I need to close just this new document (other Word documents may be open on a device) and stop any more processing of VBA.
ThisDocument.Close SaveChanges:=wdDoNotSaveChanges
When this is in place, the template seems to close, but the newly created document still exists and the template VBA continues to run.
Is anyone able to suggest a way to close the template and abort the creation of the new document?
EDIT: Including an example of how I'm looking for errors.
In Document_New - I call ValidateProperties that loops through an arrayProps array that stores properties required for the template. Each property in the array is checked using the function CustomDocumentPropertyExists and if that returns false I call the sub ExitFailedValidation. This is the sub I want to call if the template fails a validation test. I want to be able to cleanly close the new document without saving and leave any other Word windows open.
Sub ValidateProperties()
Dim arrayProps(1) As String
Dim i As Long
arrayProps(0) = "prop-doc-blueprint"
arrayProps(1) = "prop-doc-stationery"
For i = 0 To UBound(arrayProps)
If CustomDocumentPropertyExists(arrayProps(i)) = False Then
ExitFailedValidation ("The required custom document property " & arrayProps(i) & " is missing. Please check " & _
"the config.xml file to ensure it is included.")
End If
Next i
End Sub
Sub ExitFailedValidation(Message As String)
MsgBox "The Template failed to load and validate." & vbCrLf & vbCrLf & _
Message, vbCritical, "Error loading template"
MsgBox ThisDocument.Name
MsgBox ActiveDocument.Name
ThisDocument.Close SaveChanges:=wdDoNotSaveChanges
ActiveDocument.Close SaveChanges:=wdDoNotSaveChanges
End Sub
The Document_New() is the entrance point in code, so it should handle the tasks that need to be run and take appropriate action should an error occurs or something did not go as expected as in your case.
In order to be able to do that, the tasks it calls must report their status, e.g. completed, failed, something is missing etc.
Therefore, change the ValidateProperties() sub into a function that returns true or false and pass a string to it as an output parameter that will hold the error message if the function fails. If all goes well, it will simply be unused.
The main point of the app. This method decides what happens in the app.
Private Sub Document_New()
Dim errorMessage As String
If Not TryValidateProperties(errorMessage) Then
ExitFailedValidation errorMessage
Exit Sub
End If
'all good - continue
End Sub
The ValidateProperties() sub changed to a method that returns true or false with an optional error message if something is wrong. Since false is the default value of a boolean, exiting the function if a property doesn't exist will return false - no need to set it explicitly.
Private Function TryValidateProperties(ByRef outMessage As String) As Boolean
'...
For i = 0 To UBound(arrayProps)
If Not CustomDocumentPropertyExists(arrayProps(i)) Then
outMessage = "The required custom document property " & arrayProps(i) & " is missing. Please check " & _
"the config.xml file to ensure it is included."
Exit Function
End If
Next i
'all good
TryValidateProperties = True
End Function
Lastly, the helper method for communicating the error. In my opinion, the document shouldn't be closed here, but within the Document_New() method if property validation fails, but I'll leave this with you.
Private Sub ExitFailedValidation(Message As String)
MsgBox Message
End Sub
To add error handling in a method:
Sub T()
On Error GoTo Trap
'main method body
Leave:
'Release any references here, e.g. close db connection, release file handle etc.
Exit Sub
Trap:
MsgBox Err.Description, vbCritical
Resume Leave
End Sub

My global variable is not transferring to Dialog Form when called from Report

Update 3/15/19 to add new declaration code in General Declarations section:
Option Compare Database
' Access global variables definition
Global bInReportOpenEvent As Boolean
Option Explicit
I am getting error:
"The expression On Open you entered as the event property setting produced the following error: Constants, fixed-length strings, arrays, user-defined types and Declare statements not allowed as Pubblic members of object modules."
Update 3/15/19 to add declaration code. Still bInReportOpenEvent value lost on call to Dialog form.
Option Compare Database
Dim bInReportOpenEvent As Boolean
Function IsLoaded(strNme As String) As Boolean
IsLoaded = CurrentProject.AllForms(strNme).IsLoaded
End Function
I am creating an Access Report that calls a Dialog Form to prompt for specific record to display in report. The report uses a query as the record source. I am setting a global field in the Report Open module so that the Dialog Form cannot be executed on it's own. If the Dialog Form is called and the global field set by the Report is not set, then I want to exit out with a message. My Report Open module looks like this:
Public Sub Report_Open(Cancel As Integer)
Dim outCome1 As String
' Set public variable to true to indicate that the report
' is in the Open event
bInReportOpenEvent = True
MsgBox (bInReportOpenEvent)
' Open Appt Query Dialog
DoCmd.OpenForm "craid CMM Client Report Dialog", , , , , acDialog
' Cancel Report if User Clicked the Cancel Button
If IsLoaded("craid CMM Client Report Dialog") = False Then Cancel = True
MsgBox ("Is Dialog Form Loaded?")
MsgBox (IsLoaded("craid CMM Client Report Dialog"))
'outCome1 = (Reports("CMM Client Status Report").Controls("googleoutcome").Value)
'MsgBox (outCome1)
' Set public variable to false to indicate that the
' Open event is completed
bInReportOpenEvent = False
End Sub
My Form Open for my Dialog Form looks like this:
Private Sub Form_Open(Cancel As Integer)
If Not bInReportOpenEvent Then
MsgBox ("In Not bInReportOpenEvent Logic")
MsgBox (bInReportOpenEvent)
' If we're not called from the report
MsgBox "For Use From CMM Client Status Report Only", _
vbOKOnly
Cancel = True
End If
End Sub
Any ideas on why? Any help appreciated.
My question was answered. Solution is to put declaration of global variable in VBA code module.

MS Access vba save button error 3021

For various reasons, I want to set up a custom button on my forms to save the current record. I use a navigation form and want to trigger the same process (integrity-checks, user input etc.) whenever the entry is saved, thus whenever the user presses the "save"-button or switches to another form. The user will conditionally be asked to confirm the process and is thus able to cancel it as well.
Everything is running smoothly with one really odd and annoying exception: Whenever I click the save button on a new record and prompt a message within the "BeforeUpdate" event, I receive
RTE 3021 ("no current record")
Without the MsgBox, everything is fine. Even more strange:
When I trigger the save process by switching to another form using the navigation form (or simply press "outside" the form used for data entry), everything is fine as well.
Here is a minimalistic example (similar results with DoCmd.Save, Requery or acCmdSaveRecord):
Private Sub vt_save_Click()
Me.Dirty = False
End Sub
Private Form_BeforeUpdate(Cancel As Integer)
Cancel = True
MsgBox "Test"
End Sub
Any ideas? I simply can't wrap my head around that error.
You could maybe try to run a query using the values in the form while checking if the record exists or not.
Is there a primary key on the table? if so, the primary key will be your focal point.
Private Sub vt_Save_Click()
dim rst as DAO>Recordset
Dim strSQL as String
Dim strID as string
strID = me.YourPrimaryKeyField
strSQL = "SELECT * " & _
"FROM YourTableName " & _
"WHERE (((YourTableName.YourFieldName) =" & me.PrimaryKeyField & "));"
set rst = currentdb.openrecordset(strsql)
if rst.recordcount = 0 then
currentdb.execute "INSERT INTO YourTableName ( List All Fields to Add ) " & _
"SELECT List All Field controls with values to add;"
End IF
'Anything else you want the code to do from here
EndCode:
If not rst is nothing then
rst.close
set rst = nothing
End IF
End Sub
Repeat this process for the Form_LostFocus() event. If you want to make it easier, make this code a module and call within both event triggers on your form.
If this doesn't work please let me know and I will be happy to further assist.
The most straight forward and reasonable solution is to use an Error Handler - which I ignored so far tenaciously.
Private Sub save_Click()
On Error GoTo Err_Handler
Me.Dirty = False
Exit_Here:
Exit Sub
Err_Handler:
If Err.Number = 2101 Then
'ignore or message
Else
MsgBox Err.Description
End If
Resume Exit_Here
End Sub

Excel VBA Userform QueryClose: Cancel not working

I've written the code below so that it will check if a process has been completed or not before closing the form. This userform is used as a scoresheet that will make range("A6") green to signify a pass, or range("B6") red to signify a fail as the final step of the sub, before unloading the form.
From what I've checked online so far, it should be working. While debugging, the macro gets all the way to where it says Cancel = True, reads over the line, but the form closes anyway.
Why isn't the cancel registering even when it reads over the line?
Private Sub Userform_queryclose(CloseMode As Integer, Cancel As Integer)
Dim wbScoreCard As Workbook
Dim wsScoreCard As Worksheet
Dim MSG As String
Set wbScoreCard = Workbooks(NameBox.Value)
Set wsScoreCard = wbScoreCard.Worksheets(Format(Date, "MM.dd.yy") & " " & CallType.Caption)
If Err.Number = 0 Then
If wsScoreCard.Range("A6").Interior.Color <> vbGreen Then
If wsScoreCard.Range("B6").Interior.Color <> vbRed Then
Beep
MSG = MsgBox("This scorecard is not complete! If you close it now, this scorecard will not be saved. Continue?", vbYesNo, "Warning - Scorecard Incomplete")
If MSG = vbYes Then
wbScoreCard.Close savechanges:=False
Exit Sub
Else
Cancel = True
Exit Sub
End If
End If
End If
End If
End Sub
Couple of things:
You're not shutting off error handling, so the Err.Number = 0 check has no effect; if there's a runtime error, execution jumps straight out of the procedure anyway.
MSG should be a vbMsgBoxResult, not a String. Your code only works because of implicit type conversions from the underlying Integer value to the String type you're forcing it into.
Unless you didn't post your entire code, Exit Sub is redundant in both branches.
The problem can be reproduced with simpler code:
Private Sub Userform_queryclose(CloseMode As Integer, Cancel As Integer)
Cancel = True
End Sub
The problem is that you made up that signature or somehow typed it up from memory. This is the signature for the QueryClose handler:
Private Sub UserForm_QueryClose(Cancel As Integer, CloseMode As Integer)
Notice the ordering of parameters.
You'll get the expected behavior by setting your CloseMode to True instead of Cancel... but a better fix would be to put the parameters in the correct order.
Event handlers don't really care about parameter names: it's about types and order. Since both parameters are Integer, it's down to ordering: the first Integer parameter is interpreted as the Cancel parameter, and the second is the CloseMode - the form / COM doesn't care how you called them, it's going to read the Cancel value from the first parameter anyway.
You can avoid this problem in the future, by selecting the event from the dropdowns at the top of the code pane:
Make sure the left-hand dropdown says "UserForm", and then select "QueryClose" from the right-hand dropdown:
If there's no handler for it, the VBE will create one properly formed for you.

Trouble trapping 2501 error

I am sending data from frmSearchEmployeeWorksheets to frmStatsCorr which runs a query (qryStatsCorr). On frmStatsCorr I am checking to make sure the query returns records otherwise I will Msg the user and return to the search form. My problem is that I am having problems 'ignoring' the 2501 caused by the DoCmd.OpenForm ("frmStatsCorr") which I learned here on Stackoverflow...
What am I doing wrong that is causing me major Access VBA Frustration??
This is the sub on the Search form (frmSearchEmployeeWorksheets):
Private Sub btnSearch_Click()
' I only change focus to force the updated data to submit to query
Me.[txtEmployee].SetFocus
Me.txtShift.SetFocus
If txtUnit = "7" Then
'First close the form in order to update
DoCmd.Close acForm, "frmStatsCorr"
' Open Stats form
On Error GoTo myErr
**DoCmd.OpenForm ("frmStatsCorr") 'causes error**
End If
myExit:
Exit Sub
myErr:
Echo True
If Err.Number = 2501 Then GoTo myExit
MsgBox Err.Description
GoTo myExit
End Sub
In frmStatsCorr I simply check to make sure the query returns records if not I inform the user, close the form, and return to the frmSearchEmployeeWorksheets
Private Sub Form_Load()
If strFormStatus = "view" Then
If DCount("*", "qryStatsCorr") = 0 Then
MsgBox "Your search does not produce any results. Try a different search.", vbOKOnly
DoCmd.Close
DoCmd.OpenForm ("frmSearchEmployeeWorksheets")
Exit Sub
End If
txtDay = WeekdayName(Weekday(Me.WorkDate)) 'This line returns an error so I check for an empty query and return to the search form.
Me.[WorkDate].SetFocus
Me.txtUnit.Enabled = False...
I'm unsure how well I understand your code or the logic behind it. My hunch is you should check the DCount result from btnSearch_Click, and not fiddle with closing then re-opening frmStatsCorr, and having frmStatsCorr close itself when it contains no data. Just do not open frmStatsCorr when it will not contain data.
If the current form (frmSearchEmployeeWorksheets) which holds your btnSearch_Click procedure contains unsaved data changes, you can save them with Me.Dirty = False
Private Sub btnSearch_Click()
Dim strPrompt As String
If Me.Dirty Then ' unsaved data changes
Me.Dirty = False ' save them
End If
If Me.txtUnit = "7" Then
If DCount("*", "qryStatsCorr") = 0 Then
strPrompt = "Your search does not produce any results. " & _
"Try a different search."
MsgBox strPrompt, vbOKOnly
Else
' if frmStatsCorr is open, just Requery
' else open frmStatsCorr
If CurrentProject.AllForms("frmStatsCorr").IsLoaded Then
Forms("frmStatsCorr").Requery
Else
DoCmd.OpenForm "frmStatsCorr"
End If
' uncomment next line to close current form
'DoCmd.Close acForm, Me.Name
End If
End If
End Sub
If frmStatsCorr is open and you need to check whether it is in Design View, examine its CurrentView property.
Forms("frmStatsCorr").CurrentView ' Design View = 0
I suggested that approach because I suspected frmStatsCorr's Form_Load may trigger the 2501 error when it closes itself. But I'm not certain that's the cause of the error and I'm not motivated enough to set up a test.
If you still have 2501 errors with the approach I suggested, there are two other possible causes I've encountered:
corruption
broken references