'Why do we need to use vbObjectError constant when raising user-defined errors in VBA? [duplicate]
Microsoft Visual Basic for Applications 7.1; Version 1088
I created a custom error handler by following online tutorials and I've been using it for about a year now but I still don't get the part where vbObjectError
constant is added to a number between 513-65535, which is reserved for user-defined errors. Most tutorials would recommend to use Err.Raise vbOjectError + 1000
as an example to generate custom errors. The reason for this is to avoid overlapping with errors 0-512, which is reserved for system errors. If I have to write a code around that idea, the code would look like this:
Option Explicit
Sub raiseError()
On Error GoTo errorHandler
Dim x As Double
Dim y As Double
Let x = 4.8
Let y = 5.5
If x <> y Then
Err.Raise vbObjectError + 1000
End If
errorHandler:
Select Case Err.Number
Case vbEmpty
MsgBox "alright!"
Case vbObjectError + 1000
MsgBox ("User-defined error '" & Err.Number & "':" & _
vbNewLine & _
vbNewLine & _
"X is not equal to Y")
Case Is <> vbObjectError + 1000
MsgBox "All other errors"
End Select
End Sub
Now, quoting Microsoft from this documentation:
"Visual Basic errors (both Visual Basic-defined and user-defined errors) are in the range 0–65535. The range 0–512 is reserved for system errors; the range 513–65535 is available for user-defined errors.
When setting the Number property to your own error code in a class module, you add your error code number to the vbObjectError constant. For example, to generate the error number 513, assign vbObjectError + 513 to the Number property."
But what confuses me is vbObjectError
constant has a value of -2147221504
. As you can see if you run the code, the sum of vbObjectError
and 1000
or any number between 513–65535
is far from the range 513–65535, which is available for user-defined errors according to Microsoft.
If I need to use error numbers in the range of 513–65535
, why not use those numbers directly like Err.Raise 513
or Err.Raise 1000
?
I'd really appreciate any clarifications from you guys. Thank you all very much.
Solution 1:[1]
I finally found a good answer to this question. The Microsoft documentation for Err.Number explains it well and provides this example:
' Using Number property with an error from an
' Automation object
Dim MyError, Msg
' First, strip off the constant added by the object to indicate one
' of its own errors.
MyError = Err.Number - vbObjectError
' If you subtract the vbObjectError constant, and the number is still
' in the range 0-65,535, it is an object-defined error code.
If MyError > 0 And MyError < 65535 Then
Msg = "The object you accessed assigned this number to the error: " _
& MyError & ". The originator of the error was: " _
& Err.Source & ". Press F1 to see originator's Help topic."
' Otherwise it is a Visual Basic error number.
Else
Msg = "This error (# " & Err.Number & ") is a Visual Basic error" & _
" number. Press Help button or F1 for the Visual Basic Help" _
& " topic for this error."
End If
MsgBox Msg, , "Object Error", Err.HelpFile, Err.HelpContext
The key is that you are expected to subtract the large negative number from Err.Number and do your Select Case
on the result. 0 - 65535 means the error was generated by Err.Raise
.
Solution 2:[2]
As nobody answered, I'll hazard a (hopefully educated) guess. The "error numbers" generated aren't really those between 0 and 65535 (2^16-1). Those numbers are error offsets that create a negative error code.
For example, in Access, you'll often see positive error numbers (like 3146 if you can't connect to a DAO workspace). I wouldn't call those "user errors", but they are out of the "system error" range.
Also, if the true error numbers couldn't be larger than 65535 (the largest signed 16-bit number), you wouldn't need a Long type to hold them.
Finally, if you've ever noticed some error codes displayed by Microsoft products, you'll see hex codes like "8xxxxxxx", which are large negative numbers in signed decimal, as if they added vbObjectError to their own internal error numbers.
So your error messages between 513 and 65535 are really convenient numbers for you to use to create error codes by adding to vbObjectError. I suppose it also makes it easier to create a type that stores error information (error number, Description, Help ID, etc.) and create an array of those types. For example, Errors(0) would return the type with error number 513 and other information that you might need in your ERR.Raise statement.
But why is vbObjectError equal to -2147221504? I don't know. That's not -(2^31) + 512. In hex, it's FFFFFFFF80040000. I guess you'll have to ask Microsoft about that one.
For more information, here's another site's thoughts on this: http://www.vbforums.com/showthread.php?570075-vbObjectError-what-is-it-for
Solution 3:[3]
It's better and more secure use vbObjectError + 1001 based on this Microsoft article, Trappable errors, where it is said:
Unused error numbers in the range 1–1000 are reserved for future use by Visual Basic.
I was using vbObjectError + 513 a lot in my Enums definitions inside Interfaces for controling errors in the Classes that implement that interfaces but on one ocassion I've got an ambiguous name error while I was trying to use a second element from an Enum where the first element were equal to vbObjectError + 513.
Public Enum WorkbookXErrors
InvalidExtension = vbObjectError + 513
CannotCreateObject '***I got an error trying to use this Enum element.***
End Enum
Solution: I only changed to InvalidExtension = vbObjectError + 1001 and since then everything it's ok.
Greetings,
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | nunzabar |
Solution 2 | Pony99CA |
Solution 3 | kennyk4silva |