Vba try catch word

  1. Use On Error Resume Next to Handle Errors in VBA
  2. Use On Error GoTo 0 to Handle Errors in VBA
  3. Use On Error GoTo [Label] to Handle Errors in VBA

Use Try-Catch in VBA

The Try-Catch method prevents program crashes when an internal error occurs in computer programming. It is useful to prevent system errors and let the smooth flow of code execution occur.

However, unlike other programming languages, VBA does not have the Try-Catch block. On the good side, it has workaround methods designed explicitly for error handling procedures.

In this article, error handling procedures in VBA will be discussed and demonstrated together with several samples that would help you implement error handling schemes in your VBA project.

Error handlers are an important part of your code. They are our go-to guy when the VBA compiler cannot handle things.

Listed below are the VBA error handling methods:

  1. On Error Resume Next — will ignore any encountered error, and the code will continue to run.
  2. On Error GoTo 0 — will stop the code on the line that causes the error and show a message box describing the error.
  3. On Error GoTo [Label] — you can specify what you want to do if your code has an error.

We will discuss all of these error-handling routines in detail below.

Use On Error Resume Next to Handle Errors in VBA

This error handler allows the compiler to ignore the error and execute the next code line. It is the frequently used error handler in VBA as it does not need any complicated code to implement.

However, when using this error handler, proceed with precaution since it ignores errors. The code execution might not execute as planned with these undetected errors.

On Error Resume Next is best to know what kind of errors you are likely to encounter. And then, if you think it is safe to ignore these errors, you can use this.

The code block below will output an error without error-handling routines because division by zero is not allowed mathematically.

Sub DivideNumbers()

Dim x,y,z as integer

x = 10/4
y = 15/0
z= 2/5

Debug.Print x & vbNewLine & y & vbNewLine & z

End Sub

DivideNumbers Output:

Error: ! Runtime Error '11':
         Division by Zero

Using the On Error Resume Next error handler:

Sub DivideNumbers()
    On Error Resume Next
 
Dim x, y, z As Integer

x = 10 / 4
y = 15 / 0
z = 2 / 5

Debug.Print x & vbNewLine & y & vbNewLine & z

End Sub

DivideNumbers Output:

The DivideNumbers output shows that the second line was skipped since a Division by Zero error occurred on that line.

Use On Error GoTo 0 to Handle Errors in VBA

The On Error GoTo 0 error handler resets the default error behavior of the compiler.

So why still use it? On Error GoTo 0 error handler addresses the risk of non-detection of errors induced by On Error Resume Next error handler. Thus, On Error GoTo 0 is typically used in conjunction with On Error Resume Next to enable error detection on the code section where no error should occur.

To have a better explanation, see the code block below:

Sub ErrorSub()
    On Error Resume Next

'An error could happen in this area but will not be detected.

    On Error Goto 0

'Once an Error occurs, an error message will appear.

End Sub

For a better example, see below code block.

Sub DivideNumbers()
    On Error Resume Next

Dim x, y, z, a, b, c

x = 3 / 2
y = 0 / 0
z = 2 / 6

Debug.Print x & vbNewLine & y & vbNewLine & z
    On Error GoTo 0

a = 8 / 7
b = 2 / 0
c = 2 / 7

Debug.Print a & vbNewLine & b & vbNewLine & c
End Sub

DivideNumbers Output:

Then an error occurred since the On Error Resume Next was negated by the On Error GoTo 0 on the second part of the code.

Error: ! Runtime Error '11':
         Division by Zero

Use On Error GoTo [Label] to Handle Errors in VBA

The two error handlers above don’t handle errors; either they skipped or neglected the error. The third error handler, On Error GoTo [Label], will allow you to deal with the error and let you choose the action to be taken when an error occurs.

There are several best practices in using On Error GoTo [Label], one is to terminate the code execution when an error occurs, and the other is to correct the error, then retry, and many more. The example below will demonstrate the usage of On Error GoTo [Label].

The code block below will automatically terminate the code when an error occurs.

Sub DivideNumbertoNumber()
    On Error GoTo ErrHandler

Dim i As Integer

For i = 5 To -5 Step -1
Debug.Print i / i

Next i

ErrHandler:

End Sub

DivideNumbertoNumber Output:

As observed, code execution stopped when i = 0 since i divided by i would mean 0 divided by 0, which would result in an overflow.

In the next example, we will demonstrate how to print in the Immediate Window if an error occurs. We can also use the Err.Description property to print the actual error.

Sub DivideNumbertoNumber()
    On Error GoTo ErrHandler

Dim i As Integer

For i = 5 To -5 Step -1
Debug.Print i / i

Next i

Exit Sub

ErrHandler:
Debug.Print "An Error occured at i is equal to " & i & vbNewLine & "Error Type: " & Err.Description

End Sub

DivideNumbertoNumber Output:

 1 
 1 
 1 
 1 
 1 
An Error occured at i is equal to 0
Error Type: Overflow

