My application has several forms which call each other. I ran into a problem with error handling and since the project is too large to post here, I created the smallest subset of the code that still reproduces the problem. The file can be found here
Components of the problem:
raiseError - a function that simply raises an errormainForm - a form with one button - upon being clicked opens up addClientFormaddClientForm - a form which raises the error via raiseError showMainForm - a caller which shows a mainForm The code is really simple,
Module Error
Public Sub raiseError()
Call Err.Raise(2048, "errorSource", "errorDescription")
End Sub
MainForm
Private Sub cbAddClientForm_Click()
Dim xAddClientForm As New addClientForm: Call xAddClientForm.Show
End Sub
AddClientForm
Private Sub UserForm_Initialize()
Call raiseError
End Sub
Caller
Public Sub caller()
On Error GoTo ErrorHandler
Dim xMainForm As New mainForm: Call xMainForm.Show
ErrorExit:
Exit Sub
ErrorHandler:
Call MsgBox("Error appeared", vbOKOnly)
On Error Resume Next
GoTo ErrorExit
End Sub
The caller shows a mainForm and once the user clicks the button, an addClientForm is initialized which causes a call to raiseError. The problem is that ErrorHandler in caller does not catch the error! Instead, the error raised in raiseError is treated as an unhandled error! That means that an ugly messageBox comes up and shoves the user right into the code in VBEditor - this is what I want to avoid.
I fiddled around with various setups of this problem and as long as there is not a sequence of forms where one calls the other, the error handling works as expected. In the attached file, all investigations are written into different modules along with the tested hypothesis.
So the questions are
ANY help or workaround is MUCH appreciated. Daniel
I can't say for certain why this is happening. I can't quite grok it myself, but there is a bit of a work around. You can declare the ClientForm WithEvents and catch the errors there by listening for a custom OnError event that gets raised from within the ClientForm itself. Note that you can't do this for the MainForm because you can't declare a variable WithEvents inside of a module. It has to be a class.
The big downfall here is that you need to manually redirect errors in the client form to it's OnError event and then have a Event procedure for each client form that you expect to handle errors from. The other downfall is you can't "hear" events raised in the Class_Intialize event procedure.
So, all in all, you may want to consider handling any errors locally in the client form.
Module1
Public Sub caller()
Dim xMainForm As New MainForm
xMainForm.Show
End Sub
MainForm
Option Explicit
Private WithEvents xClientForm As ClientForm
Private Sub cbAddClientForm_Click()
Set xClientForm = New ClientForm
xClientForm.Show
End Sub
Private Sub xClientForm_OnError(Err As ErrObject)
MsgBox Err.Number & ": " & Err.Description & vbNewLine & Err.Source & " raised an error.", vbCritical, "Error"
End Sub
ClientForm
Option Explicit
Public Event OnError(Err As ErrObject)
Private Sub UserForm_Click()
On Error GoTo ErrHandler:
raiseError
Exit Sub
ErrHandler:
RaiseEvent OnError(Err)
End Sub
Private Sub UserForm_Initialize()
' can't raise events from initialize, they won't be "heard"
' https://stackoverflow.com/q/26589039/3198973
End Sub
Public Sub raiseError()
Err.Raise 2048, TypeName(Me), "errorDescription"
End Sub
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With