Why does Err.Description remain empty in Excel / VBA error handling? - excel

I am not able to access the error description (or error number) in Excel VBA error handling.
If I run the following code, the error description remains Empty:
Option Explicit
Sub TestError()
On Error GoTo ErrorHandler
Debug.Print 1 / 0
'Alternative: (Does not display error number either):
'Err.Raise 10000, , "Some error description"
ErrorExit:
Exit Sub
ErrorHandler:
On Error Resume Next
MsgBox Err.Description
Resume ErrorExit
End Sub
If I replace the Debug.Print 1 / 0 with an Err.Raise statement, the description remains empty as well.
However, if I remove the On Error GoTo ErrorHandler, the description and error number is shown as expected.
What am I doing wrong? Is there any other way to access the error description? Thank you!

The only problem here, is the presence of an On Error statement inside the error-handling subroutine: when that code runs, it's too late to tell VBA what to do "on error": it's here because there was an error.
Just remove the On Error Resume Next line, and you're good to go!
However, if I remove the On Error GoTo ErrorHandler, the description and error number is shown as expected.
What you're seeing is an unhandled runtime error, not the MsgBox you're expecting.

Related

how to get error detail in VBA programming?

How can I get error details like line number, error message in VBA.
It displays simple message like "Compile error", but does not show detail and line number of error.
How can I get error details like line number, error message in VBA.
Compile error will not let you compile the code and will directly take you to the line which has the error. For other runtime errors, you need to add line numbers to your code and then use ERL to get the line number. For example
Option Explicit
Sub Sample()
Dim i As Long
10 On Error GoTo Whoa
20 i = "Sid"
30 Debug.Print i
Whoa:
40 MsgBox Err.Description & ". Error on line " & Erl
End Sub
Tip: I use MZ-Tools which helps in inserting/removing line numbers. I think (I am not sure) rubberduck also does that.
If your VBA code doesn't contain line numbers, then VBA can not show it.
Purpose of displaying line number is to trace and resolve an error which you can handle using:
On Error GoTo ErrHandler
And then Error Handler Block
ErrHandler:
Refer this.
Compile error is different than runtime error.
The compile error will not let the application build and run and the line of code which causes the error is highlighted. On the other hand, runtime error is when the application runs but something unexpected happens which raises an error, a division by zero for exampe.
Once you have sorted out the compile error and the app runs, you can handle rutime errors like this:
Option Explicit
Sub Something()
On Error GoTo Trap
'your code here
Leave:
On Error GoTo 0
Exit Sub
Trap:
MsgBox Err.Number & " - " & Err.Description, vbCritical
Resume Leave
End Sub

Excel VBA run time error is raised by the IDE while there is an error handler set

I have a weird error reported by a user of a VBA based application
and I wonder how this just possible that an error is raised by the VBA IDE considreing the line above is an error handler.
The code is the following. It creates a form of class frmCfgPrjctTm. I used to have some automation errors once in a while with weird message from the VBA IDE.
Run-time error '-2147418105 (800100007)':
Automation error
The object invoked has disconnected from its clients.
I use Excel 2016 32 bits on windows 7.
To work around the problem I had to implement a retry strategy to create the form. This explains the retry loop.
The error is raised on line mForm.Show vbModeless.
The error handler is set with instruction On Error GoTo ErrorHandler the line just before!
Private mForm As frmCfgPrjctTm
''
' U_CfgPrjctTm_OnOpen
Public Sub U_CfgPrjctTm_OnOpen()
Dim iRetry As Integer
iRetry = 0
If (mForm Is Nothing) Then
ErrorExit:
If (iRetry > 1) Then
Call U_UnlockTeam
GoTo ExitSub
End If
iRetry = iRetry + 1
Set mForm = New frmCfgPrjctTm
End If
On Error GoTo ErrorHandler
'>>>>>> the error occurs after this comment
mForm.Show vbModeless
ExitSub:
Exit Sub
ErrorHandler:
Debug.Print "***** Error trapped in U_CfgPrjctTm_OnOpen *****"
GoTo ErrorExit
End Sub
this post raises 2 questions but I am seeking for help or sharing for the following :
why an error is raised by the IDE while there is an error handler set ?
The answer to your question "why an error is raised by the IDE while there is an error handler set ?" is that you use error handling in a wrong way. Look at the following example
Option Explicit
Sub TestErrH()
Dim i As Long
i = 42
ErrorExit:
On Error GoTo ErrorHandler
Debug.Print 42 / i
Debug.Print 1 / 0
Exit Sub
ErrorHandler:
i = 0
GoTo ErrorExit
End Sub
The error handler will raise in the line Debug.print 1/0 and then the error handler will set i = 0 and jump back to the line debug.print 42/i. At that time the error handling is in your hands. You have to make sure the code is fail safe. The error handler will not again jump to the label ErrorHandler instead a run time error will pop up.

