Programming Microsoft Access 2000 (Microsoft Programming Series)
You can use VBA in Access to create classes for instantiating objects, but VBA objects cannot initiate their own events. However, you can build classes around type libraries and ActiveX controls that propagate their events to a host environment. For objects that propagate events, your VBA application can wrap code around events that occur within the class. When a host procedure for an instance of a class launches a method that causes the firing of a propagating event from inside the class, the event procedure works its way to the host for the class module. (See Figure 7-4.)
The References collection relates hierarchically to the Application object. You invoke the AddFromFile and Remove methods to enable an application to programmatically add and delete references to type libraries. These library files contain standard descriptions of exposed objects, methods, properties, and events. Recall that the ADODB object model is dependent on a library. You can add references to it and other libraries manually or programmatically.
Figure 7-4. The WithEvents keyword propagates an object's event procedures to the object's host when an event fires.
Chapter 2 explains how to add references manually to the three ADO libraries. The following section will explain how to add references programmatically to any library or ActiveX control. You can issue a confirmation message when your application finishes adding or removing a reference.
Two Built-In Class Events
Class modules have two built-in events: Initialize and Terminate. The Initialize event occurs when you create a new instance of a class module. You create a shell for the Initialize event procedure by selecting Class from the class's Object box and Initialize from the Procedure box. You can do anything necessary in an Initialize event procedure to prepare your class instance for use.
In the Terminate event procedure, you should clean up after your current application. This can be as simple as setting an object reference to Nothing. The Initialize and Terminate events occur just once at the beginning and end of the life of a class instance. Therefore, they are not particularly handy for generating interactive or dynamic behavior at any times other than the birth and death of the instance of a class.
Using the WithEvents Keyword to Trap Propagated Events
The following class module uses the WithEvents keyword to trap events propagated by the References collection. The References collection has a separate item for each checked item in the References dialog box. The ItemAdded and ItemRemoved events occur only when your code adds or removes references. If a user manually modifies the References collection, these events do not fire.
Option Compare Database 'Declare object variable to represent References collection. Public WithEvents evtReferences As References 'When instance of class is created, initialize evtReferences 'variable. Private Sub Class_Initialize() Set evtReferences = Application.References End Sub 'When instance is removed, set evtReferences to Nothing. Private Sub Class_Terminate() Set evtReferences = Nothing End Sub 'Display message when reference is added. Private Sub evtReferences_ItemAdded(ByVal Reference As _ Access.Reference) MsgBox "Reference to " & Reference.Name & " added.", _ vbInformation, "Programming Microsoft Access 2000" End Sub 'Display message when reference is removed. Private Sub evtReferences_ItemRemoved(ByVal Reference As _ Access.Reference) MsgBox "Reference to " & Reference.Name & " removed.", _ vbInformation, "Programming Microsoft Access 2000" End Sub |
Starting and ending a WithEvents reference
You use the WithEvents keyword in combination with a class that propagates events. The Public statement in the class module above declares a reference (evtReferences) to the References collection in the Access application object. The WithEvents keyword within the statement enables the class module to trap events propagated by the References collection. The Class_Initialize event procedure sets a reference. Recall that you cannot use the New keyword for a reference that you declare with WithEvents.
Wrapping code around captured events
Two event procedures in the class module, ItemAdded and ItemRemoved, invoke message block statements. These show messages naming the reference that a method adds or removes. The event procedures show the syntax for wrapping custom code around objects that propagate events. In this case, the object is the References collection. The event procedures merely write out the name of the library being added to or removed from the References collection.
Standard Modules Cause Events
As with any class module, you need one or more procedures in a standard module to instantiate the class (see the sample below) and to invoke methods, assign property values, or read property values. In the declarations area of the module hosting the class, you include a Dim or Public statement with the New keyword and the class name. This instantiates the class and sets an object reference (objRefEvents in the sample).
Standard module syntax for events
If the instance of the class propagates events from an embedded object, you should use a Public statement with the WithEvents keyword. This statement exposes the events to other modules referencing the class. When you invoke the methods from the underlying class, you must traverse the local object reference (objRefEvents), the reference within the class module exposing the events (evtReferences), and then a specific method name, such as AddFromFile or Remove. Unlike a normal reference to a class module, this one points to a method for the source object in the WithEvents declaration.
'Create new instance of RefEvents class. Dim objRefEvents As New RefEvents Sub InvokeAddReference() 'Pass file name and path of type library to AddReference procedure. AddReference _ "C:\Program Files\Common Files\System\ado\msjro.dll" End Sub Sub InvokeRemoveReference() 'Pass name of existing reference. (Use internal name from File 'Properties list; same name appears when adding reference.) RemoveReference "JRO" End Sub Sub AddReference(strFileName As String) objRefEvents.evtReferences.AddFromFile (strFileName) End Sub Sub RemoveReference(strRefName As String) objRefEvents.evtReferences.Remove _ objRefEvents.evtReferences(strRefName) End Sub |
The sample above adds a reference to the library holding the JRO model. (This model enables Jet replication via ADO.) You run the InvokeAddReference procedure to create the reference. The procedure calls a procedure, AddReference, with the syntax for adding an item to the References collection via the RefEvents class module. The library holding the JRO model is a dynamic link library (DLL) that typically resides in the ADO folder of the System folder in the Common Files directory of the Program Files directory. Launching the InvokeRemoveReference procedure eliminates the JRO item from the References collection. The JRO designation is the Name property for the item in the References collection.
NOTE
To discover the arguments for the AddFromFile and Remove methods, you add references manually. Then you enumerate the items in the References collection with a For...Each statement while listing their Name and FullPath properties. You use these property values to uniquely identify arguments for the AddFromFile and Remove methods.
Extending the application
You can easily adapt the RefEvents class by using the AddReference and RemoveReference procedures to accommodate a broader and more flexible selection process. For example, your application can derive the input to the AddReference procedure from a collection of type libraries, executables, ActiveX controls, and even database files. A combo box can offer users a list of references to add or remove. Alternatively, your procedure can make a selection from a list based on other factors, such as what a user is trying to accomplish.