Catch error in vba

In this ArticleVBA Errors Cheat SheetErrorsVBA Error HandlingVBA On Error StatementOn Error GoTo 0On Error Resume NextErr.Number, Err.Clear, and Catching ErrorsError Handling with Err.NumberOn Error GoTo LineOn Error Exit SubErr.Clear, On Error GoTo -1,  and Resetting Err.NumberVBA On Error MsgBoxVBA IsErrorIf Error VBAVBA Error TypesRuntime ErrorsSyntax ErrorsCompile ErrorsDebug > CompileOverFlow ErrorOther VBA Error TermsVBA Catch ErrorVBA…

In this Article

  • VBA Errors Cheat Sheet
    • Errors
  • VBA Error Handling
  • VBA On Error Statement
    • On Error GoTo 0
    • On Error Resume Next
    • Err.Number, Err.Clear, and Catching Errors
      • Error Handling with Err.Number
    • On Error GoTo Line
      • On Error Exit Sub
      • Err.Clear, On Error GoTo -1,  and Resetting Err.Number
      • VBA On Error MsgBox
  • VBA IsError
  • If Error VBA
  • VBA Error Types
    • Runtime Errors
    • Syntax Errors
    • Compile Errors
    • Debug > Compile
    • OverFlow Error
  • Other VBA Error Terms
    • VBA Catch Error
    • VBA Ignore Error
    • VBA Throw Error / Err.Raise
    • VBA Error Trapping
    • VBA Error Message
    • VBA Error Handling in a Loop
  • VBA Error Handling in Access

VBA Errors Cheat Sheet

Errors

On Error – Stop code and display error

On Error Goto 0

On Error – Skip error and continue running

On Error Resume Next

On Error – Go to a line of code [Label]

On Error Goto [Label]

Clears (Resets) Error

On Error GoTo1

Show Error number

MsgBox Err.Number

Show Description of error

MsgBox Err.Description

Function to generate own error

Err.Raise

See more VBA “Cheat Sheets” and free PDF Downloads

VBA Error Handling

VBA Error Handling refers to the process of anticipating, detecting, and resolving VBA Runtime Errors. The VBA Error Handling process occurs when writing code, before any errors actually occur.

VBA Runtime Errors are errors that occur during code execution. Examples of runtime errors include:

  • Referencing a non-existent workbook, worksheet, or other object (Run-time Error 1004)
  • Invalid data ex. referencing an Excel cell containing an error (Type Mismatch – Run-time Error 13)
  • Attempting to divide by zero

VBA On Error Statement

Most VBA error handling is done with the On Error Statement. The On Error statement tells VBA what to do if it encounters an error. There are three On Error Statements:

  • On Error GoTo 0
  • On Error Resume Next
  • On Error GoTo Line

On Error GoTo 0

On Error GoTo 0 is VBA’s default setting. You can restore this default setting by adding the following line of code:

On Error GoTo 0

When an error occurs with On Error GoTo 0, VBA will stop executing code and display its standard error message box.

vba runtime error 13

Often you will add an On Error GoTo 0 after adding On Error Resume Next error handling (next section):

Sub ErrorGoTo0()

On Error Resume Next
    ActiveSheet.Shapes("Start_Button").Delete
On Error GoTo 0

'Run More Code

End Sub

On Error Resume Next

On Error Resume Next tells VBA to skip any lines of code containing errors and proceed to the next line.

On Error Resume Next

Note: On Error Resume Next does not fix an error, or otherwise resolve it. It simply tells VBA to proceed as if the line of code containing the error did not exist. Improper use of On Error Resume Next can result in unintended consequences.

A great time to use On Error Resume Next is when working with objects that may or may not exist. For example, you want to write some code that will delete a shape, but if you run the code when the shape is already deleted, VBA will throw an error. Instead you can use On Error Resume Next to tell VBA to delete the shape if it exists.

On Error Resume Next
    ActiveSheet.Shapes("Start_Button").Delete
On Error GoTo 0

Notice we added On Error GoTo 0 after the line of code containing the potential error. This resets the error handling.

In the next section we’ll show you how to test if an error occurred using Err.Number, giving you more advanced error handling options.

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!

automacro

Learn More

Err.Number, Err.Clear, and Catching Errors

Instead of simply skipping over a line containing an error, we can catch the error by using On Error Resume Next and Err.Number.

Err.Number returns an error number corresponding with the type of error detected. If there is no error, Err.Number = 0.

For example, this procedure will return “11” because the error that occurs is Run-time error ’11’.

Sub ErrorNumber_ex()

On Error Resume Next
ActiveCell.Value = 2 / 0
MsgBox Err.Number

End Sub

vba run-time error 11 err.number

Error Handling with Err.Number

The true power of Err.Number lies in the ability to detect if an error occurred (Err.Number <> 0).  In the example below, we’ve created a function that will test if a sheet exists by using Err.Number.

Sub TestWS()
    MsgBox DoesWSExist("test")
End Sub

Function DoesWSExist(wsName As String) As Boolean
    Dim ws As Worksheet
    
    On Error Resume Next
    Set ws = Sheets(wsName)
    
    'If Error WS Does not exist
    If Err.Number <> 0 Then
        DoesWSExist = False
    Else
        DoesWSExist = True
    End If

    On Error GoTo -1
End Function

Note: We’ve added a On Error GoTo -1 to the end which resets Err.Number to 0 (see two sections down).

With On Error Resume Next and Err.Number, you can replicate the “Try” & “Catch” functionality of other programming languages.

On Error GoTo Line