Note that Exit Sub was placed before the ErrHandler to exit the subroutine before it reached the ErrHandler for the cases that error did not occur. If the Exit Sub were not inserted, the compiler would execute the ErrHandler even if there is no error.

Return to VBA Code Examples

This article will demonstrate how to use VBA to Try Catch Errors.

In most programming languages, you can use the syntax Try…Catch…End Try to prevent errors from occurring.  The code literally tries to run and if it encounters and error, it jumps down to the catch line where the error can be documented and retuned to the user.  VBA does not use the Try…Catch…End Try syntax but we can mimic this syntax by using the On Error GoTo syntax instead.

On Error GoTo

The On Error GoTo statement in VBA will force our code to move to a specific line of code if an error occurs.

Sub RenameSheet ()
  On Error GoTo eh
    ActiveSheet.Name = "Sheet1"
    Exit Sub
  eh:
    MsgBox Err.Description
End Sub

In the above example, we have put added an error trap where we direct the code to move to the error handler if an error occurs. We then try to rename the sheet to be Sheet1. If we are in Sheet2 for example, and try to rename it to Sheet1 BUT Sheet1 already exists, then the error will occur and the code will jump down to the error handler.

VBATryCatch MsgBox

However, if there is no sheet 1 in the workbook, then the code will run perfectly and as there is an Exit Sub BEFORE the error handler, the error handler code will not be reached.

VBA Coding Made Easy

Stop searching for VBA code online. Learn more about AutoMacro — A VBA Code Builder that allows beginners to code procedures from scratch with minimal coding knowledge and with many time-saving features for all users!
vba save as

Learn More!

The code below is pretty self explanatory: just copy and paste it all into a module and run it, it provides a few use cases and many explanatory comments in the text. (It works but I’m interested to know what other people make of it and for any suggestions you might like to make.)

The most important facts to realise are:

  1. When you use on error goto Label1 the procedure enters into a state of «I’m handling an error» as an exception has been raised. When it is in this state, if another «On Error Goto» label2 statement is executed it will NOT goto label2, but raises and error which is passed to the code that called the procedure.

  2. You can stop a procedure being in the «I’m handling an error» state by clearing the exception (setting err to nothing so the err.number property becomes 0) by using

    Err.clear
    or
    
    On Error Goto -1    ' Which I think is less clear!
    

(NOTE that On Error Goto 0 is different from the above)

Also important to note is that Err.Clear 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

I use the above techniques with various labels to simulate the sometimes useful functionality that Visual basic TRY CATCH blocks give, which I think have their place in writing readable code.

Admittedly this technique creates a few more lines of code than a nice VB try catch statement, but it’s not too messy and pretty easy to get your head around.

PS. Also of interest might be the procedure ManageErrSource which makes the Err.Source property store the procedure where the error occurred.

Option Compare Database
Option Explicit

Dim RememberErrNumber As Long
Dim RememberErrDescription As String
Dim RememberErrSource As String
Dim RememberErrLine  As Integer

Private Sub RememberThenClearTheErrorObject()

    On Error Resume Next

    ' For demo purposes
    Debug.Print "ERROR RAISED"
    Debug.Print Err.Number
    Debug.Print Err.Description
    Debug.Print Err.Source
    Debug.Print " "


    ' This function has to be declared in the same scope as the variables it refers to
    RememberErrNumber = Err.Number
    RememberErrDescription = Err.Description
    RememberErrSource = Err.Source
    RememberErrLine = Erl()

    ' Note that the next line will reset the error object to 0, the variables above are used to remember the values
    ' so that the same error can be re-raised
    Err.Clear

    ' Err.Clear  is used to clear the raised exception and set the err object to nothing (ie err.number to 0)
    ' If Err.Clear has not be used, then the next "On Error GoTo ALabel" that is used in this or the procedure that called it
    ' will actually NOT pass execution to the ALabel: label BUT the error is paseed to the procedure that called this procedure.
    ' Using Err.Clear (or "On Error GoTo -1 ")  gets around this and facilitates the whole TRY CATCH block scenario I am using there.


    ' For demo purposes
    Debug.Print "ERROR RAISED is now 0 "
    Debug.Print Err.Number
    Debug.Print Err.Description
    Debug.Print Err.Source
    Debug.Print " "

    ' For demo purposes
    Debug.Print "REMEMBERED AS"
    Debug.Print RememberErrNumber
    Debug.Print RememberErrDescription
    Debug.Print RememberErrSource
    Debug.Print " "

End Sub

Private Sub ClearRememberedErrorObjectValues()

    ' This function has to be declared in the same scope as the variables it refers to
    RememberErrNumber = 0
    RememberErrDescription = ""
    RememberErrSource = ""
    RememberErrLine = 0

End Sub




Sub ExampleOfTryCatchBlockInVBA()

    On Error GoTo HandleError


    ' -----------------------------------------------------
    ' SubProcedure1 has the example of a multiple line TRY block with a block of code executed in the event of an error

    SubProcedure1



