Return error to initial function

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • TheSmileyCoder
    Recognized Expert Moderator Top Contributor
    • Dec 2009
    • 2322

    #1

    Return error to initial function

    Im having some issues with Error handling or maybe the understanding thereoff. Say I have a function TopFunction which calls a function MiddleFunction 10 times which again calls a function LowFunction 10 times.


    Now If LowFunction throws a fatal error and I have no error handling, access is "reset" so to speak. All variable values are wiped from memory, and code execution is stopped (or possibly paused with debug options if its a development version).

    However if I do have error handling and catch a unexpected error (One I did not anticipate and therefore basicly don't know how to handle) I want to quit the LowFunction, BUT I also want to quit MiddleFunction and TopFunction from proceeding. Simply exiting the LowFunction just makes middlefunction proceed with the next function call of LowFunction.



    Not exactly sure these are the right words to describe it, but its the best I can do. How should I propagate the error back up through MiddleFunction and TopFunction?

    OR
    If you feel im barking up the wrong tree, please explain how you guys handle this.
  • NeoPa
    Recognized Expert Moderator MVP
    • Oct 2006
    • 32669

    #2
    I suspect when you say function, you really mean procedure. The trick is to ensure the procedure is a function procedure, and have a return value that indicates an error.

    When a lower-level function returns a value indicating an error has occurred then you have a choice of returning an error indicator straightaway, or throwing an exception (Raise) yourself to trigger the error-handling at the current level (which itself, would presumably handle returning an error value as well as anything else necessary to handle errors for that procedure).

    Does that help?

    Comment

    • TheSmileyCoder
      Recognized Expert Moderator Top Contributor
      • Dec 2009
      • 2322

      #3
      Thank you for your reply.

      Yea, I was thinking along those lines, but was wondering if there was something more efficient.

      My concern is that it means (As I understand it) that after each run of LowFunction I would need to have an IF statement to check whether or not it threw an error, adding extra overhead to my code. If that is the only way to go about it, then so be it, I was just hoping there might be a more efficient setup. I do realise that in alot of cases its a very very slight overhead, but still. I want to do it the Right/Best Practice way, and being self-taught I sometimes wonder if I am doing that.

      Another thing I noticed is that if MiddleFunction has an errorhandler, but LowFunction does not, then the error is handled (or attempted to be handled) in MiddleFunction. I was wondering if I could use that somehow. The issue with this approach is that LowFunction might be reused in many places, and I might desire it to have error handling some times, and not other times (in which I want the higher level function to handle it).

      P.s.
      Its not necessary to have it be a function. You could do it with a sub as well (Example below)
      Code:
      Private sub MiddleFunction()
        Dim errNo as long
        LowFunction errNo 
        If ErrNo then
          Err.Raise ErrNo
        End if
        Exit sub
      End Sub
      
      
      Private Sub LowFunction(errNo as long)
      On Error goto ErrHandler
        'Code here
        
      
      exit Sub
      ErrHandler:
        errNo=Err.Nr
        Exit Sub
      End Sub

      Comment

      • NeoPa
        Recognized Expert Moderator MVP
        • Oct 2006
        • 32669

        #4
        It is possible to use a Sub procedure as you say. I would certainly consider declaring it explicitly as ByRef in that case though.

        An alternative I hinted at, when it is required for the higher level function to handle the error instead, would be to Raise the same error after ensuring error handling had been disabled. A higher level error handler will always pick up errors in lower levels when they occur without any active error handler therein.

        Otherwise, error handling does appear to be a little clumsy in VBA. Not as sophisticated as many parts of the syntax for sure.

        Comment

        • ADezii
          Recognized Expert Expert
          • Apr 2006
          • 8834

          #5
          @TheSmileyCoder :
          Sorry about coming in a little late, but I found your scenario very interesting, and a challenge to resolve. Give a series of Nested Functions(3), calling each other multiple times, you can actually control as to whether the Top Level or Bottom Level Function controls Error Handling.
          1. Enable Error Handling in the Top Level Function:
            Code:
            Public Function TopFunction()
            On Error GoTo Err_TopFunction
            
            Dim bytCtr As Byte
            
            'Call Middle Function 3 Times
            For bytCtr = 1 To 3
              Debug.Print "Top: " & Format$(bytCtr, "00")
                MiddleFunction
            Next
            
            Exit_TopFunction:
              Exit Function
            
            Err_TopFunction:
              MsgBox Err.Description, vbExclamation, "ERROR Somewhere"
                Resume Exit_TopFunction
            End Function
          2. Do not enable Error Handling in the Middle Level Function:
            Code:
            Public Function MiddleFunction()
            Dim bytCtr2 As Byte
            
            'Call Low Function 3 Times
            For bytCtr2 = 1 To 3
              Debug.Print "  |-- Middle: " & Format$(bytCtr2, "00")
                LowFunction
            Next
            End Function
          3. Enable Error Handling in the Low Level Function, in conjunction with the #If...Then...#E lse Directive:
            Code:
            Public Function LowFunction()
            #If HANDLE_LOW_ERRORS Then
              On Error GoTo Err_LowFunction
            #End If
            
            Dim bytCtr3 As Byte
            
            'Call Low Function 3 Times
            For bytCtr3 = 1 To 3
              If bytCtr3 = 3 Then Err.Raise 13
                Debug.Print "      |-- Low: " & Format$(bytCtr3, "00")
            Next
            
            Exit_LowFunction:
              Exit Function
              
            Err_LowFunction:
              MsgBox Err.Description, vbExclamation, "Error in LowFunction()"
                Resume Exit_LowFunction
            End Function
          4. Declare a Conditional Compilation Constant that will control which Level Function (Top/Bottom) will handle Errors:
            Code:
            'Top Level Function will handle Errors
            #Const HANDLE_LOW_ERRORS = False
            
            'Bottom Level Function will handle Errors
            '#Const HANDLE_LOW_ERRORS = True
          5. With HANDLE_LOW_ERRO RS = False, the Error will travel up the Stack, and be handled by the Top Level Handler. A Single Error Message will be generated.
          6. With HANDLE_LOW_ERRO RS = True, the Error will be handled by the Bottom Level Handler. Multiple Error Messages will be generated.
          7. Debug.Print Statements are for Testing Purposes only.
          8. Code has been tested, and appears to be fully operational.
          Last edited by ADezii; Dec 18 '11, 07:47 PM. Reason: Additional Information supplied

          Comment

          • NeoPa
            Recognized Expert Moderator MVP
            • Oct 2006
            • 32669

            #6
            That's a good illustration of what the Context-Sensitive Help system has to say on the matter.

            Comment

            Working...