Access vba Replacing runtime error with custom message - ms-access

I've been trying to set a outlook task item through Access and replace a runtime error 440 with a custom message.
This error popped when a certain field (me.dueBy) was empty.
Currently the code I have is successful with creating a task for records with dueBy data, but when I click on the button for a record with no due date, then nothing happens. No message box, no error, nothing.
I just need a message box telling me that I require a due date to set a task when that field is empty.
Private Sub Command15_Click()
Dim db As DAO.Database
Dim rs As DAO.Recordset
Dim DataErr As Integer
Dim Response As Integer
On Error GoTo err_handler
Set db = CurrentDb
Set rs = db.OpenRecordset("tblActions")
Set outLookApp = CreateObject("outlook.application")
Set OutlookTask = outLookApp.CreateItem(olTaskItem)
With OutlookTask
.Subject = "Action Due Date: " & Me.dueBy & " for Contract ID " & Me.contractID
.Body = "Due date for Action: < " & Me.actionNote & " > is " & Me.dueBy & "."
.ReminderSet = True
.ReminderTime = Me.dueBy + TimeValue("8:00:00 AM")
.Save
End With
MsgBox "Action Task has been set in Outlook successfully."
exit_err_handler: Exit Sub
err_handler:
If DataErr = 440 Then
Response = acDataErrContinue
MsgBox "Due date is required.", vbOKOnly, "Due date Error"
End If
Resume exit_err_handler
Set rs = Nothing
Set db = Nothing
End Sub

DataErr and Response are arguments to the Form_Error-Event. They have no effect in error handling in general. In your procedure DataErr is simply an integer variable and will always have the value 0 unless you explicitly assign another value.
You need to check for Err.Number in the error handler to identify specific error conditions.

Related

How do I programmatically retrieve the values from a linked table's property sheet?

