Link to home
Create AccountLog in
VBA

VBA

--

Questions

--

Followers

Top Experts

Avatar of Robert Berke
Robert Berke🇺🇸

Does [On Error Goto 0 : End Sub] function exactly like [end sub]

While reviewing some VBA code that I wrote 15 years ago, I noticed something annoying.

A handful of those old subroutines looked like this for no obvious reason.

Function xyz()
' .... bunch of code ....
On error Go To 0
End Function

--- and one of them actually had this version of the code ----
On Error Go To 0: End Sub

Open in new window


I  am 99% sure those Go To 0 lines are effectively useless, so I intend to remove them.

Can anybody think of a functional reason that I shouldn't delete them? (I am not interested in "cosmetic reasons"**).


rberke (aka UncleBob)


P.S.

"If it is not broke don't fix it."  is advice I have been hearing all my life. I agree completely, but I will not give anybody points for that.


** I will not delete every occurrence of < on error go to 0 : End sub >

I might retain some for  "cosmetic reasons".  For example I usually match every on error resume next with  a corresponding on error go to 0, so I would not change the following code.

Sub MyUnchangedSub()

   --- bunch of code that calls subroutines the manipulate  workbookObject
On error resume next   ' the workbook might already be closed
      WorkbookObject.close false  
on error go to 0  ' <===== this is "cosmetic".
End sub

Open in new window


Zero AI Policy

We believe in human intelligence. Our moderation policy strictly prohibits the use of LLM content in our Q&A threads.


Avatar of Martin LissMartin Liss🇺🇸

The only time you need the On Error GoTo 0 line is if there's a matched On Error... line.

Avatar of Éric MoreauÉric Moreau🇨🇦

if you don't set "on error goto 0", the previous error handler (ie "on error resume next") will still be effective even after the method (sub or function) ends which might leads to undesirable effects.

Avatar of Robert BerkeRobert Berke🇺🇸

ASKER

Eric, I think you missed my point.  These particular On Error Goto 0 are all followed by Exit Sub.
That means there is no  On Error Resume Next.



Reward 1Reward 2Reward 3Reward 4Reward 5Reward 6

EARN REWARDS FOR ASKING, ANSWERING, AND MORE.

Earn free swag for participating on the platform.


Avatar of Éric MoreauÉric Moreau🇨🇦

check your MyUnchangedSub sub.

You find a "on error resume next" statement just before the Close. If you don't have a "on error goto 0" statement somewhere after, all errors will just be silently skipped.

I agree that if you don't have any "on error do something", it is useless to have the "on error goto 0" (but I don't think it hurts to have it).

It's a protection mechanism.

It doesn't hurt to have it, but forces error handling after any sub is called.  This way if someone adds on error resume next somewhere else in the sub, it'll clean itself up at the end of the procedure.

Essentially forces the program to behave with normal error handling.  

Avatar of Robert BerkeRobert Berke🇺🇸

ASKER

Martin, I agree with your statement but would extend it as follows:

The only time you need the On Error GoTo 0 line is if there's a matched On Error... line in the same subroutine.

But that still does not quite get to the heart of my question.

I originally thought that the following subroutine would have no affect whatsoever on any higher level program.

It turns out that the scope of any On Error is indeed limited to the active program.
Nonetheless, there is a subtlety that can have an affect on a higher program.

The subtlety is that every On Error statement does an automatic Err.Clear.
In other words I should stick with "if its not broke don't fix it"

Does  everyone  agree with this statement?
<on error goto 0:End sub> is equivalent to <err.clear:End Sub>

I do not intend to actually make such a change because it "looks weird". Nonetheless, I believe the abovestatement is true.

Sub test030()
Call NoAffect
MsgBox err
Stop

End Sub

Sub NoAffect()
On error resume next
debug.print 1/0
if  rnd() > .5 then on error goto 0
end sub
 
 





Free T-shirt

Get a FREE t-shirt when you ask your first question.

We believe in human intelligence. Our moderation policy strictly prohibits the use of LLM content in our Q&A threads.


Avatar of Robert BerkeRobert Berke🇺🇸

ASKER

 
This comment was Irrelevant to this questionUser generated image
 




Avatar of Martin LissMartin Liss🇺🇸

All I can say is that I've looked at thousands (perhaps tens of thousands) of macros and I don't believe any of them had a stand-alone On Error GoTo 0 line.

and can someone tell me how to fix the title of this question?  

Use the "Edit Question" link in the original question post of this question, and adjust the title as desired.


»bp

Reward 1Reward 2Reward 3Reward 4Reward 5Reward 6

EARN REWARDS FOR ASKING, ANSWERING, AND MORE.

Earn free swag for participating on the platform.


Avatar of Robert BerkeRobert Berke🇺🇸

ASKER