Exit Sub
HandleError:

    Select Case Err.Number
        Case 0
            ' This shold never happen as this code is an error handler!
            ' However if it does still allow the Err.raise to execute below. (In this case Err.raise will fail
            ' and itself will raise an error "Invalid procedure call or argument" indicating that 0 cannot be used to raise and error!

        Case 111111
            ' You might want to do special error handling for some predicted error numbers
            ' perhaps resulting in a exit sub with no error or
            ' perhaps using the Err.raise below

         Case Else
            ' Just the Err.raise below is used for all other errors

    End Select

    '
    ' I include the procedure ManageErrSource  as an exmple of how Err.Source can be used to maintain a call stack of procedure names
    ' and store the name of the procedure that FIRST raised the error.
    '
    Err.Raise Err.Number _
            , ManageErrSource("MyModuleName", Err.Source, Erl(), "tsub1_RaisesProcedureNotFoundError") _
            , Err.Number & "-" & Err.Description

    ' Note the next line never gets excuted, but I like to have resume in the code for when I am debugging.
    ' (When a break is active, by moving the next executable line onto it, and using step over, it moves the exection point to the line that actually raised the error)
    Resume

End Sub

Sub SubProcedure1()

    ' -----------------------------------------------------
    ' Example of a multiple line TRY block with a Case statement used to CATCH the error

    '
    ' It is sometimes better to NOT use this technique but to put the code in it's own procedure
    ' (ie I refer to the code below that is surrounded by the tag #OWNSUB) .
    ' However,sometimes using this technique makes code more readable or simpler!
    '

    Dim i As Integer

' This line puts in place the defualt error handler found at the very foot of the procedure
On Error GoTo HandleError


    '
    ' Perhaps lots of statements and code here
    '


    ' First an example with comments


    ' -----------------------------------------------------
    ' TRY BLOCK START

        ' This next line causes execution to "jump" to the "catch" block in the event an error is detected.
On Error GoTo CatchBlock1_Start

        ' #OWNSUB

        tsub_WillNotRaiseError_JustPrintsOk

        If vbYes = MsgBox("1. Do you want to raise an error in the try block? - (PRESS CTRL+BREAK now then choose YES, try no later.)", vbYesNo) Then
            i = 100 / 0
        End If

        '
        ' Perhaps lots of statements and code here
        '

        ' #OWNSUB

    ' TRY BLOCK END
    ' -----------------------------------------------------


    ' -----------------------------------------------------
    ' CATCH BLOCK START
CatchBlock1_Start:

    If Err.Number = 0 Then
        On Error GoTo HandleError
        ' Re-instates the procedure's generic error handler
        ' This is also done later, but I think putting it here reduces the likelyhood of a coder accidentally removing it.

    Else

        ' WARNING: BE VERY CAREFUL with any code that is written here as
        ' the "On Error GoTo CatchBlock1_Start" is still in effect and therefore any errors that get raised could goto this label
        ' and cause and infinite loop.
        ' NOTE that a replacement "On Error Goto" cannot be executed until Err.clear is used, otherwise the "On Error Goto"
        ' will itself raise and error.
        ' THEREFORE KEEP THE CODE HERE VERY SIMPLE!
        ' RememberThenClearTheErrorObject should be the only code executed and this called procedure must be tight!

        ' This saves the details of the error in variables so that the "On Error GoTo HandleError" can be used
        ' to determine how the next Err.Raise used below is handled (and also how any unexpected implicitly raised errors are handled)
        RememberThenClearTheErrorObject

        On Error GoTo HandleError   '#THISLINE#

        If vbYes = MsgBox("2. Do you want to raise an error in the erro handler? - (PRESS CTRL+BREAK now then try both YES and NO )", vbYesNo) Then
            i = 100 / 0
        End If

        Select Case RememberErrNumber
            Case 0:  ' No Error, do Nothing

            Case 2517
                Debug.Print "The coder has decided to just give a Warning: Procedure not found " & Err.Number & " - " & Err.Description
                ClearRememberedErrorObjectValues ' Not essential, but might save confusion if coding errors are made

            Case Else
                ' An unexepected error or perhaps an (user) error that needs re-raising occurred and should to be re-raised

                ' NOTE this is giving an example of what woudl happen if the CatchBlock1_ErrorElse is not used below
                If vbYes = MsgBox("3. Do you want to raise an error in the ELSE error handler? CatchBlock1_ErrorElse *HAS NOT*  been used? - (PRESS CTRL+BREAK now then try both YES and NO )", vbYesNo) Then
                    i = 100 / 0
                End If

     On Error GoTo CatchBlock1_ErrorElse


                ' SOME COMPLEX ERROR HANDLING CODE - typically error logging, email, text file, messages etc..
                ' Because the error objects values have been stored in variables, you can use
                ' code here that might itself raise an error and CHANGE the values of the error object.
                ' You might want to surround the code with the commented out CatchBlock1_ErrorElse lines
                ' to ignore these errors and raise the remembered error.  (or if calling a error handling module
                ' just use on error resume next).
                ' Without the CatchBlock1_ErrorElse lines any error raised in this "complex code" will be handled by the
                ' active error handler which was set by the "On Error GoTo HandleError" tagged as '#THISLINE#" above.

                If vbYes = MsgBox("4. Do you want to raise an error in the ELSE error handler when CatchBlock1_ErrorElse   HAS  been used? - (PRESS CTRL+BREAK now then try both YES and NO )", vbYesNo) Then
                    i = 100 / 0
                End If

