Reputation:
I am in Excel 2010 and I seem to be getting a strange rather unexpected behaviour working with custom events.
I am like 99% sure this approach has worked for me a few years ago (maybe it was in Excel 03/07 - can't remember) or maybe I've just messed something up...
Here's a repro:
Add a new class module and name it Factory
Public Event AfterInitialize()
Private Sub Class_Initialize()
RaiseEvent AfterInitialize
End Sub
Add another class module and name is FactoryTest
Private WithEvents cFactory As Factory
Private Sub Class_Initialize()
Set cFactory = New Factory
End Sub
Private Sub cFactory_AfterInitialize()
Debug.Print "after inialized..."
End Sub
and a standard Module1
and run the below
Sub Main()
Dim fTest As FactoryTest
Set fTest = New FactoryTest
End Sub
At this point I expected to see after initialized..
in the Immediate Window but I don't...
Stepping-through the code it seems that the Private Sub cFactory_AfterInitialize()
is never reached...
Note:
I can add a public sub: RaiseAfterInitialize()
to the Factory
class and then call that explicitly in the Initialize()
event in the FactoryTest
like cFactory.RaiseAfterInitialize()
so that could be a possible work around but what I am really trying to understand is why it doesn't work the original way showed above?
There isn't much on VBA events on MSDN
Can anyone point out what I am doing wrong?
Upvotes: 12
Views: 1794
Reputation: 6120
Based on the VBA Language Specification section 5.3.1.10 Lifecycle Handler Declarations, I would guess this is the reason (emphasis mine):
If a class defines a Class_Initialize lifecycle handler, that subroutine will be invoked as an method each time an instance of that class is created by the New operator, by referencing a variable that was declared with an
<as-auto-object>
and whose current value is Nothing, or by call the CreateObject function (section 6.1.2.8.1.4) of the VBA Standard Library. The target object of the invocation is the newly created object. The invocation occurs before a reference to the newly created object is returned from the operations that creates it.
So in your case, in the line
Set cFactory = New Factory
The Class_Initialize
method of Factory
is run before the assignment is made, which means while the event IS raised, the FactoryTest
class instance doesn't know about it.
UPDATE
I gave it a quick test by adding a method to Factory
which calls the Class_Initialize
function:
Public Sub test()
Class_Initialize
End Sub
And then added a call to it as part of the FactoryTest.Class_Initialize
method:
Private Sub Class_Initialize()
Set cFactory = New Factory
cFactory.test
End Sub
Since the call to the method test
takes place after the New Factory
has been assigned to cFactory
, the "after initialized..." message displays as expected.
Upvotes: 16