The ADO Connection and Recordset
objects support several events for a variety of operations. Capturing
these events and having the chance to run custom code when the event
occurs can be very useful, especially for asynchronous Recordset operations. There are several things that need to be done when working with ADO events.
1. Declaring WithEvents
To use the ADO events for either the Connection or the Recordset object, the Connection must be declared with the WithEvents keyword. The important thing to understand about the WithEvents keyword is that it can be used only within a class module
in VBA. It will generate the compile error "Only valid in object
module" in a regular VBA code module. Also, this Connection variable must be declared as a global member of the Class object. At the top of the class module file, this Connection object can be declared as follows:
' The Connection is declared as a class member, using the WithEvents keyword
Public WithEvents cn As ADODB.Connection
Public WithEvents rs As ADODB.Recordset
Once the Connection variable has been defined, you can begin implementing the various events for the Connection object. All of these rules apply to the Recordset object when implementing its events as well.
2. Implementing ADO Event Methods
To implement a specific ADO event for the Connection (or Recordset)
object, create an event subroutine. This subroutine is required to have
the name format of the variable name, then the underscore character,
and then the event name with its given parameters. For example, the ConnectComplete event could be implemented for the Connection as follows:
Public Sub cn_ConnectComplete( _
ByVal pError As ADODB.Error, _
adStatus As ADODB.EventStatusEnum, _
ByVal pConnection As ADODB.Connection)
' Do something when the ConnectComplete event fires
MsgBox "The ConnectComplete event fired!"
' Set the event arugments
If adStatus = adStatusOK Then
Set pError = Nothing
Set pConnection = cn
End If
End Sub
It is a best practice
to set the event's parameter values to return error information to the
caller about the execution status of this event, if there is a failure.
These types of subroutines are called event handlers and are one of the powerful features supported by both ADO and VBA.
3. Implicitly Triggering Events
The true power of creating
event handlers is that they are automatically called any time that an
event occurs for the object. That is, your code is run implicitly
whenever that event happens. For example, we can create the following
method in our class:
Public Function GetConnection() As ADODB.Connection
' Set the Connection
Set cn = New ADODB.Connection
cn.ConnectionString = CurrentProject.Connection
cn.CursorLocation = adUseClient
cn.Mode = adModeShareDenyNone
' Open the Connection - the ConnectComplete event will be fired
cn.Open
' Return the Connection
Set GetConnection = cn
End Function
Because this function opens a Connection object with the Connection member variable we created earlier, it triggers the ConnectComplete
event automatically when the connection has been established. We can
see the event being triggered by creating a subroutine to call our GetConnection method like this:
Public Sub ImplicitlyCallAdoEvent()
' Define Variables
Dim aee As New ADOEventsExample
Dim cn As New ADODB.Connection
' Call the Class to Trigger the ConnectComplete event
Set cn = aee.GetConnection
End Sub
Running this code will implicitly fire the ConnectComplete event implemented for the ADOEventExample class because the GetConnection method triggers the event.
4. Explicitly Calling Events
One other feature is the
ability to also call events explicitly. This is done exactly the same as
any other method call, and only requires the proper code access level.
Public Sub ExplicitlyCallAdoEvent()
' Define Variables
Dim aee As New ADOEventsExample
Dim cn As Adodb.Connection
Dim errors As Adodb.Error
' Call the event directly from the Class object
aee.cn_ConnectComplete errors, adStatusOK, cn
End Sub
It is a best practice to check the pError parameter of the event to ensure that no errors occurred when the event completed.
5. Testing the State Property
It is worth mentioning that the Connection and Recordset objects' State
property can be tested to determine the current status of the object,
particularly for asynchronous operations. The following code checks the
state of the Connection to see if it is open:
Public Sub CheckConnectionState()
' Define Variables
Dim cn As Adodb.Connection
' Get the connection
Set cn = CreateConnection
' Test the state
If cn.State = adStateOpen Then
MsgBox "The Connection is Open"
Else
MsgBox "The Connection in not Open yet"
End If
End Sub