CatchBlock1_ErrorElse:
     On Error GoTo HandleError
                ' This line must be preceeded by an new "On error goto" for obvious reasons
                Err.Raise RememberErrNumber, RememberErrSource, RememberErrDescription

        End Select

        On Error GoTo HandleError

    End If
    ' CATCH BLOCK END
    ' -----------------------------------------------------
On Error GoTo HandleError  ' Unnecessary but used to delimt the catch block




'
' lots of code here perhaps
'




    ' -----------------------------------------------------
    ' Example 2
    '
    ' In this example goto statements are used instead of the IF statement used in example 1
    ' and no explanitory comments are given (so you can see how simple it can look)
    '

    ' -----------------------------------------------------
    ' TRY BLOCK START

On Error GoTo CatchBlock2_Start

        tsub_WillNotRaiseError_JustPrintsOk

        If vbYes = MsgBox("Do you want to raise an error? - (PRESS CTRL+BREAK now then choose YES)", vbYesNo) Then
            i = 100 / 0
        End If

        '
        ' Perhaps lots of statements and code here
        '

    ' TRY BLOCK END
    ' -----------------------------------------------------


GoTo CatchBlock2_End:
CatchBlock2_Start:

        RememberThenClearTheErrorObject

        On Error GoTo HandleError

        Select Case RememberErrNumber
            Case 0:  ' No Error, do Nothing

            Case 2517
                Debug.Print "The coder has decided to just give a Warning: Procedure not found " & Err.Number & " - " & Err.Description
                ClearRememberedErrorObjectValues ' Not essential, but might save confusion if coding errors are made

            Case Else
                ' An unexepected error or perhaps an (user) error that needs re-raising occurred and should to be re-raised
                ' In this case the unexpecetd erro will be handled by teh code that called this procedure
                ' This line must be preceeded by an new "On error goto" for obvious reasons
                Err.Raise RememberErrNumber, RememberErrSource, RememberErrDescription

        End Select

        On Error GoTo HandleError

    End If

CatchBlock2_End:
    ' CATCH BLOCK END
    ' -----------------------------------------------------
On Error GoTo HandleError  ' Unnecessary but used to delimt the catch block




'
' Here you could add lots of lines of vba statements that use the generic error handling that is after the HandleError: label
'
'

'
' You could of course, alway add more TRY CATCH blocks like the above
'
'



Exit Sub
HandleError:

    Select Case Err.Number
        Case 0
            ' This shold never happen as this code isan error handler!
            ' However if it does still allow the Err.raise to execute below. (In this case Err.raise will fail
            ' and itself will raise an error "Invalid procedure call or argument" indicating that 0 cannot be used to raise and error!

        Case 111111
            ' You might watch to do special error handling for some predicted error numbers
            ' perhaps exit sub
            ' Perhaps using the Err.raise below
    End Select

    ' ie Otherwise
    '
    ' Note that I use the Err.Source to maintain a call stack of procedure names
    '
    Err.Raise Err.Number _
            , ManageErrSource("MyModuleName", Err.Source, Erl(), "tsub1_RaisesProcedureNotFoundError") _
            , Err.Number & "-" & Err.Description

    ' Note the next line never gets excuted, but I like to have resume in the code for when I am debugging.
    ' (By moving the next executable line onto it, and using step over, it moves the exection point to the line that actually raised the error)
    Resume

End Sub



Sub tsub_WillNotRaiseError_JustPrintsOk()

    Static i As Integer

    i = i + 1

    Debug.Print "OK " & i

End Sub



Public Function ManageErrSource(MyClassName As String, ErrSource As String, ErrLine As Integer, ProcedureName As String) As String

    ' This function would normally be in a global error handling module

    ' On Error GoTo err_ManageErrSource

    Const cnstblnRecordCallStack  As Boolean = True

    Select Case ErrSource

        Case Application.VBE.ActiveVBProject.Name

            ' Err.Source is set to this value when a VB statement raises and error. eg In Access by defualt it is set to "Database"

            ManageErrSource = Application.VBE.ActiveVBProject.Name & " " & MyClassName & "." & ProcedureName & ":" & ErrLine

        Case ""

            ' When writing code ouside of the error handling code, the coder can raise an error explicitly, often using a user error number.
            ' ie by using err.raise MyUserErrorNumber, "", "My Error descirption".
            ' The error raised by the coder will be handled by an error handler (typically at the foot of a procedure where it was raised), and
            ' it is this handler that calls the ManageErrSource function changing the Err.Source from "" to a meaningful value.

            ManageErrSource = Application.VBE.ActiveVBProject.Name & " " & MyClassName & "." & ProcedureName & ":" & ErrLine

        Case Else

            ' This code is executed when ManageErrSource has already been called.  The Err.Source will already have been set to hold the
            ' Details of where the error occurred.
            ' This option can be used to show the call stack, ie the names of the procdures that resulted in the prcedure with the error being called.

            If cnstblnRecordCallStack Then

                If InStr(1, ErrSource, ";") = 0 Then
                    ManageErrSource = ErrSource & ":: Called By: "
                End If
                ManageErrSource = ErrSource & ";" & ProcedureName & ":" & ErrLine

            Else
                ManageErrSource = ErrSource

            End If

    End Select