VBA Change error handling method during code execution

I have a macro, and part of the code is concerned with:
1) detecting if a column contains empty cells - if so filling them with some value
2) detecting if a column contains cells containing errors (such as N/A) and if so filling them with some value
Now if there are no error/empty cells in the column, the line that finds them gives a "Run-time error 1004 no cells were found".
I use error handling to skip this with GoTo.
Below is the code - the first error handling GoTo works perfectly, while the second gives the expected error, although there is Error handling GoTo set, that does not seem to work. Code with comments:
On Error GoTo EErrorOne
'depending on file I get, below line will generate error and code successfully skips to ErrorOne label
Workbooks(nazwawb).Sheets(szitnr).Columns(ktorepole).SpecialCells (xlCellTypeBlanks)
' code to be skipped
Workbooks(nazwawb).Sheets(szitnr).Columns(ktorepole).Select
Selection.SpecialCells(xlCellTypeBlanks).Select
Selection.Value = "Some Value"
' end of code to be skipped
EErrorOne:
' successfully skipped error line by now. Below line should set a new Error handling procedure.
On Error GoTo EErrorTwo
Workbooks(nazwawb).Sheets(szitnr).Columns(ktorepole).Select
' Below line generates an error but does not skip to EErrorTwo label as detailed in the current Error handling procedure
Selection.SpecialCells(xlCellTypeFormulas, 16).Select
' code to be skipped
Selection.SpecialCells(xlCellTypeFormulas, 16).Select
Selection.Value = "Some Value"
' end of code to be skipped
EErrorTwo:
' Below line should reset error handling procedure to normal for subsequent handling of other errors:
On Error GoTo 0
It seems that error handling procedure (GoTo specific label) is ignored, and instead, an error message is shown as if the error handling was reset to GoTo 0. How do I skip the second error?
You're not clearing your errors when they occur, just trying to jump over them and the code is wondering what's going on with the error.
As Chip Pearson says on his site:
When the first error is raised, execution transfers to the line
following Err1:. The error hander is still active when the second
error occurs, and therefore the second error is not trapped by the On
Error statement
and continues with
The Resume statement instructs VBA to resume execution at a specified
point in the code. You can use Resume only in an error handling
block; any other use will cause an error. Moreover, Resume is the only
way, aside from exiting the procedure, to get out of an error handling
block. Do not use the Goto statement to direct code execution out of
an error handling block. Doing so will cause strange problems with
the error handlers.
http://www.cpearson.com/excel/errorhandling.htm
The ideal way is to avoid the error in the first place - check the workbook exists before opening it, check the sheet exists in the workbook before trying to reference it and if an error occurs jump out of the main body of the routine, deal with the error and then jump back in again.
As an example:
Sub Test()
On Error GoTo ERR_HANDLE
'.... code ....
FAST_EXIT:
'Code to tidy up, clear references etc before finishing.
Exit Sub
ERR_HANDLE:
Select Case Err.Number
Case 1004
'Code to resolve error
'.
'.
'Resume - clear error, jump back to line that caused it.
'Resume Next - clear error, jump to line after the one that caused error.
'Resume FAST_EXIT - clear error and go to line label.
Case 92 'Do something else to resolve error.
Case Else
End Select
End Sub
Inside error handling routines, it seems as though defining new error handling routines won't work, unless you clear the previously set error routine (https://excelmacromastery.com/vba-error-handling/):
'...
EErrorOne:
On Error GoTo -1 'Clears error trap flag
On Error GoTo EErrorTwo 'Reset error handling
'...
Edit after accepted:
As was discussed in the comments, On Error GoTo -1 clears the error trap flag, while Err.Clear only clears the error.
The code below illustrates this by creating two errors and trying to trap them.
On Error Goto -1 allows the second error to be trapped by the On Error GoTo NextLabel line and the code jumps to the label when the error occurs.
Err.Clear keeps the first error live, so when the second error occurs the error message is displayed rather than the code jumping to the label.
Sub ClearErr()
Dim x As Long
Dim y As Worksheet
'Jump to label when "Division by 0" occurs.
On Error GoTo ErrorLabel
x = 1 / 0
Debug.Print x
ErrorLabel:
'On Error GoTo -1 'Next error is trapped.
Err.Clear 'Untrapped error on y=Worksheets(1)
'Jump to label when "Object Variable not set" occurs.
On Error GoTo NextLabel
y = Worksheets(1)
Debug.Print y.Name
NextLabel:
End Sub