On Error GoTo Line tells VBA to “go to” a labeled line of code when an error is encountered.  You declare the Go To statement like this (where errHandler is the line label to go to):

On Error GoTo errHandler

and create a line label like this:

errHandler:

Note: This is the same label that you’d use with a regular VBA GoTo Statement.

Below we will demonstrate using On Error GoTo Line to Exit a procedure.

On Error Exit Sub

You can use On Error GoTo Line to exit a sub when an error occurs.

You can do this by placing the error handler line label at the end of your procedure:

Sub ErrGoToEnd()

On Error GoTo endProc

'Some Code
    
endProc:
End Sub

or by using the Exit Sub command:

Sub ErrGoToEnd()

On Error GoTo endProc

'Some Code
GoTo skipExit
    
endProc:
Exit Sub

skipExit:

'Some More Code

End Sub

Err.Clear, On Error GoTo -1,  and Resetting Err.Number

After an error is handled, you should generally clear the error to prevent future issues with error handling.

After an error occurs, both Err.Clear and On Error GoTo -1 can be used to reset Err.Number to 0. But there is one very important difference: Err.Clear does not reset the actual error itself, it only resets the Err.Number.

What does that mean?  Using Err.Clear, you will not be able to change the error handling setting. To see the difference, test out this code and replace On Error GoTo -1 with Err.Clear:

Sub ErrExamples()

    On Error GoTo errHandler:
        
    '"Application-defined" error
    Error (13)
    
Exit Sub
errHandler:
    ' Clear Error
    On Error GoTo -1
    
    On Error GoTo errHandler2:
    
    '"Type mismatch" error
    Error (1034)
    
Exit Sub
errHandler2:
    Debug.Print Err.Description
End Sub

Typically, I recommend always using On Error GoTo -1, unless you have a good reason to use Err.Clear instead.

VBA On Error MsgBox

You might also want to display a Message Box on error.  This example will display different message boxes depending on where the error occurs:

Sub ErrorMessageEx()
 
Dim errMsg As String
On Error GoTo errHandler

    'Stage 1
    errMsg = "An error occured during the Copy & Paste stage."
    'Err.Raise (11)
    
    'Stage 2
    errMsg = "An error occured during the Data Validation stage."
    'Err.Raise (11)
     
    'Stage 3
    errMsg = "An error occured during the P&L-Building and Copy-Over stage."
    Err.Raise (11)
     
    'Stage 4
    errMsg = "An error occured while attempting to log the Import on the Setup Page"
    'Err.Raise (11)

    GoTo endProc
    
errHandler:
    MsgBox errMsg
   
endProc:
End Sub

Here you would replace Err.Raise(11) with your actual code.

VBA IsError

Another way to handle errors is to test for them with the VBA ISERROR Function. The ISERROR Function tests an expression for errors, returning TRUE or FALSE if an error occurs.

Sub IsErrorEx()
    MsgBox IsError(Range("a7").Value)
End Sub

VBA Programming | Code Generator does work for you!

If Error VBA

You can also handle errors in VBA with the Excel IFERROR Function.  The IFERROR Function must be accessed by using the WorksheetFunction Class:

Sub IfErrorEx()

Dim n As Long
n = WorksheetFunction.IfError(Range("a10").Value, 0)

MsgBox n
End Sub

This will output the value of Range A10, if the value is an error, it will output 0 instead.

VBA Error Types

Runtime Errors

As stated above:

VBA Runtime Errors are errors that occur during code execution. Examples of runtime errors include:

  • Referencing a non-existent workbook, worksheet, or other object
  • Invalid data ex. referencing an Excel cell containing an error
  • Attempting to divide by zero

vba runtime error 13

You can “error handle” runtime errors using the methods discussed above.

Syntax Errors

VBA Syntax Errors are errors with code writing. Examples of syntax errors include:

  • Mispelling
  • Missing or incorrect punctuation

The VBA Editor identifies many syntax errors with red highlighting:

vba syntax error example

The VBA Editor also has an option to “Auto Syntax Check”:

vba syntax error option

When this is checked, the VBA Editor will generate a message box alerting you syntax errors after you enter a line of code:

vba syntax compile error

I personally find this extremely annoying and disable the feature.

Compile Errors

Before attempting to run a procedure, VBA will “compile” the procedure. Compiling transforms the program from source code (that you can see) into executable form (you can’t see).

VBA Compile Errors are errors that prevent the code from compiling.

A good example of a compile error is a missing variable declaration:

vba compile error variable

Other examples include:

  • For without Next
  • Select without End Select
  • If without End If
  • Calling a procedure that does not exist

Syntax Errors (previous section) are a subset of Compile Errors.

AutoMacro | Ultimate VBA Add-in | Click for Free Trial!

Debug > Compile

Compile errors will appear when you attempt to run a Procedure. But ideally, you would identify compile errors prior to attempting to run the procedure.

You can do this by compiling the project ahead of time. To do so, go to Debug > Compile VBA Project.

vba debug compile

The compiler will “go to” the first error. Once you fix that error, compile the project again. Repeat until all errors are fixed.

You can tell that all errors are fixed because Compile VBA Project will be grayed out:

vba compile vbaproject

OverFlow Error

The VBA OverFlow Error occurs when you attempt to put a value into a variable that is too large. For example, Integer Variables can only contain values between -32,768 to 32,768. If you enter a larger value, you’ll receive an Overflow error:

vba overflow error

Instead, you should use the Long Variable to store the larger number.

Other VBA Error Terms

VBA Catch Error

