VBA raising errors from within Class modules (with Class_Initialize) fails

Viewed 300

I've been trying to implement error handling in class modules so I can log if users face any bugs ,and in which module/class did it happen.

my approach is to handle error reporting in the calling sub/function and and use err.raise in called sub/function to bubble-up the error to the calling sub.

This worked okay for modules (calling modules from within a module), But when I tested for raising errors from within class modules it gave me Error # 440 Automation error instead of the actual error (like type mismatch for ex).

I boiled down the (bug?) to the fact that the Err object is not initialized for some reason after class_Initialize is run, I'm using Excel 2016; Application.Version = 16.

For Example the following module calls a class property:

Option Explicit

Private Sub TestCRef()

On Error GoTo ErrHandlr

    Dim y As New CellRef
    'Call y.SetRef  'normal behavior when Class_Initialize() is commented and this is used instead
    Debug.Print y.CstOrdrNo
    
Exit Sub
ErrHandlr:

    If Err.Source = ThisWorkbook.VBProject.Name Then
        Err.Source = "Module1.TestCRef"
    End If
    
    Dim ErrStr As String
    ErrStr = "Error # " & Str(Err.Number) & ", was generated by :" _
                    & Err.Source & ", Description : " & Err.Description
                    
    Debug.Print (ErrStr)
    
End Sub

the class module (CellRef):

Option Explicit

Public CstOrdrNo As Range
Private x As Integer
    
    
Sub Class_Initialize()

On Error GoTo ErrHandlr

    x = "Bug" 'intentional
    Set CstOrdrNo = ThisWorkbook.Worksheets(1).Range("A1")

Exit Sub
ErrHandlr:
    Err.Raise vbObjectError + 5050, "CellRef.Class_Initialize", "Error While Initializing Class"
End Sub

'Used instead of Class_Initialize
Sub SetRef()
On Error GoTo ErrHandlr

    x = "Bug" 'intentional
    Set CstOrdrNo = ThisWorkbook.Worksheets(1).Range("A1")
    
Exit Sub
ErrHandlr:
    Err.Raise vbObjectError + 5050, "CellRef.SetRef", "Error While Intializing x"
End Sub

First Case: Class_Initialize is used to set the range when called the first time, error occurs.
Expected behavior:- Error # -2147216454, was generated by :CellRef.SetRef, Description : Error While Initializing Class.
What happens:- Error # 440, was generated by :Module1.TestCRef, Description : Automation error.
Second Case: Class_Initialize is commented and SetRef is used instead
behavior: Expected behaviour.

1 Answers

As you already know Class_Initialize raises error

440: Automation error

when any error is raised directly inside it.

But nevertheless Class_Initialize can bubble any error up like any other procedure.

So I use this paradigma, where I place the code of Class_Initialize into a new procedure ClassInitialize and call it from Class_Initialize:

Private Sub Class_Initialize()
    ClassInitialize
End Sub

Private Sub ClassInitialize()
    On Error GoTo Catch

   Any code here ...

Done:
    Exit Sub

Catch:
    Err.Raise ...
End Sub

So I can raise any error I need in ClassInitialize and Class_Initialize will let it bubble up to its caller.

Adapted to your sample is looks like this:

Private Sub Class_Initialize()
    ClassInitialize
End Sub

Private Sub ClassInitialize()
    On Error GoTo ErrHandlr

    x = "Bug" 'intentional
    Set CstOrdrNo = ThisWorkbook.Worksheets(1).Range("A1")

    Exit Sub

ErrHandlr:
    Err.Raise vbObjectError + 5050, "CellRef.Class_Initialize", "Error While Initializing Class"
End Sub

Also be aware of handling runtime errors in Class_Terminate:

A runtime error in the procedure Class_Terminate of a class (no matter if raised by Err.Raise itself or not) without a local error handler leads to an uncatchable runtime error with a standard error handler message box (the behavior is the same as with event handler procedures).

So in Class_Terminate (like in event handler procedures too) always a 'local' error handler must be enabled!

And because this error handler can not bubble up errors, you have to handle runtime errors in Class_Terminate locally, at all.

Related