47

Can anyone find the difference between 'On error goto -1' and 'on error goto 0' in VBA? I've tried google and msdn, but I've had no luck.

sterlingalston
  • 655
  • 1
  • 6
  • 6
  • This [documentation](http://msdn.microsoft.com/en-us/library/5hsw66as%28v=vs.80%29.aspx) is for Visual Basic, not VBA, but the concepts are similar enough in this case that it should explain the difference. – vcsjones Jan 04 '13 at 14:30

3 Answers3

71

On Error GoTo 0 disables any error trapping currently present in the procedure.

On Error GoTo -1 clears the error handling and sets it to nothing which allows you to create another error trap.

Example: On Error GoTo -1

After the first error is raised, it will GoTo ErrorFound which will then clear the routine's error handling and set a new one, which will GoTo AnotherErrorFound when an error is found.

Sub OnErrorGotoMinusOneTest()

    On Error GoTo ErrorFound

    Err.Raise Number:=9999, Description:="Forced Error"

    Exit Sub

ErrorFound:

    On Error GoTo -1 'Clear the current error handling
    On Error GoTo AnotherErrorFound 'Set a new one
    Err.Raise Number:=10000, Description:="Another Forced Error"

AnotherErrorFound:

    'Code here

End Sub

Example: On Error GoTo 0

After the first error is raised, you will receive the error as error handling has been disabled.

Sub OnErrorGotoZeroTest()

    On Error GoTo 0

    Err.Raise Number:=9999, Description:="Forced Error"

End Sub
Francis Dean
  • 2,386
  • 2
  • 22
  • 29
  • 7
    +1, good explanation. It is interesting to point out that ONLY `On Error Goto -1` will allow further error trapping within error trapping. Infact, even `On Error Resume Next` will still result in an untrapped error that halts operation. – Daniel Jan 04 '13 at 15:32
  • 1
    Thank you both so much, @Francis Dean and Daniel Cook. I've ended up using this in my code a long time ago, but never knew why I could get it to work after Goto -1. – sterlingalston Jan 04 '13 at 17:27
  • 2
    Interesting, thanks for the explanation. Is there any difference between `On Error Goto -1` and `Err.Clear`? – Peter Albert Jan 04 '13 at 18:36
  • 2
    @DanielCook Actually according to: http://www.cpearson.com/excel/errorhandling.htm#Resume you can use `Resume`, `Resume Next` or `Resume – D_Bester Jun 23 '15 at 04:16
  • @FrancisDean Actually `Err.clear` doesn't actually exit the error handling block and you can not functionally assign another error handler without using `Resume`, `Resume Next`, `Resume – D_Bester Jun 23 '15 at 04:19
  • 2
    ergh. VBA will let you define a numbered line/label as `&hFFFFFFFF` which the VBE resolves/autocorrects to `-1`. In that case, `On Error Goto -1` actually goes to the line numbered with `-1` – ThunderFrame Sep 20 '16 at 00:08
24

This answer addresses the confusion between the error object and the error handler.

The error object can be cleared using Err.Clear. This does not affect the error handler.

The error handler becomes enabled by using On Error Goto <label>. It becomes active when an error occurs.

While the error handler is active, you can not assign a new error handler. On Error Goto <label> will have no effect. VBA simply ignores the attempt to assign a new error handler.

Using Err.Clear does not cancel the error handler.

Jumping to a different place in the code using Goto <label> does not cancel the error handler. Using Goto <label> in an error handling block can cause confusion and should be avoided. You might think the error handler is no longer active when in fact it is still active.

The effect of an active error handler is that you can not assign a new error handler. On Error Goto <label> will have no effect. VBA simply ignores the attempt to assign a new error handler. Any additional errors will be unhandled while the error handler is active.

The only way to exit an active error handler is:

  1. Resume
  2. Resume Next
  3. Resume <label>
  4. On error goto -1
  5. exit the procedure

Using any one of these ways to exit the error handler will also clear the error object.

Excellent source: Pearson Error Handling In VBA Chip Pearson doesn't mention On error goto -1 in his article. To quote him:

I deliberately did not include On Error GoTo -1 because it serves no real purpose and can lock up the entire Excel application unless used in exactly the right way. Yes, On Error GoTo -1 is syntactically valid, but it is like giving a gun to drunk teenager. Nothing good will come from it.

You can also handle errors inline without using an error handler using the error object: MSDN Inline Error Handling

Community
  • 1
  • 1
D_Bester
  • 5,723
  • 5
  • 35
  • 77
  • Visual Basic calls the Clear method automatically whenever it executes any type of Resume statement, Exit Sub, Exit Function, Exit Property, or any On Error statement. There is no difference between Err.Clear and On Error GoTo -1 in that they both clear any raised exception. Ie Err object becomes nothing. – HarveyFrench Jun 23 '15 at 08:24
  • 3
    @HarveyFrench The difference between `Err.Clear` and `On Error GoTo -1` is that the first does not exit (reset) the error handler but the second does. Only after exiting (resetting) the error handler can you enable another error handler. – D_Bester Jun 23 '15 at 17:21
  • @HarveyFrench `On Error GoTo -1` is equivalent to `Err.Clear` followed by a `Resume ...` statement. – D_Bester Jun 23 '15 at 17:28
  • 1
    @D_Bester `On Error GoTo -1` is not equivalent to `Err.Clear` followed by a `Resume ...`, because `Resume ...` redirects (somewhere) while `On Error GoTo -1` doesn't. Anyway `Err.Clear` is incorporated in `Resume ...` therefore superfluous. – 6diegodiego9 Jan 19 '22 at 21:15
-1

It is important to realise there are two distinct things that happen when an error occurs in VBA.

  1. The error object has it's properties set (ie err.number, err.desciption, err.source etc)

  2. The next line to be executed changes.
    Which line is executed is determined by the last "On Error Goto" statement that was executed - if any.

These are separate but highly related topics and you will write what is in effect distinct but interwoven code to manage them both.

When ANY error occurs or you use Err.Raise the Err object is ALWAYS set up. Even if "On Error Resmue next" or any other On error statement has been used.

So code like this could ALWAYS be used:

Dim i as integer 
On error resume next 
i = 100/0  ' raises error
if err.number <> 0 then 
   ' respond to the error
end if

It is really important to realise that when the error object has a non zero value for err.number an exception has been raised AND that if you then try and execute any "On Error Goto " statement doing so will raise an error and execution will be passed to any code that called the current procedure. (or where not called by any code the usual VBA error dialogue is given). Note that in this scenario "On Error Goto ALabel1" would NOT change the next line to be the line with Label1: on it.

eg

Sub ErrorTest()

    Dim dblValue        As Double

    On Error GoTo ErrHandler1
    dblValue = 1 / 0

ErrHandler1:
    debug.print "Exception Caught"
    debug.print Err.Number

    On Error GoTo ALabel1
    dblValue = 1 / 0

Exit sub
ALabel1:
    debug.print "Again caught it."

End Sub

Once the err.number property is set to non zero, you can reset it to zero by using

On Error Goto -1 

Note that Err.Clear also resets it to zero but it is actually equivalent to:

On Error Goto -1 
On Error Goto 0

ie Err.Clear removes an "On Error Goto" that is currently in place. So therefore it is mostly best to use:

On Error Goto -1   

as using Err.clear You would often need to write

Err.Clear
On Error Goto MyErrorHandlerLabel

It is worth noting that Err.Clear is implicitly carried out by VBA whenever it executes any type of Resume statement, Exit Sub, Exit Function, Exit Property, or any On Error statement.

You can also set the error object it to whatever number you like using

Err.Raise Number:=, Source:=, Description:=

Err.Raise is very important as it allows you to propagate an error to the calling program AND raise your own error numbers known as "user defined errors" that provide a means of telling the calling program that it could not continue for a logical reason. (eg a business rule was broken).

You can control which line of code is executed next using statements like

On Error Goto ALabelName On Error Goto ANonZeroLineNumber and On Error Goto 0 ' This is a special case as it in effect says "within the current scope (typically a sub or function), in the event that an error happens pass the error object back to the code that called the current sub or function.

Error handling in VBA is tricky, especially as the MSDN pages do not really give complete examples of how error handling can be used.

HarveyFrench
  • 4,440
  • 4
  • 20
  • 36
  • 2
    `Err.Clear` and `On Error Goto -1` are NOT equivalent. If you replace `On Error Goto -1` with `Err.Clear` in your code you will see that the second error is unhandled with `Err.Clear`. They are NOT equivalent. – D_Bester Jun 23 '15 at 13:33
  • Golly your right. From my experiments: On Error Goto -1 sets the err object to nothing (ie err.number to 0) Err.clear is equivalent to On Error Goto -1 ' followed by a On Error Goto 0 I will change me code accordingly. Would you agree @D_Bester ? – HarveyFrench Jun 23 '15 at 13:50
  • I've started a new question with my above answer as the basis of the question! Here http://stackoverflow.com/questions/31007009/can-you-help-me-understand-more-about-good-practise-with-vba-error-handling-plea – HarveyFrench Jun 23 '15 at 15:27
  • @HarveyFrench: I do not see `Err.Clear` to be equivalent to `On Error GoTo -1` followed by `On Error GoTo 0` _**(inside a error handler)**_, but rather to be equivalent to `On Error GoTo 0` alone. In fact, it seems `On Error GoTo 0` overrides any effect of `On Error GoTo -1`. – AntoineL Jul 17 '17 at 18:07