To be honest, for a long time I was lazy to dig deeper and also did not find any other "real" use for VBA Events, except these common Events for Excel workbook objects. I think this is not anything uncommon. If you use Google to find some practical examples, you will find a lot of examples, but they are almost always some examples with VBA User Forms. Anyway, at some point I was doing some semi-serious woodshedding with Observer Design Pattern and started to think about Events again. I started to study these a bit deeper and found out one pretty nice thing: I could create my own Events and use those in my classes. This current post is a result of that discovery.
In this post, I am opening up one possible Observer Design Pattern implementation with VBA Event mechanism. Remember to check my previous post on doing the same thing without VBA Events http://mikejuniperhill.blogspot.fi/2013/05/implementing-observer-design-pattern-in.html
First we create data source class (VBA Class Module, name = DataSource):
Option Explicit ' Public Event dataFeedUpdate(ByVal marketData As Double) ' Public Function getMarketDataUpdate(ByVal marketData As Double) ' RaiseEvent dataFeedUpdate(marketData) End Function '
Then we create class for all "observers" (VBA Class Module, name = DataObserver):
Option Explicit ' Private WithEvents source As DataSource ' Public Function registerPublisher(ByRef dataFeed As DataSource) ' Set source = dataFeed Debug.Print "Observer " & ObjPtr(Me) & " registered data feed" End Function ' Public Function unRegisterPublisher() ' Set source = Nothing Debug.Print "Observer " & ObjPtr(Me) & " unregistered data feed" End Function ' Private Sub source_dataFeedUpdate(ByVal marketData As Double) ' Debug.Print "Market data update from observer " & ObjPtr(Me) & ": " & marketData End Sub '
Then again, we create one tester program (VBA Standard Module). In tester program, I have been creating one test run, in which observers are registering/unregistering data source, which is sending data feed updates for observers:
Option Explicit ' Public Sub tester() ' ' create data source object and two observers Dim source As New DataSource Dim observer1 As New DataObserver Dim observer2 As New DataObserver ' ' register datafeed publisher for both observers observer1.registerPublisher source observer2.registerPublisher source ' ' send data feed source.getMarketDataUpdate 100.25 source.getMarketDataUpdate 100.15 ' ' observer2 unregistering, send data feed observer2.unRegisterPublisher source.getMarketDataUpdate 100.1 ' ' observer1 unregistering, send data feed observer1.unRegisterPublisher source.getMarketDataUpdate 100.1 ' ' observer1 re-registering, send data feed observer1.registerPublisher source source.getMarketDataUpdate 100.2 ' ' observer2 re-registering, send data feed observer2.registerPublisher source source.getMarketDataUpdate 100.25 ' ' destroy datafeed and both observers Set observer2 = Nothing Set observer1 = Nothing Set source = Nothing End Sub '
Resulting Immediate Window printout (observer1 in blue, observer2 in red):
Observer 237412240 registered data feed
Observer 237411920 registered data feed
Market data update from observer 237412240: 100,25
Market data update from observer 237411920: 100,25
Market data update from observer 237412240: 100,15
Market data update from observer 237411920: 100,15
Observer 237411920 unregistered data feed
Market data update from observer 237412240: 100,1
Observer 237412240 unregistered data feed
Observer 237412240 registered data feed
Market data update from observer 237412240: 100,2
Observer 237411920 registered data feed
Market data update from observer 237412240: 100,25
Market data update from observer 237411920: 100,25
One more thing: when you create your custom event, the object (DataObserver) in which the Event-related function is going to be called, must have reference to its caller (DataSource). Otherwise calling object (DataSource) do not know, what object it should call. I am doing that "binding" in registerPublisher function. This issue was actually causing a lot of grey hairs for me, until I got the point.
This was another possible implementation of Observer DP in VBA by using Event mechanism. Nice to know also. Have a nice weekend!
-Mike