The Usual Approach
The idea for this function came to me while responding to a question in the forums on how to check if a query exist. The usual approach is to assign the query's name to a QueryDef object and trap the error, if the query does not exist. For example:
Public Function QueryExists(QueryName As String) As Boolean 'thedbguy@gmail.com '11/5/2021
Dim qdf As DAO.QueryDef
On Error Resume Next
Set qdf = CurrentDb.QueryDefs(QueryName)
If Err = 0 Then QueryExists = True Else QueryExists = False End If
Set qdf = Nothing
End Function
A Better Approach
Now, the above approach of using On Error Resume Next and then checking for errors is a very common approach. However, someone in the forums mentioned that this is not a very "clean" approach, because it leaves an Error Object hanging in the Errors Collection. They mentioned that their preferred method is to loop through the QueryDefs collection and check for the name of the query. For instance:
Public Function QueryExists_1(QueryName As String) As Boolean'thedbguy@gmail.com'11/5/2021Dim qdf As DAO.QueryDefDim blnReturn As BooleanFor Each qdf In CurrentDb.QueryDefsIf qdf.Name = QueryName ThenblnReturn = TrueExit ForEnd IfNextQueryExists_1 = blnReturnEnd Function
An Even Better Approach
Now, that makes a lot of sense, doesn't it? However, another smart person said: "Why not just use the MSysObjects table to check if the query exist?" Well, isn't that genius. So, inspired by that comment, I decided to create the following function as another option for checking if an Access database object exist or not. It goes something like this:
Option Compare DatabaseOption ExplicitPublic Enum dbgObjectTypedbgTable = 1dbgQuery = 5dbgForm = -32768dbgReport = -32764dbgMacro = -32766dbgModule = -32761dbgODBCLinkedTable = 4dbgOtherLinkedTable = 6End EnumPublic Function ObjectExists(ObjectName As String, ObjectType As dbgObjectType, _ Optional DatabasePath As String) As Boolean'thedbguy@gmail.com'11/5/2021Dim blnReturn As BooleanIf DatabasePath = "" ThenblnReturn = DCount("*", "MSysObjects", "[Name]='" _ & ObjectName & "' AND [Type]=" & ObjectType)ElseIf Dir(DatabasePath) = "" Then'MsgBox "Cannot find " & DatabasePath, vbInformation, "Info!"Debug.Print "Cannot find " & DatabasePathblnReturn = FalseElseblnReturn = CurrentDb.OpenRecordset("SELECT Count(*) FROM [;Database=" _& DatabasePath & "].MSysObjects WHERE [Name]='" _& ObjectName & "' AND [Type]=" & ObjectType)(0)End IfObjectExists = blnReturnEnd Function
As you can see, I have decided to use an enumeration and allow the user to specify which object they want to search. Also, the above function allows the user to search objects in an external database. I just thought these additional features might help make the function a lot more flexible and allow the developer to use it in multiple situations. So, now, the above approach does not rely on the Error object and also skips going through a loop to search for a single object.
Extension
Having the above function available, we can even extend the idea by creating smaller helper functions designed to search for a specific object. Here are some examples:
Public Function TableExists(TableName As String, Optional DatabasePath As String) As BooleanTableExists = ObjectExists(TableName, dbgTable, DatabasePath)End FunctionPublic Function FormExists(FormName As String, Optional DatabasePath As String) As BooleanFormExists = ObjectExists(FormName, dbgForm, DatabasePath)End Function
I hope the above information was useful, and I welcome any comments, recommendations, or criticisms.
As always, thanks for reading. Cheers!