Меню

Vba условие если ошибка

Обработка ошибок в VBA Excel с помощью оператора On Error. Синтаксис выражений с оператором On Error. Пример кода с простым обработчиком ошибок.

On Error – это оператор, который используется для отслеживания ошибок во время исполнения кода VBA. При возникновении ошибки On Error передает информацию о ней в объект Err и включает программу обработки ошибок, начинающуюся с указанной строки.

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

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

Синтаксис выражений с On Error

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

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

Отключает любой включенный обработчик ошибок в текущей процедуре.

Простой обработчик ошибок

Шаблон простейшего обработчика ошибок:

Sub Primer()

On Error GoTo Stroka

    ‘Блок операторов процедуры

Exit Sub

Stroka:

    MsgBox «Произошла ошибка: « & Err.Description

End Sub

Оператор On Error GoTo размещается в начале процедуры, метка и обработчик ошибок – в конце процедуры. Название метки можно сменить на другое, в том числе на кириллице.

Оператор Exit Sub обеспечивает выход из процедуры, если блок операторов выполнен без ошибок. Для вывода описания ошибки используется свойство Description объекта Err.

Примеры обработки ошибок

Пример 1
Деление на ноль:

Sub Primer1()

On Error GoTo Инструкция

    Dim a As Double

    a = 45 / 0

Exit Sub

Instr:

    MsgBox «Произошла ошибка: « & Err.Description

End Sub

Результат выполнения кода VBA Excel с обработчиком ошибок:

Пример 2
Выход за границы диапазона:

Sub Primer2()

On Error GoTo Instr

    Dim myRange As Range

    Set myRange = Range(«A1:D4»).Offset(2)

Exit Sub

Instr:

    MsgBox «Произошла ошибка: « & Err.Description

End Sub

Результат выполнения кода VBA Excel с оператором On Error GoTo:

Пример использования выражений On Error Resume Next и On Error GoTo 0 смотрите в статье: Отбор уникальных значений с помощью Collection.

In this Article

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

VBA Errors Cheat Sheet

Errors

On Error – Stop code and display error

On Error Goto 0

On Error – Skip error and continue running

On Error Resume Next

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

On Error Goto [Label]

Clears (Resets) Error

On Error GoTo1

Show Error number

MsgBox Err.Number

Show Description of error

MsgBox Err.Description

Function to generate own error

Err.Raise

See more VBA “Cheat Sheets” and free PDF Downloads

VBA Error Handling

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

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

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

VBA On Error Statement

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

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

On Error GoTo 0

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

On Error GoTo 0

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

vba runtime error 13

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

Sub ErrorGoTo0()

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

'Run More Code

End Sub

On Error Resume Next

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

On Error Resume Next

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

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

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

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

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

VBA Coding Made Easy

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

automacro

Learn More

Err.Number, Err.Clear, and Catching Errors

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

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

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

Sub ErrorNumber_ex()

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

End Sub

vba run-time error 11 err.number

Error Handling with Err.Number

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

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

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

    On Error GoTo -1
End Function

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

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

On Error GoTo Line

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

On Error GoTo errHandler

and create a line label like this:

errHandler:

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

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

On Error Exit Sub

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

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

Sub ErrGoToEnd()

On Error GoTo endProc

'Some Code
    
endProc:
End Sub

or by using the Exit Sub command:

Sub ErrGoToEnd()

On Error GoTo endProc

'Some Code
GoTo skipExit
    
endProc:
Exit Sub

skipExit:

'Some More Code

End Sub

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

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

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

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

Sub ErrExamples()

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

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

VBA On Error MsgBox

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

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

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

    GoTo endProc
    
errHandler:
    MsgBox errMsg
   
endProc:
End Sub

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

VBA IsError

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

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

VBA Programming | Code Generator does work for you!

If Error VBA

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

Sub IfErrorEx()

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

MsgBox n
End Sub

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

VBA Error Types

Runtime Errors

As stated above:

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

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

vba runtime error 13

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

Syntax Errors

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

  • Mispelling
  • Missing or incorrect punctuation

The VBA Editor identifies many syntax errors with red highlighting:

vba syntax error example

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

vba syntax error option

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

vba syntax compile error

I personally find this extremely annoying and disable the feature.

Compile Errors

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

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

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

vba compile error variable

Other examples include:

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

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

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

Debug > Compile

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

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

vba debug compile

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

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

vba compile vbaproject

OverFlow Error

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

vba overflow error

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

Other VBA Error Terms

VBA Catch Error

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

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

VBA Ignore Error

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

On Error Resume Next

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

VBA Throw Error / Err.Raise

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

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

Err.Raise (13)

vba runtime error 13

VBA Error Trapping

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

VBA Error Message

A VBA Error Message looks like this:

vba runtime error 13

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

vba raise error

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

VBA Error Handling in a Loop

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

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

Sub test()
Dim cell As Range

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

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

VBA Error Handling in Access

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

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

Обработка ошибок

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

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

Типы ошибок

Существуют три типа ошибок в программе:

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

Инструкция On Error

Ошибки времени выполнения можно перехватывать внутри подпрограммы. Для этого используется инструкция On Error, которая имеет три формата:

  • On Error GoTo <Метка> — при возникновении ошибки управление передается инструкции, помеченной меткой <Метка>. Метка должна быть допустимым идентификатором, к которому предъявляются такие же требования как и к переменным. Внутри подпрограммы метка указывается в самом начале помечаемой строки и после метки ставится двоеточие. В качестве примера создадим функцию для деления двух целых чисел. Внутри функции предусмотрим обработку ошибки деления на 0:
Function Деление(x As Integer, y As Integer) As Double
   On Error GoTo ПриОшибке
   Деление = x / y
   Exit Function
ПриОшибке:
   Деление = 0
End Function