martin said "All I can say is that I've looked at thousands (perhaps tens of thousands) of macros and I don't believe any of them had a stand-alone On Error GoTo 0 line. "

I agree.  It looked weird when I saw it, but it is code that I wrote at least 15 years ago.  I probably will go ahead and delete it even though that violates the "if its not broken" rule 

Avatar of Martin LissMartin Liss🇺🇸

and can someone tell me how to fix the title of this question?
Report it as a bug. In case you don't know how to do that...
  1. Click your 'My account' logo
  2. Click 'FEEDBACK' near the bottom
  3. Click 'Report a bug'
  4. Select the '2022, Q2: General EE Defect Reports' file
  5. Follow the instructions


<on error goto 0:End sub> is equivalent to <err.clear:End Sub>

No.

Err.Clear will just clear the error, but leaves the error handling in place.

On Error GoTo 0 removes the custom error handling.  


Free T-shirt

Get a FREE t-shirt when you ask your first question.

We believe in human intelligence. Our moderation policy strictly prohibits the use of LLM content in our Q&A threads.


On Error Goto  0:
This instruction reset the error handler to the default one in the current function.
Calling it right before the end of the function has no effects since error handlers are local to the function they're implemented in.
In other words, the top level function's error handler is not reseted by the sub level functio, so you can safelly remove it.

The following illustrate this:
Public Sub test()
On Error GoTo Error
    subTest
    Dim i As Integer
    i = i / 0
Exit Sub
Error:
    Debug.Print "divide by zero detected."
End Sub

Public Sub subTest()
On Error GoTo 0
End Sub

Open in new window


Avatar of Robert BerkeRobert Berke🇺🇸

ASKER

kyle:

I am pretty convinced that there is no functional difference between these two code snips. (Cosmetic and 'best practice' differences are obvious.)

101 On Error goto 0  ' remove the local error handler and clear the err object
102 end sub ' end the subroutine

101 err.clear ' clear the err object
102 end sub ' remove the local error hander, and end the subroutine.

If you disagree can you give an working example that illustrates the difference.  
For instance something similar to sub test030  that I posted above?


ASKER CERTIFIED SOLUTION
Avatar of Fabrice LambertFabrice Lambert🇫🇷

Link to home
membership
Log in or create a free account to see answer.
Signing up is free and takes 30 seconds. No credit card required.
Create Account

Avatar of Robert BerkeRobert Berke🇺🇸

ASKER

Fabrice said: "Removing the local error handler or clearing the error object right before exiting a function is useless. "

I agree with one big exception which is illustrated below. In that code it is highly advisable that alternative1 be coded.  Otherwise the err will be reported to the higher level program.  Alternative2 is functionally equivalent, but it looks "weird" and future reviewers would not understand what is going on.



Sub Main
   call level2
   If err <> 0 then msgbox "err=" & err
end sub


sub Level2
--- bunch of other code followed by ---
on error resume next
-- small chunk of code
Alternative1:     on error goto 0 
OrAlternative2: err.clear
end sub






Reward 1Reward 2Reward 3Reward 4Reward 5Reward 6

EARN REWARDS FOR ASKING, ANSWERING, AND MORE.

Earn free swag for participating on the platform.


False,

The on Error Goto 0 statement clear the error object (as you mentionned earlyer).
The only way for the if statement to be true is the Level2 function ignore any error.
Sub Main()
   Call Level2
   If Err <> 0 Then MsgBox "err=" & Err
End Sub

Sub Level2()
On Error Resume Next
    Dim i As Integer
    i = 5 / 0
End Sub

Open in new window

But,this is pure garbage programming and must be forbidden at all costs, or if you have the bad luck to see it somewhere, fix it immediatly.


Avatar of Robert BerkeRobert Berke🇺🇸

ASKER

I must apologize to everyone that my original post was unclear.  My desire was to focus on a "stand alone" On Error GoTo 0".  I was not talking about  a "goto 0" that is paired with a preceding  Resume Next.

Fabrice:

My examples may be garbage, but what exactly do you think is "False" about what I wrote?   I have feeling we are both in agreement about, but that you are objecting to the quirky examples that conflict with best practices.  If so, you can feel free to ignore the rest of the post, and I will soon close the question.

Often my examples  are not taken from real life, but they are designed to clearly display quirky behavior.  So forgive me if they look a little junky.   In real life I always try to avoid clever code that utilizes quirky behavior.

I also try to be precise and to deeply understand quirky stuff, so forgive me if the following seems argumentative and/or defensive -  that is not my intention

Earlier you said:  "Removing the local error handler or clearing the error object right before exiting a function is useless. "

That statement is a bit too general. For instance, I think you will agree that Line999 in the following example is not useless.  First:, it is "best practice" to pair every "Resume Next" with a corresponding "Goto 0".  Second:  Line999 provides stability to Err object.  If we drop line999, the routine will sometime return err 53 file not found.

