|
Номер |
Сообщение |
Описание |
|
3 |
Return |
Оператор Return без GoSub |
|
5 |
Invalid |
Неверный вызов процедуры |
|
6 |
Overflow |
Переполнение |
|
7 |
Out of |
Недостаточно памяти |
|
9 |
Subscript |
Индекс вне заданного диапазона |
|
10 |
This |
Этот массив имеет фиксированную длину или он временно |
|
11 |
Division |
Деление на ноль |
|
13 |
Type mismatch |
Несоответствие типа |
|
14 |
Out of |
Не хватает памяти для строки |
|
16 |
Expression |
Выражение слишком сложное |
|
17 |
Can’t |
Невозможно выполнить требуемую операцию |
|
18 |
User |
Произошло прерывание по команде пользователя |
|
20 |
Resume |
Оператор Resume применен за пределами кода, отвечающего за |
|
28 |
Out of |
В стеке не хватает памяти |
|
35 |
Sub, |
Процедура Sub, Function или Property не определена |
|
47 |
Too many |
Слишком много приложений обращаются к DLL |
|
48 |
Error in |
Ошибка при загрузке DLL |
|
49 |
Bad DLL |
Неверный вызов DLL |
|
51 |
Internal |
Внутренняя ошибка |
|
52 |
Bad file |
Неверное имя или номер файла |
|
53 |
File not |
Файл не найден |
|
54 |
Bad file |
Неверный тип доступа |
|
55 |
File |
Файл уже открыт |
|
57 |
Device |
Ошибка устройства ввода/вывода |
|
58 |
File |
Файл уже существует |
|
59 |
Bad |
Неверный размер записи |
|
61 |
Disk full |
Диск переполнен |
|
62 |
Input |
Чтение файла невозможно, т.к. достигнут его конец |
|
63 |
Bad |
Неверный номер записи |
|
67 |
Too many |
Слишком много файлов |
|
68 |
Device unavailable |
Устройство недоступно |
|
70 |
Permission |
Доступ запрещен |
|
71 |
Disk not |
Диск не готов |
|
74 |
Can’t |
Нельзя переименовать файл со сменой носителя |
|
75 |
Path/File |
Ошибка доступа к каталогу/файлу |
|
76 |
Path not |
Каталог не найден |
|
91 |
Object |
Переменная объекта или переменная блока With не задана |
|
92 |
For loop |
Цикл For не инициализирован |
|
93 |
Invalid |
Неверная маска |
|
94 |
Invalid |
Неверное использование Null |
|
97 |
Can’t |
Нельзя вызвать процедуру Friend, т.к. она не является |
|
98 |
A |
Обращение к свойству или методу не может включать ссылку |
|
260 |
No timer |
Ни один таймер не доступен |
|
282 |
No |
Ни одно внешнее приложение не ответило на инициативу DDE |
|
288 |
Destination |
Адресат занят |
|
290 |
Data is |
Неправильный формат данных |
|
294 |
Invalid |
Неверный формат данных в DDE-диалоге |
|
296 |
PasteLink |
PasteLink для этого элемента управления уже выполнен |
|
297 |
Can’t set |
Нельзя установить LinkMode; неправильный LinkTopic |
|
298 |
System |
Системная DLL |
|
320 |
Can’t use |
Нельзя использовать имя устройства в определении имени |
|
321 |
Invalid |
Неверный формат файла |
|
322 |
Can’t |
Не могу создать необходимый временный файл |
|
325 |
Invalid |
Неверный формат файла ресурсов |
|
327 |
Data |
Значение не найдено |
|
328 |
Illegal |
Неверный параметр; не могу записать массив |
|
335 |
Could not |
Доступ к системному реестру невозможен |
|
336 |
ActiveX |
Компонент ActiveX зарегистрирован неправильно |
|
337 |
ActiveX |
Компонент ActiveX не найден |
|
338 |
ActiveX |
Компонент ActiveX не может быть корректно выполнен |
|
340 |
Control |
Элемент управления ‘имя’ не найден |
|
341 |
Invalid |
Неверный индекс массива элементов управления |
|
342 |
Not |
Недостаточно памяти для создания элемента управления ‘имя’ |
|
343 |
Object |
Объект не является массивом |
|
344 |
Must |
Необходимо указать индекс массива |
|
345 |
Reached |
Достигнута верхняя граница: нельзя создать больше ни |
|
360 |
Object |
Объект уже загружен |
|
361 |
Can’t |
Невозможно загрузить или выгрузить данный объект |
|
363 |
ActiveX |
Элемент управления ActiveX не найден |
|
364 |
Object |
Объект был выгружен |
|
365 |
Unable to |
Нет возможности в данном контексте произвести выгрузку |
|
366 |
No MDI |
Форма, не определенная как MDI, не может быть загружена |
|
368 |
The |
Данный файл устарел. Эта программа требует более новой |
|
371 |
The |
Данный объект не может быть использован как родитель формы |
|
380 |
Invalid |
Неверное значение свойства |
|
381 |
Invalid |
Неверный индекс массива свойств |
|
382 |
Property |
Процедура установки свойства (Property Set) не может быть запущена |
|
383 |
Property |
Процедура установки свойства (Property Set) не может быть |
|
385 |
Need |
Для массива свойств надо указать индекс |
|
387 |
Property |
Процедура установки свойства (Property Set) не разрешена |
|
389 |
Invalid key |
Нажата неверная клавиша |
|
393 |
Property |
Процедура чтения свойства (Property Get) не поддерживается |
|
394 |
Property |
Процедура чтения свойства (Property Get) не может быть |
|
396 |
‘Item’ |
Свойство ‘имя’ нельзя установить для страницы (объект |
|
400 |
Form |
Форма уже отображена, ее нельзя отобразить как модальную |
|
401 |
Can’t |
Немодальную форму нельзя отобразить одновременно с модальной |
|
402 |
Must |
Сначала необходимо закрыть верхнюю модальную форму |
|
403 |
HDI forms |
MDI-формы не могут быть отображены как модальные |
|
404 |
MDI child |
Дочерние MDI-формы не могут быть отображены модальными |
|
419 |
Permission |
Использование объекта запрещено |
|
422 |
Property |
Свойство не найдено |
|
423 |
Property |
Свойство или метод не найдены |
|
424 |
Object required |
Необходим объект |
|
425 |
Invalid |
Неверное использование объекта |
|
427 |
Invalid |
Неверный тип объекта; требуется элемент управления типа |
|
429 |
ActiveX |
Компонент ActiveX |
|
430 |
Class |
Класс не поддерживает программирование объектов |
|
432 |
File name |
Имя файла или класса не найдено в процессе операции |
|
438 |
Object |
Объект не поддерживает данное свойство или метод |
|
440 |
Automation error |
Ошибка программирования объектов (Automation) |
|
442 |
Connection |
Связь с библиотекой типов или объектов для удаленного |
|
443 |
Automation |
Объект Automation |
|
444 |
Method not applicable in this context |
Метод в этом контексте недоступен |
|
445 |
Object doesn’t support this action |
Объект не поддерживает эту команду |
|
446 |
Object |
Объект не поддерживает указанные аргументы |
|
447 |
Object doesn’t support current locale setting |
Объект не поддерживает текущие национальные стандарты |
|
448 |
Name argument not found |
Именованный аргумент не найден |
|
449 |
Argument |
Аргумент обязателен или неверное |
|
450 |
Wrong |
Неправильное количество аргументов |
|
451 |
Object not a collection |
Объект не является коллекцией |
|
452 |
Invalid ordinal |
Неверный порядковый номер |
|
453 |
Specified DLL function not found |
Указанная функция DLL не найдена |
|
454 |
Code |
Код ресурса не найден |
|
457 |
This key |
Этот ключ уже ассоциирован с элементом этой коллекции |
|
458 |
Variable |
Переменная использует тип, не поддерживаемый Visual Basic |
|
459 |
This |
Этот компонент не поддерживает установку событий |
|
460 |
Invalid Clipboard format |
Неверный формат Буфера обмена |
|
461 |
Specified |
Данный формат не совпадает с форматом данных |
|
462 |
The |
Удаленная машина сервера не существует или недоступна |
|
463 |
Class not |
Класс не зарегистрирован на локальной машине |
|
480 |
Can’t create AutoRedraw image |
Нельзя создать автоматически восстанавливаемое изображение |
|
481 |
Invalid picture |
Неверный рисунок |
|
482 |
Printer error |
Ошибка принтера |
|
483 |
Printer driver does not support specified property |
Драйвер принтера не поддерживает указанное свойство |
|
484 |
Problem |
Проблема при чтении информации принтером из системы. |
|
485 |
Invalid |
Неверный тип рисунка |
|
486 |
Can’t |
Нельзя распечатать изображение формы на принтере такого |
|
520 |
Can’t empty Clipboard |
Нельзя очистить буфер обмена |
|
521 |
Can’t open Clipboard |
Нельзя открыть буфер обмена |
|
735 |
Can’t save file to TEMP directory |
Нельзя сохранить файл в каталоге TEMP |
|
744 |
Search text not found |
Исходный текст не найден |
|
746 |
Replacements too long |
Слишком длинная замена |
|
Номер |
Сообщение |
Описание |
|
2420 |
Syntax error in number |
Число содержит синтаксическую ошибку |
|
2421 |
Syntax error in date |
Дата содержит синтаксическую ошибку |
|
2422 |
Syntax error in string |
Строка содержит синтаксическую ошибку |
|
2423 |
Invalid use of ‘.’, ‘!’ or ‘( )’ |
Неверное использование ‘.’, ‘!’ или ‘( )’ |
|
2424 |
Unknown name |
Неизвестное имя |
|
2425 |
Unknown function name |
Неизвестное имя функции |
|
2427 |
Object has no value |
Объект не имеет значения |
|
2428 |
Invalid arguments used with domain function |
Неверные аргументы статистической функции по подмножеству |
|
2431 |
Syntax error(missing operator) |
Синтаксическая ошибка (отсутствует оператор) |
|
2433 |
Syntax error |
Синтаксическая ошибка |
|
2439 |
Wrong number of arguments used with function |
Неверное число аргументов функции |
|
2442 |
Invalid use of parentheses |
Неверное использование скобок |
|
2443 |
Invalid use of Is operator |
Неверное использование оператора Is |
|
2445 |
Expression too complex |
Слишком сложное выражение |
|
2446 |
Out of memory during calculation |
Недостаточно памяти при вычислениях |
|
2448 |
Can’t set value |
Не удается задать значение |
|
3001 |
Invalid argument |
Ошибочный аргумент |
|
3005 |
<Database name> isn’t a valid database name |
Имя базы данных не является допустимым именем базы данных |
|
3006 |
Database <name> is exclusively locked |
Для базы данных <name> установлен монопольный доступ |
|
3007 |
Can’t open library database <name> |
Не удается открыть библиотечную базу данных <name> |
|
3011 |
The Microsoft Jet database engine could not find the |
Объект <name> не найден ядром базы данных Microsoft |
|
3012 |
Object <name> already exists |
Объект <name> уже существует |
|
3017 |
The size of a field is too long |
Слишком большая длина поля |
|
3021 |
No current record |
Текущая запись отсутствует |
|
3024 |
Couldn’t find file <name> |
Не удается найти файл <name> |
|
3025 |
Can’t open any moor |
Открытие дополнительных файлов невозможно |
|
3027 |
Can’t update. Database or object is read-only |
Обновление невозможно. База данных или объект доступны |
|
3036 |
Database has reached maximum size |
Достигнут максимальный размер базы данных |
|
3037 |
Can’t open any more tables or queries |
Открытие дополнительных таблиц или запросов невозможно |
|
3042 |
Out of MS-DOS file handles |
Не хватает дескрипторов файлов MS-DOS |
|
3043 |
Disk or network error |
Дисковая или сетевая ошибка |
|
3046 |
Couldn’t save; currently locked by another user |
Сохранение невозможно; блокировка другим пользователем |
|
3056 |
Couldn’t repair this database |
Не удается восстановить эту базу данных |
|
3107 |
Record(s) can’t be added; no insert permission or |
Записи не могут быть добавлены; отсутствует разрешение на |
|
3108 |
Record(s) can’t be edited; no update permission or |
Записи не могут быть изменены; отсутствует разрешение на |
|
3109 |
Record(s) can’t be deleted; no delete permission or |
Записи не могут быть удалены; отсутствует разрешение на |
|
3111 |
Couldn’t create; no modify design permission for table or |
Создание невозможно; отсутствует разрешение на изменение |
|
3117 |
Can’t sort on Memo or OLE Object <clause> |
Невозможна сортировка по полю Memo или объекта ActiveX в |
|
3116 |
Can’t join on Memo or OLE Object <name> |
Невозможно объединение с полем Memo или объекта ActiveX |
|
3146 |
ODBC – call failed |
ODBC – ошибка вызова |
|
3154 |
ODBC – couldn’t find DLL <name> |
ODBC – не удается найти DLL <name> |
|
3197 |
The Microsoft Jet database engine stopped the process |
Процесс остановлен ядром базы данных Microsoft Jet, так |
|
3230 |
Out-of-date Paradox lock file |
Устаревший файл блокировок Paradox |
|
3231 |
ODBC – field would be too long; data truncated |
ODBC – слишком большое поле; произошло усечение данных |
|
3232 |
ODBC – couldn’t create table |
ODBC – создание таблицы невозможно |
|
3235 |
ODBC – data type not supported on server |
ODBC – тип данных не поддерживается сервером |
|
3238 |
ODBC – data out of range |
ODBC – данные выходят за пределы допустимого диапазона |
|
3276 |
Invalid database object reference |
Неверная ссылка на объект Database |
|
3322 |
Crosstab query contains one or more invalid fixed column |
Перекрестный запрос содержит один или несколько неверных |
|
3342 |
Invalid Memo or OLE Object in sub-query<name> |
Ошибочное поле Memo или поле объекта ActiveX в подчиненном |
|
3360 |
Query is too complex |
Слишком сложный запрос |
|
3409 |
Invalid field name<name> in definition of index or |
Неверное имя поля <name> при определении индекса или |
|
3411 |
Invalid entry. Can’t perform cascading operation in |
Ошибочное значение. Невозможно выполнить каскадную |
|
3423 |
You cannot use ODBC to import from, export to, or link an |
Не допускается использование ODBC для импорта, экспорта |
|
3424 |
Can’t create database because the locale is invalid |
Создание базы данных невозможно; неверная национальная |
|
3436 |
Failure creating file |
Ошибка при создании, файла |
|
3462 |
Failure to load DLL |
Сбой при загрузке библиотеки |
|
3506 |
The Synchronizer is unable to open the Synchronizer log |
Синхронизатору не удается открыть журнал |
|
3507 |
Failure writing to the Synchronizer log |
Сбой при записи в журнал синхронизатора |
|
3517 |
Synchronizer could not find any messages to process |
Синхронизатор не может найти сообщение для обработки |
|
3519 |
Failed to send a message |
Сбой при отправке сообщения |
|
3558 |
Disk I/O error at destination dropbox folder |
Ошибка ввода/вывода на диске для результирующего банка |
|
3581 |
Can’t open replication system table <name> because |
Невозможно открыть системную таблицу репликации |
|
3584 |
Insufficient memory to complete operation |
Не хватает памяти для завершения операции |
|
3586 |
Syntax |
Ошибка синтаксиса в выражении фильтра для таблицы |
|
3613 |
Can’t |
Не допускается создание связи между присоединенными |
|
3614 |
GUID not allowed in Find method criteria expression |
Не допускается использование типа GUID в выражениях для |
|
3621 |
Can’t change password on a shared open database |
Невозможно изменение пароля базы данных, открытой для |
|
3624 |
Couldn’t read the record; currently locked by another user |
Чтение невозможно. Блокировка другим сеансом на данной |
|
3637 |
Cannot use the crosstab of as a non-fixed column a |
Нельзя использовать составной или нефиксированный столбец |
Содержание
- Типы ошибок VBA в Excel
- Использование отладки для поиска ошибок компиляции / синтаксиса
- Настройка параметров ошибок (обработанные и необработанные ошибки)
- Обработка ошибок VBA с помощью операторов «при ошибке»
- Объект ошибки
- Рекомендации по обработке ошибок VBA
Независимо от того, насколько вы опытны в программировании на VBA, ошибки всегда будут частью этого.
Разница между новичком и опытным программистом VBA заключается в том, что опытные программисты знают, как эффективно обрабатывать и использовать ошибки.
В этом руководстве я покажу вам различные способы эффективной обработки ошибок в Excel VBA.
Прежде чем мы перейдем к обработке ошибок VBA, давайте сначала разберемся с различными типами ошибок, с которыми вы, вероятно, столкнетесь при программировании в Excel VBA.
В Excel VBA есть четыре типа ошибок:
- Синтаксические ошибки
- Ошибки компиляции
- Ошибки времени выполнения
- Логические ошибки
Давайте быстро поймем, что это за ошибки и когда вы с ними столкнетесь.
Ошибка синтаксиса
Синтаксическая ошибка, как следует из названия, возникает, когда VBA обнаруживает что-то не так с синтаксисом в коде.
Например, если вы забудете часть необходимого оператора / синтаксиса, вы увидите ошибку компиляции.
В приведенном ниже коде, как только я нажимаю Enter после второй строки, я вижу ошибку компиляции. Это потому, что Заявление ЕСЛИ необходимо иметь «Затем‘, Которая отсутствует в приведенном ниже коде.
Примечание: Когда вы вводите код в Excel VBA, он проверяет каждое предложение, как только вы нажимаете клавишу ВВОД. Если VBA обнаруживает, что в синтаксисе чего-то не хватает, он мгновенно отображает сообщение с текстом, который может помочь вам понять недостающую часть.
Чтобы убедиться, что вы видите синтаксическую ошибку всякий раз, когда чего-то не хватает, вам необходимо убедиться, что проверка автосинтаксиса включена. Для этого нажмите «Инструменты», а затем «Параметры». Убедитесь, что в диалоговом окне параметров включена опция «Автоматическая проверка синтаксиса».
Если опция «Автоматическая проверка синтаксиса» отключена, VBA по-прежнему будет выделять строку с синтаксической ошибкой красным цветом, но не будет отображать диалоговое окно с ошибкой.
Ошибка компиляции
Ошибки компиляции возникают, когда что-то отсутствует, что необходимо для запуска кода.
Например, в приведенном ниже коде, как только я попытаюсь запустить код, он покажет следующую ошибку. Это происходит, поскольку я использовал оператор IF Then, не закрывая его обязательным «End If».
Синтаксическая ошибка также является разновидностью ошибки компиляции. Синтаксическая ошибка возникает, как только вы нажимаете клавишу ВВОД, и VBA определяет, что чего-то не хватает. Ошибка компиляции также может возникать, когда VBA не находит ничего недостающего при вводе кода, но это происходит при компиляции или выполнении кода.
VBA проверяет каждую строку при вводе кода и выделяет синтаксическую ошибку, как только строка оказывается неверной и вы нажимаете клавишу ВВОД. С другой стороны, ошибки компиляции выявляются только тогда, когда весь код анализируется VBA.
Ниже приведены несколько сценариев, при которых вы столкнетесь с ошибкой компиляции:
- Использование оператора IF без конечного IF
- Использование оператора For с оператором Next
- Использование оператора Select без использования End Select
- Не объявлять переменную (это работает только при включенном Option Explicit)
- Вызов несуществующей подпрограммы / функции (или с неправильными параметрами)
Примечание о «Option Explicit»: Когда вы добавляете «Option Explicit», вам нужно будет объявить все переменные перед запуском кода. Если есть переменная, которая не была объявлена, VBA выдаст ошибку. Это хорошая практика, поскольку она показывает ошибку, если у вас есть переменная с ошибкой. Вы можете узнать больше о Option Explicit здесь.
Ошибки времени выполнения
Ошибки времени выполнения — это те, которые возникают во время выполнения кода.
Ошибки времени выполнения будут возникать только тогда, когда будут устранены все синтаксические ошибки и ошибки компиляции.
Например, если вы запускаете код, который должен открывать книгу Excel, но эта книга недоступна (либо удалена, либо изменено имя), ваш код выдаст ошибку во время выполнения.
Когда возникает ошибка времени выполнения, код останавливается и отображается диалоговое окно ошибки.
Сообщение в диалоговом окне «Ошибка выполнения» немного более полезно. Он пытается объяснить проблему, что может помочь вам ее исправить.
Если вы нажмете кнопку «Отладка», будет выделена часть кода, которая приводит к ошибке.
Если вы исправили ошибку, вы можете нажать кнопку «Выполнить» на панели инструментов (или нажать F5), чтобы продолжить выполнение кода с того места, где он был оставлен.
Или вы также можете нажать кнопку «Конец», чтобы выйти из кода.
Важный: Если вы нажмете кнопку «Конец» в диалоговом окне, код будет остановлен на той строке, в которой он встречается. Однако все предыдущие строки кода были бы выполнены.
Логические ошибки
Логические ошибки не остановят ваш код, но могут привести к неверным результатам. Это также могут быть самые сложные типы ошибок для устранения.
Эти ошибки не выделяются компилятором, и их нужно устранять вручную.
Один из примеров логической ошибки (с которой я часто сталкиваюсь) — это бесконечный цикл.
Другой пример может быть, когда он дает неправильный результат. Например, вы можете использовать неправильную переменную в коде или добавить две переменные, если одна из них неверна.
Я использую несколько способов устранения логических ошибок:
- Вставьте окно сообщения в какое-либо место в коде и выделите значения / данные, которые могут помочь понять, идет ли eberything, как ожидалось.
- Вместо того, чтобы запускать код за один раз, просматривайте каждую строку одну за другой. Для этого щелкните в любом месте кода и нажмите F8. вы могли бы заметить, что каждый раз, когда вы нажимаете F8, выполняется одна строка. Это позволяет просматривать код по одной строке за раз и определять логические ошибки.
Использование отладки для поиска ошибок компиляции / синтаксиса
Когда вы закончите работу с кодом, рекомендуется сначала скомпилировать его перед запуском.
Чтобы скомпилировать код, выберите параметр «Отладка» на панели инструментов и нажмите «Скомпилировать VBAProject».
Когда вы компилируете проект VBA, он просматривает код и выявляет ошибки (если таковые имеются).
Если он обнаружит ошибку, он покажет вам диалоговое окно с ошибкой. Он обнаруживает ошибки одну за другой. Поэтому, если он обнаружит ошибку, и вы ее исправили, вам нужно снова запустить компиляцию, чтобы найти другие ошибки (если они есть).
Если в вашем коде нет ошибок, параметр Compile VBAProject будет неактивен.
Обратите внимание, что при компиляции будут обнаружены только ошибки «Синтаксис» и «Компиляция». Он НЕ найдет ошибок времени выполнения.
Когда вы пишете код VBA, вы не хотите, чтобы ошибки возникали. Чтобы избежать этого, вы можете использовать множество методов обработки ошибок.
В следующих нескольких разделах этой статьи я расскажу о методах, которые вы можете использовать для обработки ошибок VBA в Excel.
Настройка параметров ошибок (обработанные и необработанные ошибки)
Прежде чем вы начнете работать со своим кодом, вам необходимо проверить один параметр в Excel VBA.
Перейдите на панель инструментов VBA и нажмите Инструменты, а затем нажмите Параметры.
В диалоговом окне «Параметры» перейдите на вкладку «Общие» и убедитесь, что в группе «Перехват ошибок» установлен флажок «Прерывание по необработанным ошибкам».
Позвольте мне объяснить три варианта:
- Прервать все ошибки: Это остановит ваш код на всех типах ошибок, даже если вы использовали методы для обработки этих ошибок.
- Модуль Break in Class: Это остановит ваш код на всех необработанных ошибках, и в то же время, если вы используете такие объекты, как пользовательские формы, он также сломается внутри этих объектов и выделит точную строку, вызвавшую ошибку.
- Перерыв в связи с необработанными ошибками: Это остановит ваш код только для тех ошибок, которые не обрабатываются. Это настройка по умолчанию, так как она обеспечивает уведомление о любых необработанных ошибках. Если вы используете такие объекты, как пользовательские формы, при этом не будет выделена строка, вызывающая ошибку в объекте, а будет выделена только строка, относящаяся к этому объекту.
Примечание: Если вы работаете с такими объектами, как пользовательские формы, вы можете изменить этот параметр на «Прерывание по модулям класса». Разница между №2 и №3 заключается в том, что при использовании Break в модуле класса вы перейдете к определенной строке в объекте, вызывающем ошибку. Вы также можете выбрать этот вариант вместо «Прерывание по необработанным ошибкам».
Вкратце: если вы только начинаете работу с Excel VBA, убедитесь, что установлен флажок «Прерывание при необработанных ошибках».
Обработка ошибок VBA с помощью операторов «при ошибке»
Когда ваш код обнаруживает ошибку, вы можете сделать следующее:
- Игнорируйте ошибку и позвольте коду продолжить
- Имейте код обработки ошибок и запускайте его при возникновении ошибки.
Оба этих метода обработки ошибок гарантируют, что конечный пользователь не увидит ошибку.
Есть несколько операторов «При ошибке», которые вы можете использовать для этого.
При ошибке Возобновить Далее
Когда вы используете в своем коде «Возобновить после ошибки», любая обнаруженная ошибка будет проигнорирована, и код продолжит работу.
Этот метод обработки ошибок используется довольно часто, но при его использовании нужно соблюдать осторожность. Поскольку он полностью игнорирует любые ошибки, которые могут возникнуть, вы не сможете определить ошибки, которые необходимо исправить.
Например, если выполнить приведенный ниже код, он вернет ошибку.
Sub AssignValues () x = 20/4 y = 30/0 End Sub
Это происходит потому, что вы не можете разделить число на ноль.
Но если я использую в этом коде оператор «On Error Resume Next» (как показано ниже), он проигнорирует ошибку, и я не узнаю, что есть проблема, которую необходимо исправить.
Sub AssignValues () При ошибке Возобновить След. X = 20/4 y = 30/0 Конец Sub
On Error Resume Next следует использовать только в том случае, если вы четко знаете, какие ошибки ожидаются от вашего кода VBA, и можете их игнорировать.
Например, ниже приведен код события VBA, который мгновенно добавит значение даты и времени в ячейку A1 только что вставленного листа (этот код добавляется на лист, а не в модуль).
Private Sub Workbook_NewSheet (ByVal Sh As Object) Sh.Range ("A1") = Format (Теперь, "дд-ммм-гггг чч: мм: сс") End Sub
Хотя в большинстве случаев это отлично работает, при добавлении листа диаграммы вместо листа будет отображаться ошибка. Поскольку на листе диаграммы нет ячеек, код выдает ошибку.
Итак, если я использую в этом коде оператор «При ошибке возобновить следующий», он будет работать, как ожидалось, с листами и ничего не будет делать с листами диаграмм.
Private Sub Workbook_NewSheet (ByVal Sh As Object) При ошибке Возобновить Далее Sh.Range ("A1") = Format (Теперь, "dd-mmm-yyyy hh: mm: ss") End Sub
Примечание. Оператор «Возобновить следующее при ошибке» лучше всего использовать, когда вы знаете, с какими ошибками вы, скорее всего, столкнетесь. А затем, если вы считаете, что эти ошибки можно игнорировать, вы можете использовать это.
Вы можете вывести этот код на следующий уровень, проанализировав, была ли ошибка, и отобразив соответствующее сообщение для нее.
В приведенном ниже коде будет отображаться окно сообщения, которое будет информировать пользователя о том, что рабочий лист не вставлен.
Private Sub Workbook_NewSheet (ByVal Sh As Object) При ошибке Возобновить Далее Sh.Range ("A1") = Format (Теперь, "dd-mmm-yyyy hh: mm: ss") Если Err.Number 0, то MsgBox "Похоже на вас вставлен лист диаграммы "& vbCrLf &" Error - "& Err.Description End If End Sub
«Err.Number» используется для получения номера ошибки, а «Err.Description» используется для получения описания ошибки. Они будут рассмотрены позже в этом руководстве.
При ошибке GoTo 0
«On Error GoTo 0» остановит код в строке, которая вызывает ошибку, и отобразит окно сообщения, описывающее ошибку.
Проще говоря, он включает поведение проверки ошибок по умолчанию и показывает сообщение об ошибке по умолчанию.
Тогда зачем вообще его использовать?
Обычно вам не нужно использовать «On Error Goto 0», но это может быть полезно, когда вы используете его вместе с «On Error Resume Next».
Позволь мне объяснить!
Приведенный ниже код выберет все пустые ячейки в выделенном фрагменте.
Подложка SelectFormulaCells () Selection.SpecialCells (xlCellTypeBlanks) .Select End Sub
Но он покажет ошибку, если в выбранных ячейках нет пустых ячеек.
Поэтому, чтобы не отображать ошибку, вы можете использовать «Возобновить при ошибке».
Теперь он также покажет любую ошибку, когда вы запустите приведенный ниже код:
Sub SelectFormulaCells () При ошибке Возобновить следующий выбор. SpecialCells (xlCellTypeBlanks). Выберите End Sub
Все идет нормально!
Проблема возникает, когда есть часть кода, в которой может произойти ошибка, и поскольку вы используете «При ошибке возобновить следующее», код просто проигнорирует ее и перейдет к следующей строке.
Например, в приведенном ниже коде не будет сообщения об ошибке:
Sub SelectFormulaCells () При ошибке Возобновить следующий выбор.SpecialCells (xlCellTypeBlanks) .Select '… дополнительный код, который может содержать ошибку End Sub
В приведенном выше коде есть два места, где может произойти ошибка. В первом месте мы выбираем все пустые ячейки (используя Selection.SpecialCells), а во втором — оставшийся код.
Хотя ожидается первая ошибка, никаких ошибок после нее нет.
Здесь на помощь приходит On Error Goto 0.
Когда вы его используете, вы сбрасываете настройку ошибки на значение по умолчанию, где она начинает показывать ошибки при их обнаружении.
Например, в приведенном ниже коде не будет ошибки, если нет пустых ячеек, но будет сообщение об ошибке из-за ’10 / 0 ‘
Sub SelectFormulaCells () При ошибке Возобновить следующий выбор. SpecialCells (xlCellTypeBlanks). Select On Error GoTo 0 '… больше кода, который может содержать ошибку End Sub
При ошибке Перейти к [ярлык]
Два вышеуказанных метода — «При ошибке возобновить следующее» и «При ошибке перейти к 0» — не позволяют нам по-настоящему обработать ошибку. Один заставляет код игнорировать ошибку, а второй возобновляет проверку ошибок.
On Error Go [Label] — это способ, с помощью которого вы можете указать, что вы хотите делать, если в вашем коде есть ошибка.
Ниже приведена структура кода, в которой используется этот обработчик ошибок:
Sub Test () On Error GoTo Label: X = 10/0 'эта строка вызывает ошибку' … ваш оставшийся код идет сюда Exit Sub Label: 'код для обработки ошибки End Sub
Обратите внимание, что перед меткой обработки ошибок находится подпрограмма выхода. Это гарантирует, что в случае отсутствия ошибок подпрограмма будет закрыта, а код «Label» не будет выполнен. Если вы не используете Exit Sub, он всегда будет выполнять код «Label».
В приведенном ниже примере кода при возникновении ошибки код перескакивает и выполняет код в разделе обработчика (и показывает окно сообщения).
Sub Errorhandler () При ошибке GoTo ErrMsg X = 12 Y = 20/0 Z = 30 Exit Sub ErrMsg: MsgBox «Похоже, произошла ошибка» & vbCrLf & Err.Description End Sub
Обратите внимание, что при возникновении ошибки код уже был запущен и выполнил строки перед строкой, вызвавшей ошибку. В приведенном выше примере код устанавливает значение X как 12, но поскольку ошибка возникает в следующей строке, он не устанавливает значения для Y и Z.
Как только код перейдет к коду обработчика ошибок (ErrMsg в этом примере), он продолжит выполнение всех строк в коде обработчика ошибок и ниже и завершит выполнение подпрограммы.
При ошибке Goto -1
Это немного сложно, и в большинстве случаев вы вряд ли им воспользуетесь.
Но я все же расскажу об этом, поскольку я столкнулся с ситуацией, когда это было необходимо (не стесняйтесь игнорировать и переходить к следующему разделу, если вы ищете только основы).
Прежде чем я углублюсь в механику этого, позвольте мне попытаться объяснить, где это может быть полезно.
Предположим, у вас есть код, в котором обнаружена ошибка. Но все в порядке, поскольку у вас есть один обработчик ошибок. Но что происходит, когда в коде обработчика ошибок появляется еще одна ошибка (да… что-то вроде начального фильма).
В таком случае вы не можете использовать второй обработчик, так как первая ошибка не была устранена. Итак, хотя вы обработали первую ошибку, она все еще существует в памяти VBA. А в памяти VBA есть место только для одной ошибки, а не для двух или более.
В этом сценарии вы можете использовать On Error Goto -1.
Он очищает ошибку и освобождает память VBA для обработки следующей ошибки.
Хватит разговоров!
Теперь позвольте мне объяснить на примерах.
Предположим, у меня есть приведенный ниже код. Это вызовет ошибку, так как есть деление на ноль.
Дополнительный обработчик ошибок () X = 12 Y = 20/0 Z = 30 End Sub
Чтобы справиться с этим, я использую код обработчика ошибок (с именем ErrMsg), как показано ниже:
Sub Errorhandler () При ошибке GoTo ErrMsg X = 12 Y = 20/0 Z = 30 Exit Sub ErrMsg: MsgBox «Похоже, произошла ошибка» & vbCrLf & Err.Description End Sub
Теперь все снова хорошо. Как только возникает ошибка, используется обработчик ошибок и отображается окно сообщения, как показано ниже.
Теперь я расширяю код, чтобы у меня было больше кода в обработчике ошибок или после него.
Sub Errorhandler () При ошибке GoTo ErrMsg X = 12 Y = 20/0 Z = 30 Exit Sub ErrMsg: MsgBox «Кажется, произошла ошибка» & vbCrLf & Err.Description A = 10/2 B = 35/0 End Sub
Поскольку первая ошибка была обработана, а вторая нет, я снова вижу ошибку, как показано ниже.
По-прежнему все хорошо. Код ведет себя так, как мы и ожидали.
Поэтому для обработки второй ошибки я использую другой обработчик ошибок (ErrMsg2).
Sub Errorhandler () При ошибке GoTo ErrMsg X = 12 Y = 20/0 Z = 30 Выход Sub ErrMsg: MsgBox «Похоже, произошла ошибка» & vbCrLf & Err.Description On Error GoTo ErrMsg2 A = 10/2 B = 35 / 0 Exit Sub ErrMsg2: MsgBox "Кажется, снова произошла ошибка" & vbCrLf & Err.Description End Sub
И вот где это не работает должным образом.
Если вы запустите приведенный выше код, он все равно будет выдавать ошибку времени выполнения, даже после того, как будет установлен второй обработчик ошибок.
Это происходит из-за того, что мы не удалили первую ошибку из памяти VBA.
Да, мы справились! Но все еще остается в памяти.
И когда VBA обнаруживает другую ошибку, он все равно зависает с первой ошибкой, и, следовательно, второй обработчик ошибок не используется. Код останавливается на строке, вызвавшей ошибку, и показывает сообщение об ошибке.
Чтобы очистить память VBA и удалить предыдущую ошибку, вам необходимо использовать «On Error Goto -1».
Поэтому, если вы добавите эту строку в приведенный ниже код и запустите ее, она будет работать должным образом.
Sub Errorhandler () При ошибке GoTo ErrMsg X = 12 Y = 20/0 Z = 30 Выход Sub ErrMsg: MsgBox «Похоже, произошла ошибка» & vbCrLf & Err.Description On Error GoTo -1 При ошибке GoTo ErrMsg2 A = 10 / 2 B = 35/0 Выход из подпрограммы ErrMsg2: MsgBox «Похоже, снова произошла ошибка» & vbCrLf & Err.Description End Sub
Примечание: Ошибка автоматически очищается после завершения подпрограммы.Таким образом, «On Error Goto -1» может быть полезен, когда вы получаете две или более двух ошибок в одной и той же подпрограмме.
Объект ошибки
Когда в коде возникает ошибка, для получения подробных сведений об ошибке (например, номера ошибки или описания) используется объект Err.
Свойства объекта Err
Объект Err имеет следующие свойства:
| Свойство | Описание |
| Номер | Число, представляющее тип ошибки. Если ошибки нет, это значение равно 0. |
| Описание | Краткое описание ошибки |
| Источник | Название проекта, в котором произошла ошибка |
| HelpContext | Идентификатор контекста справки для ошибки в файле справки |
| HelpFile | Строка, представляющая расположение папки и имя файла справки. |
Хотя в большинстве случаев вам не нужно использовать объект Err, иногда он может быть полезен при обработке ошибок в Excel.
Например, предположим, что у вас есть набор данных, как показано ниже, и для каждого числа в выделенном фрагменте вы хотите вычислить квадратный корень в соседней ячейке.
Приведенный ниже код может это сделать, но поскольку в ячейке A5 есть текстовая строка, он показывает ошибку, как только это происходит.
Sub FindSqrRoot () Dim rng As Range Set rng = Selection For Each cell In rng cell.Offset (0, 1) .Value = Sqr (cell.Value) Следующая ячейка End Sub
Проблема с этим типом сообщений об ошибках заключается в том, что они ничего не говорят о том, что пошло не так и где возникла проблема.
Вы можете использовать объект Err, чтобы сделать эти сообщения об ошибках более значимыми.
Например, если я сейчас использую приведенный ниже код VBA, он остановит код, как только возникнет ошибка, и покажет окно сообщения с адресом ячейки, в которой есть проблема.
Sub FindSqrRoot () Dim rng As Range Set rng = Selection For each cell In rng On Error GoTo ErrHandler cell.Offset (0, 1) .Value = Sqr (cell.Value) Следующая ячейка ErrHandler: MsgBox "Номер ошибки:" & Err .Number & vbCrLf & _ "Описание ошибки:" & Err.Description & vbCrLf & _ "Ошибка в:" & cell.Address End Sub
Приведенный выше код предоставит вам гораздо больше информации, чем простое «Несоответствие типов», особенно адрес ячейки, чтобы вы знали, где произошла ошибка.
Вы можете дополнительно уточнить этот код, чтобы убедиться, что ваш код работает до конца (вместо прерывания при каждой ошибке), а затем выдает вам список адресов ячеек, в которых возникает ошибка.
Следующий код сделает это:
Sub Найти ErrorCells & vbCrLf & cell.Address On Error GoTo -1 End If Следующая ячейка MsgBox «Ошибка в следующих ячейках» & ErrorCells Exit Sub End Sub
Приведенный выше код выполняется до конца и дает квадратный корень из всех ячеек, в которых есть числа (в соседнем столбце). Затем отображается сообщение, в котором перечислены все ячейки, в которых произошла ошибка (как показано ниже):
Методы объекта Err
Хотя свойства Err полезны для отображения полезной информации об ошибках, есть также два метода Err, которые могут помочь вам с обработкой ошибок.
| Метод | Описание |
| Прозрачный | Очищает все настройки свойств объекта Err |
| Поднимать | Генерирует ошибку времени выполнения |
Давайте быстро узнаем, что это такое и как / зачем их использовать с VBA в Excel.
Err Clear Method
Предположим, у вас есть набор данных, показанный ниже, и вы хотите получить квадратный корень из всех этих чисел в соседнем столбце.
Следующий код получит квадратные корни из всех чисел в соседнем столбце и покажет сообщение о том, что произошла ошибка для ячеек A5 и A9 (поскольку в них есть текст).
Sub Найти ErrorCells & vbCrLf & cell.Address Err.Clear End If Next cell MsgBox «Ошибка в следующих ячейках» & ErrorCells End Sub
Обратите внимание, что я использовал метод Err.Clear в операторе If Then.
После того, как ошибка возникла и была перехвачена условием If, метод Err.Clear сбрасывает номер ошибки обратно на 0. Это гарантирует, что условие IF перехватывает ошибки только для тех ячеек, в которых оно возникло.
Если бы я не использовал метод Err.Clear, при возникновении ошибки она всегда была бы истинной в условии IF, и номер ошибки не был сброшен.
Другой способ сделать это — использовать On Error Goto -1, который полностью сбрасывает ошибку.
Примечание: Err.Clear отличается от On Error Goto -1. Err.Clear очищает только описание ошибки и номер ошибки. он не сбрасывает его полностью. Это означает, что если в том же коде есть еще один экземпляр ошибки, вы не сможете обработать его до его сброса (что можно сделать с помощью «On Error Goto -1», а не «Err.Clear»).
Err Raise Method
Метод Err.Raise позволяет вызвать ошибку времени выполнения.
Ниже приведен синтаксис использования метода Err.Raise:
Err.Raise [номер], [источник], [описание], [файл справки], [контекст помощи]
Все эти аргументы являются необязательными, и вы можете использовать их, чтобы сделать ваше сообщение об ошибке более значимым.
Но зачем вам самому создавать ошибку?
Хороший вопрос!
Вы можете использовать этот метод, когда есть экземпляр ошибки (что означает, что в любом случае произойдет ошибка), а затем вы используете этот метод, чтобы сообщить пользователю больше об ошибке (вместо менее полезного сообщения об ошибке, которое показывает VBA. по умолчанию).
Например, предположим, что у вас есть набор данных, показанный ниже, и вы хотите, чтобы все ячейки имели только числовые значения.
Sub RaiseError () Dim rng As Range Set rng = Selection On Error GoTo ErrHandler For each Cell in rng If Not (IsNumeric (Cell.Value)) Then Err.Raise vbObjectError + 513, Cell.Address, "Not a number", " Test.html "End If Next Cell ErrHandler: MsgBox Err.Description & vbCrLf & Err.HelpFile End Sub
В приведенном выше коде будет отображаться сообщение об ошибке с указанным описанием и файлом контекста.
Лично я никогда не использовал Err.Raise, так как в основном работаю только с Excel. Но для тех, кто использует VBA для работы с Excel вместе с другими приложениями, такими как Outlook, Word или PowerPoint, это может быть полезно.
Вот подробная статья о методе Err.Raise, если вы хотите узнать больше.
Рекомендации по обработке ошибок VBA
Независимо от того, насколько квалифицированно вы пишете код VBA, ошибки всегда будут его частью. Лучшие кодировщики — это те, кто умеет правильно обрабатывать эти ошибки.
Вот несколько рекомендаций, которые вы можете использовать при обработке ошибок в Excel VBA.
- Используйте «On Error Go [Label]» в начале кода. Это гарантирует, что любая ошибка, которая может произойти оттуда, будет обработана.
- Используйте «Возобновить при ошибке» ТОЛЬКО в том случае, если вы уверены в том, какие ошибки могут произойти. Используйте его только с ожидаемой ошибкой. Если вы используете его с неожиданными ошибками, он просто проигнорирует его и двинется вперед. Вы можете использовать «On Error Resume Next» с «Err.Raise», если хотите игнорировать определенный тип ошибки и улавливать остальные.
- При использовании обработчиков ошибок убедитесь, что вы используете Exit Sub перед обработчиками. Это гарантирует, что код обработчика ошибок будет выполняться только при возникновении ошибки (иначе он будет выполняться всегда).
- Используйте несколько обработчиков ошибок для перехвата различных типов ошибок. Наличие обработчика множественных ошибок гарантирует, что ошибка будет исправлена должным образом. Например, вы хотите обрабатывать ошибку «несоответствие типа» иначе, чем ошибку времени выполнения «Деление на 0».
Надеюсь, вы нашли эту статью в Excel полезной!
Вот еще несколько руководств по Excel VBA, которые могут вам понравиться:
- Типы данных Excel VBA — полное руководство
- Циклы Excel VBA — для «Далее», «Сделать пока», «Сделать до», «Для каждого»
- События Excel VBA — простое (и полное) руководство
- Редактор Excel Visual Basic — как открыть и использовать в Excel
На чтение 25 мин. Просмотров 16.3k.
Эта статья содержит полное руководство по обработке ошибок VBA. Если вы ищете краткое резюме, посмотрите таблицу быстрого руководства в первом разделе.
Если вы ищете конкретную тему по обработке ошибок VBA, ознакомьтесь с приведенным ниже содержанием.
Если вы новичок в VBA, то вы можете прочитать пост от начала до конца, так как он выложен в логическом порядке.
Содержание
- Краткое руководство по обработке ошибок
- Введение
- Ошибки VBA
- Заявление об ошибке
- Err объект
- Логирование
- Другие элементы, связанные с ошибками
- Простая стратегия обработки ошибок
- Полная стратегия обработки ошибок
- Обработка ошибок в двух словах
Краткое руководство по обработке ошибок
| Пункт | Описание |
| On Error Goto 0 | При возникновении ошибки код останавливается и отображает ошибку. |
| On Error Resume Next | Игнорирует ошибку и продолжает. |
| On Error Goto [Label] | Переход к определенной метке при возникновении ошибки. Это позволяет нам справиться с ошибкой. |
| Err Object | При возникновении ошибки информация об ошибке сохраняется здесь. |
| Err.Number | Номер ошибки. (Полезно, только если вам нужно проверить, произошла ли конкретная ошибка.) |
| Err.Description | Содержит текст ошибки. |
| Err.Source | Вы можете заполнить это, когда используете Err.Raise. |
| Err.Raise | Функция, которая позволяет генерировать вашу собственную ошибку. |
| Error Function | Возвращает текст ошибки из номера ошибки. Вышло из употребления. |
| Error Statement | Имитирует ошибку. Вместо этого используйте Err.Raise. |
Введение
Обработка ошибок относится к коду, который написан для обработки ошибок, возникающих во время работы вашего приложения. Эти ошибки обычно вызваны чем-то вне вашего контроля, например отсутствующим файлом, недоступностью базы данных, недействительными данными и т.д.
Если мы считаем, что ошибка может произойти в какой-то
момент, рекомендуется написать специальный код для обработки ошибки, если она
возникнет, и устранить ее.
Для всех остальных ошибок мы используем общий код для их
устранения. Это где оператор обработки ошибок VBA вступает в игру. Они
позволяют нашему приложению корректно обрабатывать любые ошибки, которые мы не
ожидали.
Чтобы понять обработку ошибок, мы должны сначала понять
различные типы ошибок в VBA.
Ошибки VBA
В VBA есть три типа ошибок
- Синтаксис
- Компиляция
- Время выполнения
Мы используем обработку ошибок для устранения ошибок во
время выполнения. Давайте посмотрим на каждый из этих типов ошибок, чтобы было
ясно, что такое ошибка во время выполнения.
Синтаксические ошибки
Если вы использовали VBA в течение какого-то времени, вы
увидите синтаксическую ошибку. Когда вы набираете строку и нажимаете return,
VBA оценивает синтаксис и, если он неверен, выдает сообщение об ошибке.
Например, если вы введете If и забудете ключевое слово Then,
VBA отобразит следующее сообщение об ошибке.
Некоторые примеры синтаксических ошибок
' then отсутствует
If a > b
' не хватает = после i
For i 2 To 7
' отсутствует правая скобка
b = left("АБВГ",1
Синтаксические ошибки относятся только к одной строке. Они
возникают, когда синтаксис одной строки неверен.
Примечание. Диалоговое окно «Ошибка синтаксиса» можно отключить, выбрав «Сервис» -> «Параметры» и отметив «Автосинтаксическая проверка». Строка по-прежнему будет отображаться красным цветом в случае ошибки, но диалоговое окно не появится.
Ошибки компиляции
Ошибки компиляции происходят более чем в одной строке.
Синтаксис в одной строке правильный, но неверный, если учесть весь код проекта.
Примеры ошибок компиляции:
- Оператор If без соответствующего оператора End If
- For без Next
- Select без End Select
- Вызов Sub или Function, которые не существуют
- Вызов Sub или Function с неверными параметрами
- Присвоение Sub или Function того же имени, что и для модуля
- Переменные не объявлены (Option Explicit должен присутствовать в верхней части модуля)
На следующем снимке экрана показана ошибка компиляции,
которая возникает, когда цикл For не имеет соответствующего оператора Next.
Использование Debug-> Compile
Чтобы найти ошибки компиляции, мы используем Debug->
Compile VBA Project из меню Visual Basic.
Когда вы выбираете Debug-> Compile, VBA отображает первую
обнаруженную ошибку.
Когда эта ошибка исправлена, вы можете снова запустить
Compile, и VBA найдет следующую ошибку.
Debug-> Compile также будет включать синтаксические
ошибки в поиск, что очень полезно.
Если ошибок не осталось и вы запускаете Debug-> Compile,
может показаться, что ничего не произошло. Однако «Компиляция» будет недоступна
в меню «Отладка». Это означает, что ваше приложение не имеет ошибок компиляции
в текущий момент.
Debug->Compile Error Summary
Debug-> Compile находит ошибки компиляции (проекта).
Он также найдет синтаксические ошибки.
Он находит одну ошибку каждый раз, когда вы ее используете.
Если нет ошибок компиляции, оставленная опция Компиляция
будет отображаться серым цветом в меню.
Debug-> Compile Usage
Вы должны всегда использовать Debug-> Compile, прежде чем
запускать свой код. Это гарантирует, что ваш код не будет иметь ошибок
компиляции при запуске.
Если вы не запускаете Debug-> Compile, то VBA может
обнаружить ошибки компиляции при запуске. Их не следует путать с ошибками
времени выполнения.
Ошибки во время выполнения
Ошибки во время выполнения возникают, когда ваше приложение
работает. Обычно они находятся вне вашего контроля, но могут быть вызваны
ошибками в вашем коде.
Например, представьте, что ваше приложение читает из внешней
рабочей книги. Если этот файл будет удален, то VBA отобразит ошибку, когда ваш
код попытается открыть его.
Другие примеры ошибок времени выполнения
- база данных недоступна
- пользователь вводит неверные данные
- ячейка, содержащая текст вместо числа
Как мы уже видели, целью обработки ошибок является обработка
ошибок времени выполнения, когда они возникают.
Ожидаемые и неожиданные ошибки
Когда мы думаем, что может произойти ошибка во время
выполнения, мы помещаем код на место для ее обработки. Например, мы обычно
помещаем код на место, чтобы иметь дело с файлом, который не найден.
Следующий код проверяет, существует ли файл, прежде чем он
пытается его открыть. Если файл не существует, отображается сообщение, удобное
для пользователя, и код выходит из подпрограммы.
Sub OtkritFail()
Dim sFile As String
sFile = "C:ДокументыОтчет.xlsx"
' Используйте Dir, чтобы проверить, существует ли файл
If Dir(sFile) = "" Then
' если файл не существует, отобразить сообщение
MsgBox "Файл не найден" & sFile
Exit Sub
End If
' Код достигнет только если файл существует
Workbooks.Open sFile
End Sub
Когда мы думаем, что в какой-то момент может произойти
ошибка, рекомендуется добавить код для обработки ситуации. Мы обычно называем
эти ошибки ожидаемыми.
Если у нас нет специального кода для обработки ошибки, это
считается неожиданной ошибкой. Мы используем операторы обработки ошибок VBA для
обработки непредвиденных ошибок.
Ошибки времени выполнения, которые не являются ошибками VBA
Прежде чем мы рассмотрим VBA Handling, мы должны упомянуть
один тип ошибок. Некоторые ошибки во время выполнения не рассматриваются как
ошибки VBA, а только пользователем.
Позвольте мне объяснить это на примере. Представьте, что у
вас есть приложение, которое требует, чтобы вы добавили значения в переменные a
и b
Допустим, вы по ошибке используете звездочку вместо знака
плюс
Это не ошибка VBA. Ваш синтаксис кода является совершенно
законным. Однако, с вашей точки зрения, это ошибка.
Эти ошибки не могут быть обработаны с помощью обработки ошибок, поскольку они, очевидно, не будут генерировать никаких ошибок. Вы можете справиться с этими ошибками, используя Unit Testing and Assertions.
Заявление об ошибке
Как мы видели, есть два способа обработки ошибок во время
выполнения
- Ожидаемые ошибки — напишите конкретный код для
их обработки. - Неожиданные ошибки — используйте операторы
обработки ошибок VBA для их обработки.
Оператор VBA On Error используется для обработки ошибок.
Этот оператор выполняет некоторые действия при возникновении ошибки во время
выполнения.
Есть четыре различных способа использовать это утверждение
- On Error Goto 0 — код останавливается на строке с ошибкой и отображает сообщение.
- On Error Resume Next — код перемещается на следующую строку. Сообщение об ошибке не отображается.
- On Error Goto [label] — код перемещается на определенную строку или метку. Сообщение об ошибке не отображается. Это тот, который мы используем для обработки ошибок.
- On Error Goto -1 — очищает текущую ошибку.
Давайте посмотрим на каждое из этих утверждений по очереди.
On Error Goto 0
Это поведение по умолчанию VBA. Другими словами, если вы не
используете On Error, это поведение вы увидите.
При возникновении ошибки VBA останавливается на строке с
ошибкой и отображает сообщение об ошибке. Приложение требует вмешательства
пользователя с кодом, прежде чем оно сможет продолжить. Это может быть
исправление ошибки или перезапуск приложения. В этом случае обработка ошибок не
происходит.
Давайте посмотрим на пример. В следующем коде мы не
использовали строку On Error, поэтому VBA будет использовать поведение On Error
Goto 0 по умолчанию.
Sub IspDefault()
Dim x As Long, y As Long
x = 6
y = 6 / 0
x = 7
End Sub
Вторая строка присваивания приводит к ошибке деления на ноль. Когда мы запустим этот код, мы получим сообщение об ошибке, показанное на скриншоте ниже.
Когда появляется ошибка, вы можете выбрать End или Debug
Если вы выберете Конец, то приложение просто остановится.
Если вы выберете Отладить, приложение остановится на строке
ошибки, как показано на скриншоте ниже.
Это нормально, когда вы пишете код VBA, поскольку он
показывает вам точную строку с ошибкой.
Это поведение не подходит для приложения, которое вы
передаете пользователю. Эти ошибки выглядят непрофессионально и делают
приложение нестабильным.
Подобная ошибка, по сути, приводит к сбою приложения.
Пользователь не может продолжить работу без перезапуска приложения. Они могут
вообще не использовать его, пока вы не исправите для них ошибку.
Используя On Error Goto [label], мы можем дать пользователю
более контролируемое сообщение об ошибке. Это также предотвращает остановку
приложения. Мы можем заставить приложение работать предопределенным образом.
On Error Resume Next
Использование On Error Resume Next указывает VBA
игнорировать ошибку и продолжать работу.
Есть конкретные случаи, когда это полезно. Большую часть
времени вы должны избегать его использования.
Если мы добавим Resume Next к нашему примеру Sub, то VBA
проигнорирует ошибку деления на ноль
Sub UsingResumeNext()
On Error Resume Next
Dim x As Long, y As Long
x = 6
y = 6 / 0
x = 7
End Sub
Это не очень хорошая идея, чтобы сделать это. Если вы
игнорируете ошибку, то поведение может быть непредсказуемым. Ошибка может
повлиять на приложение несколькими способами. Вы можете получить неверные
данные. Проблема в том, что вы не знаете, что что-то пошло не так, потому что
вы подавили ошибку.
Приведенный ниже код является примером использования Resume
Next.
Sub OtprSoobsch()
On Error Resume Next
' Требуется ссылка:
' Библиотека объектов Microsoft Outlook 15.0
Dim Outlook As Outlook.Application
Set Outlook = New Outlook.Application
If Outlook Is Nothing Then
MsgBox " Не удается создать сеанс Microsoft Outlook." _
& " Письмо не будет отправлено."
Exit Sub
End If
End Sub
В этом коде мы проверяем, доступен ли Microsoft Outlook на компьютере. Все,
что мы хотим знать — это доступно или нет. Нас не интересует конкретная ошибка.
В приведенном выше коде мы продолжаем, если есть ошибка.
Затем в следующей строке мы проверяем значение переменной Outlook. Если произошла ошибка, тогда
значение этой переменной будет установлено равным Nothing.
Это пример того, когда Резюме может быть полезным. Дело в
том, что, хотя мы используем Resume,
мы все равно проверяем наличие ошибки. Подавляющее большинство времени вам не
нужно будет использовать Resume.
On Error Goto [label]
Вот как мы используем обработку ошибок в VBA. Это эквивалент функциональности Try and Catch, которую вы видите на
таких языках, как C # и
Java.
При возникновении ошибки вы отправляете ошибку на
определенный ярлык. Обычно это внизу саба.
Давайте применим это к подводной лодке, которую мы
использовали
Sub IspGotoLine()
On Error Goto eh
Dim x As Long, y As Long
x = 6
y = 6 / 0
x = 7
Done:
Exit Sub
eh:
MsgBox "Произошла следующая ошибка: " & Err.Description
End Sub
Снимок экрана ниже показывает, что происходит при возникновении ошибки.
VBA переходит на метку eh, потому что мы указали это в
строке «Перейти к ошибке».
Примечание 1: Метка, которую мы используем в операторе On… Goto, должна быть в текущей Sub / Function. Если нет, вы получите ошибку компиляции.
Примечание 2: Когда возникает ошибка при использовании On Error Goto [label], обработка ошибок возвращается к поведению по умолчанию, т.е. код остановится на строке с ошибкой и отобразит сообщение об ошибке. См. Следующий раздел для получения дополнительной информации об этом.
On Error Goto -1
Это утверждение отличается от других трех. Он используется
для очистки текущей ошибки, а не для настройки конкретного поведения.
При возникновении ошибки с помощью функции On Error Goto [label] поведение обработки ошибки возвращается к поведению по умолчанию, т.е. On Error Goto 0 . Это означает, что если произойдет другая ошибка, код остановится на текущей строке.
Это поведение относится только к текущей подпрограмме. Как
только мы выйдем из саба, ошибка будет очищена автоматически.
Посмотрите на код ниже. Первая ошибка приведет к переходу
кода на метку eh. Вторая ошибка остановится на строке с ошибкой 1034.
Sub DveOshibki()
On Error Goto eh
' генерировать ошибку «Несоответствие типов»
Error (13)
Done:
Exit Sub
eh:
' генерировать «определенную приложением» ошибку
Error (1034)
End Sub
Если мы добавим дальнейшую обработку ошибок, она не будет
работать, поскольку ловушка ошибок не была очищена.
В коде ниже мы добавили строку
после того как мы поймаем первую ошибку.
Это не имеет никакого эффекта, так как ошибка не была
очищена. Другими словами, код остановится на строке с ошибкой и отобразит
сообщение.
Sub DveOshibki()
On Error Goto eh
' генерировать ошибку «Несоответствие типов»
Error (13)
Done:
Exit Sub
eh:
On Error Goto eh_other
' генерировать «определенную приложением» ошибку
Error (1034)
Exit Sub
eh_other:
Debug.Print "ehother " & Err.Description
End Sub
Для устранения ошибки мы используем On Error Goto -1.
Думайте об этом как об установке ловушки для мыши. Когда ловушка сработает, вам
нужно установить ее снова.
В приведенном ниже коде мы добавляем эту строку, и вторая
ошибка теперь приведет к переходу кода на метку eh_other.
Sub DveOshibki()
On Error Goto eh
' генерировать ошибку «Несоответствие типов»
Error (13)
Done:
Exit Sub
eh:
' явная ошибка
On Error Goto -1
On Error Goto eh_other
' генерировать «определенную приложением» ошибку
Error (1034)
Exit Sub
eh_other:
Debug.Print "ehother " & Err.Description
End Sub
Примечание 1. Вероятно, в редких случаях полезно использовать On Error Goto -1. Мне лично никогда не приходилось пользоваться этой линией. Помните, что как только вы выйдете из Sub, ошибка все равно будет очищена.
Примечание 2. у объекта Err есть член Clear. Использование Clear очищает текст и цифры в объекте Err, но НЕ сбрасывает ошибку.
Использование On Error
Как мы уже видели, VBA будет делать одну из трех вещей при возникновении ошибки:
- Остановитесь и отобразите ошибку.
- Игнорируйте ошибку и продолжайте.
- Перейти к определенной строке.
VBA всегда будет настроен на одно из этих действий. Когда вы
используете On Error, VBA изменит ваше поведение и забудет о любом предыдущем.
В следующем подпункте VBA изменяет поведение ошибки каждый
раз, когда мы используем оператор On Error
Sub ErrorSostoyaniya()
Dim x As Long
' Перейти на этикетке, если ошибка
On Error Goto eh
' это проигнорирует ошибку в следующей строке
On Error Resume Next
x = 1 / 0
' это отобразит сообщение об ошибке в следующей строке
On Error Goto 0
x = 1 / 0
Done:
Exit Sub
eh:
Debug.Print Err.Description
End Sub
Err объект
При возникновении ошибки вы можете просмотреть детали
ошибки, используя объект Err.
При возникновении ошибки времени выполнения VBA
автоматически заполняет объект Err деталями.
Приведенный ниже код выведет «Error Number: 13 Type
Mismatch», которое возникает, когда мы пытаемся поместить строковое значение в
длинное целое число.
Sub IspErr()
On Error Goto eh
Dim total As Long
total = "aa"
Done:
Exit Sub
eh:
Debug.Print "Номер ошибки: " & Err.Number _
& " " & Err.Description
End Sub
Err.Description предоставляет подробную информацию об ошибке, которая происходит. Это текст, который вы обычно видите, когда возникает ошибка, например, «Несоответствие типов»
Err.Number — это идентификационный номер ошибки, например, номер ошибки для «Несоответствие типов» — 13. Единственное время, когда вам действительно нужно это, если вы проверяете, что произошла конкретная ошибка, и это необходимо только в редких случаях.
Свойство Err.Source кажется отличной идеей, но оно не работает при ошибке VBA. Источник вернет имя проекта, которое вряд ли сузит место возникновения ошибки. Однако, если вы создаете ошибку с помощью Err.Raise, вы можете установить источник самостоятельно, и это может быть очень полезно.
Получение номера строки
Функция Erl используется для возврата номера строки, где
произошла ошибка.
Это часто вызывает путаницу. В следующем коде Erl вернет ноль.
Sub IspErr()
On Error Goto eh
Dim val As Long
val = "aa"
Done:
Exit Sub
eh:
Debug.Print Erl
End Sub
Это потому, что нет номеров строк. Большинство людей не
понимают этого, но VBA позволяет вам иметь номера строк.
Если мы изменим подпрограмму, указав номер строки, она теперь выведет 20.
Sub IspErr()
10 On Error Goto eh
Dim val As Long
20 val = "aa"
Done:
30 Exit Sub
eh:
40 Debug.Print Erl
End Sub
Добавление номеров строк в код вручную затруднительно.
Однако есть инструменты, которые позволят вам легко добавлять и удалять номера
строк в подпрограмме.
Когда вы закончите работу над проектом и передадите его
пользователю, в этот момент может быть полезно добавить номера строк. Если вы
используете стратегию обработки ошибок в последнем разделе этого поста, то VBA
сообщит строку, где произошла ошибка.
Использование Err.Raise
Err.Raise позволяет нам создавать ошибки. Мы можем
использовать его для создания пользовательских ошибок для нашего приложения,
что очень полезно. Это эквивалент оператора Throw в Java C #.
Формат следующий
Err.Raise [error number], [error source], [error description]
Давайте посмотрим на простой пример. Представьте, что мы
хотим убедиться, что в ячейке есть запись длиной 5 символов. Мы могли бы иметь конкретное сообщение для
этого
Public Const ERROR_INVALID_DATA As Long = vbObjectError + 513
Sub ReadWorksheet()
On Error Goto eh
If Len(Sheet1.Range("A1")) <> 5 Then
Err.Raise ERROR_INVALID_DATA, "ReadWorksheet" _
, "Значение в ячейке A1 должно иметь ровно 5 символов."
End If
' продолжить, если ячейка имеет действительные данные
Dim id As String
id = Sheet1.Range("A1")
Done:
Exit Sub
eh:
' Err.Raise отправит код сюда
MsgBox " Обнаружена ошибка: " & Err.Description
End Sub
Когда мы создаем ошибку, используя Err.Raise, нам нужно присвоить ей номер. Мы можем использовать любое
число от 513 до 65535 для нашей ошибки. Мы должны использовать vbObjectError с номером,
например
Err.Raise vbObjectError + 513
Использование Err.Clear
Err.Clear используется для очистки текста и чисел из объекта
Err.Object. Другими словами, он очищает описание и номер.
Редко вам понадобится его использовать, но давайте
рассмотрим пример, где вы могли бы.
В приведенном ниже коде мы подсчитываем количество ошибок,
которые могут возникнуть. Для простоты мы генерируем ошибку для каждого
нечетного числа.
Мы проверяем номер ошибки каждый раз, когда проходим цикл.
Если число не равно нулю, то произошла ошибка. Как только мы посчитаем ошибку,
нам нужно установить номер ошибки на ноль, чтобы он был готов проверить
следующую ошибку.
Sub IspErrClear()
Dim count As Long, i As Long
' Продолжите, если ошибка, так как мы проверим номер ошибки
On Error Resume Next
For i = 0 To 9
' генерировать ошибку для каждого второго
If i Mod 2 = 0 Then Error (13)
' Проверьте на ошибку
If Err.Number <> 0 Then
count = count + 1
Err.Clear ' Очистить Err, как только он считается
End If
Next
Debug.Print " Количество ошибок было: " & count
End Sub
Примечание: Err.Clear сбрасывает текст и цифры в объекте ошибки, но не очищает ошибку — см. On Error Goto -1 для получения дополнительной информации об очистке фактической ошибки.
Логирование
Ведение журнала означает запись информации из вашего
приложения, когда оно запущено. При возникновении ошибки вы можете записать
детали в текстовый файл, чтобы у вас была запись об ошибке.
Код ниже показывает очень простую процедуру регистрации
Sub Logger(sType As String, sSource As String, sDetails As String)
Dim sFilename As String
sFilename = "C:templogging.txt"
' Архивный файл определенного размера
If FileLen(sFilename) > 20000 Then
FileCopy sFilename _
, Replace(sFilename, ".txt", Format(Now, "ddmmyyyy hhmmss.txt"))
Kill sFilename
End If
' Откройте файл для записи
Dim filenumber As Variant
filenumber = FreeFile
Open sFilename For Append As #filenumber
Print #filenumber, CStr(Now) & "," & sType & "," & sSource _
& "," & sDetails & "," & Application.UserName
Close #filenumber
End Sub
Вы можете использовать это так:
' Создать уникальный номер ошибки
Public Const ERROR_DATA_MISSING As Long = vbObjectError + 514
Sub CreateReport()
On Error Goto eh
If Sheet1.Range("A1") = "" Then
Err.Raise ERROR_DATA_MISSING, "CreateReport", "Данные отсутствуют в ячейке A1"
End If
' другой код здесь
Done:
Exit Sub
eh:
Logger "Error", Err.Source, Err.Description
End Sub
Журнал не только для записи ошибок. Вы можете записывать
другую информацию во время работы приложения. При возникновении ошибки вы
можете проверить последовательность событий до того, как произошла ошибка.
Ниже приведен пример регистрации. То, как вы реализуете
журналирование, зависит от характера приложения и его полезности.
Sub ReadingData()
Logger "Information", "ReadingData()", "Starting to read data."
Dim coll As New Collection
' Read data
Set coll = ReadData
If coll.Count < 10 Then
Logger "Warning", "ReadingData()", "Number of data items is low."
End If
Logger "Information", "ReadingData()", "Number of data items is " & coll.Count
Logger "Information", "ReadingData()", "Finished reading data."
End Sub
Наличие большого количества информации при работе с ошибкой
может быть очень полезным. Часто пользователь может не дать вам точную информацию
об ошибке, которая произошла. Глядя на журнал, вы можете получить более точную
информацию об информации.
Другие элементы, связанные с ошибками
В этом разделе рассматриваются некоторые другие инструменты
обработки ошибок, которые есть в VBA. Эти элементы считаются устаревшими, но я
включил их, поскольку они могут существовать в устаревшем коде.
Функция ошибки
Функция Error используется для печати описания ошибки с
заданным номером ошибки. Он включен в VBA для обеспечения обратной
совместимости и не нужен, поскольку вместо него можно использовать описание
Err.Description.
Ниже приведены некоторые примеры
' Распечатать текст «Деление на ноль» Debug.Print Error(11) ' Распечатать текст "Несоответствие типов" Debug.Print Error(13) ' Распечатать текст "Файл не найден" Debug.Print Error(53)
Заявление об ошибке
Заявление об ошибке позволяет имитировать ошибку. Он включен
в VBA для обратной совместимости. Вместо этого вы должны использовать
Err.Raise.
В следующем коде мы моделируем ошибку «Разделить на ноль».
Sub ZayavlObOshibke()
On Error Goto eh
' Это создаст деление на ноль ошибок
Error 11
Exit Sub
eh:
Debug.Print Err.Number, Err.Description
End Sub
Это утверждение включено в VBA для обратной совместимости.
Вместо этого вы должны использовать Err.Raise.
Простая стратегия обработки ошибок
Со всеми различными опциями вы можете быть озадачены тем,
как использовать обработку ошибок в VBA. В этом разделе я покажу вам, как
реализовать простую стратегию обработки ошибок, которую вы можете использовать
во всех своих приложениях.
Основная реализация
Это простой обзор нашей стратегии
- Поместите строку On Error Goto Label в начале нашего верхнего Sub.
- Поместите Label у обработки ошибок в конце нашего верхнего
Sub. - Если происходит ожидаемая ошибка, обработайте ее и продолжайте.
- Если приложение не может продолжить работу, используйте Err.Raise для перехода к метке обработки ошибок.
- В случае непредвиденной ошибки код автоматически перейдет к метке обработки ошибок.
На следующем рисунке показан обзор того, как это выглядит
Следующий код показывает простую реализацию этой стратегии
Public Const ERROR_NO_ACCOUNTS As Long = vbObjectError + 514
Sub BuildReport()
On Error Goto eh
' Если ошибка в ReadAccounts, то перейти к ошибке
ReadAccounts
' Сделай что-нибудь с кодом
Done:
Exit Sub
eh:
' Все ошибки будут прыгать сюда
MsgBox Err.Source & ": Произошла следующая ошибка " & Err.Description
End Sub
Sub ReadAccounts()
' ОЖИДАЕМАЯ ОШИБКА - Может обрабатываться кодом
' Приложение может обрабатывать A1 равным нулю
If Sheet1.Range("A1") = 0 Then
Sheet1.Range("A1") = 1
End If
' ОЖИДАЕМАЯ ОШИБКА - не может быть обработана кодом
' Приложение не может быть продолжено, если нет учетной записи
If Dir("C:ДокументыОтчет.xlsx") = "" Then
Err.Raise ERROR_NO_ACCOUNTS, "UsingErr" _
, "There are no accounts present for this month."
End If
' НЕОЖИДАННАЯ ОШИБКА - не может быть обработана кодом
' Если ячейка B3 содержит текст, мы получим ошибку несоответствия типов
Dim total As Long
total = Sheet1.Range("B3")
' продолжить и читать счета
End Sub
Это хороший способ реализации обработки ошибок, потому что
- Нам не нужно добавлять код обработки ошибок в
каждую подпрограмму. - Если возникает ошибка, то VBA корректно
завершает работу приложения.
Полная стратегия обработки ошибок
Стратегия выше имеет один недостаток. Он не сообщает вам,
где произошла ошибка. VBA не наполняет Err.Source чем-либо полезным, поэтому мы
должны сделать это сами.
В этом разделе я собираюсь представить более полную
стратегию ошибок. Я написал два сабвуфера, которые выполняют всю тяжелую
работу, поэтому все, что вам нужно сделать, это добавить их в свой проект.
Целью этой стратегии является предоставление вам стека * и
номера строки в случае возникновения ошибки.
* Стек — это список вспомогательных функций, которые
использовались в данный момент при возникновении ошибки.
Это наша стратегия
- Разместите обработку ошибок во всех
подпрограммах. - Когда происходит ошибка, обработчик ошибок
добавляет подробности к ошибке и вызывает ее снова. - Когда ошибка достигает самой верхней
подпрограммы, она отображается.
Мы просто «всплываем» из-за ошибки. Следующая диаграмма
показывает простое визуальное представление о том, что происходит, когда в Sub3
возникает ошибка
Единственная грязная часть этого — правильное форматирование
строк. Я написал две подводные лодки, которые справляются с этим, поэтому он
позаботится о вас.
Это две вспомогательные подводные лодки
Option Explicit
Public Const MARKER As String = "NOT_TOPMOST"
' Вызывает ошибку и добавляет номер строки и имя текущей процедуры
Sub RaiseError(ByVal errorno As Long, ByVal src As String _
, ByVal proc As String, ByVal desc As String, ByVal lineno As Long)
Dim sLineNo As Long, sSource As String
' Если маркера нет, тогда RaiseError вызывается впервые.
If Left(src, Len(MARKER)) <> MARKER Then
' Добавить номер строки ошибки, если она есть
If lineno <> 0 Then
sSource = vbCrLf & "Line no: " & lineno & " "
End If
' Добавить маркер и процедуру к источнику
sSource = MARKER & sSource & vbCrLf & proc
Else
' Если ошибка уже возникла, просто добавьте имя процедуры
sSource = src & vbCrLf & proc
End If
' Если код останавливается здесь, убедитесь, что DisplayError находится в верхней части Sub
Err.Raise errorno, sSource, desc
End Sub
' Отображает ошибку, когда она достигает самого верхнего sub
' Примечание: вы можете добавить вызов для входа из этого подпункта
Sub DisplayError(ByVal src As String, ByVal desc As String _
, ByVal sProcname As String)
' Удалить маркер
src = Replace(src, MARKER, "")
Dim sMsg As String
sMsg = " Произошла следующая ошибка: " & vbCrLf & Err.Description _
& vbCrLf & vbCrLf & " Расположение ошибки: "
sMsg = sMsg + src & vbCrLf & sProcname
' Показать сообщение
MsgBox sMsg, Title:="Ошибка "
End Sub
Пример использования этой стратегии
Вот простое кодирование, которое использует эти Sub. В этой стратегии мы не размещаем какой-либо код в верхнем подпрограмме. Мы только вызываем подводные лодки.
Sub Topmost()
On Error Goto EH
Level1
Done:
Exit Sub
EH:
DisplayError Err.source, Err.Description, "Module1.Topmost"
End Sub
Sub Level1()
On Error Goto EH
Level2
Done:
Exit Sub
EH:
RaiseError Err.Number, Err.source, "Module1.Level1", Err.Description, Erl
End Sub
Sub Level2()
On Error Goto EH
' Ошибка здесь
Dim a As Long
a = "7 / 0"
Done:
Exit Sub
EH:
RaiseError Err.Number, Err.source, "Module1.Level2", Err.Description, Erl
End Sub
Результат выглядит так
Если в вашем проекте есть номера строк, результат будет содержать номер строки ошибки.
Примечание: вы можете получить следующую ошибку при использовании этого кода:
“Programmatic Access to Visual Basic Project is not trusted”
Чтобы решить эту проблему, выполните следующие действия.
- Перейдите в раздел «Разработчик» на ленте и
нажмите «Macro Security», которая находится под кодом. - Нажмите «Настройка макроса» в левом списке.
- Поставьте флажок в поле «Доверительный доступ к
объектной модели проекта VBA». - Нажмите Ok.
Обработка ошибок в двух словах
- Обработка ошибок используется для обработки ошибок, возникающих во время работы приложения.
- Вы пишете определенный код для обработки ожидаемых ошибок. Вы используете оператор обработки ошибок VBA
On Error Goto [label] для отправки VBA на метку при возникновении непредвиденной ошибки. - Вы можете получить подробную информацию об ошибке из Err.Description.
- Вы можете создать свою собственную ошибку, используя Err.Raise.
- Использование одного оператора On Error в самой верхней подпрограмме перехватит все ошибки в подпрограммах, которые вызываются отсюда.
- Если вы хотите записать имя Sub с ошибкой, вы можете обновить ошибку и сбросить ее.
- Вы можете использовать журнал для записи информации о приложении, когда оно запущено.
In this Article
- VBA Errors Cheat Sheet
- Errors
- VBA Error Handling
- VBA On Error Statement
- On Error GoTo 0
- On Error Resume Next
- Err.Number, Err.Clear, and Catching Errors
- On Error GoTo Line
- VBA IsError
- If Error VBA
- VBA Error Types
- Runtime Errors
- Syntax Errors
- Compile Errors
- Debug > Compile
- OverFlow Error
- Other VBA Error Terms
- VBA Catch Error
- VBA Ignore Error
- VBA Throw Error / Err.Raise
- VBA Error Trapping
- VBA Error Message
- VBA Error Handling in a Loop
- VBA Error Handling in Access
VBA Errors Cheat Sheet
Errors
On Error – Stop code and display error
On Error Goto 0
On Error – Skip error and continue running
On Error Resume Next
On Error – Go to a line of code [Label]
On Error Goto [Label]
Clears (Resets) Error
On Error 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
“Abort, Retry, Fail?” – MS-DOS error message circa 1986
This post provides a complete guide to VBA Error Handing. If you are looking for a quick summary then check out the quick guide table in the first section.
If you are looking for a particular topic on VBA Error Handing then check out the table of contents below(if it’s not visible click on the post header).
If you are new to VBA Error Handling, then you can read the post from start to finish as it is laid out in logical order.
Contents
- 1 A Quick Guide to Error Handing
- 2 The Webinar
- 3 Download the Error Handling Library
- 4 Introduction
- 5 VBA Errors
- 5.1 Syntax Errors
- 5.2 Compilation Errors
- 5.2.1 Using Debug->Compile
- 5.2.2 Debug->Compile Error Summary
- 5.2.3 Debug->Compile Usage
- 5.3 Runtime Errors
- 5.3.1 Expected Versus Unexpected Errors
- 5.4 Runtime Errors that are not VBA Errors
- 6 The On Error Statement
- 6.1 On Error GoTo 0
- 6.2 On Error Resume Next
- 6.3 On Error GoTo [label]
- 6.4 On Error GoTo -1
- 6.5 Using On Error
- 7 Resume Next
- 8 The Err Object
- 8.1 Getting the Line Number
- 8.2 Using Err.Raise
- 8.3 Using Err.Clear
- 9 Logging
- 10 Other Error Related Items
- 10.1 Error Function
- 10.2 Error Statement
- 11 A Simple Error Handling Strategy
- 11.1 The Basic Implementation
- 12 A Complete Error Handling Strategy
- 12.1 An Example of using this strategy
- 13 Error Handling in a Nutshell
- 14 What’s Next?
A Quick Guide to Error Handing
| Item | Description |
|---|---|
| On Error Goto 0 | When error occurs, the code stops and displays the error. |
| On Error Goto -1 | Clears the current error setting and reverts to the default. |
| On Error Resume Next | Ignores the error and continues on. |
| On Error Goto [Label] | Goes to a specific label when an error occurs. This allows us to handle the error. |
| Err Object | When an error occurs the error information is stored here. |
| Err.Number | The number of the error. (Only useful if you need to check a specific error occurred.) |
| Err.Description | Contains the error text. |
| Err.Source | You can populate this when you use Err.Raise. |
| Err.Raise | A function that allows you to generate your own error. |
| Error Function | Returns the error text from an error number. Obsolete. |
| Error Statement | Simulates an error. Use Err.Raise instead. |
The Webinar
Members of the Webinar Archives can access the webinar for this article by clicking on the image below.
(Note: Archive members have access to the webinar archive.)
Download the Error Handling Library
Introduction
Error Handling refers to code that is written to handle errors which occur when your application is running. These errors are normally caused by something outside your control like a missing file, database being unavailable, data being invalid etc.
If we think an error is likely to occur at some point, it is good practice to write specific code to handle the error if it occurs and deal with it.
For all other errors, we use generic code to deal with them. This is where the VBA error handling statement comes into play. They allow our application to deal gracefully with any errors we weren’t expecting.
To understand error handling we must first understand the different types of errors in VBA.
VBA Errors
There are three types of errors in VBA:
- Syntax
- Compilation
- Runtime
We use error handling to deal with runtime errors. Let’s have a look at each of these error types so that it is clear what a runtime error is.
Syntax Errors
If you have used VBA for any length of time you will have seen a syntax error. When you type a line and press return, VBA will evaluate the syntax and if it is not correct it will display an error message.
For example if you type If and forget the Then keyword, VBA will display the following error message
Some examples of syntax errors are
' then is missing If a > b ' equals is missing after i For i 2 To 7 ' missing right parenthesis b = left("ABCD",1
Syntax errors relate to one line only. They occur when the syntax of one line is incorrect.
Note: You can turn off the Syntax error dialog by going to Tools->Options and checking off “Auto Syntax Check”. The line will still appear red if there is an error but the dialog will not appear.
Compilation Errors
Compilation errors occur over more than one line. The syntax is correct on a single line but is incorrect when all the project code is taken into account.
Examples of compilation errors are:
- If statement without corresponding End If statement
- For without Next
- Select without End Select
- Calling a Sub or Function that does not exist
- Calling a Sub or Function with the wrong parameters
- Giving a Sub or Function the same name as a module
- Variables not declared(Option Explicit must be present at the top of the module)
The following screenshot shows a compilation error that occurs when a For loop has no matching Next statement.
Using Debug->Compile
To find compilation errors, we use Debug->Compile VBA Project from the Visual Basic menu.
When you select Debug->Compile, VBA displays the first error it comes across.
When this error is fixed, you can run Compile again and VBA will then find the next error.
Debug->Compile will also include syntax errors in it’s search which is very useful.
If there are no errors left and you run Debug->Compile , it may appear that nothing happened. However, “Compile” will be grayed out in the Debug menu. This means your application has no compilation errors at the current time.
Debug->Compile Error Summary
- Debug->Compile finds compilation(project wide) errors.
- It will also find syntax errors.
- It finds one error each time you use it.
- When there are no compilation errors left the Compile option will appear grayed out in the menu.
Debug->Compile Usage
You should always use Debug->Compile before you run your code. This ensures that your code has no compilation errors when you run it.
If you do not run Debug->Compile then VBA may find compile errors when it runs. These should not be confused with Runtime errors.
Runtime Errors
Runtime errors occur when your application is running. They are normally outside of your control but can be caused by errors in your code.
For example, imagine your application reads from an external workbook. If this file gets deleted then VBA will display an error when your code tries to open it.
Other examples of runtime errors are
- a database not being available
- the user entering invalid data
- a cell containing text instead of a number
As we have seen, the purpose of error handling is to deal with runtime errors when they occur.
Expected Versus Unexpected Errors
When we think a runtime error could occur we put code in place to handle it. For example, we would normally put code in place to deal with a file not being found.
The following code checks if the file exists before it tries to open it. If the file does not exist then a user friendly message is displayed and the code exits the sub.
' https://excelmacromastery.com/ Sub OpenFile() Dim sFile As String sFile = "C:docsdata.xlsx" ' Use Dir to check if file exists If Dir(sFile) = "" Then ' if file does not exist display message MsgBox "Could not find the file " & sFile Exit Sub End If ' Code will only reach here if file exists Workbooks.Open sFile End Sub
When we think an error is likely to occur at some point, it is good practice to add code to handle the situation. We normally refer to these errors as expected errors.
If we don’t have specific code to handle an error it is considered an unexpected error. We use the VBA error handling statements to handle the unexpected errors.
Runtime Errors that are not VBA Errors
Before we look at the VBA Handling there is one type of error we must mention. Some runtime errors are not considered errors by VBA but only by the user.
Let me explain this with an example. Imagine you have an application that requires you to add the values in the variables a and b
result = a + b
Let’s say you mistakenly use an asterisk instead of the plus sign
result = a * b
This is not a VBA error. Your code syntax is perfectly legal. However, from your requirements point of view it is an error.
These errors cannot be dealt with using error handling as they obviously won’t generate any error. You can deal with these errors using Unit Testing and Assertions. I have an in-depth post about using VBA assertions – see How to Make Your Code BulletProof.
The On Error Statement
As we have seen there are two ways to treat runtime errors
- Expected errors – write specific code to handle them.
- Unexpected errors – use VBA error handling statements to handle them.
The VBA On Error statement is used for error handling. This statement performs some action when an error occurs during runtime.
There are four different ways to use this statement
- On Error GoTo 0 – the code stops at the line with the error and displays a message.
- On Error Resume Next – the code moves to next line. No error message is displayed.
- On Error GoTo [label] – the code moves to a specific line or label. No error message is displayed. This is the one we use for error handling.
- On Error GoTo -1 – clears the current error.
Let’s look at each of these statements in turn.
On Error GoTo 0
This is the default behavior of VBA. In other words, if you don’t use On Error then this is the behavior you will see.
When an error occurs, VBA stops on the line with the error and displays the error message. The application requires user intervention with the code before it can continue. This could be fixing the error or restarting the application. In this scenario no error handling takes place.
Let’s look at an example. In the following code, we have not used any On Error line so VBA will use the On Error GoTo 0 behavior by default.
' https://excelmacromastery.com/ Sub UsingDefault() Dim x As Long, y As Long x = 6 y = 6 / 0 x = 7 End Sub
The second assignment line results in a divide by zero error. When we run this code we will get the error message shown in the screenshot below
When the error appears you can choose End or Debug
If you select End then the application simply stops.
If you select Debug the application stops on the error line as the screenshot below shows
This behaviour is fine when you are writing VBA code as it shows you the exact line with the error.
This behavior is unsuitable for an application that you are given to a user. These errors look unprofessional and they make the application look unstable.
An error like this is essentially the application crashing. The user cannot continue on without restarting the application. They may not use it at all until you fix the error for them.
By using On Error GoTo [label] we can give the user a more controlled error message. It also prevents the application stopping. We can get the application to perform in a predefined manner.
On Error Resume Next
Using On Error Resume Next tells VBA to ignore the error and continue on.
There are specific occasions when this is useful. Most of the time you should avoid using it.
If we add Resume Next to our example Sub then VBA will ignore the divide by zero error
' https://excelmacromastery.com/ Sub UsingResumeNext() On Error Resume Next Dim x As Long, y As Long x = 6 y = 6 / 0 x = 7 End Sub
It is not a good idea to do this. If you ignore the error, then the behavior can be unpredictable. The error can affect the application in multiple ways.You could end up with invalid data. The problem is that you aren’t aware that something went wrong because you have suppressed the error.
The code below is an example of where using Resume Next is valid
' https://excelmacromastery.com/ Sub SendMail() On Error Resume Next ' Requires Reference: ' Microsoft Outlook 15.0 Object Library Dim Outlook As Outlook.Application Set Outlook = New Outlook.Application If Outlook Is Nothing Then MsgBox "Cannot create Microsoft Outlook session." _ & " The email will not be sent." Exit Sub End If End Sub
In this code we are checking to see if Microsoft Outlook is available on a computer. All we want to know is if it is available or not. We are not interested in the specific error.
In the code above, we continue on if there is an error. Then in the next line we check the value of the Outlook variable. If there has been an error then the value of this variable will be set to Nothing.
This is an example of when Resume could be useful. The point is that even though we use Resume we are still checking for the error. The vast majority of the time you will not need to use Resume.
On Error GoTo [label]
This is how we use Error Handling in VBA. It is the equivalent of the Try and Catch functionality you see in languages such as C# and Java.
When an error occurs you send the error to a specific label. It is normally at the bottom of the sub.
Let’s apply this to the sub we have been using
' https://excelmacromastery.com/ Sub UsingGotoLine() On Error GoTo eh Dim x As Long, y As Long x = 6 y = 6 / 0 x = 7 Done: Exit Sub eh: MsgBox "The following error occurred: " & Err.Description End Sub
The screenshot below shows what happens when an error occurs
VBA jumps to the eh label because we specified this in the On Error Goto line.
Note 1: The label we use in the On…GoTo statement, must be in the current Sub/Function. If not you will get a compilation error.
Note 2: When an error occurs when using On Error GoTo [label], the error handling returns to the default behaviour i.e. The code will stop on the line with the error and display the error message. See the next section for more information about this.
On Error GoTo -1
This statement is different than the other three. It is used to clear the current error rather than setting a particular behaviour.
When an error occurs using On Error GoTo [label], the error handling behaviour returns to the default behaviour i.e. “On Error GoTo 0”. That means that if another error occurs the code will stop on the current line.
This behaviour only applies to the current sub. Once we exit the sub, the error will be cleared automatically.
Take a look at the code below. The first error will cause the code to jump to the eh label. The second error will stop on the line with the 1034 error.
' https://excelmacromastery.com/ Sub TwoErrors() On Error Goto eh ' generate "Type mismatch" error Error (13) Done: Exit Sub eh: ' generate "Application-defined" error Error (1034) End Sub
If we add further error handling it will not work as the error trap has not been cleared.
In the code below we have added the line
On Error Goto eh_other
after we catch the first error.
This has no effect as the error has not been cleared. In other words the code will stop on the line with the error and display the message.
' https://excelmacromastery.com/ Sub TwoErrors() On Error Goto eh ' generate "Type mismatch" error Error (13) Done: Exit Sub eh: On Error Goto eh_other ' generate "Application-defined" error Error (1034) Exit Sub eh_other: Debug.Print "eh_other " & Err.Description End Sub
To clear the error we use On Error GoTo -1. Think of it like setting a mouse trap. When the trap goes off you need to set it again.
In the code below we add this line and the second error will now cause the code to jump to the eh_other label
' https://excelmacromastery.com/ Sub TwoErrors() On Error Goto eh ' generate "Type mismatch" error Error (13) Done: Exit Sub eh: ' clear error On Error Goto -1 On Error Goto eh_other ' generate "Application-defined" error Error (1034) Exit Sub eh_other: Debug.Print "eh_other " & Err.Description End Sub
Note 1: There are probably rare cases where using On Error GoTo -1 is useful. In most cases using Resume Next is better as it clears the error and resumes the code at the next line after the error occurs.
Note 2: The Err Object has a member Clear. Using Clear clears the text and numbers in the Err object, but it does NOT reset the error.
Using On Error
As we have seen, VBA will do one of three things when an error occurs
- Stop and display the error.
- Ignore the error and continue on.
- Jump to a specific line.
VBA will always be set to one of these behaviors. When you use On Error, VBA will change to the behaviour you specify and forget about any previous behavior.
In the following Sub, VBA changes the error behaviour each time we use the On Error statement
' https://excelmacromastery.com/ Sub ErrorStates() Dim x As Long ' Go to eh label if error On Error Goto eh ' this will ignore the error on the following line On Error Resume Next x = 1 / 0 ' this will display an error message on the following line On Error Goto 0 x = 1 / 0 Done: Exit Sub eh: Debug.Print Err.Description End Sub
Resume Next
The Resume Next statement is used to clear the error and then resume the code from the line after where the error occurred.
If your code can have multiple errors and you want to keep detecting them then this line is very useful.
For example, in the following code we want to resume the code after the error has been reported:
Private Sub Main() On Error Goto eh Dim i As Long For i = 1 To 3 ' Generate type mismatch error Error 13 Next i done: Exit Sub eh: Debug.Print i, Err.Description End Sub
We could use On Error Goto -1 to clear the code and then use a goto statement to go back to the code like this:
Private Sub Main() On Error Goto eh Dim i As Long For i = 1 To 3 ' Generate type mismatch error Error 13 continue: Next i done: Exit Sub eh: Debug.Print i, Err.Description On Error Goto -1 ' clear the error Goto continue ' return to the code End Sub
The Resume Next provides a nicer way of doing it and it always means the code is much clearer and easier to understand:
Private Sub Main() On Error Goto eh Dim i As Long For i = 1 To 3 ' Generate type mismatch error Error 13 continue: Next i done: Exit Sub eh: Debug.Print i, Err.Description ' clear the error and return to the code Resume Next End Sub
The Err Object
When an error occurs you can view details of the error using the Err object.
When an runtime error occurs, VBA automatically fills the Err object with details.
The code below will print “Error Number: 13 Type Mismatch” which occurs when we try to place a string value in the long integer total
' https://excelmacromastery.com/ Sub UsingErr() On Error Goto eh Dim total As Long total = "aa" Done: Exit Sub eh: Debug.Print "Error number: " & Err.Number _ & " " & Err.Description End Sub
The Err.Description provides details of the error that occurs. This is the text you normally see when an error occurs e.g. “Type Mismatch”
The Err.Number is the ID number of the error e.g. the error number for “Type Mismatch” is 13. The only time you really need this is if you are checking that a specific error occurred and this is only necessary on rare occasions.
The Err.Source property seems like a great idea but it does not work for a VBA error. The source will return the project name, which hardly narrows down where the error occurred. However, if you create an error using Err.Raise you can set the source yourself and this can be very useful.
Getting the Line Number
The Erl function is used to return the line number where the error occurs.
It often causes confusion. In the following code, Erl will return zero
' https://excelmacromastery.com/ Sub UsingErr() On Error Goto eh Dim val As Long val = "aa" Done: Exit Sub eh: Debug.Print Erl End Sub
This is because there are no line numbers present. Most people don’t realise it but VBA allows you to have line numbers.
If we change the Sub above to have line number it will now print out 20
' https://excelmacromastery.com/ Sub UsingErr() 10 On Error Goto eh Dim val As Long 20 val = "aa" Done: 30 Exit Sub eh: 40 Debug.Print Erl End Sub
Adding line numbers to your code manually is cumbersome. However there are tools available that will allow you to easily add and remove line numbers to a sub.
When you are finished working on a project and hand it over to the user it can be useful to add line numbers at this point. If you use the error handling strategy in the last section of this post, then VBA will report the line where the error occurred.
Using Err.Raise
Err.Raise allows us to create errors. We can use it to create custom errors for our application which is very useful. It is the equivalent of the Throw statement in JavaC#.
The format is as follows
Err.Raise [error number], [error source], [error description]
Let’s look at a simple example. Imagine we want to ensure that a cell has an entry that has a length of 5 characters. We could have a specific message for this
' https://excelmacromastery.com/ Public Const ERROR_INVALID_DATA As Long = vbObjectError + 513 Sub ReadWorksheet() On Error Goto eh If Len(Sheet1.Range("A1")) <> 5 Then Err.Raise ERROR_INVALID_DATA, "ReadWorksheet" _ , "The value in the cell A1 must have exactly 5 characters." End If ' continue on if cell has valid data Dim id As String id = Sheet1.Range("A1") Done: Exit Sub eh: ' Err.Raise will send code to here MsgBox "Error found: " & Err.Description End Sub
When we create an error using Err.Raise we need to give it a number. We can use any number from 513 to 65535 for our error. We must use vbObjectError with the number e.g.
Err.Raise vbObjectError + 513
Using Err.Clear
Err.Clear is used to clear the text and numbers from the Err.Object. In other words, it clears the description and number.If you want the clear the actual error you can use either On Error GoTo -1 or Resume Next
It is rare that you will need to use Err.Clear but let’s have a look at an example where you might.
In the code below we are counting the number of errors that will occur. To keep it simple we are generating an error for each odd number.
We check the error number each time we go through the loop. If the number does not equal zero then an error has occurred. Once we count the error we need to set the error number back to zero so it is ready to check for the next error.
' https://excelmacromastery.com/ Sub UsingErrClear() Dim count As Long, i As Long ' Continue if error as we will check the error number On Error Resume Next For i = 0 To 9 ' generate error for every second one If i Mod 2 = 0 Then Error (13) ' Check for error If Err.Number <> 0 Then count = count + 1 Err.Clear ' Clear Err once it is counted End If Next Debug.Print "The number of errors was: " & count End Sub
Note 1: Err.Clear resets the text and numbers in the error object but it does not clear the error – see Resume Next Or On Error GoTo -1 for more information about clearing the actual error.
Logging
Logging means writing information from your application when it is running. When an error occurs you can write the details to a text file so you have a record of the error.
The code below shows a very simple logging procedure
' https://excelmacromastery.com/ Sub Logger(sType As String, sSource As String, sDetails As String) Dim sFilename As String sFilename = "C:templogging.txt" ' Archive file at certain size If FileLen(sFilename) > 20000 Then FileCopy sFilename _ , Replace(sFilename, ".txt", Format(Now, "ddmmyyyy hhmmss.txt")) Kill sFilename End If ' Open the file to write Dim filenumber As Variant filenumber = FreeFile Open sFilename For Append As #filenumber Print #filenumber, CStr(Now) & "," & sType & "," & sSource _ & "," & sDetails & "," & Application.UserName Close #filenumber End Sub
You can use it like this
' Create unique error number ' https://excelmacromastery.com/ Public Const ERROR_DATA_MISSING As Long = vbObjectError + 514 Sub CreateReport() On Error Goto eh If Sheet1.Range("A1") = "" Then Err.Raise ERROR_DATA_MISSING, "CreateReport", "Data is missing from Cell A1" End If ' other code here Done: Exit Sub eh: Logger "Error", Err.Source, Err.Description End Sub
The log is not only for recording errors. You can record other information as the application runs. When an error occurs you can then check the sequence of events before an error occurred.
Below is an example of logging. How you implement logging really depends on the nature of the application and how useful it will be:
' https://excelmacromastery.com/ Sub ReadingData() Logger "Information", "ReadingData()", "Starting to read data." Dim coll As New Collection ' add data to the collection coll.Add "Apple" coll.Add "Pear" If coll.Count < 3 Then Logger "Warning", "ReadingData()", "Number of data items is low." End If Logger "Information", "ReadingData()", "Number of data items is " & coll.Count Logger "Information", "ReadingData()", "Finished reading data." End Sub
Having a lot of information when dealing with an error can be very useful. Often the user may not give you accurate information about the error that occurred. By looking at the log you can get more accurate information about the information.
This section covers some of the other Error Handling tools that VBA has. These items are considered obsolete but I have included them as they may exist in legacy code.
Error Function
The Error Function is used to print the error description from a given error number. It is included in VBA for backward compatibility and is not needed because you can use the Err.Description instead.
Below are some examples:
' Print the text "Division by zero" Debug.Print Error(11) ' Print the text "Type mismatch" Debug.Print Error(13) ' Print the text "File not found" Debug.Print Error(53)
Error Statement
The Error statement allows you to simulate an error. It is included in VBA for backward compatibility. You should use Err.Raise instead.
In the following code we simulate a “Divide by zero” error.
' https://excelmacromastery.com/ Sub SimDivError() On Error Goto eh ' This will create a division by zero error Error 11 Exit Sub eh: Debug.Print Err.Number, Err.Description End Sub
This statement is included in VBA for backward compatibility. You should use Err.Raise instead.
A Simple Error Handling Strategy
With all the different options you may be confused about how to use error handling in VBA. In this section, I’m going to show you how to implement a simple error handling strategy that you can use in all your applications.
The Basic Implementation
This is a simple overview of our strategy
- Place the On Error GoTo Label line at the start of our topmost sub.
- Place the error handling Label at the end of our topmost sub.
- If an expected error occurs then handle it and continue.
- If the application cannot continue then use Err.Raise to jump to the error handling label.
- If an unexpected error occurs the code will automatically jump to the error handling label.
The following image shows an overview of how this looks
The following code shows a simple implementation of this strategy:
' https://excelmacromastery.com/ Public Const ERROR_NO_ACCOUNTS As Long = vbObjectError + 514 Sub BuildReport() On Error Goto eh ' If error in ReadAccounts then jump to error ReadAccounts ' Do something with the code Done: Exit Sub eh: ' All errors will jump to here MsgBox Err.Source & ": The following error occured " & Err.Description End Sub Sub ReadAccounts() ' EXPECTED ERROR - Can be handled by the code ' Application can handle A1 being zero If Sheet1.Range("A1") = 0 Then Sheet1.Range("A1") = 1 End If ' EXPECTED ERROR - cannot be handled by the code ' Application cannot continue if no accounts workbook If Dir("C:DocsAccount.xlsx") = "" Then Err.Raise ERROR_NO_ACCOUNTS, "UsingErr" _ , "There are no accounts present for this month." End If ' UNEXPECTED ERROR - cannot be handled by the code ' If cell B3 contains text we will get a type mismatch error Dim total As Long total = Sheet1.Range("B3") ' continue on and read accounts End Sub
This is a nice way of implementing error handling because
- We don’t need to add error handling code to every sub.
- If an error occurs then VBA exits the application gracefully.
A Complete Error Handling Strategy
The above strategy has one major drawback. It doesn’t provide any information about the error. It is better than having no strategy as it prevents the application crashing. But that is the only real benefit.
VBA doesn’t fill Err.Source with anything useful so we have to do this ourselves.
In this section, I am going to introduce a more complete error strategy. I have written two subs that perform all the heavy lifting so all you have to do is add them to your project.
The purpose of this strategy is to provide you with the Stack* and line number when an error exists.
*The Stack is the list of sub/functions that were currently in use when the error occurred.
This is our strategy
- Place error handling in all the subs.
- When an error occurs, the error handler adds details to the error and raises it again.
- When the error reaches the topmost sub it is displayed.
We are simply “bubbling” the error to the top. The following diagram shows a simple visual of what happens when an error occurs in Sub3
The only messy part to this is formatting the strings correctly. I have written two subs that handle this, so it is taken care of for you.
There are the two helper subs, RaiseError and DisplayError. You can download the library below:
An Example of using this strategy
Here is a simple coding example that uses these subs. In this strategy, we don’t place any code in the topmost sub. We only call subs from it.
' https://excelmacromastery.com/ Sub Topmost() On Error Goto EH Level1 Done: Exit Sub EH: DisplayError Err.source, Err.Description, "Module1.Topmost", Erl End Sub Sub Level1() On Error Goto EH Level2 Done: Exit Sub EH: RaiseError Err.Number, Err.source, "Module1.Level1", Err.Description, Erl End Sub Sub Level2() On Error Goto EH ' Error here Dim a As Long a = "7 / 0" Done: Exit Sub EH: RaiseError Err.Number, Err.source, "Module1.Level2", Err.Description, Erl End Sub
The result looks like this:
If your project has line numbers the result will include the line number of the error:
Error Handling in a Nutshell
- Error Handling is used to handle errors that occur when your application is running.
- You write specific code to handle expected errors. You use the VBA error handling statement On Error GoTo [label] to send VBA to a label when an unexpected error occurs.
- You can get details of the error from Err.Description.
- You can create your own error using Err.Raise.
- Using one On Error statement in the top most sub will catch all errors in subs that are called from here.
- If you want to record the name of the Sub with the error, you can update the error and rethrow it.
- You can use a log to record information about the application as it is running.
What’s Next?
Free VBA Tutorial If you are new to VBA or you want to sharpen your existing VBA skills then why not try out the The Ultimate VBA Tutorial.
Related Training: Get full access to the Excel VBA training webinars and all the tutorials.
(NOTE: Planning to build or manage a VBA Application? Learn how to build 10 Excel VBA applications from scratch.)


















