Not able to handle runtime error 9 with on error go to [label]

I have the followin code. But the error does not get handled
Sub Some_sub()
Some code here
On Error GoTo resumeCode
If Workbooks("Some file.xlsm").ReadOnly Then
GoTo readOnlyError
End If
resumeCode:
On Error GoTo fileNotOpen
Workbooks("Some file.xlsm").Activate
some more code here
Exit Sub
fileNotOpen:
MsgBox "Error: Claims followup.xlsm is not open." & Chr(10) & Chr(10) &
"Open the file in read/write"
Exit Sub
End Sub
When I run debug mode it shows me this line: Workbooks("Some file.xlsm").Activate in yellow. Instead of handling the error and going to the label.
Within VBA under Tools -> Options -> General Tab: Break on Unhandled Errors active.
When I have the file open it runs the code like it should. When it is closed it does not handle the error.
What am I doing wrong?
Thanks in advance for your help
That's it. As I said in the comments, when an error occurs, and you handle it, you cannot setup a new On Error mechanism until you explicitly invoke the Resume keyword in any way.
One possible way to achieve it, if you dont want to change the flow of your routine, is just to add a label before your new On Error statement and Resume on it. Like this, for example:
Sub Some_sub()
' Some code ...
On Error GoTo resumeCode
If Workbooks("Some file.xlsm").ReadOnly Then
GoTo readOnlyError
End If
' Some more code ...
resumeCode:
Resume ResumeHere ' <---------------------------------------- Invoke Resume
ResumeHere: ' <------------------------------------- Add some label
On Error GoTo fileNotOpen
Workbooks("Some file.xlsm").Activate
Exit Sub
fileNotOpen:
msgBox "Error: Claims followup.xlsm is not open." & Chr(10) & Chr(10) & "Open the file in read/write"
Exit Sub
End Sub
You should be careful though, the keyword Resume will itself raise an error if the error status is blank and it is reached from normal flow, In that case you should put the error handling sections, each apart, in the end of your routine and resume at any labels within the normal flow from there. This is generally the usual approach.

VBA Nested On Error GoTo

I have VBA code that is supposed to be nested error checking, but it does not. The code is psuedo as below. However, whenever an error occurs within an error (For instance, an error is tripped in the loop, goto SmallError occurs, and an error occurs in SmallError) The second GoTo is not used. The error then breaks the code.
Ex:
Error in Loop
GoTo SmallError
Error in SmallError
Code Breaks (Here code should GoTo FatalError)
Sub DoThings()
On Error GoTo SmallError
'Coding Happens
Do While(conditionhere)
'Looping things happen
GoTo LoopResume
SmallError:
source = Err.source
descript = Err.Description
On Error GoTo Fatal Error
'Small error processing happens
Resume LoopResume
FatalError:
source = Err.source
descript = Err. Description
On Error GoTo ExitError
'Fatal Error processing happens
ExitError:
Exit Sub
LoopResume:
count = count + 1
Loop
On Error GoTo FatalError
'Finishing code happens
End Sub
You can't use an On Error statement within an error handler. See e.g. this article that explains this.
What you CAN do however is to have a separate routine that handles the "regular error". This routine can have a "fatal error" handler. Your code would then look something like this:
(Edit: Edited the code to enable exit when there is a fatal error):
Sub DoThings()
On Error GoTo SmallError
Dim fatalExit As Boolean
'Coding Happens
Do While(conditionhere)
'Looping things happen
LoopResume:
count = count + 1
Loop
On Error Goto SmallError2
'Finishing code happens
Exit Sub
SmallError:
handleError Err.Source, Err.Description, fatalExit
If fatalExit Then
Exit Sub
Else
Resume LoopResume
End If
SmallError2:
handleError Err.Source, Err.Description, fatalExit
Exit Sub
End Sub
Private Sub handleError(ByVal source As String,ByVal description As String, ByRef fatalExit As Boolean)
On Error Goto FatalError
'Do "small error" handling here
Exit Sub
FatalError:
fatalExit = True
'Do "fatal error" handling here
End Sub
... you have Fatal Error in your Goto rather than FatalError, that won't get you to the right location...
Update your code to:
On Error GoTo FatalError

Resources