sancarn / stdVBA

VBA Standard Library - A Collection of libraries to form a common standard layer for modern VBA applications.
MIT License
288 stars 60 forks source link

Odd VBA bug littered throughout stdVBA which destroys error handling #61

Closed sancarn closed 1 year ago

sancarn commented 1 year ago

This works as expected:

Public Property Get Test() As String
  On Error GoTo CannotQuery
    Call B
    Test = "Not ok"
    Exit Property
CannotQuery:
  Test = "OK"
End Property
Public Sub B()
  Err.Raise 1, "stdCOM", "IUnknown::QueryInterface - Interface not implemented."
End Sub

This does not:

Public Property Get Test() As String
  On Error GoTo CannotQuery
    Call Me.B
    Test = "Not ok"
    Exit Property
CannotQuery:
  Test = "OK"
End Property
Public Sub B()
  Err.Raise 1, "stdCOM", "IUnknown::QueryInterface - Interface not implemented."
End Sub

As shown in the following video:

https://user-images.githubusercontent.com/7938900/190852355-7ed2abd3-e49a-4024-8dbb-f2c127e4d49c.mp4

Additionally, Me. error handling fails in both these cases too:

Public Property Get Test() As String
  On Error GoTo CannotQuery
    Call Me.A
    Test = "Not ok"
    Exit Property
CannotQuery:
  Test = "OK"
End Property

Public Sub A()
  Call B
End Sub

Public Sub B()
  Err.Raise 1, "stdCOM", "IUnknown::QueryInterface - Interface not implemented."
End Sub

and

Public Property Get Test() As String
  On Error GoTo CannotQuery
    Call A
    Test = "Not ok"
    Exit Property
CannotQuery:
  Test = "OK"
End Property

Public Sub A()
  Call Me.B
End Sub

Public Sub B()
  Err.Raise 1, "stdCOM", "IUnknown::QueryInterface - Interface not implemented."
End Sub

Finally you can't get around this using With Me ... End With.

Ultimately using Me. anywhere in the call stack can cause major issues when it comes to error handling, and thus it must be purged.

You can get around this using CallByName(Me, propName, vbGet) but this seems a little overkill.

sancarn commented 1 year ago

@RetailCoder Don't suppose you know a way around this?

I always included Me. as it declares intent and looks less like you're accessing a variable which isn't defined...

retailcoder commented 1 year ago

Hey, thanks for the ping! I couldn't reproduce this behavior without setting VBIDE general options to "Break on all errors"; with or without a Me qualifier prints "OK" here (hosted in current/latest Excel 365 x64), with or without the explicit Call keyword.

sancarn commented 1 year ago

Hey, thanks for the ping! I couldn't reproduce this behavior without setting VBIDE general options to "Break on all errors"; with or without a Me qualifier prints "OK" here (hosted in current/latest Excel 365 x64), with or without the explicit Call keyword.

Hmm, that is really strange... I have Break in Class Module selected while running this. tested in both Excel 2019 64-bit and Excel 365 32-bit; with the same results as above...

However don't get that behaviour when having Break on Unhandled Errors selected, is this what you have selected by default? That could explain it...

retailcoder commented 1 year ago

However don't get that behaviour when having Break on Unhandled Errors selected, is this what you have selected by default? That could explain it...

Indeed, that's what the default is, or should be anyway! Typically you'd switch it to something else to debug error-handling and break deeper in the stack than where you'd normally handle it... and then inevitably forget to set it back to "unhandled errors"!

sancarn commented 1 year ago

I see, that is at least one way around this issue anyhow... Though not very satisfying haha. I think for now I'll replace all x=Me.Whatever with x=Whatever(), at least that's somewhat more self explanatory than x=whatever