Please note that Line999 could be replaced with err.clear and there would be no functional difference.  But, it would make the code much less
 
Sub DeleteFileAndOtherStartup(fullpath as string)
Call OtherStartUpStuff
on error resume next
kill fullpath
Line999: On Error Goto 0
Exit function





Honestly, I don't see the point of arging about of bad practices, even if that's doable.

Free T-shirt

Get a FREE t-shirt when you ask your first question.

We believe in human intelligence. Our moderation policy strictly prohibits the use of LLM content in our Q&A threads.


Avatar of Robert BerkeRobert Berke🇺🇸

ASKER

I agree so we will stop arguing.  



Avatar of Robert BerkeRobert Berke🇺🇸

ASKER

-------------------------------
Recap of original question
Does [On Error Goto 0 : End Sub] function exactly like [end sub]
-------------------------------
While reviewing some VBA code that I wrote 15 years ago, I noticed something annoying.
A handful of those old subroutines looked like this for no obvious reason.
Function xyz()
' ----- Big Chunk of code with many <On Error resume Next> statements 
' ----- all of which were correctly terminated with <On Error goto 0" 
' ----- But the Chunk of code was followed with a standalone <On Error GoTo 0>
' ----- which was immediately followed by End Function
On error GoTo 0
End Function

Open in new window

I  am 100% sure those GoTo 0 lines are effectively useless, so I am deleting them from my code.
 
Can anybody think of a functional reason that I shouldn't delete the useless statement? (I am not interested in discussing "cosmetic reasons").
--------------------------------
The following "Summary Correct Answer"  applies to End Function | Exit Function | End Sub | Exit Sub
--------------------------------
 
Every Expert said approximately the same thing, but Fabrice came the closest to giving the correct answer:
 
" There is no functional difference, but code with useless statements should be avoided as it provides confusion."
 
The correct answer is
   Line980:  On Error Goto 0
   Line990:  End Function
Is almost exactly like
   Line990:  End Function
 
 
But if the code is not following VBA "best practices" there are some quirky differences that might cause problems in very rare circumstances.
 
I examined my code carefully and decided to delete the superfluous On Error GoTo 0 statements.
--------------------------------
The following is a way too  long winded "More Correct Answer" .
--------------------------------
 
When <On Error GoTo 0> appears to be superfluous  it can almost always be removed.
But every <On Error> statement automatically invokes Err.Clear.. In pathologically bad code deleting such a superfluous line might make a higher level program misfire, but it is very unlikely to happen in real life. Don't worry about it.
 
But, if you do want to worry about it, then the appropriate best practice is:
  1. Match every <On Error Resume Next> with  a corresponding <On Error GoTo 0>, and keep the code path between them as small as possible.
  2. Do not put in standalone On Error statements that serve no purpose.
 
Example 1 where the <On Error GoTo 0> is "best practice" because it matches line800: Line980 should not be removed.
Sub DeleteFileAndOtherStartup(fullpath as string)
Call OtherStartUpStuff
Line800: On Error Resume Next
kill fullpath
Line980:  On Error GoTo 0
Line990:  End Function
 
Example 2 where the <On Error GoTo 0 is superfluous and Line980 should be removed.
Sub DeleteFileAndOtherStartup(fullpath as string)
on error resume next
kill fullpath
On Error GoTo 0
Call OtherStartUpStuff
Line980:  <On Error GoTo 0
Line990:  End Function
 
Example 3 where the <On Error GoTo 0 is  probably superfluous.  Somebody (but not me)  might argue that Line980 should be left in place  because it is paired with line100. .
Option Explicit
 
Sub AnySub(fullpath As String)
line100: On Error GoTo err_show
    ' ----- there is a bunch of  unrelated code that I am not showing--
    On Error Resume Next
    Kill fullpath
    On Error GoTo err_show
    ' ----- and some more  unrelated code that I am not showing--
exit_routine:
Line980:  On Error GoTo 0
Line990:  Exit Function
 
err_show: ' This routine is not expected to ever throw an error, so we use Err_Show.
    MsgBox Err & "(" & Error & ") encountered " & IIf(Erl <> 0, " at or after Erl=" & Erl, "")
    Resume exit_routine
End Function
VBA

VBA

--

Questions

--

Followers

Top Experts

Visual Basic for Applications (VBA) enables building user-defined functions (UDFs), automating processes and accessing Windows API and other low-level functionality through dynamic-link libraries (DLLs). VBA is closely related to Visual Basic and uses the Visual Basic Runtime Library, but it can normally only run code within a host application rather than as a standalone program. It can, however, be used to control one application from another via OLE Automation. VBA is built into most Microsoft Office applications.