Unlike other programming languages, In VBA there is no Catch Statement. However, you can replicate a Catch Statement by using On Error Resume Next and If Err.Number <> 0 Then. This is covered above in Error Handling with Err.Number.

AutoMacro | Ultimate VBA Add-in | Click for Free Trial!

VBA Ignore Error

To ignore errors in VBA, simply use the On Error Resume Next statement:

On Error Resume Next

However, as mentioned above, you should be careful using this statement as it doesn’t fix an error, it just simply ignores the line of code containing the error.

VBA Throw Error / Err.Raise

To through an error in VBA, you use the Err.Raise method.

This line of code will raise Run-time error ’13’: Type mismatch:

Err.Raise (13)

vba runtime error 13

VBA Error Trapping

VBA Error Trapping is just another term for VBA Error Handling.

VBA Error Message

A VBA Error Message looks like this:

vba runtime error 13

When you click ‘Debug’, you’ll see the line of code that is throwing the error:

vba raise error

AutoMacro | Ultimate VBA Add-in | Click for Free Trial!

VBA Error Handling in a Loop

The best way to error handle within a Loop is by using On Error Resume Next along with Err.Number to detect if an error has occurred (Remember to use Err.Clear to clear the error after each occurrence).

The example below will divide two numbers (Column A by Column B) and output the result into Column C. If there’s an error, the result will be 0.

Sub test()
Dim cell As Range

On Error Resume Next
For Each cell In Range("a1:a10")

    'Set Cell Value
    cell.Offset(0, 2).Value = cell.Value / cell.Offset(0, 1).Value
    
    'If Cell.Value is Error then Default to 0
    If Err.Number <> 0 Then
         cell.Offset(0, 2).Value = 0
         Err.Clear
    End If
 Next
End Sub

VBA Error Handling in Access

All of the above examples work exactly the same in Access VBA as in Excel VBA.

Function DelRecord(frm As Form)
'this function is used to delete a record in a table from a form
   On Error GoTo ending
   With frm
      If .NewRecord Then
         .Undo
         Exit Function
      End If
   End With
   With frm.RecordsetClone
      .Bookmark = frm.Bookmark
      .Delete
      frm.Requery
   End With
   Exit Function
   ending:
   End
End Function

  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.

“Abort, Retry, Fail?” – MS-DOS error message circa 1986

This post provides a complete guide to VBA Error Handing. If you are looking for a quick summary then check out the quick guide table in the first section.

If you are looking for a particular topic on VBA Error Handing then check out the table of contents below(if it’s not visible click on the post header).

If you are new to VBA Error Handling, then you can read the post from start to finish as it is laid out in logical order.

Contents

  • 1 A Quick Guide to Error Handing
  • 2 The Webinar
  • 3 Download the Error Handling Library
  • 4 Introduction
  • 5 VBA Errors
    • 5.1 Syntax Errors
    • 5.2 Compilation Errors
      • 5.2.1 Using Debug->Compile
      • 5.2.2 Debug->Compile Error Summary
      • 5.2.3 Debug->Compile Usage
    • 5.3 Runtime Errors
      • 5.3.1 Expected Versus Unexpected Errors
    • 5.4 Runtime Errors that are not VBA Errors
  • 6 The On Error Statement
    • 6.1 On Error GoTo 0
    • 6.2 On Error Resume Next
    • 6.3 On Error GoTo [label]
    • 6.4 On Error GoTo -1
    • 6.5 Using On Error
  • 7 Resume Next
  • 8 The Err Object
    • 8.1 Getting the Line Number
    • 8.2 Using Err.Raise
    • 8.3 Using Err.Clear
  • 9 Logging
  • 10 Other Error Related Items
    • 10.1 Error Function
    • 10.2 Error Statement
  • 11 A Simple Error Handling Strategy
    • 11.1 The Basic Implementation
  • 12 A Complete Error Handling Strategy
    • 12.1 An Example of using this strategy
  • 13 Error Handling in a Nutshell
  • 14 What’s Next?

A Quick Guide to Error Handing

Item Description
On Error Goto 0 When error occurs, the code stops and displays the error.
On Error Goto -1 Clears the current error setting and reverts to the default.
On Error Resume Next Ignores the error and continues on.
On Error Goto [Label] Goes to a specific label when an error occurs.
This allows us to handle the error.
Err Object When an error occurs the error information is stored here.
Err.Number The number of the error.
(Only useful if you need to check a specific error occurred.)
Err.Description Contains the error text.
Err.Source You can populate this when you use Err.Raise.
Err.Raise A function that allows you to generate your own error.
Error Function Returns the error text from an error number.
Obsolete.
Error Statement Simulates an error. Use Err.Raise instead.

The Webinar

Members of the Webinar Archives can access the webinar for this article by clicking on the image below.

(Note: Archive members have access to the webinar archive.)

vba error handling video

Download the Error Handling Library

Introduction

Error Handling refers to code that is written to handle errors which occur when your application is running. These errors are normally caused by something outside your control like a missing file, database being unavailable, data being invalid etc.

If we think an error is likely to occur at some point, it is good practice to write specific code to handle the error if it occurs and deal with it.

For all other errors, we use generic code to deal with them. This is where the VBA error handling statement comes into play. They allow our application to deal gracefully with any errors we weren’t expecting.

To understand error handling we must first understand the different types of errors in VBA.

VBA Error Handling

VBA Errors

There are three types of errors in VBA:

  1. Syntax
  2. Compilation
  3. Runtime

We use error handling to deal with runtime errors. Let’s have a look at each of these error types so that it is clear what a runtime error is.