Exit Function
err_ManageErrSource:
    Err.Raise Err.Number, "MyModuleName.err_ManageErrSource", Err.Description
    Resume

End Function

In visual basic, Try Catch statement is useful to handle unexpected or runtime exceptions which will occur during execution of the program. The Try-Catch statement will contain a Try block followed by one or more Catch blocks to handle different exceptions.

In visual basic, whenever an exception occurred in the Try block, then the CLR (common language runtime) will look for the catch block that handles an exception. In case, if currently executing method does not contain such a Catch block, then the CLR will display an unhandled exception message to the user and stops the execution of the program.

Visual Basic Try Catch Syntax

Following is the syntax of handling errors in visual basic using Try, Catch blocks.

Try

‘ Code that may cause exception

Catch ex As Exception

‘ Exception handling

End Try

As per the above syntax, the Try block will contain the guarded code that may cause an exception so that if any errors occurred in our code, then immediately the code execution will be moved to Catch block to handle those exceptions.

In Try-Catch statement, the Catch block will execute only when an exception occurred in the code that is guarded by Try block.

Visual Basic Try Catch Example

Following is the example of using Try-Catch statement in visual basic to handle the exceptions.

Module Module1

    Sub Main(ByVal args As String())

        Dim name As String = Nothing

        Try

            If name.Length > 0 Then ‘ Exception will occur

                Console.WriteLine(«Name: « & name)

            End If

        Catch ex As Exception

            Console.WriteLine(«Exception: {0}», ex.Message)

        End Try

        Console.ReadLine()

    End Sub

End Module

If you observe the above code, we used Try and Catch blocks to handle runtime or unexpected errors during the execution of the program. Here, we wrote a code that may throw an exception inside of Try block and in Catch block we are handling the exception.

When we execute the above code, we will get the result as shown below.

Exception: Object reference not set to an instance of an object.

This is how we can use Try-Catch blocks to handle unexpected or runtime exceptions based on our requirements.

In visual basic, the Try block must be followed by Catch or Finally or both blocks otherwise we will get a compile-time error.

Visual Basic Try with Multiple Catch Blocks

In the above Try-Catch statement example, we used only a single Catch block with the Exception base class argument to handle all the exceptions.

In case, if we want to handle a different type of exceptions in different ways, then we can specify multiple Catch blocks with different exception types in the same Try-Catch statement and this process called an exception filtering.

If we define multiple Catch blocks with a Try statement, then the first Catch statement that can handle an exception will be executed, any following Catch statements that are even more compatible to handle an exception will be ignored so the order of Catch blocks must be always from most specific to least specific.

Following is the example of defining multiple catch blocks in a Try-Catch statement to handle different exceptions in different ways.

Module Module1

    Sub Main(ByVal args As String())

        Try

            Console.WriteLine(«Enter x value:»)

            Dim x As Integer = Integer.Parse(Console.ReadLine())

            Console.WriteLine(«Enter y value:»)

            Dim y As Integer = Integer.Parse(Console.ReadLine())

            Console.WriteLine(x / y)

        Catch ex As FormatException

            Console.WriteLine(«Input string was not in a correct format.»)

        Catch ex As InvalidOperationException

            Console.WriteLine(«Not a valid numbers to perform operation»)

        Catch ex As DivideByZeroException

            Console.WriteLine(«Cannot Divide By Zero»)

        End Try

        Console.ReadLine()

    End Sub

End Module

If you observe the above example, we defined multiple Catch blocks to handle different exception types so that we can easily get know what exact error it is and we can fix it easily.

When we execute the above example, we will get the result as shown below.

Enter x value:

10

Enter y value:

0

Cannot Divide By Zero

This is how we can use multiple Catch blocks with a single Try block to handle different types of exceptions based on our requirements.

Visual Basic Invalid Catch Blocks

In visual basic, defining a parameterless Catch block (Catch) and Catch block with an exception argument (Catch ex As Exception) are not allowed in the same Try-Catch statement because both will do the same thing.

Following is the example of defining an invalid Catch blocks in same Try-Catch statement.

Try

‘ Code that may cause an exception

Catch

‘ Exception Handling

Catch ex As Exception

‘ Exception Handling

End Try

In case, if we use a parameterless catch block (Catch) or Catch block with an exception argument (Catch ex As Exception) with other Catch blocks, then those parameters must be last otherwise we will get a compile-time error.