Если при вызове функции во втором параметре передать значение 0, то управление будет передано в строку, помеченную с помощью метки ПриОшибке. Обратите внимание на то, что метка расположена после инструкции Exit Function. В этом случае код после инструкции Exit Function будет выполнен только в том случае, если возникнет ошибка;

  • On Error Resume Next — при возникновении ошибки управление передается следующей инструкции;
  • On Error GoTo 0 — отключает перехват ошибок.

Если внутри подпрограммы не предусмотрен перехват ошибки, то при возникновении ошибки работа программы прерывается и выводится стандартное окно с описанием и несколькими кнопками: Continue (продолжить), End (завершить выполнение программы), Debug (перейти в режим отладки) и Help (вывод справки).

Инструкция Resume

Инструкция Resume позволяет указать куда следует переходить после обработки ошибки. Инструкция имеет несколько форматов:

  • Resume [0] — управление передается инструкции, вызвавшей ошибку;
  • Resume Next — управление передается инструкции, следующей за инструкцией, вызвавшей ошибку;
  • Resume <Метка> — управление передается инструкции, помеченной меткой <Метка>.

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

Получение информации об ошибке и генерация ошибки

Вся информация о последней ошибке доступна через объект Err. Объект содержит следующие свойства:

  • Number — код ошибки, например, код 11 для ошибки деления на 0. Если ошибки не произошло, то свойство содержит значение 0;
  • Description — описание ошибки, например, строка "Division by zero" для ошибки деления на 0. Пример вывода кода и описания ошибки:
Debug.Print Err.Number; Err.Description
  • Source — название текущего проекта;
  • HelpFile — путь к файлу справки;
  • HelpContext — идентификатор раздела в справочном файле;
  • LastDLLError — системный код ошибки при работе с DLL.

Объект Err содержит следующие методы:

  • Clear() — очищает всю информацию о последней ошибке. Этот метод следует вызвать после успешной обработки ошибки. Информация об ошибке автоматически очищается при выходе из подпрограммы и ряде других случаев;
  • Raise() — позволяет сгенерировать ошибку в программе. Формат метода:
Raise Number[, Source][, Description][, HelpFile][, HelpContext]

В параметре Number указывается код генерируемой ошибки (целое число от 0 до 65 535). Коды от 0 до 512 зарезервированы под системные ошибки, а остальные коды можно использовать под пользовательские ошибки. Чтобы сгенерировать ошибку с пользовательским кодом необходимо сложить код с константой vbObjectError. Остальные параметры являются необязательными и полностью аналогичны одноименным свойствам объекта Err. Пример генерации и обработки пользовательской ошибки:

Sub ГенерацияОшибки()
   On Error GoTo ПриОшибке
   Err.Raise vbObjectError + 513
   Exit Sub
ПриОшибке:
   Debug.Print Err.Number; Err.Description
   ' -2147220991 Automation error
End Sub

Способы поиска ошибок в программе

В предыдущих разделах мы научились обрабатывать ошибки времени выполнения. Однако, наибольшее количество времени программист затрачивает на другой тип ошибок — логические ошибки. В этом случае программа компилируется без ошибок, но результат выполнения программы не соответствует ожидаемому результату. Ситуация еще более осложняется, когда неверный результат проявляется лишь периодически, а не постоянно. Инсценировать такую же ситуацию, чтобы получить этот же неверный результат, бывает крайне сложно и занимает очень много времени. В этом разделе мы рассмотрим лишь «дедовские» (но по прежнему актуальные) способы поиска ошибок, а современные способы отладки приложений, доступные в VBA, изучим в следующем разделе.

Первое, на что следует обратить внимание, — на объявления переменных. Например, рассмотрим простой пример:

Как вы думаете, какое значение отобразится в окне Immediate после выполнения этого кода? Думаете, что число 10? Не факт! Вот тут-то и кроется проблема не видная на первый взгляд. В первой инструкции присваивается значение переменной x, имя которой набрано на английской раскладке клавиатуры, а вот во второй инструкции выводится значение переменной x, имя которой набрано на русской раскладке клавиатуры. В результате значение присваивается одной переменной, а выводится значение другой переменной. Такие ситуации очень часто встречаются в программах на языке VBA, так как объявлять переменную не обязательно. Чтобы избежать такой ситуации следует обязательно объявлять переменные явным образом. Контроль за соблюдением этого правила можно возложить на компилятор, добавив в начале модуля следующую инструкцию:

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

Option Explicit
...
Dim x As Integer
x = 10
Debug.Print x ' 10

Далее следует обратить внимание на форматирование кода. Начинающие программисты обычно не обращают на это никакого внимания, считая этот процесс лишним. А на самом деле зря! Компилятору абсолютно все равно, разместите вы все инструкции на одной строке или выполните форматирование кода. Однако, при поиске ошибок форматирование кода позволит найти ошибку гораздо быстрее.

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

Dim Массив As Variant, i As Integer, j As Integer
Массив = Array(Array(0, 1), Array(2, 3), Array(4, 5))
For i = 0 To 2
   For j = 0 To 1
      Debug.Print Массив(i)(j)
   Next
Next

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

Если программа слишком большая, то следует задуматься о разделении программы на отдельные подпрограммы или классы, которые выполняют логически законченные действия. Помните, что отлаживать отдельную подпрограмму гораздо легче, чем «спагетти»-код. Причем прежде чем вставить подпрограмму (или класс) в основную программу ее следует протестировать в отдельном проекте, передавая подпрограмме различные значения и проверяя результат ее выполнения.

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

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

Метод Print() объекта Debug удобно использовать для вывода промежуточных значений. В этом случае значения переменных вначале выводятся в самом начале программы и производится проверка соответствия значений. Если значения соответствуют, то инструкция с методом Print() перемещается на следующую строку программы и опять производится проверка и т. д. Если значения не совпали, то ошибка возникает в инструкции, расположенной перед инструкцией с методом Print(). Если это пользовательская подпрограмма, то проверку значений производят внутри подпрограммы, каждый раз перемещая инструкцию с выводом значений. На одном из этих многочисленных этапов ошибка обычно обнаруживается. В больших программах можно логически догадаться о примерном расположении инструкции с ошибкой и начать поиск ошибки оттуда, а не с самого начала программы.