Syntax Errors

If you have used VBA for any length of time you will have seen a syntax error. When you type a line and press return, VBA will evaluate the syntax and if it is not correct it will display an error message.

For example if you type If and forget the Then keyword, VBA will display the following error message

VBA Error Handling

Some examples of syntax errors are

' then is missing
If a > b

' equals is missing after i
For i 2 To 7

' missing right parenthesis
b = left("ABCD",1

Syntax errors relate to one line only. They occur when the syntax of one line is incorrect.

Note: You can turn off the Syntax error dialog by going to Tools->Options and checking off “Auto Syntax Check”. The line will still appear red if there is an error but the dialog will not appear.

Compilation Errors

Compilation errors occur over more than one line. The syntax is correct on a single line but is incorrect when all the project code is taken into account.

Examples of compilation errors are:

  • If statement without corresponding End If statement
  • For without Next
  • Select without End Select
  • Calling a Sub or Function that does not exist
  • Calling a Sub or Function with the wrong parameters
  • Giving a Sub or Function the same name as a module
  • Variables not declared(Option Explicit must be present at the top of the module)

The following screenshot shows a compilation error that occurs when a For loop has no matching Next statement.

VBA Error Handling

Using Debug->Compile

To find compilation errors, we use Debug->Compile VBA Project from the Visual Basic menu.

When you select Debug->Compile, VBA displays the first error it comes across.

When this error is fixed, you can run Compile again and VBA will then find the next error.

Debug->Compile will also include syntax errors in it’s search which is very useful.

If there are no errors left and you run Debug->Compile , it may appear that nothing happened. However, “Compile” will be grayed out in the Debug menu. This means your application has no compilation errors at the current time.

Debug->Compile Error Summary

  • Debug->Compile finds compilation(project wide) errors.
  • It will also find syntax errors.
  • It finds one error each time you use it.
  • When there are no compilation errors left the Compile option will appear grayed out in the menu.

Debug->Compile Usage

You should always use Debug->Compile before you run your code. This ensures that your code has no compilation errors when you run it.

If you do not run Debug->Compile then VBA may find compile errors when it runs. These should not be confused with Runtime errors.

Runtime Errors

Runtime errors occur when your application is running. They are normally outside of your control but can be caused by errors in your code.

VBA Error Handling

For example, imagine your application reads from an external workbook. If this file gets deleted then VBA will display an error when your code tries to open it.

Other examples of runtime errors are

  • a database not being available
  • the user entering invalid data
  • a cell containing text instead of a number

As we have seen, the purpose of error handling is to deal with runtime errors when they occur.

Expected Versus Unexpected Errors

When we think a runtime error could occur we put code in place to handle it. For example, we would normally put code in place to deal with a file not being found.

The following code checks if the file exists before it tries to open it. If the file does not exist then a user friendly message is displayed and the code exits the sub.

' https://excelmacromastery.com/
Sub OpenFile()
    
    Dim sFile As String
    sFile = "C:docsdata.xlsx"
    
    ' Use Dir to check if file exists
    If Dir(sFile) = "" Then
        ' if file does not exist display message
        MsgBox "Could not find the file " & sFile
        Exit Sub
    End If
    
    ' Code will only reach here if file exists
    Workbooks.Open sFile
    
End Sub

When we think an error is likely to occur at some point, it is good practice to add code to handle the situation. We normally refer to these errors as expected errors.

If we don’t have specific code to handle an error it is considered an unexpected error. We use the VBA error handling statements to handle the unexpected errors.

Runtime Errors that are not VBA Errors

Before we look at the VBA Handling there is one type of error we must mention. Some runtime errors are not considered errors by VBA but only by the user.

Let me explain this with an example. Imagine you have an application that requires you to add the values in the variables a and b

result = a + b

Let’s say you mistakenly use an asterisk instead of the plus sign

result = a * b

This is not a VBA error. Your code syntax is perfectly legal. However, from your requirements point of view it is an error.

These errors cannot be dealt with using error handling as they obviously won’t generate any error. You can deal with these errors using Unit Testing and Assertions. I have an in-depth post about using VBA assertions – see How to Make Your Code BulletProof.

The On Error Statement

As we have seen there are two ways to treat runtime errors

  1. Expected errors – write specific code to handle them.
  2. Unexpected errors – use VBA error handling statements to handle them.

The VBA On Error statement is used for error handling. This statement performs some action when an error occurs during runtime.

There are four different ways to use this statement

  1. On Error GoTo 0 – the code stops at the line with the error and displays a message.
  2. On Error Resume Next – the code moves to next line. No error message is displayed.
  3. On Error GoTo [label] – the code moves to a specific line or label. No error message is displayed. This is the one we use for error handling.
  4. On Error GoTo -1 – clears the current error.

Let’s look at each of these statements in turn.

On Error GoTo 0

This is the default behavior of VBA. In other words, if you don’t use On Error then this is the behavior you will see.

When an error occurs, VBA stops on the line with the error and displays the error message. The application requires user intervention with the code before it can continue. This could be fixing the error or restarting the application. In this scenario no error handling takes place.

Let’s look at an example. In the following code, we have not used any On Error line so VBA will use the On Error GoTo 0 behavior by default.

' https://excelmacromastery.com/
Sub UsingDefault()

    Dim x As Long, y As Long
    
    x = 6
    y = 6 / 0
    x = 7

End Sub

The second assignment line results in a divide by zero error. When we run this code we will get the error message shown in the screenshot below

VBA Error Handling

When the error appears you can choose End or Debug

If you select End then the application simply stops.
If you select Debug the application stops on the error line as the screenshot below shows

VBA Error Handling

This behaviour is fine when you are writing VBA code as it shows you the exact line with the error.

This behavior is unsuitable for an application that you are given to a user. These errors look unprofessional and they make the application look unstable.

An error like this is essentially the application crashing. The user cannot continue on without restarting the application. They may not use it at all until you fix the error for them.

By using On Error GoTo [label] we can give the user a more controlled error message. It also prevents the application stopping. We can get the application to perform in a predefined manner.

On Error Resume Next

Using On Error Resume Next tells VBA to ignore the error and continue on.

There are specific occasions when this is useful. Most of the time you should avoid using it.

If we add Resume Next to our example Sub then VBA will ignore the divide by zero error

' https://excelmacromastery.com/
Sub UsingResumeNext()

    On Error Resume Next
    
    Dim x As Long, y As Long
    
    x = 6
    y = 6 / 0
    x = 7

End Sub

It is not a good idea to do this. If you ignore the error, then the behavior can be unpredictable. The error can affect the application in multiple ways.You could end up with invalid data. The problem is that you aren’t aware that something went wrong because you have suppressed the error.

The code below is an example of where using Resume Next is valid

' https://excelmacromastery.com/
Sub SendMail()

   On Error Resume Next
   
    ' Requires Reference:
    ' Microsoft Outlook 15.0 Object Library
    Dim Outlook As Outlook.Application
    Set Outlook = New Outlook.Application

    If Outlook Is Nothing Then
        MsgBox "Cannot create Microsoft Outlook session." _
                   & " The email will not be sent."
        Exit Sub
    End If
    
End Sub

In this code we are checking to see if Microsoft Outlook is available on a computer. All we want to know is if it is available or not. We are not interested in the specific error.

In the code above, we continue on if there is an error. Then in the next line we check the value of the Outlook variable. If there has been an error then the value of this variable will be set to Nothing.

This is an example of when Resume could be useful. The point is that even though we use Resume we are still checking for the error. The vast majority of the time you will not need to use Resume.

On Error GoTo [label]

This is how we use Error Handling in VBA. It is the equivalent of the Try and Catch functionality you see in languages such as C# and Java.

When an error occurs you send the error to a specific label. It is normally at the bottom of the sub.

Let’s apply this to the sub we have been using

' https://excelmacromastery.com/
Sub UsingGotoLine()

    On Error GoTo eh
    
    Dim x As Long, y As Long
    
    x = 6
    y = 6 / 0
    x = 7
    
Done:
    Exit Sub
eh:
    MsgBox "The following error occurred: " & Err.Description
End Sub

The screenshot below shows what happens when an error occurs

VBA Error Handling

VBA jumps to the eh label because we specified this in the On Error Goto line.

Note 1: The label we use in the On…GoTo statement, must be in the current Sub/Function. If not you will get a compilation error.

Note 2: When an error occurs when using On Error GoTo [label], the error handling returns to the default behaviour i.e. The code will stop on the line with the error and display the error message. See the next section for more information about this.

On Error GoTo -1

This statement is different than the other three. It is used to clear the current error rather than setting a particular behaviour.

When an error occurs using On Error GoTo [label], the error handling behaviour returns to the default behaviour i.e. “On Error GoTo 0”. That means that if another error occurs the code will stop on the current line.

This behaviour only applies to the current sub. Once we exit the sub, the error will be cleared automatically.

Take a look at the code below. The first error will cause the code to jump to the eh label. The second error will stop on the line with the 1034 error.

' https://excelmacromastery.com/
Sub TwoErrors()

    On Error Goto eh
        
    ' generate "Type mismatch" error
    Error (13)

Done:
    Exit Sub
eh:
    ' generate "Application-defined" error
    Error (1034)
End Sub

If we add further error handling it will not work as the error trap has not been cleared.

In the code below we have added the line

On Error Goto eh_other

after we catch the first error.

This has no effect as the error has not been cleared. In other words the code will stop on the line with the error and display the message.

' https://excelmacromastery.com/
Sub TwoErrors()

    On Error Goto eh
        
    ' generate "Type mismatch" error
    Error (13)

Done:
    Exit Sub
eh:
    On Error Goto eh_other
    ' generate "Application-defined" error
    Error (1034)
Exit Sub
eh_other:
    Debug.Print "eh_other " & Err.Description
End Sub

To clear the error we use On Error GoTo -1. Think of it like setting a mouse trap. When the trap goes off you need to set it again.

In the code below we add this line and the second error will now cause the code to jump to the eh_other label

' https://excelmacromastery.com/
Sub TwoErrors()

    On Error Goto eh
        
    ' generate "Type mismatch" error
    Error (13)

Done:
    Exit Sub
eh:
    ' clear error
    On Error Goto -1
    
    On Error Goto eh_other
    ' generate "Application-defined" error
    Error (1034)
Exit Sub
eh_other:
    Debug.Print "eh_other " & Err.Description
End Sub

Note 1: There are probably rare cases where using On Error GoTo -1 is useful. In most cases using Resume Next is better as it clears the error and resumes the code at the next line after the error occurs.

Note 2: The Err Object has a member Clear. Using Clear clears the text and numbers in the Err object, but it does NOT reset the error.

Using On Error

As we have seen, VBA will do one of three things when an error occurs

  • Stop and display the error.
  • Ignore the error and continue on.
  • Jump to a specific line.

VBA will always be set to one of these behaviors. When you use On Error, VBA will change to the behaviour you specify and forget about any previous behavior.

In the following Sub, VBA changes the error behaviour each time we use the On Error statement

' https://excelmacromastery.com/
Sub ErrorStates()

    Dim x As Long
    
    ' Go to eh label if error
    On Error Goto eh
    
    ' this will ignore the error on the following line
    On Error Resume Next
    x = 1 / 0
    
    ' this will display an error message on the following line
    On Error Goto 0
    x = 1 / 0
  
Done:  
   Exit Sub
eh:
    Debug.Print Err.Description
End Sub

Resume Next

The Resume Next statement is used to clear the error and then resume the code from the line after where the error occurred.

If your code can have multiple errors and you want to keep detecting them then this line is very useful.

For example, in the following code we want to resume the code after the error has been reported:

Private Sub Main()

    On Error Goto eh
    
    Dim i As Long
    For i = 1 To 3
        ' Generate type mismatch error
         Error 13
    Next i

done:
    Exit Sub
eh:
    Debug.Print i, Err.Description
End Sub

 
We could use On Error Goto -1 to clear the code and then use a goto statement to go back to the code like this:

Private Sub Main()

    On Error Goto eh
    
    Dim i As Long
    For i = 1 To 3
        ' Generate type mismatch error
         Error 13
continue:
    Next i

done:
    Exit Sub
eh:
    Debug.Print i, Err.Description
    On Error Goto -1 ' clear the error
    Goto continue ' return to the code
End Sub

 
The Resume Next provides a nicer way of doing it and it always means the code is much clearer and easier to understand:

Private Sub Main()

    On Error Goto eh
    
    Dim i As Long
    For i = 1 To 3
        ' Generate type mismatch error
         Error 13
continue:
    Next i

done:
    Exit Sub
eh:
    Debug.Print i, Err.Description
    ' clear the error and return to the code
    Resume Next  
End Sub

The Err Object

When an error occurs you can view details of the error using the Err object.

When an runtime error occurs, VBA automatically fills the Err object with details.

The code below will print “Error Number: 13 Type Mismatch” which occurs when we try to place a string value in the long integer total

' https://excelmacromastery.com/
Sub UsingErr()

    On Error Goto eh
    
    Dim total As Long
    total = "aa"

Done:
    Exit Sub
eh:
    Debug.Print "Error number: " & Err.Number _
            & " " & Err.Description
End Sub

The Err.Description provides details of the error that occurs. This is the text you normally see when an error occurs e.g. “Type Mismatch”

The Err.Number is the ID number of the error e.g. the error number for “Type Mismatch” is 13. The only time you really need this is if you are checking that a specific error occurred and this is only necessary on rare occasions.

The Err.Source property seems like a great idea but it does not work for a VBA error. The source will return the project name, which hardly narrows down where the error occurred. However, if you create an error using Err.Raise you can set the source yourself and this can be very useful.

Getting the Line Number

The Erl function is used to return the line number where the error occurs.

It often causes confusion. In the following code, Erl will return zero

' https://excelmacromastery.com/
Sub UsingErr()

    On Error Goto eh
    
    Dim val As Long
    val = "aa"

Done:
    Exit Sub
eh:
    Debug.Print Erl
End Sub

This is because there are no line numbers present. Most people don’t realise it but VBA allows you to have line numbers.

If we change the Sub above to have line number it will now print out 20

' https://excelmacromastery.com/
Sub UsingErr()

10        On Error Goto eh
          
          Dim val As Long
20        val = "aa"

Done:
30        Exit Sub
eh:
40        Debug.Print Erl
End Sub

Adding line numbers to your code manually is cumbersome. However there are tools available that will allow you to easily add and remove line numbers to a sub.

When you are finished working on a project and hand it over to the user it can be useful to add line numbers at this point. If you use the error handling strategy in the last section of this post, then VBA will report the line where the error occurred.

Using Err.Raise

Err.Raise allows us to create errors. We can use it to create custom errors for our application which is very useful. It is the equivalent of the Throw statement in JavaC#.

The format is as follows

Err.Raise [error number], [error source], [error description]

Let’s look at a simple example. Imagine we want to ensure that a cell has an entry that has a length of 5 characters. We could have a specific message for this

' https://excelmacromastery.com/
Public Const ERROR_INVALID_DATA As Long = vbObjectError + 513

Sub ReadWorksheet()

    On Error Goto eh
    
    If Len(Sheet1.Range("A1")) <> 5 Then
        Err.Raise ERROR_INVALID_DATA, "ReadWorksheet" _
            , "The value in the cell A1 must have exactly 5 characters."
    End If
    
    ' continue on if cell has valid data
    Dim id As String
    id = Sheet1.Range("A1")
    

Done:
    Exit Sub
eh:
    ' Err.Raise will send code to here
    MsgBox "Error found: " & Err.Description
End Sub

When we create an error using Err.Raise we need to give it a number. We can use any number from 513 to 65535 for our error. We must use vbObjectError with the number e.g.

Err.Raise vbObjectError + 513

Using Err.Clear

Err.Clear is used to clear the text and numbers from the Err.Object. In other words, it clears the description and number.If you want the clear the actual error you can use either On Error GoTo -1 or Resume Next

It is rare that you will need to use Err.Clear but let’s have a look at an example where you might.

In the code below we are counting the number of errors that will occur. To keep it simple we are generating an error for each odd number.

We check the error number each time we go through the loop. If the number does not equal zero then an error has occurred. Once we count the error we need to set the error number back to zero so it is ready to check for the next error.

' https://excelmacromastery.com/
Sub UsingErrClear()

    Dim count As Long, i As Long

    ' Continue if error as we will check the error number
    On Error Resume Next
    
    For i = 0 To 9
        ' generate error for every second one
        If i Mod 2 = 0 Then Error (13)
        
        ' Check for error
        If Err.Number <> 0 Then
            count = count + 1
            Err.Clear    ' Clear Err once it is counted
        End If
    Next

    Debug.Print "The number of errors was: " & count
End Sub

Note 1: Err.Clear resets the text and numbers in the error object but it does not clear the error – see Resume Next Or On Error GoTo -1 for more information about clearing the actual error.

Logging

Logging means writing information from your application when it is running. When an error occurs you can write the details to a text file so you have a record of the error.

The code below shows a very simple logging procedure

' https://excelmacromastery.com/
Sub Logger(sType As String, sSource As String, sDetails As String)
    
    Dim sFilename As String
    sFilename = "C:templogging.txt"
    
    ' Archive file at certain size
    If FileLen(sFilename) > 20000 Then
        FileCopy sFilename _
            , Replace(sFilename, ".txt", Format(Now, "ddmmyyyy hhmmss.txt"))
        Kill sFilename
    End If
    
    ' Open the file to write
    Dim filenumber As Variant
    filenumber = FreeFile 
    Open sFilename For Append As #filenumber
    
    Print #filenumber, CStr(Now) & "," & sType & "," & sSource _
                                & "," & sDetails & "," & Application.UserName
    
    Close #filenumber
    
End Sub

You can use it like this

' Create unique error number
' https://excelmacromastery.com/
Public Const ERROR_DATA_MISSING As Long = vbObjectError + 514

Sub CreateReport()

    On Error Goto eh
    
    If Sheet1.Range("A1") = "" Then
       Err.Raise ERROR_DATA_MISSING, "CreateReport", "Data is missing from Cell A1"
    End If

    ' other code here
Done:
    Exit Sub
eh:
    Logger "Error", Err.Source, Err.Description
End Sub

The log is not only for recording errors. You can record other information as the application runs. When an error occurs you can then check the sequence of events before an error occurred.

Below is an example of logging. How you implement logging really depends on the nature of the application and how useful it will be:

' https://excelmacromastery.com/
Sub ReadingData()
    
    Logger "Information", "ReadingData()", "Starting to read data."
       
    Dim coll As New Collection
    ' add data to the collection
    coll.Add "Apple"
    coll.Add "Pear"
    
    If coll.Count < 3 Then
        Logger "Warning", "ReadingData()", "Number of data items is low."
    End If
    Logger "Information", "ReadingData()", "Number of data items is " & coll.Count
    
    Logger "Information", "ReadingData()", "Finished reading data."

End Sub

Having a lot of information when dealing with an error can be very useful. Often the user may not give you accurate information about the error that occurred. By looking at the log you can get more accurate information about the information.

This section covers some of the other Error Handling tools that VBA has. These items are considered obsolete but I have included them as they may exist in legacy code.

Error Function

The Error Function is used to print the error description from a given error number. It is included in VBA for backward compatibility and is not needed because you can use the Err.Description instead.

Below are some examples:

' Print the text "Division by zero"
Debug.Print Error(11)
' Print the text "Type mismatch"
Debug.Print Error(13)
' Print the text "File not found"
Debug.Print Error(53)

Error Statement

The Error statement allows you to simulate an error. It is included in VBA for backward compatibility. You should use Err.Raise instead.

In the following code we simulate a “Divide by zero” error.

' https://excelmacromastery.com/
Sub SimDivError()

    On Error Goto eh
        
    ' This will create a division by zero error
    Error 11
    
    Exit Sub
eh:
    Debug.Print Err.Number, Err.Description
End Sub

This statement is included in VBA for backward compatibility. You should use Err.Raise instead.

A Simple Error Handling Strategy

With all the different options you may be confused about how to use error handling in VBA. In this section, I’m going to show you how to implement a simple error handling strategy that you can use in all your applications.

The Basic Implementation

This is a simple overview of our strategy

  1. Place the On Error GoTo Label line at the start of our topmost sub.
  2. Place the error handling Label at the end of our topmost sub.
  3. If an expected error occurs then handle it and continue.
  4. If the application cannot continue then use Err.Raise to jump to the error handling label.
  5. If an unexpected error occurs the code will automatically jump to the error handling label.

The following image shows an overview of how this looks

error-handling

The following code shows a simple implementation of this strategy:

' https://excelmacromastery.com/
Public Const ERROR_NO_ACCOUNTS As Long = vbObjectError + 514

Sub BuildReport()

    On Error Goto eh
    
    ' If error in ReadAccounts then jump to error
    ReadAccounts
    
    ' Do something with the code
    
Done:
    Exit Sub
eh:
    ' All errors will jump to here
    MsgBox Err.Source & ": The following error occured  " & Err.Description
End Sub

Sub ReadAccounts()
    
    ' EXPECTED ERROR - Can be handled by the code
    ' Application can handle A1 being zero
    If Sheet1.Range("A1") = 0 Then
        Sheet1.Range("A1") = 1
    End If
    
    ' EXPECTED  ERROR - cannot be handled by the code
    ' Application cannot continue if no accounts workbook
    If Dir("C:DocsAccount.xlsx") = "" Then
        Err.Raise ERROR_NO_ACCOUNTS, "UsingErr" _
                , "There are no accounts present for this month."
    End If

    ' UNEXPECTED ERROR - cannot be handled by the code
    ' If cell B3 contains text we will get a type mismatch error
    Dim total As Long
    total = Sheet1.Range("B3")
    
    
    ' continue on and read accounts
    
End Sub

This is a nice way of implementing error handling because

  • We don’t need to add error handling code to every sub.
  • If an error occurs then VBA exits the application gracefully.

A Complete Error Handling Strategy

The above strategy has one major drawback. It doesn’t provide any information about the error. It is better than having no strategy as it prevents the application crashing. But that is the only real benefit.

VBA doesn’t fill Err.Source with anything useful so we have to do this ourselves.

In this section, I am going to introduce a more complete error strategy. I have written two subs that perform all the heavy lifting so all you have to do is add them to your project.

The purpose of this strategy is to provide you with the Stack* and line number when an error exists.

*The Stack is the list of sub/functions that were currently in use when the error occurred.

This is our strategy

  1. Place error handling in all the subs.
  2. When an error occurs, the error handler adds details to the error and raises it again.
  3. When the error reaches the topmost sub it is displayed.

We are simply “bubbling” the error to the top. The following diagram shows a simple visual of what happens when an error occurs in Sub3

Error Handling - bubbling

The only messy part to this is formatting the strings correctly. I have written two subs that handle this, so it is taken care of for you.

There are the two helper subs, RaiseError and DisplayError. You can download the library below:

An Example of using this strategy

Here is a simple coding example that uses these subs. In this strategy, we don’t place any code in the topmost sub. We only call subs from it.

' https://excelmacromastery.com/
Sub Topmost()

    On Error Goto EH
    
    Level1

Done:
    Exit Sub
EH:
    DisplayError Err.source, Err.Description, "Module1.Topmost", Erl
End Sub

Sub Level1()

    On Error Goto EH
    
    Level2

Done:
    Exit Sub
EH:
   RaiseError Err.Number, Err.source, "Module1.Level1", Err.Description, Erl
End Sub

Sub Level2()

    On Error Goto EH
    
    ' Error here
    Dim a As Long
    a = "7 / 0"

Done:
    Exit Sub
EH:
    RaiseError Err.Number, Err.source, "Module1.Level2", Err.Description, Erl
End Sub

The result looks like this:

error handling output

If your project has line numbers the result will include the line number of the error:

error handling output line

Error Handling in a Nutshell

  • Error Handling is used to handle errors that occur when your application is running.
  • You write specific code to handle expected errors. You use the VBA error handling statement On Error GoTo [label] to send VBA to a label when an unexpected error occurs.
  • You can get details of the error from Err.Description.
  • You can create your own error using Err.Raise.
  • Using one On Error statement in the top most sub will catch all errors in subs that are called from here.
  • If you want to record the name of the Sub with the error, you can update the error and rethrow it.
  • You can use a log to record information about the application as it is running.

What’s Next?

Free VBA Tutorial If you are new to VBA or you want to sharpen your existing VBA skills then why not try out the The Ultimate VBA Tutorial.

Related Training: Get full access to the Excel VBA training webinars and all the tutorials.

(NOTE: Planning to build or manage a VBA Application? Learn how to build 10 Excel VBA applications from scratch.)

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

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

As we learned in the previous vb exception topic, exceptions are generated by CLR (common language runtime) or application code. To handle runtime or unexpected errors in applications, visual basic has provided a built-in exception handling support by using Try, Catch and Finally blocks.

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

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

Try

‘ Code that may cause exception

Catch ex As Exception

‘ Exception handling

Finally

‘ Cleanup resources

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, immediately the code execution will be moved to Catch block to handle those exceptions. In case, if no exception occurred in the Try block, then the Catch block will be skipped and the execution will be moved to Finally block.

After completion of Try or Try & Catch blocks, the Finally block will always execute even if an exception occurred or not and it is useful to clean up or dispose the unmanaged objects based on the 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. In Try-Catch-Finally statement, only one Try & Finally blocks are allowed but we can use multiple Catch blocks to handle different exception types.

Visual Basic Exception Handling Example

Following is the example of handling exceptions in visual basic using Try, Catch and Finally blocks.

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)

        Finally

            Console.WriteLine(«Finally Block.»)

        End Try

        Console.ReadLine()

    End Sub