Following is the invalid way of defining a multiple catch blocks with a parameterless Catch block in same Try-Catch statement.

Try

‘ Code that may cause an exception

Catch

‘ Exception Handling

Catch ex As FormatException

‘ Exception Handling

Catch ex As InvalidOperationException

‘ Exception Handling

End Try

The following are the few points which we need to consider while defining a multiple Catch blocks.

  • Multiple Catch blocks with the same exception type are not allowed.
  • Defining a parameterless catch block (Catch) and catch block with an exception argument (Catch ex As Exception) are not allowed in the same try-catch statement because both will do the same thing.
  • While defining multiple catch blocks, the order of catch blocks must be always from most specific to least specific.
  • A parameterless catch block (Catch) or catch block with an exception argument (Catch ex As Exception) must be the last block if we use it with other catch blocks otherwise we will get a compile-time error.

Visual Basic Nested Try-Catch Statements

In visual basic, we can define a Try-Catch statement within another Try-Catch statement based on our requirements. In nested Try-Catch statements, if there isn’t any inner Catch block with an appropriate exception type, then the exception will flow to the outer Catch block.

Following is the example of defining nested Try-Catch statements in visual basic.

Module Module1

    Sub Main(ByVal args As String())

        Try

            Try

                Console.WriteLine(«Enter x value:»)

                Dim x As Integer = Integer.Parse(Console.ReadLine())

                Console.WriteLine(«Enter y value:»)

                Dim y As Integer = Integer.Parse(Console.ReadLine())

                Console.WriteLine(x / y)

            Catch ex As FormatException

                Console.WriteLine(«Input string was not in a correct format.»)

            End Try

        Catch ex As Exception

            Console.WriteLine(«Exception: « & ex.Message)

        End Try

        Console.ReadLine()

    End Sub

End Module

If you observe the above example, we defined a Try-Catch statement within another Try-Catch statement. Here, if we get any exception other than FormatException in an inner Try-Catch statement, the exception will flow to outer Catch block until it finds an appropriate exception filter.

When we execute the above program, we will get the result like as shown below.

Enter x value:

10

Enter y value:

0

Exception: Attempted to divide by zero.

If you observe the above result, the inner Try-Catch statement has failed to handle the exception so the catch block in the outer Try-Catch statement has been handled the exception.

Visual Basic Try-Catch Overview

The following are the important points which we need to remember about the Try-Catch statement.

  • In Try-Catch statement, the Try block will hold the code that may raise an exception and in the Catch block, exception handling can be done.
  • The Try-Catch statement will contain a Try block followed by one or more Catch blocks to handle different exceptions.
  • In visual basic, whenever an exception occurred in the Try block, then the CLR (common language runtime) will look for the appropriate Catch block that handles an exception.
  • In visual basic, we can use nested Try-Catch statements.
  • In nested Try-Catch statements, if there isn’t any inner Catch block with an appropriate exception type, then the exception will be caught by an outer Catch block.
title description ms.date f1_keywords helpviewer_keywords ms.assetid

Try…Catch…Finally statement

Learn to use exception handling with Visual Basic Try/Catch/Finally statements.

12/07/2018

vb.Try…Catch…Finally

vb.when

vb.Finally

vb.Catch

vb.Try

Try…Catch…Finally statements

Try statement [Visual Basic]

try-catch exception handling, Try…Catch…Finally statements

error handling, while running code

Try statement [Visual Basic], Try…Catch…Finally

Finally keyword [Visual Basic], Try…Catch…Finally

Catch statement [Visual Basic]

When keyword [Visual Basic]

Visual Basic code, handling errors while running

structured exception handling, Try…Catch…Finally statements

d6488026-ccb3-42b8-a810-0d97b9d6472b

Try…Catch…Finally Statement (Visual Basic)

Provides a way to handle some or all possible errors that may occur in a given block of code, while still running code.

Syntax

Try
    [ tryStatements ]
    [ Exit Try ]
[ Catch [ exception [ As type ] ] [ When expression ]
    [ catchStatements ]
    [ Exit Try ] ]
[ Catch ... ]
[ Finally
    [ finallyStatements ] ]
End Try

Parts

Term Definition
tryStatements Optional. Statement(s) where an error can occur. Can be a compound statement.
Catch Optional. Multiple Catch blocks permitted. If an exception occurs when processing the Try block, each Catch statement is examined in textual order to determine whether it handles the exception, with exception representing the exception that has been thrown.
exception Optional. Any variable name. The initial value of exception is the value of the thrown error. Used with Catch to specify the error caught. If omitted, the Catch statement catches any exception.
type Optional. Specifies the type of class filter. If the value of exception is of the type specified by type or of a derived type, the identifier becomes bound to the exception object.
When Optional. A Catch statement with a When clause catches exceptions only when expression evaluates to True. A When clause is applied only after checking the type of the exception, and expression may refer to the identifier representing the exception.
expression Optional. Must be implicitly convertible to Boolean. Any expression that describes a generic filter. Typically used to filter by error number. Used with When keyword to specify circumstances under which the error is caught.
catchStatements Optional. Statement(s) to handle errors that occur in the associated Try block. Can be a compound statement.
Exit Try Optional. Keyword that breaks out of the Try...Catch...Finally structure. Execution resumes with the code immediately following the End Try statement. The Finally statement will still be executed. Not allowed in Finally blocks.
Finally Optional. A Finally block is always executed when execution leaves any part of the Try...Catch statement.
finallyStatements Optional. Statement(s) that are executed after all other error processing has occurred.
End Try Terminates the Try...Catch...Finally structure.