I am working in MS Access. All the tables and views are linked to a SQL Server database. I want to write a procedure that will retrieve and store all of the formatting information about these objects. A lot of this information is available from the property sheet (I open a table in Design View, and hit F4 for the property sheet). Eg:
Filter
Order By
Filter On Load
Order by On Load
Order by On
How do I retrieve these properties programmatically? I only see them listed for Reports.
Note that I need to retrieve the values, not just set them. I know about the SetFilter method, and that's not what I need.
The linked table exists as a DAO.TableDef in your database's TableDefs collection. So you can check the TableDef.Properties collection for those 5 properties.
However beware that both Filter and OrderBy are user-created instead of default properties, which means they are not included in the Properties collection unless you've assigned them values. Attempting to retrieve one which doesn't exist triggers error 3270, "Property not found". You can trap that error, respond to it as you wish, and continue on for the other properties you're interested in. Or you could first determine whether the property exists and only attempt to retrieve its value when it does exist.
This code sample uses the first approach (trap the error):
Const cstrTable As String = "YourLinkedTableNameHere"
Dim db As DAO.Database
Dim tdf As DAO.TableDef
Dim strMsg As String
Dim varProp As Variant
Dim varProperties As Variant
On Error GoTo ErrorHandler
varProperties = Array("Filter", "FilterOnLoad", "OrderBy", _
"OrderByOn", "OrderByOnLoad")
Set db = CurrentDb
Set tdf = db.TableDefs(cstrTable)
For Each varProp In varProperties
Debug.Print varProp, tdf.Properties(varProp).Value
Next
ExitHere:
Exit Sub
ErrorHandler:
Select Case Err.Number
Case 3270 ' Property not found.
strMsg = "Property '" & varProp & "' not found."
'MsgBox strMsg
Debug.Print strMsg
Resume Next
Case Else
strMsg = "Error " & Err.Number & " (" & Err.Description & ")"
MsgBox strMsg
Resume ExitHere
End Select
How about something like this? (I've defined "table2" to have two fields, "PropertyName" and "PropertyValue"..."table1" is a placeholder for any of your existing tables)
Dim i As Integer
Dim j As Integer
Dim RS As DAO.Recordset
On Error Resume Next
Set RS = CurrentDb.OpenRecordset("select * from table2")
j = CurrentDb.TableDefs("table1").Properties.Count
For i = 0 To j - 1
RS.AddNew
RS!PropertyName = CurrentDb.TableDefs("table1").Properties(i).Name
RS!PropertyValue = Nz(CurrentDb.TableDefs("table1").Properties(i).Value, "-")
RS.Update
Next i

Why do I get run-time error '2759' when saving the record? access 2010

Using Access 2010, I have a form for Purchase_Orders where the status changes depending on the whether the Items in the sub form have been delivered or not, and, it is influenced by the date as well.
Private Sub Form_AfterUpdate()
Dim rs As Recordset
Dim db As Database
Dim var_Delivered As String
var_Delivered = "SELECT Count(*) AS d_Count" & _
" FROM Items" & _
" WHERE PO_ID =" & Me.PO_ID.Value & _
" AND Supplier_Dnote_ID IS Null" & _
" AND Delivered_Without_Dnote =0;"
Set db = CurrentDb
Set rs = db.OpenRecordset(var_Delivered, dbOpenDynaset)
'MsgBox rs!d_Count
If rs!d_Count > 0 Then
If Me.Supply_date < Date Then
Me.Status = "Overdue"
Else
Me.Status = "Submitted"
End If
Else
Me.Status = "Delivered"
End If
db.Close
Set db = Nothing
Set rs = Nothing
End Sub
This runs after_update of the Purchase_Orders. I have a save_close button that uses the following code and doesn't return an error:
If Me.Dirty = True Then
DoCmd.Close acForm, "Purchase_Orders", acSaveYes
Else
DoCmd.Close acForm, "Purchase_Orders", acSaveNo
End If
However, I also have a Save button that doesn't close the form. This is where I get run-time error 2759 : The method you tried to invoke on an object failed. Debug Highlights the saverecord line.
Private Sub SaveOnlyBtn_Click()
If Me.Dirty = True Then
docmd.RunCommand acCmdSaveRecord
End If
End Sub
If I comment the status code out and use the save button, the record saves fine without any errors. Why do I get this error? I'm completely stumped and searching the error online hasn't helped me either.
So I found that the error did not occur when I put the code in the "on dirty" event, which then made me realise that I don't need necessarily have to run the code after the form updates, only when specific fields change. So I changed my code to a public code and called it when supply date, delivered_without_dnote, or supplier_Invoice_ID changed.
the public code is :
Public Sub delivered_status()
On Error GoTo errTrap1
If Forms!Purchase_Orders_Ex.Form!Status = "Cancelled" Then
Exit Sub
Else
DoCmd.RunCommand acCmdSaveRecord
Dim rs As Recordset
Dim db As Database
Dim var_Delivered As String
var_Delivered = "SELECT Count(*) AS d_Count" & _
" FROM Items" & _
" WHERE PO_ID =" & Forms!Purchase_Orders_Ex.Form!PO_ID.Value & _
" AND Supplier_Dnote_ID IS Null" & _
" AND Delivered_Without_Dnote =0;"
Set db = CurrentDb
Set rs = db.OpenRecordset(var_Delivered, dbOpenDynaset)
'MsgBox "Outstanding Items: " & rs!d_Count
If rs!d_Count > 0 Then
If Forms!Purchase_Orders_Ex.Form!Supply_date < Date Then
Forms!Purchase_Orders_Ex.Form!Status = "Overdue"
Else
Forms!Purchase_Orders_Ex.Form!Status = "Submitted"
End If
Else
Forms!Purchase_Orders_Ex.Form!Status = "Delivered"
End If
rs.Close
Set db = Nothing
Set rs = Nothing
End If
errTrap1:
Select Case Err.Number
Case 3314 'form not complete and other required fields are empty
Exit Sub
Case Else
If Err.Number > 0 Then
MsgBox Err.Number & ": " & Err.Description
End If
End Select
End Sub
Now, when I use either the save_close or Save_Only I do not get error 2759. I do not completely understand which part of my original method caused the error but it no longer occurs with this approach.
I've just encountered this issue and moving code out of Form_AfterUpdate fixed it for me too.
What's (vaguely) interesting is that the code in question worked fine locally, but did not work when deployed to the client. I tried importing just the amended form instead of replacing the whole access app, but I still got the same issue. I also copied the back-end database back from the server to my development machine, but still didn't get the issue locally. On top of that I did endless compact/repair and decompile/compile.
My conclusion at the end of all of that was that this was yet another weird issue emanating from the Access black-box, rather than an issue with the particular code.

Check if certain data exists in a field in a table

I have a table (tblForms) in which one of the fields is a lookup to another table (tblClients). How can I find if a certain Client has data or does not have data in tblForms? DCount only works if the Client does appear in tblForms.
I have a form (frmDisclosure) with a command button - onClick:
Private Sub Command245_Click()
On Error GoTo Command245_Click_Err
DoCmd.OpenForm "frmClient", acNormal, "", "[ClientID]= " & Me.Client, , acNormal
DoCmd.Close acForm, "frmDisclosure"
Command245_Click_Exit:
Exit Sub
Command245_Click_Err:
MsgBox Error$
Resume Command245_Click_Exit
End Sub
When I click this I get the error (N.B. I f I open frmClient directly form Switchboard I don't get the error). frmClient has a subform (continuous) frmFormsList which derives its data from:
SELECT tblForms.ClientLookup, tblForms.Issued, First(tblForms.RefNo) AS FirstOfRefNo, Last(tblForms.RefNo) AS LastOfRefNo, Count(tblForms.RefNo) AS CountOfRefNo, tblClient.KnownAs, tblClient.EMail
FROM tblForms INNER JOIN tblClient ON tblForms.ClientLookup = tblClient.ClientID
GROUP BY tblForms.ClientLookup, tblForms.Issued, tblClient.KnownAs, tblClient.EMail
HAVING (((tblForms.Issued) Is Not Null));
This function resides in frmFormsList:
Public Function NumRecs() As Integer
NumRecs = DCount("*", "tblForms", "ClientLookup = " & Me.ClientLookup)
End Function
My query shows data where I have issued forms to a client. Therefore if I have not issued forms to a Client tne the query shows nothing for that client so does not give a result 0. I get RunTime Error 2427 "You entered ans expression that has no value". NumRecs = DCount("*", "tblForms", "ClientLookup = " & Me.ClientLookup) is highlighted in debug.
In frm Disclosure, if I Rem out ", acNormal, "", "[ClientID]= " & Me.Client, , acNormal" the problem does not occur, but I don't get straight to the Client I am interested in. So the problem occurs when I try to open a form using the Rem'd out bit where the client has not been issued with any forms. When I opne the frm Client directly the rocord presented does not have forms issued but the problem does not occur.
Here's the solution:
Public Function NumRecs() As Integer
Dim dbs As DAO.Database
Dim rs As Object
Set dbs = CurrentDb
Set rs = dbs.OpenRecordset("qryDisclosure", dbOpenDynaset)
If Me.Recordset.RecordCount = 0 Then
NumRecs = 0
Else
NumRecs = Nz(DCount("*", "qryDisclosure", "ClientLookup = " & Me.ClientLookup), 0)
End If
End Function

compile error: expected end of statement

A Microsoft Access 2010 database is giving me the following error message:
Compile Error: Expected End Of Statement
Here is the method that is throwing the error message:
Private Sub Form_BeforeUpdate(Cancel As Integer)
'Provide the user with the option to save/undo
'changes made to the record in the form
If MsgBox("Changes have been made to this record." _
& vbCrLf & vbCrLf & "Do you want to save these changes?" _
, vbYesNo, "Changes Made...") = vbYes Then
DoCmd.Save
Else
DoCmd.RunCommand acCmdUndo
End If
Dim sSQL As String
sSQL = "SELECT max(Clients.ClientNumber) AS maxClientNumber FROM Clients"
Dim rs As DAO Recordset
Set rs = CurrentDb.OpenRecordset(sSQL)
MsgBox ("Max client number is: " & rs.Fields(1))
End Sub
The line of code that is throwing the error message is:
Dim rs As DAO Recordset
I am not sure if the problem has to do with the syntax of what is on the line preceding it. Can anyone show how to fix this problem? And explain what is going on?
You are missing a full stop (period) between the DAO and the Recordset - it should be
Dim rs As DAO.Recordset
Beyond that, you will also have a runtime error on reading the field value, since a DAO Fields collection is indexed from 0, not 1. Hence, change the penultimate line to this:
MsgBox ("Max client number is: " & rs.Fields(0))
Alternatively, reference the field by its name:
MsgBox ("Max client number is: " & rs!maxClientNumber)
You're mising the semicolon at the end of your Sql statement

Access query need to bypass "enter parameter value" error with a msg box saying field not found

I have a simple query tied to a command button that shows a summary of the values in a particular field. It's running on a table that changes with each use of the database, so sometimes the table will contain this field and sometimes it won't. When the field (called Language) is not in the file, the user clicks the command button and gets the "Enter Parameter Value" message box. If they hit cancel they then get my message box explaining the field is not present in the file. I would like to bypass the "Enter Parameter Value" and go straight to the message if the field is not found. Here is my code:
Private Sub LangCount_Click()
DoCmd.SetWarnings False
On Error GoTo Err_LangCount_Click
Dim stDocName As String
stDocName = "LanguageCount"
DoCmd.OpenQuery stDocName, acNormal, acEdit
Err_LangCount_Click:
MsgBox "No Language field found in Scrubbed file"
Exit_LangCount_Click:
Exit Sub
DoCmd.SetWarnings True
End Sub
You can attempt to open a recordset based on the query before you run the query:
Set rs = CurrentDb.QueryDefs("query1").OpenRecordset
This will go straight to the error coding if anything is wrong with the query.
Alternatively, if it is always the language field and always in the same table, you can:
sSQL = "select language from table1 where 1=2"
CurrentDb.OpenRecordset sSQL
This will also fail and go to your error coding, but if it does not fail, you will have a much smaller recordset, one with zero records.
You can easily enough get a list of fields in a table with ADO Schemas:
Dim cn As Object ''ADODB.Connection
Dim i As Integer, msg As String
Set cn = CurrentProject.Connection
Set rs = cn.OpenSchema(adSchemaColumns, Array(Null, Null, "Scrubbed"))
While Not rs.EOF
i = i + 1
msg = msg & rs!COLUMN_NAME & vbCrLf
rs.MoveNext
Wend
msg = "Fields: " & i & vbCrLf & msg
MsgBox msg
More info: http://support.microsoft.com/kb/186246
You have a command button named LangCount. It's click event has to deal with the possibility that a field named Language is not present in your Scrubbed table.
So then consider why a user should be able to click that command button when the Language field is not present. When the field is not present, you know the OpenQuery won't work (right?) ... so just disable the command button.
See if the following approach points you to something useful.
Private Sub Form_Load()
Me.LangCount.Enabled = FieldExists("Language", "Scrubbed")
End Sub
That could work if the structure of Scrubbed doesn't change after your form is opened. If the form also includes an option to revise Scrubbed structure, update LangCount.Enabled from that operation.
Here is a quick & dirty (minimally tested, no error handling) FieldExists() function to get you started.
Public Function FieldExists(ByVal pField As String, _
ByVal pTable As String) As Boolean
Dim blnReturn As Boolean
Dim db As DAO.Database
Dim fld As DAO.Field
Dim tdf As DAO.TableDef
Set db = CurrentDb
' next line will throw error #3265 (Item not found in this collection) '
' if table named by pTable does not exist in current database '
Set tdf = db.TableDefs(pTable)
'next line is not actually needed '
blnReturn = False
For Each fld In tdf.Fields
If fld.Name = pField Then
blnReturn = True
Exit For
End If
Next fld
Set fld = Nothing
Set tdf = Nothing
Set db = Nothing
FieldExists = blnReturn
End Function