End Module

If you observe the above code, we used Try, Catch and Finally 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. As discussed, the Finally block will execute after completion of Try or Catch block execution.

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

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

Finally Block.

To know more in-detail about exception handling in visual basic, check following exception handling topics.

  • Try-Catch
  • Try-Catch-Finally
  • Throw

Visual Basic Try-Catch

In visual basic, the Try-Catch statement is useful to handle unexpected or runtime exceptions that will occur during the execution of the program.

To learn more about the try-catch statement, check Visual Basic Try Catch statement.

Visual Basic Try-Catch-Finally

In visual basic, Try-Catch-Finally is useful to handle unexpected exceptions in code. Here, Finally block is useful to clean up any resources that are allocated in the Try block.

To learn more about the Try-Catch-Finally statement, check Visual Basic Try-Catch-Finally statement.

Visual Basic throw

In visual basic, Throw keyword is useful to raise an exception manually and it will throw all the exceptions which are derived from the Exception base class.

To learn more about Throw keyword in visual basic, check Visual Basic Throw Keyword.

Понравилась статья? Поделить с друзьями:
  • Catch error flutter
  • Catch error 404
  • Catch console error
  • Catalyst control center не поддерживается версией драйвера включенного видеоадаптера как исправить
  • Cat ошибка 261 13