Remarks

If you expect that a particular exception might occur during a particular section of code, put the code in a Try block and use a Catch block to retain control and handle the exception if it occurs.

A Try…Catch statement consists of a Try block followed by one or more Catch clauses, which specify handlers for various exceptions. When an exception is thrown in a Try block, Visual Basic looks for the Catch statement that handles the exception. If a matching Catch statement is not found, Visual Basic examines the method that called the current method, and so on up the call stack. If no Catch block is found, Visual Basic displays an unhandled exception message to the user and stops execution of the program.

You can use more than one Catch statement in a Try…Catch statement. If you do this, the order of the Catch clauses is significant because they are examined in order. Catch the more specific exceptions before the less specific ones.

The following Catch statement conditions are the least specific, and will catch all exceptions that derive from the xref:System.Exception class. You should ordinarily use one of these variations as the last Catch block in the Try...Catch...Finally structure, after catching all the specific exceptions you expect. Control flow can never reach a Catch block that follows either of these variations.

  • The type is Exception, for example: Catch ex As Exception

  • The statement has no exception variable, for example: Catch

When a Try…Catch…Finally statement is nested in another Try block, Visual Basic first examines each Catch statement in the innermost Try block. If no matching Catch statement is found, the search proceeds to the Catch statements of the outer Try…Catch…Finally block.

Local variables from a Try block are not available in a Catch block because they are separate blocks. If you want to use a variable in more than one block, declare the variable outside the Try...Catch...Finally structure.

[!TIP]
The Try…Catch…Finally statement is available as an IntelliSense code snippet. In the Code Snippets Manager, expand Code Patterns — If, For Each, Try Catch, Property, etc, and then Error Handling (Exceptions). For more information, see Code Snippets.

Finally block

If you have one or more statements that must run before you exit the Try structure, use a Finally block. Control passes to the Finally block just before it passes out of the Try…Catch structure. This is true even if an exception occurs anywhere inside the Try structure.

A Finally block is useful for running any code that must execute even if there is an exception. Control is passed to the Finally block regardless of how the Try...Catch block exits.

The code in a Finally block runs even if your code encounters a Return statement in a Try or Catch block. Control does not pass from a Try or Catch block to the corresponding Finally block in the following cases:

  • An End Statement is encountered in the Try or Catch block.

  • A xref:System.StackOverflowException is thrown in the Try or Catch block.

It is not valid to explicitly transfer execution into a Finally block. Transferring execution out of a Finally block is not valid, except through an exception.

If a Try statement does not contain at least one Catch block, it must contain a Finally block.

[!TIP]
If you do not have to catch specific exceptions, the Using statement behaves like a Try…Finally block, and guarantees disposal of the resources, regardless of how you exit the block. This is true even with an unhandled exception. For more information, see Using Statement.

Exception argument

The Catch block exception argument is an instance of the xref:System.Exception class or a class that derives from the Exception class. The Exception class instance corresponds to the error that occurred in the Try block.

The properties of the Exception object help to identify the cause and location of an exception. For example, the xref:System.Exception.StackTrace%2A property lists the called methods that led to the exception, helping you find where the error occurred in the code. xref:System.Exception.Message%2A returns a message that describes the exception. xref:System.Exception.HelpLink%2A returns a link to an associated Help file. xref:System.Exception.InnerException%2A returns the Exception object that caused the current exception, or it returns Nothing if there is no original Exception.

Considerations when using a Try…Catch statement

Use a Try…Catch statement only to signal the occurrence of unusual or unanticipated program events. Reasons for this include the following:

  • Catching exceptions at run time creates additional overhead, and is likely to be slower than pre-checking to avoid exceptions.

  • If a Catch block is not handled correctly, the exception might not be reported correctly to users.

  • Exception handling makes a program more complex.

You do not always need a Try…Catch statement to check for a condition that is likely to occur. The following example checks whether a file exists before trying to open it. This reduces the need for catching an exception thrown by the xref:System.IO.File.OpenText%2A method.

