Обработка ошибок в 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.
Обработка ошибок
Если вы когда-нибудь учились водить автомобиль, то наверняка вспомните, что при первой посадке на водительское сиденье все внимание было приковано к трем деталям: рулю, педалям и рычагу переключения передач. Происходящее вне автомобиля уходило на второй план, так как вначале нужно было стронуться с места. По мере практики навыки вождения улучшались и эти три детали постепенно уходили на задний план. Как ни странно, но руль и рычаг переключения передач всегда оказывались там, куда вы не смотря протягивали руки, а ноги сами находили педали. Теперь все внимание стало занимать происходящее на дороге. Иными словами, вы стали опытным водителем.
В программировании все абсолютно также. Начинающие программисты больше обращают внимание на первые попавшиеся на глаза операторы, функции и другие элементы языка, а сам алгоритм уходит на задний план. Если программа скомпилировалась без ошибок, то это уже большое счастье, хотя это еще не означает, что программа работает правильно. По мере практики мышление программиста меняется, он начинает обращать внимание на мелочи, на форматирование программы, использует более эффективные алгоритмы и в результате всего этого допускает меньше ошибок. Подводя итоги, можно сказать, что начинающий программист просто пишет программу, а опытный программист пытается найти оптимальный алгоритм и предусмотреть поведение программы в различных ситациях. Однако, от ошибок никто не застрахован, поэтому очень важно знать как быстро найти ошибку.
Типы ошибок
Существуют три типа ошибок в программе:
- синтаксические — это ошибки в имени оператора или подпрограммы, отсутствие закрывающей или открывающей кавычек и т. д., то есть ошибки в синтаксисе языка. Как правило, компилятор предупредит о наличии ошибки, а программа не будет выполняться совсем;
- логические — это ошибки в логике работы программы, которые можно выявить только по результатам работы программы. Как правило, компилятор не предупреждает о наличии ошибки, а программа будет выполняться, так как не содержит синтаксических ошибок. Такие ошибки достаточно трудно выявить;
- ошибки времени выполнения — это ошибки, которые возникают во время работы программы. В одних случаях ошибки времени выполнения являются следствием логических ошибок, а в других случаях причиной являются внешние события, например, нехватка оперативной памяти, отсутствие прав для записи в файл и др.
Инструкция 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)
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 GoTo –1
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.
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!
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
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
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:
The VBA Editor also has an option to “Auto Syntax Check”:
When this is checked, the VBA Editor will generate a message box alerting you syntax errors after you enter a line of code:
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:
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.
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:
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:
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 Error Trapping
VBA Error Trapping is just another term for VBA Error Handling.
VBA Error Message
A VBA Error Message looks like this:
When you click ‘Debug’, you’ll see the line of code that is throwing the 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
Как уже отмечалось выше, одной из основных
проблем являются ошибки выполнения.
Эти ошибки возникают при попытке
произвести недопустимую операцию,
например, при открытии несуществующего
файла, делении на ноль, или при обработке
неправильно введенных пользователем
данных.
Так или иначе, при возникновении ошибки
выполнение программы прерывается и
выводится сообщение. К сожалению, это
сообщение несет мало полезной информации,
поскольку в нем указывается только
недопустимая операция, а не причина
возникновения ошибки. Еще хуже то, что
программа не выполняется до конца и не
произведены все необходимые действия.
Пользователь может без всякого умысла
произвести действия, которые нанесут
непоправимый вред данным. Следовательно,
необходимо каким-то образом оградить
себя от возникновения подобных ситуаций.
При программировании имеются два
подхода:
— Предотвращение ошибочных ситуаций.
— Обработка ошибки с помощью специальной
процедуры.
При разработке программ рекомендуется
по возможности предотвращать возникновение
ошибочных ситуаций. Начиная создание
алгоритма макроса, следует ответить на
ряд вопросов, например:
— Существует ли файл, который требуется
открыть?
— Находится ли курсор в требуемой для
выполнения макроса позиции?
Перехватываемые ошибки.
Перехват используется в том случае,
когда предотвратить возникновение
ошибочных ситуаций невозможно. Полный
список перехватываемых ошибок приводится
в разделе системы справочной информации
Visual Basic «Перехватываемые ошибки»
(Trappable Errors). Ниже описываются только
некоторые из них.
КОД СООБЩЕНИЕ
3 Инструкция
Return без Gosub
6 Переполнение
7 Не
хватает памяти
9 Индекс
выходит за пределы допустимого диапазона
11 Деление
на 0
18 Произошло
прерывание, вызванное пользователем
35 Процедура
Sub, Function или Property не определена
53 Файл
не найден
61 Переполнение
диска
71 Диск
не готов
91 Не
задана объектная переменная блока With
97 Невозможен
вызов процедуры Friend для объекта, не
являющегося экземпляром определяющего
класса
335 Невозможен
доступ к системному реестру
368 Истек
срок данного системного файла. Программе
требуется файл более новой версии
402 Сначала
необходимо закрыть самую верхнюю
модальную форму
422 Свойство
не найдено
440 Ошибка
программирования объектов
448 Именованный
аргумент не найден
482 Ошибка
принтера
31032 Невозможно
создать внедренный объект
Очевидно, что ни одно из показанных
сообщений не дает пользователю
исчерпывающих сведений о причине
возникновения ошибки. Профессионал
может точно определить проблему,
используя систему справочной информации,
а человеку, который захочет, например,
написать письмо или ввести данные в
отчет с помощью разрабатываемого
приложения, такие сообщения непонятны.
Предотвращая возникновение ошибок или
перехватывая их, можно исключить вывод
стандартных сообщений. Вместо них
появляется возможность либо отобразить
собственную подсказку, либо попытаться
исправить положение с помощью макроса.
Ниже объясняется, как перехватить
ошибку.
Перехват ошибок.
Обработка ошибок выполнения в VBA
называется перехватом ошибки. Правильно
разработав подпрограмму обработки
ошибок, можно задать отклик на многие
возможные ошибки. Наиболее важно, чтобы
ошибка не остановила выполнение
процедуры. При этом пользователь может
даже не заметить, что произошла ошибка.
Система перехвата ошибок включает
следующие компоненты:
— Инструкция On Error устанавливает перехват
ошибки. Она сообщает процедуре, что
делать, если произошла ошибка, обычно
передавая управление подпрограмме
обработки ошибки.
— Подпрограмма обработки ошибки — это
часть выполняемой процедуры, которая
используется для обработки ошибок.
Обычно в ней определяется тип возникшей
ошибки, а затем производятся соответствующие
действия. Начало подпрограммы обработки
идентифицируется меткой.
— Объект Err содержит информацию о возникшей
ошибке. Подобно любому объекту он имеет
свои свойства, включая номер и описание
ошибки.
— Инструкция Resume позволяет процедуре
продолжить операции после обработки
ошибки.
— Инструкция Exit позволяет выйти из
процедуры, не выполняя оставшийся код.
Данная инструкция используется очень
часто, поскольку если ошибок не возникло,
то не следует исполнять подпрограмму
обработки ошибки.
Общие сведения о перехвате ошибок.
Общее правило перехвата ошибок можно
пояснить на примере следующей процедуры:
Sub
MyProcedure ()
On
Error GoTo MyErrorHandler
‘…
‘
Обычные действия, при выполнении каждого
из
‘
которых может произойти ошибка
‘…
Exit
Sub ‘ Выход для обхода подпрограммы
обработки ошибки
MyErrorHandler:
‘…
‘
Подпрограмма обработки ошибки
‘…
Resume
End
Sub
Инструкция On Error устанавливает перехват
ошибки для невыполненной части макроса,
указывая на подпрограмму обработки
ошибки. В макросе может быть несколько
инструкций On Error, каждая из которых
определяет разные процедуры обработки.
В предыдущем примере при возникновении
ошибки управление передается инструкции
с меткой MyErrorHandler.
Инструкция On Error имеет три формы:
— Инструкция On Error GoTo метка позволяет
передать управление подпрограмме
обработки ошибки, которая идентифицируется
меткой.
— Инструкция On Error Resume Next позволяет
игнорировать ошибку и продолжить
выполнение со следующей инструкции
после той, при исполнении которой
возникла ошибка. Если ошибка вызывает
возникновение других ошибок, то лучше
не применять данную форму инструкции
On Error.
Для определение типа ошибки и выполнения,
соответствующих ей действий имеется
возможность получить значение свойства
Number объекта Err.
— Инструкция On Error GoTo 0 отключает обработку
ошибок для данной процедуры. Данная
инструкция обычно указывается после
первых двух форм инструкции On Error ниже
строк, в которых могут возникнуть ошибки.
Поскольку подпрограмма обработки уже
сыграла свою роль, можно не перехватывать
ошибки.
В любом случае инструкция On Error
устанавливает обработку ошибок только
в той процедуре, в которой она указана.
Инструкцию On Error можно указывать
произвольное число раз, изменяя способ
обработки ошибок.
Sub
MySub ()
‘…
On
Error GoTo MyHandler
‘…
OnError
Resume Next
‘…
On
Error GoTo 0
‘…
MyHandler:
‘…
Resume
End
Sub
Метка, которая помечает начало подпрограммы
обработки ошибок, является параметром
инструкции GoTo. Меткой является любое
допустимое имя, оно располагается в
самом начале строки, а сразу за ней
ставится (:).
Обратите внимание, что в инструкции
GoTo двоеточие не используется, т.к. оно
не является частью имени. Двоеточие
только идентифицирует метку.
Инструкция Resume указывается в конце
подпрограммы обработки ошибок после
выполнения всех требуемых действий.
Она возобновляет исполнение процедуры,
в которой возникла ошибка.
Совет.
Инструкцию Resume можно использовать
только в подпрограмме обработки ошибки.
В противном случае возникает ошибка.
Инструкция Resume имеет три формы:
— Инструкция Resume Next передает управление
инструкции, которая следует за той, в
которой возникла ошибка. Предполагается,
что подпрограмма обработки устранила
последствия ошибки.
— Инструкция Resume или Resume 0 передает
управление инструкции, в которой возникла
ошибка, и VBA производит попытку выполнять
эту строку снова. Предполагается, что
подпрограмма обработки устранила
причины, которые вызвали ошибку, и теперь
инструкцию можно выполнить без ошибки.
— Инструкция Resume метка передает управление
инструкции, идентифицированной указанной
меткой.
Инструкция Resume является необязательной.
Если требуется завершить выполнение
процедуры после обработки ошибки, то
можно опустить эту инструкцию.
Обратите внимание на следующее правило:
каждая процедура должна иметь только
одну точку выхода, чтобы обеспечить
выполнение некоторых вспомогательных
действий перед своим завершением.
Передавая управление хотя бы на метку
подпрограммы выхода, можно гарантировать,
что требуемые действия производятся
всегда. Кроме того, по мере возрастания
длины и сложности процедур данное
правило приобретает все большее и
большее значение.
Инструкция Exit используется для того,
чтобы не выполнять подпрограмму обработки
ошибки, если ошибка не возникла. Поскольку
подпрограмма обработки является частью
процедуры, то она будет исполняться
если не выйти из макроса.
Инструкция Exit имеет пять форм, указывающих
на блок, из которого требуется выйти:
Exit
Sub
Exit
Function
Exit
Do
Exit
For
Exit
Property
В процедурах, в которых имеется
подпрограмма обработки ошибки, обычно
используются инструкции Exit Sub или Exit
Function в зависимости от типа выполняемой
процедуры.
Объект Err и подпрограмма обработки
ошибки.
Во многих ситуациях имеется большое
число потенциальных ошибок, а подпрограмма
обработки должна выполнять определенные
действия в зависимости от возникшей
ошибки. С помощью объекта Err можно во
время выполнения процедуры выявить тип
ошибки. Обратите внимание, что если
подпрограммы обработки не имеется, то
выводится стандартное сообщение.
Объект Err — глобальный объект, который
содержит информацию о последней возникшей
ошибке. Подобно любому другому объекту
он имеет свойства и методы. Используя
свойства объекта Err и выполняя его методы
можно сообщить подпрограмме обработки
характер произошедшей ошибки.
Объект Err имеет шесть свойств:
— Свойство Number — номер возникшей ошибки.
— Свойство Source — имя проекта Visual Basic, в
котором произошла ошибка.
— Свойство Description — строка, соответствующая
номеру ошибки. Некоторые ошибки, включая
заданные пользователем ошибки, не имеют
описания и тогда строка имеет значение
«Ошибка, определяемая приложением»
или «Ошибка, определяемая объектом».
— Свойство HelpFile — полное имя файла справки
Visual Basic, включая диск и путь.
— Свойство HelpContext — идентификационный
номер в справке Visual Basic, соответствующий
возникшей ошибке.
— Свойство LastDLLError содержит код системной
ошибки для последнего вызова библиотеки
динамической компоновки. Используется
только в 32-разрядных системах Microsoft
Windows и доступно только для чтения.
Обычно, чтобы произвести определенные
действия в зависимости от типа возникшей
ошибки, требуется просто проверить
значение свойства Number. Для этого
используется любая логическая инструкция,
например, блок If..Else..End If или Select Case..End
Select. Блок Select Case..End Select удобнее, т.к. в
него проще добавить дополнительное
условие.
Заданным по умолчанию свойством объекта
Err является свойство Number, поэтому
нижеприведенные инструкции эквивалентны:
Select Case Err.Number
Select Case Err
Использование полного синтаксиса
упрощает понимание программы. Сокращенный
синтаксис совместим только в одну
сторону с предыдущими версиями Visual
Basic и WordBasic, в которых вместо объекта Err
применялась функция Err. Объект Err имеет
два метода:
— Метод Raise позволяет генерировать ошибку
во время выполнения программы. Данный
метод используется для проверки
подпрограммы обработки ошибки, которую
требуется перехватить. Кроме того, с
его помощью можно создать для приложения
собственные ошибки, указав их номер и
описание.
При задании собственных ошибок необходимо
сложить номер ошибки с константой
vbObjectError. Таким образом, можно гарантировать,
что номер не совпадает с номером
стандартной ошибки Visual Basic. Приведем
пример, в котором создается новая ошибка:
Err.Raise vbObjectError + 1, «MyProject.MyObject»,
«Служащего с таким именем в данном
отделе не имеется»
— Метод Clear сбрасывает значения всех
свойств объекта Err. Данный метод
используется после того, как обработана
ошибка и необходимо продолжить выполнение.
Примечание.
В ранних версиях Visual Basic и других языках
Basic для создания ошибок использовалась
инструкция Error. В целях обеспечения
инструкция Error имеется и в новом Visual
Basic, однако, во всех вновь создаваемых
программах рекомендуется применять
объект Err.
Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]
- #
- #
- #
- #
- #
- #
- #
- #
- #
- #
- #