Excel vba for next error

ГЛАВНАЯ

ТРЕНИНГИ

   Быстрый старт
   Расширенный Excel
   Мастер Формул
   Прогнозирование
   Визуализация
   Макросы на VBA

КНИГИ

   Готовые решения
   Мастер Формул
   Скульптор данных

ВИДЕОУРОКИ

ПРИЕМЫ

   Бизнес-анализ
   Выпадающие списки
   Даты и время
   Диаграммы
   Диапазоны
   Дубликаты
   Защита данных
   Интернет, email
   Книги, листы
   Макросы
   Сводные таблицы
   Текст
   Форматирование
   Функции
   Всякое
PLEX

   Коротко
   Подробно
   Версии
   Вопрос-Ответ
   Скачать
   Купить

ПРОЕКТЫ

ОНЛАЙН-КУРСЫ

ФОРУМ

   Excel
   Работа
   PLEX

© Николай Павлов, Planetaexcel, 2006-2022
info@planetaexcel.ru


Использование любых материалов сайта допускается строго с указанием прямой ссылки на источник, упоминанием названия сайта, имени автора и неизменности исходного текста и иллюстраций.

Техническая поддержка сайта

ООО «Планета Эксел»

ИНН 7735603520


ОГРН 1147746834949
        ИП Павлов Николай Владимирович
        ИНН 633015842586
        ОГРНИП 310633031600071 

The “Next Without For” Compile Error is a very common compile-time error in Excel VBA. It implies that a Next statement must always have a preceding For statement that matches it. If a Next statement is used without a corresponding For statement, this error is generated.

Let us look at some most common causes of the error and way to fix and avoid them.

Example 1: If statement without a corresponding “End If” statement

Sub noEndIf()
    Dim rng As Range
    Dim cell As Range

    Set rng = ActiveSheet.Range("B1:B10")
    For Each cell In rng
    If cell.Value = 0 Then
    cell.Interior.color = vbRed
    Else
    cell.Interior.color = vbGreen
    Next cell

End Sub

Every If statement (and If Else Statement) must have a corresponding End If statement along with it. As you can see in the above code, End If is missing after the Else block, causing the error. The right way to do it is

Sub withEndIf()
    Dim rng As Range
    Dim cell As Range

    Set rng = ActiveSheet.Range("B1:B10")
    For Each cell In rng
        If cell.Value = 0 Then
            cell.Interior.color = vbRed
        Else
            cell.Interior.color = vbGreen
        End If
    Next cell

End Sub

Example 2: Incorrect sequence of End If and Next statements

Sub incorrectEndIf()
    Dim rng As Range
    Dim cell As Range

    Set rng = ActiveSheet.Range("B1:B10")
    For Each cell In rng
    If cell.Value = 0 Then
    cell.Interior.color = vbRed
    Else
    cell.Interior.color = vbGreen
    Next cell
    End If
End Sub

Here, the End If statement is not placed correctly causing overlapping as shown below:

For
If
Next
End If

The entire If statement (including, If, Else and End If statements), must be placed withing the For…Next block as shown below

Sub correctEndIf()
    Dim rng As Range
    Dim cell As Range

    Set rng = ActiveSheet.Range("B1:B10")
    For Each cell In rng
        If cell.Value = 0 Then
            cell.Interior.color = vbRed
        Else
            cell.Interior.color = vbGreen
        End If
    Next cell

End Sub

Example 3: With statement has a corresponding End With Statement missing

Sub noEndWith()

    Dim counter As Integer
    Dim lastRow As Integer
    Dim fName As String, lName As String, fullName As String

    lastRow = 10

    For counter = 1 To lastRow

    With ActiveSheet
    fName = .Cells(counter, 1).Value
    lName = .Cells(counter, 2).Value

    fullName = fName & " "  lName
    'Further processing here

    Next counter

End Sub

Just like an If statement, the With statement should also have a corresponding End With statement, without which error will be thrown. The working example:

Sub withEndWith()
    Dim counter As Integer
    Dim lastRow As Integer
    Dim fName As String, lName As String, fullName As String

    lastRow = 10

    For counter = 1 To lastRow

        With ActiveSheet
            fName = .Cells(counter, 1).Value
            lName = .Cells(counter, 2).Value
        End With

        fullName = fName  " "  lName
        'Further processing here

    Next counter

End Sub

Example 4: Overlapping For and If Else statement

Say, in the example below, you want to do some processing only if a condition is false. Else you want to continue with the next counter of the For loop

Sub overlapping()
    Dim counter As Integer
    For counter = 1 To 10
        If Cells(counter, 1).Value = 0 Then
            Next counter
        Else
            'Do the processing here
        End If
    Next counter

End Sub

Note: as in other programming languages, VBA does not have a continue option for a loop. When the control of the program reaches the first “Next counter” statement after the If statement — it finds that there is a Next statement within the If statement. However, there is no corresponding For statement within this If Block. Hence, the error.

So, you can use one of the two solutions below:

Simply remove the “next” statement after If

Sub solution1()
    Dim counter As Integer
    For counter = 1 To 10
        If Cells(counter, 1).Value = 0 Then
            'Simply don't do anything here
        Else
            'Do the processing here
        End If
    Next counter

End Sub

OR

Not the if condition and place your code there. Else condition is not required at all

Sub solution2()
    Dim counter As Integer
    For counter = 1 To 10
        If Not Cells(counter, 1).Value = 0 Then
            'Not the if condition and
            'Do the processing here
        End If
    Next counter
End Sub

The bottom line is that the “If, Else, End If statement block” must be completely within the For loop.

Avoiding the Next without For error by using standard coding practices

The best way to avoid this error is to follow some standard practices while coding.

1. Code indentation: Indenting your code not only makes it more readable, but it helps you identify if a loop / if statement / with statement are not closed properly or if they are overlapping. Each of your If statements should align with an End If, each For statement with a Next, each With statement with an End With and each Select statement with an End Select

2. Use variable name with Next:  Though the loop variable name is not needed with a next statement, it is a good practice to mention it with the Next statement.

So, change

 Next 

to

 Next counter 

This is particularly useful when you have a large number of nested for Loops.

3. As soon as you start a loop, write the corresponding end statement immediately. After that you can code the remaining statements within these two start and end statements (after increasing the indentation by one level).

If you follow these best practices, it is possible to completely and very easily avoid this error in most cases.

See also: Compile Error: Expected End of Statement

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
    • On Error GoTo Line
  • 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

На чтение 25 мин. Просмотров 15.5k.

VBA Error Handling

Эта статья содержит полное руководство по обработке ошибок VBA. Если вы ищете краткое резюме, посмотрите таблицу быстрого руководства в первом разделе.

Если вы ищете конкретную тему по обработке ошибок VBA, ознакомьтесь с приведенным ниже содержанием.

Если вы новичок в VBA, то вы можете прочитать пост от начала до конца, так как он выложен в логическом порядке.

Содержание

  1. Краткое руководство по обработке ошибок
  2. Введение
  3. Ошибки VBA
  4. Заявление об ошибке
  5. Err объект
  6. Логирование
  7. Другие элементы, связанные с ошибками
  8. Простая стратегия обработки ошибок
  9. Полная стратегия обработки ошибок
  10. Обработка ошибок в двух словах

Краткое руководство по обработке ошибок

Пункт Описание
On Error Goto 0 При возникновении ошибки код останавливается и отображает
ошибку.
On Error Resume Next Игнорирует ошибку и
продолжает.
On Error Goto [Label] Переход к определенной метке при возникновении ошибки.
Это позволяет нам справиться
с ошибкой.
Err Object При возникновении ошибки
информация об ошибке
сохраняется здесь.
Err.Number Номер ошибки.
(Полезно, только если вам
нужно проверить, произошла ли конкретная ошибка.)
Err.Description Содержит текст ошибки.
Err.Source Вы можете заполнить это, когда используете Err.Raise.
Err.Raise Функция, которая позволяет
генерировать вашу собственную ошибку.
Error Function Возвращает текст ошибки из
номера ошибки.
Вышло из употребления.
Error Statement Имитирует ошибку. Вместо этого используйте Err.Raise.

Введение

Обработка ошибок относится к коду, который написан для обработки ошибок, возникающих во время работы вашего приложения. Эти ошибки обычно вызваны чем-то вне вашего контроля, например отсутствующим файлом, недоступностью базы данных, недействительными данными и т.д.

Если мы считаем, что ошибка может произойти в какой-то
момент, рекомендуется написать специальный код для обработки ошибки, если она
возникнет, и устранить ее.

Для всех остальных ошибок мы используем общий код для их
устранения. Это где оператор обработки ошибок VBA вступает в игру. Они
позволяют нашему приложению корректно обрабатывать любые ошибки, которые мы не
ожидали.

Чтобы понять обработку ошибок, мы должны сначала понять
различные типы ошибок в VBA.

VBA Error Handling

Ошибки VBA

В VBA есть три типа ошибок

  1. Синтаксис
  2. Компиляция
  3. Время выполнения

Мы используем обработку ошибок для устранения ошибок во
время выполнения. Давайте посмотрим на каждый из этих типов ошибок, чтобы было
ясно, что такое ошибка во время выполнения.

Синтаксические ошибки

Если вы использовали VBA в течение какого-то времени, вы
увидите синтаксическую ошибку. Когда вы набираете строку и нажимаете return,
VBA оценивает синтаксис и, если он неверен, выдает сообщение об ошибке.

Например, если вы введете If и забудете ключевое слово Then,
VBA отобразит следующее сообщение об ошибке.

VBA Error Handling

Некоторые примеры синтаксических ошибок

' then отсутствует
If a > b

' не хватает = после i
For i 2 To 7