Инструкции для вывода промежуточных значений можно расставить уже при написании программы, не дожидаясь возникновения ошибки. В этом случае в начале программы объявляется константа с помощью инструкции #Const, а внутри программы производится проверка значения константы:

Проверить значение константы позволяет следующая конструкция:

#If MY_DEBUG Then
   ' Здесь размещаем инструкции вывода значений
#End If

Таким образом, меняя значение константы MY_DEBUG с 1 на 0, можно отлючать вывод всех промежуточных значений.

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

Прежде чем начать отладку необходимо пометить строки внутри программы с помощью точек останова. Для добавления точки останова делаем строку активной, а затем из меню Debug выбираем пункт Toggle Breakpoint. Слева от строки появится кружок, обозначающий точку останова. Добавить точку останова можно еще быстрее. Для этого достаточно щелкнуть слева от строки левой кнопкой мыши. Повторный щелчок позволяет удалить точку останова. Кроме того, для добавления или удаления точки отстанова можно воспользоваться клавишей <F9>. Чтобы удалить все точки останова следует из меню View выбрать пункт Clear All Breakpoints.

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

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

При отладке можно контролировать значения отдельных переменных, а не всех сразу. Для этого следует выделить название переменной и из меню Debug выбрать пункт Add Watch. Можно также выделить название переменной и из контектного меню выбрать пункт Add Watch. В открывшемся окне устанавливаем флажок Watch Expression и нажимаем кнопку OK. Значение переменной будет отображаться в окне Watches. Чтобы отобразить окно Watches из меню View выбираем пункт Watch Window. Чтобы отменить отслеживание нужно выделить строку в окне Watches и нажать клавишу <Delete>.

Для пошагового выполнения программы предназначены следующие пункты в меню Debug или соответствующие кнопки на панели инструментов Debug (View | Toolbars | Debug):

  • Step Into (клавиша <F8>) — выполняет переход к следующей инструкции;
  • Step Over — выполняет одну инструкцию. Если в этой инструкции производится вызов подпрограммы, то подпрограмма выполняется за один шаг и отладчик переходит в режим ожидания после выхода из подпрограммы;
  • Step Out — при заходе в подпрограмму этот пункт позволяет выполнить подпрограмму за один шаг и выйти из нее. Отладчик переходит в режим прерывания после выхода из подпрограммы;
  • Run To Cursor — выполняет переход к инструкции, в которой расположен курсор.

Если необходимо посмотреть последовательность вызова подпрограмм, то следует открыть окно Call Stack, выбрав в меню View пункт Call Stack.

Подача звукового сигнала

При возникновении ошибки или при неправильном вводе данных имеет смысл привлечь внимание пользователя звуковым сигналом. Сгенерировать звуковой сигнал позволяет инструкция Beep. Пример:

Dim Результат
Beep
Результат = InputBox("Необходимо ввести значение")

Visual Basic for Applications (VBA)
Статьи по Visual Basic for Applications (VBA)

Точно так же, как мы используем ЕСЛИОШИБКА в Excel, чтобы знать, что делать, когда возникает ошибка перед каждой функцией, у нас есть встроенная функция ЕСЛИОШИБКА в VBA, которая используется таким же образом, поскольку это функция рабочего листа, мы используем эту функцию с worksheet.function метод в VBA, а затем мы предоставляем аргументы для функции.

Ожидать, что код будет работать без ошибок, — преступление. Для обработки ошибок в VBA у нас есть несколько способов использования таких операторов, как При ошибке Возобновить следующий VBAОператор VBA On Error Resume — это аспект обработки ошибок, используемый для игнорирования строки кода, из-за которой возникла ошибка, и продолжения со следующей строки сразу после строки кода с ошибкой.читать далее, При ошибке Возобновить Перейти к 0, При ошибке Перейти к метке. Обработчики ошибок VBA могут переходить только к следующей строке кода. Но в случае, если вычисление не происходит, нам нужно заменить ошибку на какое-то другое идентификационное слово. В этой статье мы увидим, как добиться этого с помощью VBA. ЕСЛИОШИБКА Функция в ExcelФункция ЕСЛИОШИБКА в Excel проверяет формулу (или ячейку) на наличие ошибок и возвращает указанное значение вместо ошибки.читать далее.

ЕСЛИ ОШИБКА VBA

Вы можете использовать это изображение на своем веб-сайте, в шаблонах и т. д. Пожалуйста, предоставьте нам ссылку на авторствоСсылка на статью должна быть гиперссылкой
Например:
Источник: VBA IFERROR (wallstreetmojo.com)

Как использовать ЕСЛИОШИБКА в VBA?

Здесь следует помнить, что это не Функция VBAФункции VBA служат основной цели для выполнения определенных вычислений и возврата значения. Поэтому в VBA мы используем синтаксис для указания параметров и типа данных при определении функции. Такие функции называются пользовательскими функциями.читать далее скорее просто как функция рабочего листа.

Вы можете скачать этот шаблон Excel VBA IFERROR здесь — Шаблон Excel для VBA ЕСЛИОШИБКА

Для примера возьмем приведенные выше данные только для демонстрации.

ЕСЛИ ОШИБКА VBA Пример 2

Шаг 1: Определите переменную как целое число.

Код:

Sub Iferror_Example1()

  Dim i As Integer

End Sub

Шаг 2: Для выполнения расчета откройте For Следующий цикл.

Код:

Sub Iferror_Example1()

  Dim i As Integer

  For i = 2 To 6

  Next i

End Sub

Шаг 3: Внутри напишите код как Ячейки(I,3).Значение =

Код:

Sub Iferror_Example1()

  Dim i As Integer

  For i = 2 To 6
     Cells(i,3).Value =
  Next i

End Sub