[!code-vbVbVbalrStatements#94]

Ensure that code in Catch blocks can properly report exceptions to users, whether through thread-safe logging or appropriate messages. Otherwise, exceptions might remain unknown.

Async methods

If you mark a method with the Async modifier, you can use the Await operator in the method. A statement with the Await operator suspends execution of the method until the awaited task completes. The task represents ongoing work. When the task that’s associated with the Await operator finishes, execution resumes in the same method. For more information, see Control Flow in Async Programs.

A task returned by an Async method may end in a faulted state, indicating that it completed due to an unhandled exception. A task may also end in a canceled state, which results in an OperationCanceledException being thrown out of the await expression. To catch either type of exception, place the Await expression that’s associated with the task in a Try block, and catch the exception in the Catch block. An example is provided later in this topic.

A task can be in a faulted state because multiple exceptions were responsible for its faulting. For example, the task might be the result of a call to xref:System.Threading.Tasks.Task.WhenAll%2A?displayProperty=nameWithType. When you await such a task, the caught exception is only one of the exceptions, and you can’t predict which exception will be caught. An example is provided later in this topic.

An Await expression can’t be inside a Catch block or Finally block.

Iterators

An iterator function or Get accessor performs a custom iteration over a collection. An iterator uses a Yield statement to return each element of the collection one at a time. You call an iterator function by using a For Each…Next Statement.

A Yield statement can be inside a Try block. A Try block that contains a Yield statement can have Catch blocks, and can have a Finally block. See the «Try Blocks in Visual Basic» section of Iterators for an example.

A Yield statement cannot be inside a Catch block or a Finally block.

If the For Each body (outside of the iterator function) throws an exception, a Catch block in the iterator function is not executed, but a Finally block in the iterator function is executed. A Catch block inside an iterator function catches only exceptions that occur inside the iterator function.

Partial-trust situations

In partial-trust situations, such as an application hosted on a network share, Try...Catch...Finally does not catch security exceptions that occur before the method that contains the call is invoked. The following example, when you put it on a server share and run from there, produces the error «System.Security.SecurityException: Request Failed.» For more information about security exceptions, see the xref:System.Security.SecurityException class.

[!code-vbVbVbalrStatements#85]

In such a partial-trust situation, you have to put the Process.Start statement in a separate Sub. The initial call to the Sub will fail. This enables Try...Catch to catch it before the Sub that contains Process.Start is started and the security exception produced.

Examples

The structure of Try…Catch…Finally

The following example illustrates the structure of the Try...Catch...Finally statement.

[!code-vbVbVbalrStatements#86]

Exception in a method called from a Try block

In the following example, the CreateException method throws a NullReferenceException. The code that generates the exception is not in a Try block. Therefore, the CreateException method does not handle the exception. The RunSample method does handle the exception because the call to the CreateException method is in a Try block.

The example includes Catch statements for several types of exceptions, ordered from the most specific to the most general.

[!code-vbVbVbalrStatements#91]

The Catch When statement

The following example shows how to use a Catch When statement to filter on a conditional expression. If the conditional expression evaluates to True, the code in the Catch block runs.

[!code-vbVbVbalrStatements#92]

Nested Try statements

The following example has a Try…Catch statement that is contained in a Try block. The inner Catch block throws an exception that has its InnerException property set to the original exception. The outer Catch block reports its own exception and the inner exception.

[!code-vbVbVbalrStatements#93]

Exception handling for async methods

The following example illustrates exception handling for async methods. To catch an exception that applies to an async task, the Await expression is in a Try block of the caller, and the exception is caught in the Catch block.

Uncomment the Throw New Exception line in the example to demonstrate exception handling. The exception is caught in the Catch block, the task’s IsFaulted property is set to True, and the task’s Exception.InnerException property is set to the exception.

Uncomment the Throw New OperationCancelledException line to demonstrate what happens when you cancel an asynchronous process. The exception is caught in the Catch block, and the task’s IsCanceled property is set to True. However, under some conditions that don’t apply to this example, IsFaulted is set to True and IsCanceled is set to False.

:::code language=»vb» source=»./snippets/try-catch-finally-statement/vb/AsyncExceptionExamples.vb» ID=»Snippet1″:::

Handling multiple exceptions in async methods

The following example illustrates exception handling where multiple tasks can result in multiple exceptions. The Try block has the Await expression for the task that xref:System.Threading.Tasks.Task.WhenAll%2A?displayProperty=nameWithType returned. The task is complete when the three tasks to which xref:System.Threading.Tasks.Task.WhenAll%2A?displayProperty=nameWithType is applied are complete.

Each of the three tasks causes an exception. The Catch block iterates through the exceptions, which are found in the Exception.InnerExceptions property of the task that Task.WhenAll returned.

:::code language=»vb» source=»./snippets/try-catch-finally-statement/vb/AsyncExceptionExamples.vb» ID=»Snippet3″:::

See also

  • xref:Microsoft.VisualBasic.Information.Err%2A
  • xref:System.Exception
  • Exit Statement
  • On Error Statement
  • Best Practices for Using Code Snippets
  • Exception Handling
  • Throw Statement

Понравилась статья? Поделить с друзьями:
  • Vba tools for excel
  • Vba to update sql from excel
  • Vba to kill excel
  • Vba to group rows in excel
  • Vba to color cells in excel