' отсутствует правая скобка
b = left("АБВГ",1

Синтаксические ошибки относятся только к одной строке. Они
возникают, когда синтаксис одной строки неверен.

Примечание. Диалоговое окно «Ошибка синтаксиса» можно отключить, выбрав «Сервис» -> «Параметры» и отметив «Автосинтаксическая проверка». Строка по-прежнему будет отображаться красным цветом в случае ошибки, но диалоговое окно не появится.

Ошибки компиляции

Ошибки компиляции происходят более чем в одной строке.
Синтаксис в одной строке правильный, но неверный, если учесть весь код проекта.

Примеры ошибок компиляции:

  • Оператор If без соответствующего оператора End If
  • For без Next
  •  Select без End Select
  • Вызов Sub или Function, которые не существуют
  • Вызов Sub или Function с неверными параметрами
  • Присвоение Sub или Function того же имени, что и для модуля
  • Переменные не объявлены (Option Explicit должен присутствовать в верхней части модуля)

На следующем снимке экрана показана ошибка компиляции,
которая возникает, когда цикл For не имеет соответствующего оператора Next.

VBA Error Handling

Использование Debug-> Compile

Чтобы найти ошибки компиляции, мы используем Debug->
Compile VBA Project из меню Visual Basic.

Когда вы выбираете Debug-> Compile, VBA отображает первую
обнаруженную ошибку.

Когда эта ошибка исправлена, вы можете снова запустить
Compile, и VBA найдет следующую ошибку.

Debug-> Compile также будет включать синтаксические
ошибки в поиск, что очень полезно.

Если ошибок не осталось и вы запускаете Debug-> Compile,
может показаться, что ничего не произошло. Однако «Компиляция» будет недоступна
в меню «Отладка». Это означает, что ваше приложение не имеет ошибок компиляции
в текущий момент.

Debug->Compile Error Summary

Debug-> Compile находит ошибки компиляции (проекта).

Он также найдет синтаксические ошибки.

Он находит одну ошибку каждый раз, когда вы ее используете.

Если нет ошибок компиляции, оставленная опция Компиляция
будет отображаться серым цветом в меню.

Debug-> Compile Usage

Вы должны всегда использовать Debug-> Compile, прежде чем
запускать свой код. Это гарантирует, что ваш код не будет иметь ошибок
компиляции при запуске.

Если вы не запускаете Debug-> Compile, то VBA может
обнаружить ошибки компиляции при запуске. Их не следует путать с ошибками
времени выполнения.

Ошибки во время выполнения

Ошибки во время выполнения возникают, когда ваше приложение
работает. Обычно они находятся вне вашего контроля, но могут быть вызваны
ошибками в вашем коде.

VBA Error Handling

Например, представьте, что ваше приложение читает из внешней
рабочей книги. Если этот файл будет удален, то VBA отобразит ошибку, когда ваш
код попытается открыть его.

Другие примеры ошибок времени выполнения

  • база данных недоступна
  • пользователь вводит неверные данные
  • ячейка, содержащая текст вместо числа

Как мы уже видели, целью обработки ошибок является обработка
ошибок времени выполнения, когда они возникают.

Ожидаемые и неожиданные ошибки

Когда мы думаем, что может произойти ошибка во время
выполнения, мы помещаем код на место для ее обработки. Например, мы обычно
помещаем код на место, чтобы иметь дело с файлом, который не найден.

Следующий код проверяет, существует ли файл, прежде чем он
пытается его открыть. Если файл не существует, отображается сообщение, удобное
для пользователя, и код выходит из подпрограммы.

Sub OtkritFail()
    
    Dim sFile As String
    sFile = "C:ДокументыОтчет.xlsx"
    
    ' Используйте Dir, чтобы проверить, существует ли файл
    If Dir(sFile) = "" Then
        ' если файл не существует, отобразить сообщение
        MsgBox "Файл не найден" & sFile
        Exit Sub
    End If
    
    ' Код достигнет только если файл существует
    Workbooks.Open sFile
    
End Sub

Когда мы думаем, что в какой-то момент может произойти
ошибка, рекомендуется добавить код для обработки ситуации. Мы обычно называем
эти ошибки ожидаемыми.

Если у нас нет специального кода для обработки ошибки, это
считается неожиданной ошибкой. Мы используем операторы обработки ошибок VBA для
обработки непредвиденных ошибок.

Ошибки времени выполнения, которые не являются ошибками VBA

Прежде чем мы рассмотрим VBA Handling, мы должны упомянуть
один тип ошибок. Некоторые ошибки во время выполнения не рассматриваются как
ошибки VBA, а только пользователем.

Позвольте мне объяснить это на примере. Представьте, что у
вас есть приложение, которое требует, чтобы вы добавили значения в переменные a
и b

Допустим, вы по ошибке используете звездочку вместо знака
плюс

Это не ошибка VBA. Ваш синтаксис кода является совершенно
законным. Однако, с вашей точки зрения, это ошибка.

Эти ошибки не могут быть обработаны с помощью обработки ошибок, поскольку они, очевидно, не будут генерировать никаких ошибок. Вы можете справиться с этими ошибками, используя Unit Testing and Assertions.

Заявление об ошибке

Как мы видели, есть два способа обработки ошибок во время
выполнения

  1. Ожидаемые ошибки — напишите конкретный код для
    их обработки.
  2. Неожиданные ошибки — используйте операторы
    обработки ошибок VBA для их обработки.

Оператор VBA On Error используется для обработки ошибок.
Этот оператор выполняет некоторые действия при возникновении ошибки во время
выполнения.

Есть четыре различных способа использовать это утверждение

  1. On Error Goto 0 — код останавливается на строке с ошибкой и отображает сообщение.
  2. On Error Resume Next — код перемещается на следующую строку. Сообщение об ошибке не отображается.
  3. On Error Goto [label] — код перемещается на определенную строку или метку. Сообщение об ошибке не отображается. Это тот, который мы используем для обработки ошибок.
  4. On Error Goto -1 — очищает текущую ошибку.

Давайте посмотрим на каждое из этих утверждений по очереди.

On Error Goto 0

Это поведение по умолчанию VBA. Другими словами, если вы не
используете On Error, это поведение вы увидите.

При возникновении ошибки VBA останавливается на строке с
ошибкой и отображает сообщение об ошибке. Приложение требует вмешательства
пользователя с кодом, прежде чем оно сможет продолжить. Это может быть
исправление ошибки или перезапуск приложения. В этом случае обработка ошибок не
происходит.

Давайте посмотрим на пример. В следующем коде мы не
использовали строку On Error, поэтому VBA будет использовать поведение On Error
Goto 0 по умолчанию.

Sub IspDefault()

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

End Sub

Вторая строка присваивания приводит к ошибке деления на ноль. Когда мы запустим этот код, мы получим сообщение об ошибке, показанное на скриншоте ниже.

VBA Error Handling

Когда появляется ошибка, вы можете выбрать End или Debug

Если вы выберете Конец, то приложение просто остановится.

Если вы выберете Отладить, приложение остановится на строке
ошибки, как показано на скриншоте ниже.

VBA Error Handling

Это нормально, когда вы пишете код VBA, поскольку он
показывает вам точную строку с ошибкой.

Это поведение не подходит для приложения, которое вы
передаете пользователю. Эти ошибки выглядят непрофессионально и делают
приложение нестабильным.

Подобная ошибка, по сути, приводит к сбою приложения.
Пользователь не может продолжить работу без перезапуска приложения. Они могут
вообще не использовать его, пока вы не исправите для них ошибку.

Используя On Error Goto [label], мы можем дать пользователю
более контролируемое сообщение об ошибке. Это также предотвращает остановку
приложения. Мы можем заставить приложение работать предопределенным образом.

On Error Resume Next

Использование On Error Resume Next указывает VBA
игнорировать ошибку и продолжать работу.

Есть конкретные случаи, когда это полезно. Большую часть
времени вы должны избегать его использования.

Если мы добавим Resume Next к нашему примеру Sub, то VBA
проигнорирует ошибку деления на ноль

Sub UsingResumeNext()

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

End Sub

Это не очень хорошая идея, чтобы сделать это. Если вы
игнорируете ошибку, то поведение может быть непредсказуемым. Ошибка может
повлиять на приложение несколькими способами. Вы можете получить неверные
данные. Проблема в том, что вы не знаете, что что-то пошло не так, потому что
вы подавили ошибку.

Приведенный ниже код является примером использования Resume
Next.

Sub OtprSoobsch()

   On Error Resume Next
   
    ' Требуется ссылка:
    ' Библиотека объектов Microsoft Outlook 15.0
    Dim Outlook As Outlook.Application
    Set Outlook = New Outlook.Application

    If Outlook Is Nothing Then
        MsgBox " Не удается создать сеанс Microsoft Outlook." _
                   & " Письмо не будет отправлено."
        Exit Sub
    End If
    
End Sub

В этом коде мы проверяем, доступен ли Microsoft Outlook на компьютере. Все,
что мы хотим знать — это доступно или нет. Нас не интересует конкретная ошибка.

В приведенном выше коде мы продолжаем, если есть ошибка.
Затем в следующей строке мы проверяем значение переменной Outlook. Если произошла ошибка, тогда
значение этой переменной будет установлено равным Nothing.

Это пример того, когда Резюме может быть полезным. Дело в
том, что, хотя мы используем Resume,
мы все равно проверяем наличие ошибки. Подавляющее большинство времени вам не
нужно будет использовать Resume.

On Error Goto [label]

Вот как мы используем обработку ошибок в VBA. Это эквивалент функциональности Try and Catch, которую вы видите на
таких языках, как C # и
Java.

При возникновении ошибки вы отправляете ошибку на
определенный ярлык. Обычно это внизу саба.

Давайте применим это к подводной лодке, которую мы
использовали

Sub IspGotoLine()

    On Error Goto eh
    
    Dim x As Long, y As Long
    
    x = 6
    y = 6 / 0
    x = 7
    
Done:
    Exit Sub
eh:
    MsgBox "Произошла следующая ошибка: " & Err.Description
End Sub

Снимок экрана ниже показывает, что происходит при возникновении ошибки.

VBA Error Handling

VBA переходит на метку eh, потому что мы указали это в
строке «Перейти к ошибке».

Примечание 1: Метка, которую мы используем в операторе On… Goto, должна быть в текущей Sub / Function. Если нет, вы получите ошибку компиляции.

Примечание 2: Когда возникает ошибка при использовании On Error Goto [label], обработка ошибок возвращается к поведению по умолчанию, т.е. код остановится на строке с ошибкой и отобразит сообщение об ошибке. См. Следующий раздел для получения дополнительной информации об этом.

On Error Goto -1

Это утверждение отличается от других трех. Он используется
для очистки текущей ошибки, а не для настройки конкретного поведения.

При возникновении ошибки с помощью функции On Error Goto [label] поведение обработки ошибки возвращается к поведению по умолчанию, т.е. On Error Goto 0 . Это означает, что если произойдет другая ошибка, код остановится на текущей строке.

Это поведение относится только к текущей подпрограмме. Как
только мы выйдем из саба, ошибка будет очищена автоматически.

Посмотрите на код ниже. Первая ошибка приведет к переходу
кода на метку eh. Вторая ошибка остановится на строке с ошибкой 1034.

Sub DveOshibki()

    On Error Goto eh
        
    ' генерировать ошибку «Несоответствие типов»
    Error (13)

Done:
    Exit Sub
eh:
    ' генерировать «определенную приложением» ошибку
    Error (1034)
End Sub

Если мы добавим дальнейшую обработку ошибок, она не будет
работать, поскольку ловушка ошибок не была очищена.

В коде ниже мы добавили строку

после того как мы поймаем первую ошибку.

Это не имеет никакого эффекта, так как ошибка не была
очищена. Другими словами, код остановится на строке с ошибкой и отобразит
сообщение.

Sub DveOshibki()

    On Error Goto eh
        
    ' генерировать ошибку «Несоответствие типов»
    Error (13)

Done:
    Exit Sub
eh:
    On Error Goto eh_other
    ' генерировать «определенную приложением» ошибку
    Error (1034)
Exit Sub
eh_other:
    Debug.Print "ehother " & Err.Description
End Sub

Для устранения ошибки мы используем On Error Goto -1.
Думайте об этом как об установке ловушки для мыши. Когда ловушка сработает, вам
нужно установить ее снова.

В приведенном ниже коде мы добавляем эту строку, и вторая
ошибка теперь приведет к переходу кода на метку eh_other.

Sub DveOshibki()

    On Error Goto eh
        
    ' генерировать ошибку «Несоответствие типов»
    Error (13)

Done:
    Exit Sub
eh:
    ' явная ошибка
    On Error Goto -1
    
    On Error Goto eh_other
    ' генерировать «определенную приложением» ошибку
    Error (1034)
Exit Sub
eh_other:
    Debug.Print "ehother " & Err.Description
End Sub

Примечание 1. Вероятно, в редких случаях полезно использовать On Error Goto -1. Мне лично никогда не приходилось пользоваться этой линией. Помните, что как только вы выйдете из Sub, ошибка все равно будет очищена.

Примечание 2. у объекта Err есть член Clear. Использование Clear очищает текст и цифры в объекте Err, но НЕ сбрасывает ошибку.

Использование On Error

Как мы уже видели, VBA будет делать одну из трех вещей при возникновении ошибки:

  • Остановитесь и отобразите ошибку.
  • Игнорируйте ошибку и продолжайте.
  • Перейти к определенной строке.

VBA всегда будет настроен на одно из этих действий. Когда вы
используете On Error, VBA изменит ваше поведение и забудет о любом предыдущем.

В следующем подпункте VBA изменяет поведение ошибки каждый
раз, когда мы используем оператор On Error

Sub ErrorSostoyaniya()

    Dim x As Long
    
    ' Перейти на этикетке, если ошибка
    On Error Goto eh
    
    ' это проигнорирует ошибку в следующей строке
    On Error Resume Next
    x = 1 / 0
    
    ' это отобразит сообщение об ошибке в следующей строке
    On Error Goto 0
    x = 1 / 0
  
Done:  
   Exit Sub
eh:
    Debug.Print Err.Description
End Sub

Err объект

При возникновении ошибки вы можете просмотреть детали
ошибки, используя объект Err.

При возникновении ошибки времени выполнения VBA
автоматически заполняет объект Err деталями.

Приведенный ниже код выведет «Error Number: 13 Type
Mismatch», которое возникает, когда мы пытаемся поместить строковое значение в
длинное целое число.

Sub IspErr()

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

Done:
    Exit Sub
eh:
    Debug.Print "Номер ошибки: " & Err.Number _
            & " " & Err.Description
End Sub

Err.Description предоставляет подробную информацию об ошибке, которая происходит. Это текст, который вы обычно видите, когда возникает ошибка, например, «Несоответствие типов»

Err.Number — это идентификационный номер ошибки, например, номер ошибки для «Несоответствие типов» — 13. Единственное время, когда вам действительно нужно это, если вы проверяете, что произошла конкретная ошибка, и это необходимо только в редких случаях.

Свойство Err.Source кажется отличной идеей, но оно не работает при ошибке VBA. Источник вернет имя проекта, которое вряд ли сузит место возникновения ошибки. Однако, если вы создаете ошибку с помощью Err.Raise, вы можете установить источник самостоятельно, и это может быть очень полезно.

Получение номера строки

Функция Erl используется для возврата номера строки, где
произошла ошибка.

Это часто вызывает путаницу. В следующем коде Erl вернет ноль.

Sub IspErr()

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

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

Это потому, что нет номеров строк. Большинство людей не
понимают этого, но VBA позволяет вам иметь номера строк.

Если мы изменим подпрограмму, указав номер строки, она теперь выведет 20.

Sub IspErr()

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

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

Добавление номеров строк в код вручную затруднительно.
Однако есть инструменты, которые позволят вам легко добавлять и удалять номера
строк в подпрограмме.

Когда вы закончите работу над проектом и передадите его
пользователю, в этот момент может быть полезно добавить номера строк. Если вы
используете стратегию обработки ошибок в последнем разделе этого поста, то VBA
сообщит строку, где произошла ошибка.

Использование Err.Raise

Err.Raise позволяет нам создавать ошибки. Мы можем
использовать его для создания пользовательских ошибок для нашего приложения,
что очень полезно. Это эквивалент оператора Throw в Java C #.

Формат следующий

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

Давайте посмотрим на простой пример. Представьте, что мы
хотим убедиться, что в ячейке есть запись длиной 5 символов. Мы могли бы иметь конкретное сообщение для
этого

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" _
            , "Значение в ячейке A1 должно иметь ровно 5 символов."
    End If
    
    ' продолжить, если ячейка имеет действительные данные
    Dim id As String
    id = Sheet1.Range("A1")
    

Done:
    Exit Sub
eh:
    ' Err.Raise отправит код сюда
    MsgBox " Обнаружена ошибка: " & Err.Description
End Sub

Когда мы создаем ошибку, используя Err.Raise, нам нужно присвоить ей номер. Мы можем использовать любое
число от 513 до 65535 для нашей ошибки. Мы должны использовать vbObjectError с номером,
например

Err.Raise vbObjectError + 513

Использование Err.Clear

Err.Clear используется для очистки текста и чисел из объекта
Err.Object. Другими словами, он очищает описание и номер.

Редко вам понадобится его использовать, но давайте
рассмотрим пример, где вы могли бы.

В приведенном ниже коде мы подсчитываем количество ошибок,
которые могут возникнуть. Для простоты мы генерируем ошибку для каждого
нечетного числа.

Мы проверяем номер ошибки каждый раз, когда проходим цикл.
Если число не равно нулю, то произошла ошибка. Как только мы посчитаем ошибку,
нам нужно установить номер ошибки на ноль, чтобы он был готов проверить
следующую ошибку.

Sub IspErrClear()

    Dim count As Long, i As Long

    ' Продолжите, если ошибка, так как мы проверим номер ошибки
    On Error Resume Next
    
    For i = 0 To 9
        ' генерировать ошибку для каждого второго
        If i Mod 2 = 0 Then Error (13)
        
        ' Проверьте на ошибку
        If Err.Number <> 0 Then
            count = count + 1
            Err.Clear    ' Очистить Err, как только он считается
        End If
    Next

    Debug.Print " Количество ошибок было: " & count
End Sub

Примечание: Err.Clear сбрасывает текст и цифры в объекте ошибки, но не очищает ошибку — см. On Error Goto -1 для получения дополнительной информации об очистке фактической ошибки.

Логирование

Ведение журнала означает запись информации из вашего
приложения, когда оно запущено. При возникновении ошибки вы можете записать
детали в текстовый файл, чтобы у вас была запись об ошибке.

Код ниже показывает очень простую процедуру регистрации

Sub Logger(sType As String, sSource As String, sDetails As String)
    
    Dim sFilename As String
    sFilename = "C:templogging.txt"
    
    ' Архивный файл определенного размера
    If FileLen(sFilename) > 20000 Then
        FileCopy sFilename _
            , Replace(sFilename, ".txt", Format(Now, "ddmmyyyy hhmmss.txt"))
        Kill sFilename
    End If
    
    ' Откройте файл для записи
    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

Вы можете использовать это так:

' Создать уникальный номер ошибки
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", "Данные отсутствуют в ячейке A1"
    End If

    ' другой код здесь
Done:
    Exit Sub
eh:
    Logger "Error", Err.Source, Err.Description
End Sub

Журнал не только для записи ошибок. Вы можете записывать
другую информацию во время работы приложения. При возникновении ошибки вы
можете проверить последовательность событий до того, как произошла ошибка.

Ниже приведен пример регистрации. То, как вы реализуете
журналирование, зависит от характера приложения и его полезности.

Sub ReadingData()
    
    Logger "Information", "ReadingData()", "Starting to read data."
       
    Dim coll As New Collection
    ' Read data
    Set coll = ReadData
    
    If coll.Count < 10 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

Наличие большого количества информации при работе с ошибкой
может быть очень полезным. Часто пользователь может не дать вам точную информацию
об ошибке, которая произошла. Глядя на журнал, вы можете получить более точную
информацию об информации.

Другие элементы, связанные с ошибками

В этом разделе рассматриваются некоторые другие инструменты
обработки ошибок, которые есть в VBA. Эти элементы считаются устаревшими, но я
включил их, поскольку они могут существовать в устаревшем коде.

Функция ошибки

Функция Error используется для печати описания ошибки с
заданным номером ошибки. Он включен в VBA для обеспечения обратной
совместимости и не нужен, поскольку вместо него можно использовать описание
Err.Description.

Ниже приведены некоторые примеры

' Распечатать текст «Деление на ноль»
Debug.Print Error(11)
' Распечатать текст "Несоответствие типов"
Debug.Print Error(13)
' Распечатать текст "Файл не найден"
Debug.Print Error(53)

Заявление об ошибке

Заявление об ошибке позволяет имитировать ошибку. Он включен
в VBA для обратной совместимости. Вместо этого вы должны использовать
Err.Raise.

В следующем коде мы моделируем ошибку «Разделить на ноль».

Sub ZayavlObOshibke()

    On Error Goto eh
        
    ' Это создаст деление на ноль ошибок
    Error 11
    
    Exit Sub
eh:
    Debug.Print Err.Number, Err.Description
End Sub

Это утверждение включено в VBA для обратной совместимости.
Вместо этого вы должны использовать Err.Raise.

Простая стратегия обработки ошибок

Со всеми различными опциями вы можете быть озадачены тем,
как использовать обработку ошибок в VBA. В этом разделе я покажу вам, как
реализовать простую стратегию обработки ошибок, которую вы можете использовать
во всех своих приложениях.

Основная реализация

Это простой обзор нашей стратегии

  1. Поместите строку On Error Goto Label  в начале нашего верхнего Sub.
  2. Поместите Label у обработки ошибок в конце нашего верхнего
    Sub.
  3. Если происходит ожидаемая ошибка, обработайте ее и продолжайте.
  4. Если приложение не может продолжить работу, используйте Err.Raise для перехода к метке обработки ошибок.
  5. В случае непредвиденной ошибки код автоматически перейдет к метке обработки ошибок.

На следующем рисунке показан обзор того, как это выглядит

error-handling

Следующий код показывает простую реализацию этой стратегии

Public Const ERROR_NO_ACCOUNTS As Long = vbObjectError + 514

Sub BuildReport()

    On Error Goto eh
    
    ' Если ошибка в ReadAccounts, то перейти к ошибке
    ReadAccounts
    
    ' Сделай что-нибудь с кодом
    
Done:
    Exit Sub
eh:
    ' Все ошибки будут прыгать сюда
    MsgBox Err.Source & ": Произошла следующая ошибка  " & Err.Description
End Sub

Sub ReadAccounts()
    
    ' ОЖИДАЕМАЯ ОШИБКА - Может обрабатываться кодом
    ' Приложение может обрабатывать A1 равным нулю
    If Sheet1.Range("A1") = 0 Then
        Sheet1.Range("A1") = 1
    End If
    
    ' ОЖИДАЕМАЯ ОШИБКА - не может быть обработана кодом
    ' Приложение не может быть продолжено, если нет учетной записи
    If Dir("C:ДокументыОтчет.xlsx") = "" Then
        Err.Raise ERROR_NO_ACCOUNTS, "UsingErr" _
                , "There are no accounts present for this month."
    End If

    ' НЕОЖИДАННАЯ ОШИБКА - не может быть обработана кодом
    ' Если ячейка B3 содержит текст, мы получим ошибку несоответствия типов
    Dim total As Long
    total = Sheet1.Range("B3")
    
    
    ' продолжить и читать счета
    
End Sub

Это хороший способ реализации обработки ошибок, потому что

  • Нам не нужно добавлять код обработки ошибок в
    каждую подпрограмму.
  • Если возникает ошибка, то VBA корректно
    завершает работу приложения.

Полная стратегия обработки ошибок

Стратегия выше имеет один недостаток. Он не сообщает вам,
где произошла ошибка. VBA не наполняет Err.Source чем-либо полезным, поэтому мы
должны сделать это сами.

В этом разделе я собираюсь представить более полную
стратегию ошибок. Я написал два сабвуфера, которые выполняют всю тяжелую
работу, поэтому все, что вам нужно сделать, это добавить их в свой проект.

Целью этой стратегии является предоставление вам стека * и
номера строки в случае возникновения ошибки.

* Стек — это список вспомогательных функций, которые
использовались в данный момент при возникновении ошибки.

Это наша стратегия

  1. Разместите обработку ошибок во всех
    подпрограммах.
  2. Когда происходит ошибка, обработчик ошибок
    добавляет подробности к ошибке и вызывает ее снова.
  3. Когда ошибка достигает самой верхней
    подпрограммы, она отображается.

Мы просто «всплываем» из-за ошибки. Следующая диаграмма
показывает простое визуальное представление о том, что происходит, когда в Sub3
возникает ошибка

Error Handling – bubbling

Единственная грязная часть этого — правильное форматирование
строк. Я написал две подводные лодки, которые справляются с этим, поэтому он
позаботится о вас.

Это две вспомогательные подводные лодки

Option Explicit

Public Const MARKER As String = "NOT_TOPMOST"

' Вызывает ошибку и добавляет номер строки и имя текущей процедуры
Sub RaiseError(ByVal errorno As Long, ByVal src As String _
                , ByVal proc As String, ByVal desc As String, ByVal lineno As Long)
    
    Dim sLineNo As Long, sSource As String
    
    ' Если маркера нет, тогда RaiseError вызывается впервые.
    If Left(src, Len(MARKER)) <> MARKER Then

        ' Добавить номер строки ошибки, если она есть
        If lineno <> 0 Then
            sSource = vbCrLf & "Line no: " & lineno & " "
        End If
   
        ' Добавить маркер и процедуру к источнику
        sSource = MARKER & sSource & vbCrLf & proc
        
    Else
        ' Если ошибка уже возникла, просто добавьте имя процедуры
        sSource = src & vbCrLf & proc
    End If
    
    ' Если код останавливается здесь, убедитесь, что DisplayError находится в верхней части Sub
    Err.Raise errorno, sSource, desc
    
End Sub

' Отображает ошибку, когда она достигает самого верхнего sub
' Примечание: вы можете добавить вызов для входа из этого подпункта
Sub DisplayError(ByVal src As String, ByVal desc As String _
                    , ByVal sProcname As String)

    ' Удалить маркер
    src = Replace(src, MARKER, "")
    
    Dim sMsg As String
    sMsg = " Произошла следующая ошибка: " & vbCrLf & Err.Description _
                    & vbCrLf & vbCrLf & " Расположение ошибки: "
    
    sMsg = sMsg + src & vbCrLf & sProcname
    
    ' Показать сообщение
    MsgBox sMsg, Title:="Ошибка "
    
End Sub

Пример использования этой стратегии

Вот простое кодирование, которое использует эти Sub. В этой стратегии мы не размещаем какой-либо код в верхнем подпрограмме. Мы только вызываем подводные лодки.

Sub Topmost()

    On Error Goto EH
    
    Level1

Done:
    Exit Sub
EH:
    DisplayError Err.source, Err.Description, "Module1.Topmost"
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
    
    ' Ошибка здесь
    Dim a As Long
    a = "7 / 0"

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

Результат выглядит так

error handling output

Если в вашем проекте есть номера строк, результат будет содержать номер строки ошибки.

error handling output line

Примечание: вы можете получить следующую ошибку при использовании этого кода:

“Programmatic Access to Visual Basic Project is not trusted”

Чтобы решить эту проблему, выполните следующие действия.

  1. Перейдите в раздел «Разработчик» на ленте и
    нажмите «Macro Security», которая находится под кодом.
  2. Нажмите «Настройка макроса» в левом списке.
  3. Поставьте флажок в поле «Доверительный доступ к
    объектной модели проекта VBA».
  4. Нажмите Ok.

Обработка ошибок в двух словах

  • Обработка ошибок используется для обработки ошибок, возникающих во время работы приложения.
  • Вы пишете определенный код для обработки ожидаемых ошибок. Вы используете оператор обработки ошибок VBA
    On Error Goto [label] для отправки VBA на метку при возникновении непредвиденной ошибки.
  • Вы можете получить подробную информацию об ошибке из Err.Description.
  • Вы можете создать свою собственную ошибку, используя Err.Raise.
  • Использование одного оператора On Error в самой верхней подпрограмме перехватит все ошибки в подпрограммах, которые вызываются отсюда.
  • Если вы хотите записать имя Sub с ошибкой, вы можете обновить ошибку и сбросить ее.
  • Вы можете использовать журнал для записи информации о приложении, когда оно запущено.

VBA On Error Resume Next is an error handler statement. If the error occurs while running the code, you can use this statement to resume the next line of code by ignoring the error message instead of showing an error.

Those who write codes regularly in excel VBA know they may get errors even after writing proficient codes, but they want to ignore that error and keep running with the next lines of code. An example of getting an error message is when the VLOOKUP worksheet functionThe VLOOKUP excel function searches for a particular value and returns a corresponding match based on a unique identifier. A unique identifier is uniquely associated with all the records of the database. For instance, employee ID, student roll number, customer contact number, seller email address, etc., are unique identifiers.
read more
does not find the lookup value from the table array. Therefore, it would not return the #N/A error. Rather, it will throw the error: “Unable to get the VLOOKUP property of the worksheet function class.”

Table of contents
  • Excel VBA On Error Resume Next
    • What does On Error Resume Next Do in VBA?
      • Example #1
      • Example #2
    • Things to Remember here
    • Recommended Articles

VBA on Error Resume Next Example 2.4

It is very difficult to fix the bug if you do not know why we are getting this error. In VBA, we have a feature called “On Error Resume Next.”

What Does On Error Resume Next Do in VBA?

There are certain areas as a coder. First, we know this will surely give an error message, but we need to ignore this error to keep going through the code. So, how to ignore that error is a common doubt everybody has.

We can ignore the error using the VBA On Error Resume Next statement and resume the next line of code.

You can download this VBA On Error Resume Next Excel Template here – VBA On Error Resume Next Excel Template

Example #1

Assume you have many worksheets, and you are hiding some of them as part of the VBA project. For example, below are the worksheets we have in our worksheet.

VBA on Error Resume Next Example 1

We have written codes to hide “Sales” and “Profit” sheets, and below is the code.

Code:

Sub On_Error()

    Worksheets("Sales").Visible = xlVeryHidden
    Worksheets("Profit 2019").Visible = xlVeryHidden
    Worksheets("Profit").Visible = xlVeryHidden

End Sub

Example 1.1

We will start running the code line by line using the F8 key.

VBA on Error Resume Next Example 1.2

If we press the F8 key one more time, it will hide the sheet named “Sales.”

Example 1.3

VBA on Error Resume Next Example 1.4

Now, press the F8 key one more time and see what happens.

VBA on Error Resume Next Example 1.5

We have got a “Subscript out of rangeSubscript out of range is an error in VBA that occurs when we attempt to reference something or a variable that does not exist in the code. For example, if we do not have a variable named x but use the msgbox function on x, we will receive a subscript out of range error.read more” error because the current line of code says the below.

Worksheets("Profit 2019").Visible = xlVeryHidden

It is trying to hide the worksheet named “Profit 2019,” but there is no worksheet by the name of “Profit 2019”.

In these cases, if the worksheet doesn’t exist in the workbook, we need to ignore the error and continue to run the code by ignoring the “Subscript out of range” error.

The next line in the code says

Worksheets("Profit").Visible = xlVeryHidden

This worksheet exists in this workbook, so we cannot move to this line of code without ignoring the error.

We need to add the “On Error Resume Next” statement to ignore this error.

Code:

Sub On_Error()

    On Error Resume Next
    Worksheets("Sales").Visible = xlVeryHidden
    Worksheets("Profit 2019").Visible = xlVeryHidden
    Worksheets("Profit").Visible = xlVeryHidden

End Sub

 Example 1.6

As you can see above, we have added the statement at the top of the code before any lines start. Now, run the code and see what happens.

VBA on Error Resume Next Example 1.7

Now, we are in the line given the error previously, press the F8 key, and see what happens.

Example 1.8

We have jumped to the next line of code without showing any error because of the statement we have added at the top, which is the “On Error Resume Next” VBA statement.

Example #2

We will see how to use this statement with one more example. Look at the below data structure for this example.

VBA on Error Resume Next Example 2.0.1

We have two tables above. The first table has “Emp Name” and their salary details in the second table. Unfortunately, we have only “Emp Name.” So by using VLOOKUP, we need to fetch the salary details from the left side table.

Below is the code we had written to fetch the details.

Code:

Sub On_Error1()

  Dim k As Long

  For k = 2 To 8
   Cells(k, 6).Value = WorksheetFunction.VLookup(Cells(k, 5), Range("A:B"), 2, 0)
  Next k

End Sub

Example 2.1

Now, run the code line by line and see what happens.

VBA on Error Resume Next Example 2.2

Example 2.3

Upon running the first cell code, we got the result for the first employee. Repeat the same for the second employee as well.

VBA on Error Resume Next Example 2.4

This time we got the error message. Let us look at the second employee’s name on the table.

 Example 2.5

The second employee’s name is “Gayathri,” but this name does not exist in the first table, so the VBA VLOOKUP functionThe functionality of VLOOKUP in VBA is similar to that of VLOOKUP in a worksheet, and the method of using VLOOKUP in VBA is through an application. Method WorksheetFunctionread more does not return a #N/A error when the VLOOKUP does not find the lookup value from the table. Rather, it gives the above error message.

Our aim is if the employee name is unfound in the table, then we need an empty cell for that employee, ignore the error, and give results for the remaining names.

We need to add the “On Error Resume Next” statement inside the loop.

Code:

Sub On_Error1()

  Dim k As Long

  For k = 2 To 8
   On Error Resume Next
   Cells(k, 6).Value = WorksheetFunction.VLookup(Cells(k, 5), Range("A:B"), 2, 0)
  Next k

End Sub

VBA on Error Resume Next Example 2.6

Now, run the code and see the result.

 Example 2.7

The two employee names: “Gayathri” and “Karanveer,” are not on the list. So, those line codes must have encountered an error since we have added an error handler statement of “On Error Resume Next.” It has ignored that line of code and resumed for the next employee.

Things to Remember here

  • The “On Error Resume Next” is the error handler statement when we need to ignore the known error.
  • If we want to ignore the error message only for a specific code set, close the On Error Resume Next statement by adding the “On Error GoTo 0” statement.

Recommended Articles

This article has been a guide to VBA On Error Resume Next. Here, we discuss how to ignore errors and resume the next line of code in Excel VBA with examples and a downloadable Excel template. You can learn more about VBA functions from the following articles: –

  • VBA Split String into Array
  • VBA Square Root
  • Type Mismatch Error in VBA
  • 1004 Error in VBA

VBA On Error Resume Next

Excel VBA On Error Resume Next

Error Handling is a very useful & significant mechanism for programming languages like VBA Error control or prevention which is an aspect of Error handling which means taking effective & significant measures inside a VBA script to avoid the occurrence of error pop up message. The Excel VBA On Error Resume Next statement ignores the code line that causes an error and continues or routes execution to the next line following the line that caused the error.

NOTE: On Error Resume Next statement doesn’t fix the runtime errors, it’s an error ignoring where VB program execution will continue from the line which has caused the runtime error.

Basically, On error resume next is used when you want to ignore the error & continue or resume the code execution to the next cell.

Types of Errors in VBA

Below are the different types of Errors in VBA:

  1. Syntax Error or Parsing error.
  2. Compile Or Compilation Error.
  3. Runtime Error.
  4. Logical Error.

The above errors can be rectified with the help of debugging & ‘On Error’ Statements in a code. The Runtime Error can be prevented with the help of On Error Resume Next.

VBA Runtime Error:

Before the explanation of On Error Resume Next, you should be aware of runtime error when impossible mathematical statements or terms present in a statement, then this runtime error occurs.

Examples of Excel VBA On Error Resume Next

Below are the different examples of On Error Resume Next in Excel VBA:

You can download this VBA On Error Resume Next Excel Template here – VBA On Error Resume Next Excel Template

VBA On Error Resume Next – Example #1

Here, an error will be ignored, and the execution of code will move on. In the below-mentioned example, 6 can’t be divided by zero, if you run it without entering On Error Resume Next statement, then below mentioned runtime error occurs.

Code:

Sub RUNTIME_1()
MsgBox 6 / 0
End Sub

VBA On Error Resume Next Example 1

If On Error Resume Next in entered at the top of code after SUB statement, it ignores runtime error and moves on to next statement, results in an output of 6/2 (Popup message box with result of it).

Code:

Sub RUNTIME_2()
On Error Resume Next
MsgBox 6 / 0
MsgBox 6 / 2
End Sub

VBA Error Handling

VBA On Error Resume Next – Example #2

I can use On Error Resume Next anywhere in the code from the beginning to the end. In the below-mentioned example, I have to make a 3 calculation i.e.

9/3 =?

9/0 =?

9/2 =?

In the above-mentioned example, you can observe a second calculation where any number can’t be divided by zero, i.e. 9 can’t be divided by zero in the second step. Suppose if you run the macro without entering On Error Resume Next statement, now I can execute the code step by step with the help of step into or F8 key to understand how it works.

VBA On Error Resume Next Example 1-3

Now, I run the above code, by clicking on step Into option or F8 key frequently, step by step. I just copy the above code and start running it step by step, for the first step of calculation message box 3 appears.

Code:

Sub RUNTIME_3()
MsgBox 9 / 3
MsgBox 9 / 0
MsgBox 9 / 2
End Sub

VBA On Error Resume Next Example 1-4

When I run the second line of code, then below mentioned runtime error occurs at the second step of a code, where any number can’t be divided by zero, i.e. 9 can’t be divided by zero in the second step.

Code:

Sub RUNTIME_3()
MsgBox 9 / 3
MsgBox 9 / 0
MsgBox 9 / 2
End Sub

VBA On Error Resume Next Example 1-5

Now, if I even click on debug, it can’t proceed further, where it will take me to the second line of code (It gets highlighted in yellow color), where I need to do the correction. So, here, if further click on Step Into option or F8 key, the third calculation in this code will not get executed.

VBA On Error Resume Next Example 1-9

To rectify or handle this runtime error, I have to use or execute the OnError Resume Next statement above a second code or at the beginning of code below the substatement. so that it will skip that line of code and moves on to the third step of code and calculate the value.

Code:

Sub RUNTIME_30()
MsgBox 9 / 3
On Error Resume Next
MsgBox 9 / 0
MsgBox 9 / 2
End Sub

OR

Sub RUNTIME_31()
On Error Resume Next
MsgBox 9 / 3
MsgBox 9 / 0
MsgBox 9 / 2
End Sub

Now, I have added on error resume next statement to the code, where you can use any one of above code, if you run it step by step, you will get a two-message popup, one is the output first code and third code calculation. On Error Resume Next will ignore the runtime error in the second code and move on to the third code.

Message Popup Example 1-6  Message Popup Example 1-6-1

VBA On Error Resume Next – Example #2

We will now see the Combination of On Error Resume Next with Error GoTo 0. In the below code, it will ignore errors until it reaches On Error GoTo 0 statement. After On Error GoTo 0 statement, the code goes back or proceed to normal error checking and triggers the expected error ahead.

Code:

Sub onError_Go_to_0_with_Resume_next()
On Error Resume Next
Kill "C:TempFile.exe"
On Error GoTo 0
Range("A1").Value = 100 / "PETER"
End Sub

When I run the above code, it will showcase the division error i.e. Type mismatch (numeric value can’t be divided by text).

Division Error Example

Now, you can save your workbook as an “Excel macro-enabled workbook”. By clicking on save as at the left corner of the worksheet.

Worksheet Example1-8

when you open this excel file again, you can use below-mentioned shortcut key i.e.

Function + Alt + F11 short cut key helps you out to access all the created macro code of the workbook. Function + Alt + F8 short cut key helps you out to open a “Macro” dialog box window, which contains all the macro names, where you can run a specific macro code of your choice.

Things to Remember

  • Run time error will be silently trapped and stored in the global Err object
  • On Error Resume Next usually prevent an interruption in code execution.
  • Error object properties (Err Object) get cleared automatically when Resume Next is used in an error-handling routine

Recommended Articles

This is a guide to VBA On Error Resume Next. Here we discuss different types of Error in VBA Excel along with some practical examples and downloadable excel template. You can also go through our other suggested articles –

  1. VBA Macros
  2. VBA DateDiff
  3. VBA Protect Sheet
  4. VBA Environ

When running a VBA program, things not always go as expected. Sometimes errors will occur, and it is necessary to know how to deal with them.


Types of errors

In VBA 3 types of errors can be found:

  • Syntax Error
  • Compile Error
  • Runtime Error

Syntax Error

These are errors that occur when the syntax of any line is incorrect.

E.g.: If statement without Then; or typos, such as Thn instead of Then.

No execution is required to identify this type of error. Normally the VBE itself sends out a warning as soon as the line is changed (with Enter or the mouse).

To correct this error, simply adjust the syntax, noting if everything was spelled correctly in the expected order.


Compile Error

These are errors that occur when the syntax of the lines is correct, but the logical set of the code is faulty.

Examples:

  • An If statement within a loop with the End If statement outside the loop

        For i = 1 To 10
        'Tasks...
        If i = 9 Then
        Next i
        End If
    
  • An End If statement after the End Sub

    Sub example()
        If i = 10 Then
    End Sub
        End If
    

A warning is displayed when a code with this type of error is executed.

To deal with this type of error it is enough to correct the order of the lines. The correct order will guarantee that any statement that needs a counterpart (Ex: For, If, Sub) has its closure before another statement that also needs a counterpart.


Runtime Error

These are errors that occur when the program, during execution, can not run a line of code because of improper associations or incompatibilities.

E.g.: 1/0 will result in a ‘Division by zero’ error.

There are two main approaches (which may be complementary) to handling with this type of errors:

  • Using If statements and data types to anticipate possible problems
  • Using a statement to handle error: On Error

Next, we will focus on the handling of Runtime Errors with the statement On Error.


On Error Statement

On Error is the main form of handling a VBA «Runtime Error». This informs VBA what to do when such an error occurs.

On Error can be used in three ways:

  • On Error GoTo <Label>
  • On Error Resume Next
  • On Error GoTo 0

When using an On Error statement, VBA will set a new default action to deal with errors for the next lines of code that will be executed.

To reset to the Excel standard use On Error GoTo 0.


On Error GoTo <Label>

When an error occurs, the execution will jump to a defined line, usually at the end of the code:

Sub ErroGoTo()

    On Error GoTo EH

    X = 1 / 0 'Causes an error

    '
    ' Sub Code
    '

Exit Sub
EH: 'Error Handling
    MsgBox "The following error occurred: " & Err.Description
End Sub

In this example, when the error is detected, VBA shifted its execution to the line with the label (EH).

Notice that in order to not execute the error handling without any error occurred, the instruction Exit Sub was added before EH:

The variable Err.Description will contain the description of the error, if it occurs. Division by zero, in this example.

Err Description

EH is a label used in this example. You can use any name for this label, as if it were a variable name.


On Error Resume Next

To continue the execution of the code even in case of an error, use the code On Error Resume Next.

    On Error Resume Next

    X = 1 / 0 'Causes an error, but execution will not stop

If X needs to have a value, it can be established as follow.

    On Error Resume Next

    X = 1 / 0 'Causes an error, but execution will not stop

    If Err.Number <> 0 Then 
        X = 1
    End If

Notice that Err.Number will return a number other than 0 if an error occurs.

Whenever you use the On Error Resume Next statement, make sure that the code is predicting the missing variables or lines of code that may cause problems. This is done to not get unpredictable results.


On Error Goto 0

On Error Goto 0 is the default option of VBA. In case of error, the execution will be interrupted and an error message will be displayed:

    X = 1 / 0    'Causes an error

On Error Standard

This statement is generally used when you want to reset to the default form of VBA error handling after a previous specification:

    On Error Resume Next

    X = 1 / 0 'Causes an error, but execution will not stop

    If Err.Number <> 0 Then 
        X = 1
    End If

    'Until now errors have been bypassed

    On Error Goto 0 'From here on errors will be displayed

    Y = 1 / 0

    'It will display the error message for Y


SuperExcelVBA.com is learning website. Examples might be simplified to improve reading and basic understanding. Tutorials, references, and examples are constantly reviewed to avoid errors, but we cannot warrant full correctness of all content. All Rights Reserved.

Excel ® is a registered trademark of the Microsoft Corporation.

© 2023 SuperExcelVBA | ABOUT

Protected by Copyscape

Excel VBA Errors & Error Handling, On Error & Resume Satements, Exit Statement, Err Object

————————————————————————————————-

Contents:

VBA Erros & Error Handling

Error Handling Setting, in VBE

Error Handler

On Error Statements

Using an Exit Statement

Error Handling in Nested Procedures & The Resume Statement

Get Information from the Error Object

Raise Method of the Err Object: Generate a Run-time error

————————————————————————————————-

Error Handling determines what is to be done next on the occurrence of an error. On encountering a run-time error, an On Error statement enables or disables an error-handling routine within a procedure. A Resume statement can only be used in an error-handling routine — it resumes execution at a sepcified point after the error-handline routine finishes. You can get information on the error from the properties of the Error object — this object is the Err Object. In this section, we cover:

VBA Erros & Error Handling

In vba programming you can have Syntax Errors or Run-time Errors. An error handler determines what action is to be taken within a procedure, on the occurrence of a run-time error.

A syntax error occurs when you enter a line of code which is not allowed or recognized by Visual Basic. You will encounter a syntax error on misspelling a keyword or a named argument, for incorrect punctuation (ex. not specifying a comma as a placeholder for the omitted argument), use an undefined procedure, and so on. These errors are easier to locate as the Code Editor points them out at the time you are writing your code.

A run-time error occurs at the time during which your code is running, that is after you have created your macro. There could be an error in your programming due to incorrect logic used in your code that prevents it from doing what you intended and may stop code execution, for example, if your code attempts to divide a value by zero. Another reason for an error which may cause even a valid code to crash could be a condition not being met, say, a reference to a worksheet in your code which has been deleted by the user. Other examples when a run-time error can occur are: on using incorrect variable names or variable types; if your code goes into an infinite loop; using a value or reference outside the allowable range; and so on. If you dont implement error handling in your macro, on encountering a run-time error your code will stop execution and go into Break Mode and display an error message, thereby confusing and frustrating the user.

Using Error Handling in VBA is an important tool for developers to trap & handle run-time errors in a vba procedure for seamless execution. It is important to set error handling in every procedure else your macro might just crash or stop executing on encountering a run-time error and vba will display a default error message and go into Break Mode allowing the user to debug your code.

Basic Error Handling hides the fault in the macro when it crashes and exits gracefully, and informs the users accordingly. Advanced Error Handling techniques involve saving information on the error cause and the point of the error, and attempt to resolve the error and provide information to the user on the next step.

Error Handling determines what is to be done next on the occurrence of an error. At a basic level, Error Handling involves two parts — (i) enables an error-handling routine with an On Error Statement on encountering an error, and (ii) an error-handling routine which is the section where the procedure flow is directed to on encountering an error. It is to be noted that an error-handling routine is not a procedure (Sub or Function) but a section of code marked by a line label or a line number. An On Error statement enables or disables an error-handling routine within a procedure.

Error Handling Setting, in VBE

You can determine how errors are handled in VBE, by selecting the appropriate option. In VBE, click Options on the Tools Menu, select the General tab in the dialog box. In the Error Trapping Section, you can select from 3 options.

Break on All Errors: Selecting this will stop your code execution and enter Break Mode on every error, even if you are using an error handler (including the On Error Resume Next statement), hence it is not advised to select this option.

Break on Unhandled Errors: This works well in that an error is trapped when an error handler is active else the error causes the macro to go into Break Mode, except for debugging class modules wherein on encountering an error the debugger stops on the line which calls the class and not on the actual error line in the class, thus making it difficult to spot the error and fixing it.

Break in Class Module: Selecting this option will cause an unhandled error in a class module to stop code execution and go into Break Mode at the actual error causing line of code in that class module, but does not work if you use raise errors in your classes via the Err.Raise command which will actually cause an “error”.

Error Handler

An error handler determines what action is to be taken within a procedure, on the occurrence of an error. An ‘enabled’ error handler is the one which is enabled by the On Error Statement; an ‘active’ error handler is the ‘enabled’ error handler which is in the process of handling an error. On encountering an error you may decide to exit the procedure, or else you may want to rectify the error and resume execution. For this you will use On Error statements or Resume statements. A Resume statement can only be used in an error-handling routine — it resumes execution after the error-handline routine finishes.

On Error Statements

On encountering a run-time error, an On Error statement enables or disables an error-handling routine within a procedure. If an error-handling routine is enabled, procedure flow is directed to the error-handling routine which handles the error.

On Error GoTo line

The On Error GoTo line Statement enables the error-handling routine, which is the section starting at the line specified in the line argument. The line argument is required to be specified, and it can be any line label or line number in the same procedure as the On Error statement. A compile-time error will occur if the specified line argument is not in the same procedure as as the On Error statement. The On Error GoTo statement traps all errors, without exceptions.

On Error Resume Next

This Statement specifies that on the occurrence of a run-time error, the procedure flow is directed to the next statement which follows the statement where the error occurred. This effectively skips the error and continues with the macro execution.

An On Error Resume Next statement becomes inactive on calling another procedure is called, hence it needs to be specified in every procedure that is called to use this error handling therein. Note that the properties of the Error object (Err Object) get cleared automatically when Resume Next is used in an error-handling routine, but not on using the Resume Next statement otherwise. Using the On Error Resume Next statement only defers error trapping & handling, whereas an error-handling routine handles the error and using the Resume Next statement therein resumes execution at same line that caused the error.

On Error GoTo 0

On Error GoTo 0 statement Disables any enabled error handler in the current procedure — it means as having no error handler in the code. This statement does not specify 0 as the start of the error-handling routine even though a line numbered 0 may be present in the procedure. An error handler is automatically disabled when a procedure is exited or if it has has run completely, if the procedure does not have an On Error GoTo 0 statement.

Using an Exit Statement

Placing an Exit Sub, Exit Function or Exit Property statement

For a procedure containing an error-handling routine, you will also need to include an exit routine within the procedure to ensure that the error-handling routine runs only if an error is encountered. This can be done by placing an Exit Sub, Exit Function or Exit Property statement immediately above the error-handling routine, if you don’t want it to execute when there is no error.

Single Exit Point

It may be preferable, not necessary, to have a single exit point in your procedure, so that after the Error Handler has handled the error, the procedure flow is directed to a point within the procedure so that the procedure exit is the same under all circumstances. This can be done by placing a Resume statement — Resume <Label> — the Label determines the point at which procedure flow is resumed after the Error Handler has handled the error. This Label has no effect on code execution if no error has occurred. It is preferable to have a single exit point because usually some type of clean up is required before the procedure exits, ex. you often enter Application.EnableEvents = False at the beginning of the code  for a worksheet_change event and because EnableEvents is not automatically changed back to True you add Application.EnableEvents = True at the end of the code before exit. A single exit point will obviate the need to duplicate this clean up code in the error-handling routine.

Error Handling in Nested Procedures & The Resume Statement

Using a Resume Statement

A Resume statement can only be used in an error-handling routine — it resumes execution at a sepcified point after the error-handline routine finishes. You can aslo exit or end the procedure after the error-handling routine finishes and not necessarily use the Resume statement. We discuss below three types of syntax used for the Resume statement, and how the control transfers (ie. code execution resumes) by these Resume statements. You should always use a Resume statement instead of a GoTo statement within an error-handling routine, because using a «GoTo line» statement apparantly deactivates subsequent Error Handling — even though both Resume & GoTo statements direct procedure flow out of the error-handling routine.

Resume or Resume 0: Where the error occurrs in the same procedure as the error handler, control is returned to the statement that caused the error and execution resumes at this line. Where the error occurrs in a called procedure, control is returned to the last calling statement in the procedure containing the error handler.

Resume Next: Where the error occurrs in the same procedure as the error handler, control is returned to  the next statement which follows the statement that caused the error and execution resumes at this line. Where the error occurrs in a called procedure, control is returned to the next statement which follows the last calling statement in the procedure containing the error handler.

Resume line: When an error occurrs in a procedure, control transfers to the line specified in the line argument. The line argument is a line label or line number and should be in the same procedure as the error handler.

Which Resume Statement to use:

The Resume or Resume 0 statement is used when it is necessary for the macro to correct the error and re-execute the corrected code — say when the user enters an invalid value and you want to prompt the user to enter a valid value and resume at the same line and re-excecute. The Resume Next statement is used when the error handler corrects the error and it is not required to re-execute the error code but to continue execution at the next line. The Resume line statement is used when you want to continue execution at another point in the procedure, which could also be an exit routine.

Given below are 2 Examples which illustrate using On Error Statements & Error Handler in a Procedure

Example 1: 

Sub OnErrorResNxtSt()
‘using an On Error Resume Next Statement in a procedure for handling errors
‘a run-time error 1004 occurs while naming another sheet with the same name

‘execution flows to the next statement which follows the statement that caused the error

On Error Resume Next

Dim strNewName As String, ws As Worksheet, response As Integer

‘add a new worksheet at the end

ActiveWorkbook.Worksheets.Add After:=Worksheets(Sheets.Count)

WsName:

‘enter name for worksheet

strNewName = InputBox(«Enter Worksheet Name»)

‘StrPtr — String Pointer — function used to determine if Cancel button has been pressed.

If StrPtr(strNewName) = 0 Then

MsgBox «You have pressed Cancel, Exiting Procedure without changing Worksheet Name»

Exit Sub

End If

‘rename the new worksheet — if name already exists, a run-time error 1004 will occur

ActiveSheet.Name = strNewName

‘Check Err object Number property if it corresponds to the error no. 1004.

‘Error No. 1004 occurs if worksheet with the same name already exists

If Err = 1004 Then

response = MsgBox(«Name already Exists, do you want to retry?», vbYesNo + vbQuestion)

If response = vbYes Then

‘clear error

Err.Clear

‘if worksheet name already exists, enter a new name

GoTo WsName

Else

MsgBox «Exiting Procedure without changing Worksheet Name»

Exit Sub

End If

End If

‘returns 0 — either no error occurred or error was cleared

MsgBox Err.Number

End Sub

Example 2: 

Sub OnErrorGoToSt()
‘using an On Error GoTo Statement in a procedure for handling errors, and a Resume statement within an error-handling routine
‘a run-time error 1004 occurs while naming another sheet with the same name

On Error GoTo ErrHandler

Dim strNewName As String, ws As Worksheet

‘add a new worksheet at the end

ActiveWorkbook.Worksheets.Add After:=Worksheets(Sheets.Count)

WsName:

‘enter name for worksheet

strNewName = InputBox(«Enter Worksheet Name«)

‘StrPtr — String Pointer — function used to determine if Cancel button has been pressed.

If StrPtr(strNewName) = 0 Then

MsgBox «You have pressed Cancel, Exiting Procedure»

GoTo exit_proc

End If

‘rename the new worksheet — if name already exists, a run-time error 1004 will occur

ActiveSheet.Name = strNewName

‘returns 0 — either no error occurred or error was cleared (using Resume statement in an error-handling routine, automatically clears the error)

MsgBox Err.Number

‘exit routine to skip error handler

exit_proc:

Exit Sub

ErrHandler:

‘Error No. 1004 occurs in this case if worksheet with the same name already exists

If Err = 1004 Then

MsgBox «Name already exists»

‘resumes execution at this point (WsName)

Resume WsName

Else

‘resumes execution at exit routine and exits sub

Resume exit_proc

End If

End Sub

Error Handling in a Called Procedure

If the called procedure in which an error has occurred does not have an error handler, VBA searches backward in the calling procedures for an enabled error handler, and if found the control is transferred to that error handler in the calling procedure. If an enabled error handler is not found in the backward search, then execution will stop in the current procedure displaying an error message.

Example 3:  Error in Nested Procedures — in the absence of an error handler in the called procedure in which an error has occurred, VBA searches backward in the calling procedures and control is transferred to an enabled error handler, if present, in the calling procedure.

Sub CallMarksGrades()
‘this is the calling procedure, with an error handler and Resume statements — the error handler is capable of correcting Type Mismatch, Overflow & Division by Zero errors.

On Error GoTo ErrHandler

‘Declare constants to indicate likely errors

Dim iMarks As Integer, iTotalMarks As Integer, dPcnt As Double, response As Integer

Const conErrorTypeMismatch As Long = 13

Const conErrorDivZero As Long = 11

Const conErrorOverflow As Long = 6

M:

iMarks = InputBox(«Enter Marks«)

TM:

iTotalMarks = InputBox(«Enter Total Marks«)

‘call the MarksPercent function and the result is assgined to the local variable dPcnt

dPcnt = MarksPercent(iMarks, iTotalMarks)

MsgBox «Percentage is » & dPcnt & «%»

‘exit routine to skip error handler

exit_proc:

Exit Sub

ErrHandler:

MsgBox Err

‘Check Err object Number property if it corresponds to the Type Mismatch error

‘a Type Mismatch error will occur if you have entered a non-numerical or pressed Cancel in the Input Box

If Err = conErrorTypeMismatch Then

response = MsgBox(«You may have entered a non-numerical value or pressed Cancel, do you want to Exit procedure?», vbYesNo + vbQuestion)

If response = vbYes Then

Resume exit_proc

Else

‘after correcting the error, resume execution at the same line which caused the error ie. Input Box is re-generated for making a valid entry

Resume

End If

‘Check Err object Number property if it corresponds to the Overflow error (where values exceed limitations or allowable range)

ElseIf Err = conErrorOverflow Then

MsgBox «Overflow error — also possible if both Marks & Total Marks are zero»

‘after correcting an Overflow error, resume execution at the specified line ie. M, which generates the Input Boxes afresh

Resume M

‘Check Err object Number property if it corresponds to the Division by Zero error

ElseIf Err = conErrorDivZero Then

MsgBox «Division by Zero error — Total Marks cannot be zero»

‘after correcting a division by zero error, resume execution at the specified line ie. TM, which generates the Input Box for iTotalMarks

Resume TM

Else

‘control is returned to  the next statement which follows the statement that caused the error

Resume Next

End If

End Sub

Function MarksPercent(Marks As Integer, TotalMarks As Integer) As Double
‘this is the called procedure — in case of an error in this procedure, say a division by zero run-time error no. 11,  VBA searches backward in the calling procedures for an enabled error handler, and if found the control is transferred  to that error handler in the calling procedure.

MarksPercent = Marks / TotalMarks * 100

MarksPercent = Round(MarksPercent, 2)

End Function

If an error occurs in a called procedure within an active error handler which does not correct for that error, using the Raise method to regenerate the original error will force Visual Basic to search backward through the calling procedures hierarchy for an enabled error handler. The Err object’s Raise method is useful to regenerate an original error in a vba procedure — refer the section on Error Object for details on the Raise Method. This is useful in cases where the called procedure’s error handler is not equipped to correct the error either because this type of error was not expected to occur in the called procedure or for any other reason. In this scenario the sequence will be that an error occurrs in a called procedure — the called procedure has an enabled error handler which does not correct the error, and the original error is regenerated using the Raise Method — Visual Basic is forced to do a backward search and execution flows to the error handler (if present) of the immediately preceding calling procedure, which may or may not correct the error — if the immediately preceding calling procedure does not have an error handler or its error handler is not capable of correcting the error and the error is regenerated then the backward search continues. If you do not regenerate the error in the called procedure whose enabled error handler is incapable of handling the error, the error may cause the macro to stop or continue with the error causing other errors.

Example 4:  Error in Nested Procedures — for an error in a called procedure with an active error handler which does not correct for that error, on Regenerating the error with the Raise Method, VBA searches backward in the calling procedures and control is transferred to an enabled error handler, if present, in the calling procedure.

Sub Calling_Proc()
‘calling procedure — this handles any error, and corrects in case it is a File Not Found error no. 53

Const conFileNotFound As Integer = 53

On Error GoTo ErrHandler

‘call another procedure

Call Called_Proc

‘exit routine to skip error handler

exit_routine:

Exit Sub

‘error handling routine of the calling procedure

ErrHandler:

‘error is corrected if it is a File Not Found error no. 53

If Err = conFileNotFound Then

MsgBox «Error No 53 — File Not Found, will create a New File to Copy»

Dim strFileToCopy As String, strFileCopied As String

strFileToCopy = «Book11.xlsx«

strFileCopied = «Book22.xlsx«

‘create a new workbook:

Workbooks.Add

‘save as .xlsx file, the default Excel 2007 file format, using the FileFormat Enumeration xlOpenXMLWorkbook (value 51):

ActiveWorkbook.SaveAs fileName:=strFileToCopy, FileFormat:=xlOpenXMLWorkbook

‘close workbook after saving changes:

ActiveWorkbook.Close SaveChanges:=True

‘this will copy the file

FileCopy strFileToCopy, strFileCopied

MsgBox «File Created & Copied»

‘if error is other than a File Not Found error no. 53

Else

MsgBox «Unresolved Error, Exiting Procedure»

End If

‘resumes execution at exit routine and exits sub

Resume exit_routine

End Sub

Sub Called_Proc()
‘this is a called procedure with an error handler that will correct only a Path not found error no. 76
‘for any other error in this procedure, say if the file is not found in the path/directory, the Raise method is used to regenerate the original error and execution flows to an enabled error handler (if present) in the calling procedure

‘Declare constant to indicate anticipated error

Const conPathNotFound As Integer = 76

Dim strFilePath As String, intOrigErrNum As Integer

Dim strFileToCopy As String, strFileCopied As String

strFileToCopy = «Book11.xlsx«

strFileCopied = «Book22.xlsx«

On Error GoTo ErrHandler76

‘specify file path: PATH NOT FOUND ERROR OCCURS HERE

‘not finding the specified path will give a run-time error ’76’ — Path not found

strFilePath = «C:ExcelFiles«

ChDir strFilePath

‘OTHER ERROR OCCURS HERE

‘attempting to Copy a file which does not exist will give a run-time error ’53’ — File not found

FileCopy strFileToCopy, strFileCopied

MsgBox «File Copied»

‘exit routine to skip error handler

exit_proc:

Exit Sub

ErrHandler76:

‘Check Err object Number property if it corresponds to the Path not found error.

If Err = conPathNotFound Then

‘correcting the Path in the Error Handler

strFilePath = ThisWorkbook.Path

MsgBox «Correcting Error No 76 — Path changed to ThisWorkbook path»

‘after correcting the Path, resume execution at the same line which caused the error

Resume

Else

‘for an error other than error no. 76, determine error number.

intOrigErrNum = Err.Number

‘clear error

Err.Clear

MsgBox «Error is other than error no. 76 — will Search Backward in Calling Procedures for an Error Handler to correct this error»

‘Regenerate original error — this will search backward in the calling procedures for an Error Handler if its exists

Err.Raise intOrigErrNum

‘resumes execution at exit routine and exits sub — execution flows to an enabled error handler in the calling procedure if it exists

Resume exit_proc

End If

End Sub

Get Information from the Error Object

Err Object & Properties: On the occurrence of a run-time error, you can get information on the error from the properties of the Error object (this object is the Err Object), which will help you in managing the error and to determine what is to be done next. The Number Property (Err.Number) returns a numeric value specifying the error with a value of zero meaning no error — this is the error’s number. The Number Property is the default property of the Err object. The Description Property (Err.Description) returns a short description of the error but this may not exist at times — if no Visual Basic error corresponds to the Number property, the «Application-defined or object-defined error» message is used. The Description property returns a zero-length string («») if no run-time error has occurred or ErrorNumber is 0. The property settings of the Err object relate to the most recent run-time error, so it is important that your error-handling routine saves these values before the occurrence of another error.

Use the Clear Method (Err.Clear) to to explicitly clear all property settings of the Err object. Using an Exit Sub, Exit Function or Exit Property statement, or using Resume Next statement in an error-handling routine, automatically calls the Clear Method and resets the numeric properties (viz. Number property) of the Err object to zero and the string properties (viz. Description property) to zero-length strings («»). However, the properties of the Err object are not reset when you use any Resume statement outside of an error-handling routine. Err.Clear is used to clear the properties of the Err object properties after the error is handled — using the On Error Resume Next statement defers error handling, whereas an error-handling routine handles the error and using the Resume Next statement therein resumes execution at same line that caused the error. Note that setting the error number to zero (Err.Number = 0) is not the same as using the Clear method because this does not reset the description property.

Using the Source property (Err.Source) lets you know what generated the error — Source returns the name of the object or application that generated the error. Source contains the project name for an error in a standard module. Source is the programmatic ID of your application if an error is generated by your application from code. Source contains a name with the project.class form, for an error in a class module. Source can be specifically defined by the user while using the Raise Method to generate an error. This property may not be very useful in providing information on vba run-time erros as it basically returns the name of the project in which the error occurred.

For Error Handling within a procedure it is usual to programmatically use only the Number property of the Err object, while other properties of the Err object are useful to provide additional information to the user on the cause of the error. Many times in your code it may be preferable to use the On Error Resume Next statement over On Error GoTo statement, because by checking the Err object’s properties after each interaction with an object (line of code) you can determine which object or statement originally generated what error — refer Example 1.

Example 5: Illustrating some common run-time errors in vba, with their respective Error.Number & Error.Description

Sub RunTimeErrorsInVba()
‘Illustrating some common run-time errors in vba, with their respective Error.Number & Error.Description
‘Err.Source in all cases below is «VBAProject», except in 2 instances of Run-time error ‘1004’ wherein the Source is «Microsoft Office Excel»

‘Run-time error ’11’: Division by zero (dividing a number by zero will give this error)

MsgBox 2 / 0

‘Run-time error ‘9’: Subscript out of range (This error occurs if you attempt to access array elements & members of collections beyond their defined ranges. In this case Sheet does not exist — active Workbook contains only 3 sheets)

MsgBox Sheets(7).Name

‘Run-time error ‘1004’: Application-defined or object-defined error (invalid reference). Err.Source returns ‘VBAProject’

Cells(1, 1).Offset(-1, 0) = 5

‘Run-time error ‘1004’: Select method of Range class failed (Sheet1 is not the active sheet whereas Select Method is valid for active sheet only). Err.Source returns ‘Microsoft Office Excel’

Sheets(«Sheet1»).Cells(1, 1).Select

‘Run-time error ‘1004’: Cannot rename a sheet to the same name as another sheet, a referenced object library or a workbook referenced by Visual Basic (renaming the active sheet wherein sheet with the same name already exists).

Err.Source returns ‘Microsoft Office Excel’

ActiveSheet.Name = «Sheet1«

‘Run-time error ’76’: Path not found (the specified path is not found)

ChDir «C:ExcelClients»

‘Run-time error ’68’: Device unavailable (drive does not exist)

ChDrive «H»

‘run-time error ’53’ — File not found (copy or delete a file which does not exist viz. Book1.xlsx)

FileCopy ActiveWorkbook.Path & «» & «Book1.xlsx», ActiveWorkbook.Path & «» & «Book2.xlsx»

Kill ActiveWorkbook.Path & «» & «Book1.xlsx»

‘Run-time error ’91’: Object variable or With block variable not set (using an object variable that does not yet reference a valid object: an error is generated on the reference to ws because the Set statement is omitted viz. Set ws =

ActiveSheet)

Dim ws As Worksheet

ws = ActiveSheet

MsgBox ws.Name

‘Run-time error ‘424’: Object required (sheet name is not a valid object)

Dim ws As Worksheet

Set ws = ActiveSheet.Name

‘Run-time error ’13’: Type mismatch (variable is of incorrect type — reference is to a range object & not worksheet — variable should be declared as — Dim ws As Range)

Dim ws As Worksheet

Set ws = ActiveSheet.Cells(1, 1)

‘entering a string value in the input box below will give a Run-time error ’13’: Type mismatch

Dim result As Single

result = InputBox(«Enter a number»)

‘Run-time error ‘6’: Overflow (this error occurs if you attempt to assign values exceeding the assigned target’s limit — in the present case the value of i is larger than an integer because an integer can hold whole numbers in the range -32,768

to 32,767)

Dim i As Integer

i = 100 * 20000

MsgBox i

End Sub

Raise Method of the Err Object: Generate a Run-time error

Raise Method is used to generate a run-time error. You can raise either a pre-defined error using its corresponding error number, or generate a custom (user-defined) error. Though Raise can be used in place of the Error statement, but because errors generated by using the Error statement give richer information in the Err object, Raise is useful to generate run-time errors for system errors and class modules. Syntax: Err.Raise(Number, Source, Description, HelpFile, HelpContext). The Raise method generates a specific error and the Err object properties are populated with information on that error. Only the Number argument is necessary to specify in the Raise Method, and all other arguments are optional. If optional arguments are omitted and the Err object properties contain uncleared values, those values are assumed for your error values. The Err object’s Raise method is useful to regenerate an original error in a vba procedure — if an error occurs within an active error handler which does not correct for that error, using the Raise method to regenerate the original error will force Visual Basic to search backward through the calling procedures for an enabled error handler. This has been explained & illustrated in Example 4 above.

Arguments of Raise Method: The Number argument is the error’s number. The Source argument represents the source of the error. The Description argument describes the error providing additional information about it. The HelpFile and HelpContext arguments represent the help file and help context ID used to link help to the error message box.

Raise Custom Errors (user-defined errors) using the Err Object’s Raise Method:

You can deliberately generate custom (run-time) errors in vba code, using the Raise Method of the Err Object. You may want to generate a custom error when your code does something you don’t want, for example, to prevent a user from inputting data which may be outside an acceptable range, you can stop the macro by raising an error, complete with an error code and the source of occurrence. To enable this, use the Err object’s Raise method.

The arguments of the Raise Method correspond to the properties of the Err object, and all arguments except the Number argument are optional. While raising a custom error you can set your own custom arguments in the Raise Method. You can raise pre-defined errors using their respective error numbers, but for a custom error you cannot use an error number which is in conflict with any Office built-in error number. To set Err.Number for your custom error, add the number you select as an error code to the vbObjectError constant (-2147221504) to ensure your custom error number is not in conflict with any built-in error numbers, for ex. to return the number -2147220504 as an error code, assign vbObjectError + 1000 to the Err.Number property — Err.Raise vbObjectError + 1000. One option is to set the Source argument as the name of the procedure in which the error occurs.

Example 6: Raise a custom error using Raise Method of the Err object, if length of name is less than 4 characters

Sub RaiseCustomError_1()
‘raise a custom error using Raise Method of the Err object, if length of name is less than 4 characters

   
On Error GoTo CustomError_Err

Dim strName As String

strName = «Jo«

If Len(strName) < 4 Then

‘an error occurs if name length < 4 characters — raise a custom error

Err.Raise Number:=vbObjectError + 1000, Description:=»Minimum Length of Name is 4 characters«

Else

‘macro executes if no error

MsgBox «Name: » & strName

End If

    
‘if no error, display message is «Program Executed»

MsgBox «Program Executed»

CustomError_End:

Exit Sub

    
CustomError_Err:

‘Display error number and description in message box: «Error Number: -2147220504, Description: Minimum Length of Name is 4 characters»

MsgBox «Error Number: » & Err.Number & «, Description: » & Err.Description

‘display message is «Exit Program without Executing»

MsgBox «Exit Program without Executing»

‘resume execution at this point after error handler has handled an error

Resume CustomError_End

End Sub

Понравилась статья? Поделить с друзьями:
  • Excel vba outlook getdefaultfolder
  • Excel vba for next continue for
  • Excel vba option base
  • Excel vba for loop with if
  • Excel vba open sub