Шаг 4: Чтобы получить доступ к функции ЕСЛИОШИБКА, мы не можем просто ввести формулу; скорее, нам нужно использовать «Функция рабочего листа» класс.

Код:

Sub Iferror_Example1()

  Dim i As Integer

  For i = 2 To 6
    Cells(i, 3).Value = WorksheetFunction.If
  Next i

End Sub

ЕСЛИ ОШИБКА VBA Пример 2-1

Шаг 5: Как вы можете видеть на изображении выше, после вставки класса команды «WorksheetFunction» мы получаем формулу ЕСЛИОШИБКА. Выберите формулу.

Код:

Sub Iferror_Example1()

  Dim i As Integer

  For i = 2 To 6
    Cells(i, 3).Value = WorksheetFunction.IfError(
  Next i

End Sub

Пример 2-2

Шаг 6: Одна из проблем в VBA при доступе к функциям рабочего листа: мы не видим аргументы, подобные тому, что мы видели на рабочем листе. Вы должны быть уверены в аргументах, которые мы используем.

По этой причине, прежде чем я покажу вам IFERROR в VBA, я показал вам синтаксис функции рабочего листа.

Первый аргумент здесь — «Значение», т. е. какую ячейку вы хотите проверить? Перед этим примените расчет в Cell.

Пример 2-3

Теперь в VBA примените приведенные ниже коды.

Код:

Sub Iferror_Example1()

  Dim i As Integer

  For i = 2 To 6
    Cells(i, 4).Value = WorksheetFunction.IfError(Cells(i, 3).Value, "Not Found")
  Next i

End Sub

Теперь функция ЕСЛИОШИБКА проверяет наличие ошибок в столбце C. Если обнаруживается какая-либо ошибка, в столбце D отображается результат «Не найдено».

Пример 2-4

Таким образом, используя функцию ЕСЛИОШИБКА, мы можем изменить результаты по своему желанию. В этом случае я изменил результат как «Не обнаружена.» Вы можете изменить это по своему требованию.

Типы ошибок, VBA IFERROR, можно найти

Важно знать виды Эксель ошибкиОшибки в Excel распространены и часто возникают во время применения формул. Список из девяти наиболее распространенных ошибок Excel: #DIV/0, #N/A, #NAME?, #NULL!, #NUM!, #REF!, #VALUE!, #####, Circular Reference.читать далее функция ЕСЛИОШИБКА может обработать. Ниже приведены типы ошибок, которые может обработать IFERROR.

#N/A, #VALUE!, #REF!, #DIV/0!, #NUM!, #NAME? или #NULL!.

УЗНАТЬ БОЛЬШЕ >>

Post Views: 797

Избегание условий ошибки

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

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


Избежать ошибки времени выполнения 91 — Объект или С заблокированной переменной блока:

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

Private Sub DoSomething(ByVal target As Worksheet)
    Debug.Print target.Name
End Sub

Если target не назначена ссылка, приведенный выше код вызовет ошибку, которую легко избежать, проверяя, содержит ли объект фактическую ссылку на объект:

Private Sub DoSomething(ByVal target As Worksheet)
    If target Is Nothing Then Exit Sub
    Debug.Print target.Name
End Sub

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

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


Избегайте ошибки времени выполнения 9 — Подкласс вне диапазона:

Эта ошибка возникает при доступе к массиву за пределами его границ.

Private Sub DoSomething(ByVal index As Integer)
    Debug.Print ActiveWorkbook.Worksheets(index)
End Sub

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

Private Sub DoSomething(ByVal index As Integer)
    If index > ActiveWorkbook.Worksheets.Count Or index <= 0 Then Exit Sub
    Debug.Print ActiveWorkbook.Worksheets(index)
End Sub

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

Оператор Error

Даже с защитными пунктами, один не может реально всегда учитывать все возможные ошибки , которые могут быть подняты в теле процедуры. Оператор On Error GoTo инструктирует VBA перейти к метке линии и ввести «режим обработки ошибок» всякий раз, когда во время выполнения происходит непредвиденная ошибка. После обработки ошибки, код может возобновить обратно в «нормальное» исполнение с помощью Resume ключевое слово.

Линейные метки обозначают подпрограммы : потому что подпрограммы исходят из устаревшего кода BASIC и используют GoSub GoTo и GoSub и Return чтобы вернуться к «основной» процедуре, довольно легко написать жесткий код спагетти, если все не строго структурировано , По этой причине лучше всего:

  • процедура имеет одну и только одну подпрограмму обработки ошибок
  • подпрограмма обработки ошибок работает только в состоянии ошибки

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

Private Sub DoSomething()
    On Error GoTo CleanFail

    'procedure code here

CleanExit:
    'cleanup code here
    Exit Sub

CleanFail:
    'error-handling code here
    Resume CleanExit
End Sub

Стратегии обработки ошибок

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

CleanExit:
    Exit Sub

CleanFail:
    Select Case Err.Number
        Case 9
            MsgBox "Specified number doesn't exist. Please try again.", vbExclamation
            Resume
        Case 91
            'woah there, this shouldn't be happening.
            Stop 'execution will break here
            Resume 'hit F8 to jump to the line that raised the error
        Case Else
            MsgBox "An unexpected error has occurred:" & vbNewLine & Err.Description, vbCritical
            Resume CleanExit
    End Select
End Sub

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

Private Sub DoSomething(CheckValue as Long)

    If CheckValue = 0 Then
        On Error GoTo ErrorHandler   ' turn error handling on
        ' code that may result in error
        On Error GoTo 0              ' turn error handling off - same level
    End If

CleanExit:
    Exit Sub

ErrorHandler:
    ' error handling code here
    ' do not turn off error handling here
    Resume

End Sub

Номера строк

VBA поддерживает номера строк в стиле legacy (например, QBASIC). Скрытое свойство Erl можно использовать для идентификации номера строки, которая вызвала последнюю ошибку. Если вы не используете номера строк, Erl только вернет 0.

Sub DoSomething()
10 On Error GoTo 50
20 Debug.Print 42 / 0
30 Exit Sub
40
50 Debug.Print "Error raised on line " & Erl ' returns 20
End Sub

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

Sub DoSomething()
10 On Error GoTo 50
   Debug.Print 42 / 0
30 Exit Sub

50 Debug.Print "Error raised on line " & Erl 'returns 10
End Sub

Имейте в виду, что Erl также имеет только Integer точность и будет бесшумно переполняться. Это означает, что номера строк за пределами целочисленного диапазона дадут неверные результаты:

Sub DoSomething()
99997 On Error GoTo 99999
99998 Debug.Print 42 / 0
99999
      Debug.Print Erl   'Prints 34462
End Sub

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

Резюме ключевого слова

Подпрограмма обработки ошибок будет либо:

  • выполняются до конца процедуры, и в этом случае выполнение возобновляется в процедуре вызова.
  • или используйте ключевое слово Resume для возобновления выполнения внутри той же процедуры.

Ключевое слово Resume должно использоваться только в подпрограмме обработки ошибок, потому что если VBA встречает Resume не находясь в состоянии ошибки, возникает ошибка времени выполнения 20 «Возобновить без ошибок».

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

  • Resume используется отдельно, выполнение продолжается в инструкции, вызвавшей ошибку . Если ошибка на самом деле не обрабатывается , прежде чем делать это, то та же ошибка будет поднят снова, и выполнение может войти в бесконечный цикл.
  • Resume Next продолжает выполнение инструкции сразу после инструкции, вызвавшей ошибку. Если ошибка на самом деле не обрабатывается , прежде чем делать это, то выполнение разрешается продолжать с потенциально недействительными данными, которые могут привести к логическим ошибкам и неожиданному поведению.
  • Resume [line label] продолжает выполнение на указанной метке строки (или номер строки, если вы используете номера строк в стиле устаревшего стиля). Обычно это позволяет выполнить некоторый код очистки до того, как будет чисто выйти из процедуры, например, чтобы закрыть соединение с базой данных, прежде чем вернуться к вызывающему.

Вкл.

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

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

Вышеупомянутый акцент не может быть особо подчеркнут. On Error Resume Next эффективно игнорирует все ошибки и выталкивает их под ковер . Программа, которая взрывается с ошибкой во время выполнения с учетом недопустимого ввода, — это более эффективная программа, чем программа, которая работает с неизвестными / непреднамеренными данными — будь то только потому, что ошибка намного легче идентифицируется. On Error Resume Next можно легко скрыть ошибки .

Оператор On Error является областью действия процедур — поэтому в данной процедуре обычно должен быть только один , такой оператор On Error .

Однако иногда не удается избежать ошибки, и переключение на подпрограмму обработки ошибок только на Resume Next просто не кажется правильным. В этом конкретном случае утверждение с известным до невозможности может быть обернуто между двумя On Error :

On Error Resume Next
[possibly-failing statement]
Err.Clear 'resets current error
On Error GoTo 0

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

Public Sub Caller()
    On Error GoTo Handler
    
    Callee
    
    Exit Sub
Handler:
    Debug.Print "Error " & Err.Number & " in Caller."
End Sub

Public Sub Callee()
    On Error GoTo Handler
    
    Err.Raise 1     'This will be handled by the Callee handler.
    On Error GoTo 0 'After this statement, errors are passed up the stack.
    Err.Raise 2     'This will be handled by the Caller handler.    
    
    Exit Sub
Handler:
    Debug.Print "Error " & Err.Number & " in Callee."
    Resume Next
End Sub

Пользовательские ошибки

Часто при написании специализированного класса вы хотите, чтобы он поднимал свои собственные конкретные ошибки, и вам понадобится чистый способ для кода пользователя / вызова для обработки этих пользовательских ошибок. Оптимальным способом достижения этого является определение специального типа Enum :

Option Explicit
Public Enum FoobarError
    Err_FooWasNotBarred = vbObjectError + 1024
    Err_BarNotInitialized
    Err_SomethingElseHappened
End Enum

Используя встроенную константу vbObjectError пользовательские коды ошибок не перекрываются с зарезервированными / существующими кодами ошибок. Необходимо явно указать только первое значение перечисления, поскольку базовое значение каждого члена Enum 1 больше, чем предыдущий элемент, поэтому базовое значение Err_BarNotInitialized неявно является vbObjectError + 1025 .

Повышение собственных ошибок времени выполнения

Ошибка выполнения может быть повышена с Err.Raise оператора Err.Raise , поэтому пользовательская ошибка Err_FooWasNotBarred может быть повышена следующим образом:

Err.Raise Err_FooWasNotBarred

Метод Err.Raise также может принимать пользовательские параметры Description и Source — по этой причине рекомендуется также определять константы для хранения каждого пользовательского описания ошибки:

Private Const Msg_FooWasNotBarred As String = "The foo was not barred."
Private Const Msg_BarNotInitialized As String = "The bar was not initialized."

А затем создайте выделенный частный метод для повышения каждой ошибки:

Private Sub OnFooWasNotBarredError(ByVal source As String)
    Err.Raise Err_FooWasNotBarred, source, Msg_FooWasNotBarred
End Sub

Private Sub OnBarNotInitializedError(ByVal source As String)
    Err.Raise Err_BarNotInitialized, source, Msg_BarNotInitialized
End Sub

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

Public Sub DoSomething()
    'raises the custom 'BarNotInitialized' error with "DoSomething" as the source:
    If Me.Bar Is Nothing Then OnBarNotInitializedError "DoSomething"
    '...
End Sub

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


Примечание: наследие Error ключевое слово также может быть использован вместо Err.Raise , но это устаревшее / осуждается.

Avoiding error conditions

When a runtime error occurs, good code should handle it. The best error handling strategy is to write code that checks for error conditions and simply avoids executing code that results in a runtime error.

One key element in reducing runtime errors, is writing small procedures that do one thing. The fewer reasons procedures have to fail, the easier the code as a whole is to debug.


Avoiding runtime error 91 — Object or With block variable not set:

This error will be raised when an object is used before its reference is assigned. One might have a procedure that receives an object parameter:

Private Sub DoSomething(ByVal target As Worksheet)
    Debug.Print target.Name
End Sub

If target isn’t assigned a reference, the above code will raise an error that is easily avoided by checking if the object contains an actual object reference:

Private Sub DoSomething(ByVal target As Worksheet)
    If target Is Nothing Then Exit Sub
    Debug.Print target.Name
End Sub

If target isn’t assigned a reference, then the unassigned reference is never used, and no error occurs.

This way of early-exiting a procedure when one or more parameter isn’t valid, is called a guard clause.


Avoiding runtime error 9 — Subscript out of range:

This error is raised when an array is accessed outside of its boundaries.

Private Sub DoSomething(ByVal index As Integer)
    Debug.Print ActiveWorkbook.Worksheets(index)
End Sub

Given an index greater than the number of worksheets in the ActiveWorkbook, the above code will raise a runtime error. A simple guard clause can avoid that:

Private Sub DoSomething(ByVal index As Integer)
    If index > ActiveWorkbook.Worksheets.Count Or index <= 0 Then Exit Sub
    Debug.Print ActiveWorkbook.Worksheets(index)
End Sub

Most runtime errors can be avoided by carefully verifying the values we’re using before we use them, and branching on another execution path accordingly using a simple If statement — in guard clauses that makes no assumptions and validates a procedure’s parameters, or even in the body of larger procedures.

On Error statement

Even with guard clauses, one cannot realistically always account for all possible error conditions that could be raised in the body of a procedure. The On Error GoTo statement instructs VBA to jump to a line label and enter «error handling mode» whenever an unexpected error occurs at runtime. After handling an error, code can resume back into «normal» execution using the Resume keyword.

Line labels denote subroutines: because subroutines originate from legacy BASIC code and uses GoTo and GoSub jumps and Return statements to jump back to the «main» routine, it’s fairly easy to write hard-to-follow spaghetti code if things aren’t rigorously structured. For this reason, it’s best that:

  • a procedure has one and only one error-handling subroutine
  • the error-handling subroutine only ever runs in an error state

This means a procedure that handles its errors, should be structured like this:

Private Sub DoSomething()
    On Error GoTo CleanFail

    'procedure code here

CleanExit:
    'cleanup code here
    Exit Sub

CleanFail:
    'error-handling code here
    Resume CleanExit
End Sub

Error Handling Strategies

Sometimes you want to handle different errors with different actions. In that case you will inspect the global Err object, which will contain information about the error that was raised — and act accordingly:

CleanExit:
    Exit Sub

CleanFail:
    Select Case Err.Number
        Case 9
            MsgBox "Specified number doesn't exist. Please try again.", vbExclamation
            Resume
        Case 91
            'woah there, this shouldn't be happening.
            Stop 'execution will break here
            Resume 'hit F8 to jump to the line that raised the error
        Case Else
            MsgBox "An unexpected error has occurred:" & vbNewLine & Err.Description, vbCritical
            Resume CleanExit
    End Select
End Sub

As a general guideline, consider turning on the error handling for entire subroutine or function, and handle all the errors that may occur within its scope. If you need to only handle errors in the small section section of the code — turn error handling on and off a the same level:

Private Sub DoSomething(CheckValue as Long)

    If CheckValue = 0 Then
        On Error GoTo ErrorHandler   ' turn error handling on
        ' code that may result in error
        On Error GoTo 0              ' turn error handling off - same level
    End If

CleanExit:
    Exit Sub

ErrorHandler:
    ' error handling code here
    ' do not turn off error handling here
    Resume

End Sub

Line numbers

VBA supports legacy-style (e.g. QBASIC) line numbers. The Erl hidden property can be used to identify the line number that raised the last error. If you’re not using line numbers, Erl will only ever return 0.

Sub DoSomething()
10 On Error GoTo 50
20 Debug.Print 42 / 0
30 Exit Sub
40
50 Debug.Print "Error raised on line " & Erl ' returns 20
End Sub

If you are using line numbers, but not consistently, then Erl will return the last line number before the instruction that raised the error.

Sub DoSomething()
10 On Error GoTo 50
   Debug.Print 42 / 0
30 Exit Sub

50 Debug.Print "Error raised on line " & Erl 'returns 10
End Sub

Keep in mind that Erl also only has Integer precision, and will silently overflow. This means that line numbers outside of the integer range will give incorrect results:

Sub DoSomething()
99997 On Error GoTo 99999
99998 Debug.Print 42 / 0
99999
      Debug.Print Erl   'Prints 34462
End Sub

The line number isn’t quite as relevant as the statement that caused the error, and numbering lines quickly becomes tedious and not quite maintenance-friendly.

Resume keyword

An error-handling subroutine will either:

  • run to the end of the procedure, in which case execution resumes in the calling procedure.
  • or, use the Resume keyword to resume execution inside the same procedure.

The Resume keyword should only ever be used inside an error handling subroutine, because if VBA encounters Resume without being in an error state, runtime error 20 «Resume without error» is raised.

There are several ways an error-handling subroutine may use the Resume keyword:

  • Resume used alone, execution continues on the statement that caused the error. If the error isn’t actually handled before doing that, then the same error will be raised again, and execution might enter an infinite loop.
  • Resume Next continues execution on the statement immediately following the statement that caused the error. If the error isn’t actually handled before doing that, then execution is permitted to continue with potentially invalid data, which may result in logical errors and unexpected behavior.
  • Resume [line label] continues execution at the specified line label (or line number, if you’re using legacy-style line numbers). This would typically allow executing some cleanup code before cleanly exiting the procedure, such as ensuring a database connection is closed before returning to the caller.

On Error Resume Next

The On Error statement itself can use the Resume keyword to instruct the VBA runtime to effectively ignore all errors.

If the error isn’t actually handled before doing that, then execution is permitted to continue with potentially invalid data, which may result in logical errors and unexpected behavior.

The emphasis above cannot be emphasized enough. On Error Resume Next effectively ignores all errors and shoves them under the carpet. A program that blows up with a runtime error given invalid input is a better program than one that keeps running with unknown/unintended data — be it only because the bug is much more easily identifiable. On Error Resume Next can easily hide bugs.

The On Error statement is procedure-scoped — that’s why there should normally be only one, single such On Error statement in a given procedure.

However sometimes an error condition can’t quite be avoided, and jumping to an error-handling subroutine only to Resume Next just doesn’t feel right. In this specific case, the known-to-possibly-fail statement can be wrapped between two On Error statements:

On Error Resume Next
[possibly-failing statement]
Err.Clear 'resets current error
On Error GoTo 0

The On Error GoTo 0 instruction resets error handling in the current procedure, such that any further instruction causing a runtime error would be unhandled within that procedure and instead passed up the call stack until it is caught by an active error handler. If there is no active error handler in the call stack, it will be treated as an unhandled exception.

Public Sub Caller()
    On Error GoTo Handler
    
    Callee
    
    Exit Sub
Handler:
    Debug.Print "Error " & Err.Number & " in Caller."
End Sub

Public Sub Callee()
    On Error GoTo Handler
    
    Err.Raise 1     'This will be handled by the Callee handler.
    On Error GoTo 0 'After this statement, errors are passed up the stack.
    Err.Raise 2     'This will be handled by the Caller handler.    
    
    Exit Sub
Handler:
    Debug.Print "Error " & Err.Number & " in Callee."
    Resume Next
End Sub

Custom Errors

Often when writing a specialized class, you’ll want it to raise its own specific errors, and you’ll want a clean way for user/calling code to handle these custom errors. A neat way to achieve this is by defining a dedicated Enum type:

Option Explicit
Public Enum FoobarError
    Err_FooWasNotBarred = vbObjectError + 1024
    Err_BarNotInitialized
    Err_SomethingElseHappened
End Enum

Using the vbObjectError built-in constant ensures the custom error codes don’t overlap with reserved/existing error codes. Only the first enum value needs to be explicitly specified, for the underlying value of each Enum member is 1 greater than the previous member, so the underlying value of Err_BarNotInitialized is implicitly vbObjectError + 1025.

Raising your own runtime errors

A runtime error can be raised using the Err.Raise statement, so the custom Err_FooWasNotBarred error can be raised as follows:

Err.Raise Err_FooWasNotBarred

The Err.Raise method can also take custom Description and Source parameters — for this reason it’s a good idea to also define constants to hold each custom error’s description:

Private Const Msg_FooWasNotBarred As String = "The foo was not barred."
Private Const Msg_BarNotInitialized As String = "The bar was not initialized."

And then create a dedicated private method to raise each error:

Private Sub OnFooWasNotBarredError(ByVal source As String)
    Err.Raise Err_FooWasNotBarred, source, Msg_FooWasNotBarred
End Sub

Private Sub OnBarNotInitializedError(ByVal source As String)
    Err.Raise Err_BarNotInitialized, source, Msg_BarNotInitialized
End Sub

The class’ implementation can then simply call these specialized procedures to raise the error:

Public Sub DoSomething()
    'raises the custom 'BarNotInitialized' error with "DoSomething" as the source:
    If Me.Bar Is Nothing Then OnBarNotInitializedError "DoSomething"
    '...
End Sub

The client code can then handle Err_BarNotInitialized as it would any other error, inside its own error-handling subroutine.


Note: the legacy Error keyword can also be used in place of Err.Raise, but it’s obsolete/deprecated.

VBA On Error

VBA On Error Statements

VBA On Error is an easy method for handling unexpected exceptions in Excel Macros.It is known that we cannot write code without any error. Sometimes writing big code may give us an error even at the time of compiling. To avoid this kind of situation, we add an Error Message which, instead of giving us the right answer or error code it will show us the message with the error code. That would look like we got the output of our calculation, but it is the error code that will get imprinted.

How to Use Excel VBA On Error Statements in Excel?

There are 3 ways of Error in VBA. Let’s understand different ways with some examples.

Example #1

The first error type is a Code compilation error which comes when a code is undeclared or impossible variables. To understand more, we will use a simple mathematical expression of the divide. For this, go to the Insert menu of VBA and select Module as shown below.

Insert Module

Now open Subcategory and add any name as we are using On Error, so we have named it as same.

Sub OnError()

End Sub

VBA On Error Example 1-1

Now define any 2 or 3 Integers. Here we have taking X and Y as Integers.

Sub OnError()

Dim X As Integer, Y As Integer, Z As Integer

End Sub

VBA On Error Example 1-2

Now, as discussed above, we will calculate division mathematical expression. For X, we will put a character in Numerator and divide it 0. And Y will be 20/2, which is complete numbers.

Sub OnError()

Dim X As Integer, Y As Integer

X = Test / 0

Y = 20 / 2

End Sub

VBA On Error Example 1-3

Now run the code by using the F5 key or clicking on the play button as shown below. We will get Run-time error 6, which shows Text over number error.

VBA On Error Example 1-4

Now to overrule this error, we will add one line On Error Resume Next before we write the mathematical code. It will jump the error code, but we will not able to see the outcome of the second mathematical code. This only hides the error message of various codes lines, as shown below. Now try to run the code as well.

Sub OnError()

Dim X As Integer, Y As Integer

On Error Resume Next

X = Test / 0

Y = 20 / 2

MsgBox X
MsgBox Y

End Sub

VBA On Error Example 1-5

Now to overrule this error, we will add one line On Error Resume Next before we write the mathematical code. It will jump the error code, but we will not able to see the outcome of the second mathematical code. This only hides the error message of various codes lines, as shown below. Now try to run the code as well.

VBA On Error Example 1-6

Example #2

In this example, we will consider that mathematical division which gives infinite result, but in coding, it will #DIV/0 result. To demonstrate this, we will consider one more integer Z along with X and Y in a subcategory, as shown below.

Sub OnError()

Dim X As Integer, Y As Integer, Z As Integer

End Sub

VBA On Error Example 2-1

Now frame all the integers X, Y, and Z with a mathematical expression of divide and to print it use MsgBox function in VBA of each integer’s result.

Below for Integer X, we have divided 10 by 0, 20 by 2 and 30 by 4.

Sub OnError()

Dim X As Integer, Y As Integer, Z As Integer

X = 10 / 0

Y = 20 / 2

Z = 30 / 4

MsgBox X
MsgBox Y
MsgBox Z

End Sub

VBA On Error Example 2-2

Now run the code using the F5 key or manually, as shown below.

VBA On Error Example 2-3

As we can see in the above screenshot, Run-time error 11, which means the error is related to the number. Now to overcome this, add one line On Error Resume Next before mathematical expression as shown below.

Sub OnError()

Dim X As Integer, Y As Integer, Z As Integer

On Error Resume Next

X = 10 / 0

Y = 20 / 2

Z = 30 / 4

MsgBox X
MsgBox Y
MsgBox Z

End Sub

VBA On Error Example 2-4

Now, if we run the code, we will get zero for the first integer X and for Y and Z, we will get respective division answers as shown below.

 VBA On Error Example 2-5                 

Example #3

The second type of error is seen when we enter incorrect data entry in code. For this, we will consider 3 integers, X, Y, and Z, by opening the Subcategory in VBA as shown below.

Sub OnError()

Dim X As Integer, Y As Integer, Z As Integer

End Sub

Example 3-1

Now also consider the same mathematical division which we have seen in the above example.

Sub OnError()

Dim X As Integer, Y As Integer, Z As Integer

X = 10 / 0

Y = 20 / 2

Z = 30 / 4

MsgBox X
MsgBox Y
MsgBox Z

End Sub

Example 3-2

If we run the code, we will get the same error message of Run-time error 11.

Example 3-3

Now to overrule this error, use text On Error GoTo with the word “ “Result to skip the error message and get the output which works fine, as shown below.

Sub OnError()

Dim X As Integer, Y As Integer, Z As Integer

On Error GoTo ZResult:

X = 10 / 0

Y = 20 / 2

ZResult:
Z = 30 / 4

MsgBox X
MsgBox Y
MsgBox Z

End Sub

Example 3-4

Now run the code again. We will get the same result as the previous example.

Example 3-5

On Error GoTo ZResult helps us to directly jump of mentioned result point integer as we did for integer Z.

Example #4

In the third type of error, when we run the code and VBA is not able to understand the line of code. This can be done with the help of code On Error Resume Next along with MsgBox Err.Number. Consider the same data as used in the above examples. We will again see the same 3 integers X, Y, and Z, as shown below.

Sub OnError()

Dim X As Integer, Y As Integer, Z As Integer

End Sub

Example 4-1

And for printing the result output, allow message boxes for all Integers as output.

Sub OnError()

Dim X As Integer, Y As Integer, Z As Integer

X = 10 / 0

Y = 20 / 2

Z = 30 / 4

MsgBox X
MsgBox Y
MsgBox Z

End Sub

Example 4-2

Now, if we run the complete code, then we will get an error message of mathematical error Run time error 11.

Example 4-3

Now to overrule this error, we will use On Error Resume Next.

Sub OnError()

Dim X As Integer, Y As Integer, Z As Integer

On Error Resume Next

X = 10 / 0

Y = 20 / 2

Z = 30 / 4

MsgBox X
MsgBox Y
MsgBox Z

End Sub

Example 4-4

And run the code. This will give a use result on a valid mathematical line, as shown below.

Example 4-5                               

Now further add ZResult code line before Z integer division mathematical expression and add MsgBox Err.Number code line at the end of code as shown below.

Sub OnError()

Dim X As Integer, Y As Integer, Z As Integer

On Error Resume Next

X = 10 / 0

Y = 20 / 2

ZResult:
Z = 30 / 4

MsgBox X
MsgBox Y
MsgBox Z

MsgBox Err.Number

End Sub

Example 4-6

Now run the code by using the F5 key or by pressing the play button, as shown below.

Example 4-7

As we can see in the above screenshots. The first message box has 0, which is overruling of incorrect mathematical expression. 2nd and 3rd have a division result of Y and Z integers. And last message box has run time error code 11, which is probably the error code of X integer’s division expressions.

Pros of VBA On Error

  • We can calculate any mathematical formula even if it is incorrect.
  • For bigger coding structures where there are chances of having an error, using these methods may give correct result even among the line of codes.
  • This gives a better result as compared to the result obtained from normal excel calculations.

Things to Remember

  • Always save the file in a Macro-Enabled Excel file so that we can use created VBA code many and multiple times.
  • Always compile the written code before implementing with any excel requirement.
  • If needed, assign the written code to any button so that we can quickly click on the button and run the code.

You can download this VBA On Error Excel Template here – VBA On Error Excel Template.

Recommended Articles

This has been a guide to Excel VBA On Error. Here we discussed how to use VBA On Error Statement along with some practical examples and a downloadable excel template. You can also go through our other suggested articles–

  1. VBA TRIM
  2. VBA Number Format
  3. VBA Do While Loop
  4. VBA Find

0 0 голоса
Рейтинг статьи
Подписаться
Уведомить о
guest

0 комментариев
Старые
Новые Популярные
Межтекстовые Отзывы
Посмотреть все комментарии

А вот еще интересные материалы:

  • Яшка сломя голову остановился исправьте ошибки
  • Ясность цели позволяет целеустремленно добиваться намеченного исправьте ошибки
  • Ясность цели позволяет целеустремленно добиваться намеченного где ошибка
  • Vba продолжить если ошибка
  • Vba ошибка permission denied