Симптомы
При открытии файла или попробуйте использовать макросы в Microsoft Office 2013 2 нажмите кнопку Run (C2R) возможно возникновение следующих проблем.
Microsoft Access
Постоянно мигает, окно установщика Windows.
При использовании мастера Access появляется следующее сообщение об ошибке:
«Это средство не установлено или была отключена»
При открытии редактора Visual Basic (VBE) появляется следующее сообщение об ошибке:
«Microsoft Access не удалось загрузить Visual Basic для приложений библиотеки динамической компоновки (dll) Vbe7»
Microsoft Word
После нажатия кнопки макросы, , вы получаете следующее сообщение об ошибке:
«Функция, которую вы пытаетесь запустить, содержит макросы или содержимое требует поддержки языка создания макросов»
Microsoft Excel
При открытии существующих книг, можно получить следующее сообщение об ошибке:
«Visual Basic для приложений (VBA) макросов в данной книге повреждены и были удалены.» Открытие существующей книги
Параметры Visual Basic, макросыи Записи макросов отключены в группе разработчиков и просмотр ленты.
Microsoft PowerPoint
Параметры Visual Basic и макросы отключаются на ленте.
При открытии презентаций с VBA-кодом возникает следующая ошибка:
«Документ содержит макросы. Для этого приложения поддержка макроязыка отключена. Компоненты, которым требуется VBA не доступны. Вы хотите открыть этот документ только для чтения?»
Причина
Очистители реестра сторонних разработчиков и обслуживание приложений системы удалены несколько разделов реестра, используемых для выполнения функций VBA в приложениях Microsoft Office 2013.
Решение
Запустите интерактивный ремонт пакета Office. Вот как:
-
Нажмите кнопку Пуск>Панель управления>программы и компоненты.
-
Выберите приложение Microsoft Office и нажмите кнопку Изменить.
-
Выберите Восстановление по сети и затем нажмите кнопку Восстановить.
После завершения восстановления сети следует использовать приложения Office 2013.
-
На начальном экране введите в поле поиска Панели управления и затем коснитесь или щелкните приложения.
-
Нажмите кнопку или выберите Панель управления > программы > программы и компоненты.
-
Выберите программу Microsoft Office и нажмите кнопку Изменить.
-
Выберите Восстановление по сети и затем нажмите кнопку Восстановить.
После завершения восстановления сети следует использовать приложения Office 2013.
Дополнительные сведения
Во избежание повторения обратитесь к поставщик очистки реестра или обслуживания системы приложений.
Нужна дополнительная помощь?
Нужны дополнительные параметры?
Изучите преимущества подписки, просмотрите учебные курсы, узнайте, как защитить свое устройство и т. д.
В сообществах можно задавать вопросы и отвечать на них, отправлять отзывы и консультироваться с экспертами разных профилей.
Symptoms
When you open a file or try to use macros in Microsoft Office 2013 Click 2 Run (C2R), you may experience one of the following symptoms.
Microsoft Access
Windows Installer window continuously flashes.
When you use Access wizards you get the following error:
«This feature isn’t installed, or has been disabled»
When you open the Visual Basic Editor (VBE) you get the following error:
«Microsoft Access is unable to load the Visual Basic for Applications dynamic-link library (dll) Vbe7»
Microsoft Word
After you click Macros, you get the following error:
«The function you are attempting to run contains macros or content that requires macro language support»
Microsoft Excel
When you open existing workbooks, you get the following error:
«The Visual Basic for Applications (VBA) macros in this workbook are corrupted and have been deleted.» opening existing workbooks
The Visual Basic, Macros, and Record Macro options are disabled under the Developer and View ribbon.
Microsoft PowerPoint
The Visual Basic and Macros options are disabled on the ribbon.
When you open presentations with VBA code you get the following error:
«The document contains macros. Macro language support for this application is disabled. Features requiring VBA are not available. Would you like to open this document read-only?»
Cause
Non-Microsoft registry cleaners and system maintenance applications deleted multiple registry key values that are used for VBA functionality in Microsoft Office 2013 applications.
Resolution
Run an Online Repair of Office. Here’s how:
-
Click Start>Control Panel>Programs and Features.
-
Click your Microsoft Office program, and then click Change.
-
Select Online Repair, and then click Repair.
After Online Repair is complete, you should be able to use your Office 2013 applications.
-
From the Start screen, type Control Panel in the Search box, and then tap or click Apps.
-
Tap or click Control Panel > Programs > Programs and Features.
-
Select your Microsoft Office program, and then click Change.
-
Select Online Repair, and then click Repair.
After Online Repair is complete, you should be able to use your Office 2013 applications.
More Information
To prevent recurrences, contact the provider of the registry cleaner or system-maintenance application.
Need more help?
Want more options?
Explore subscription benefits, browse training courses, learn how to secure your device, and more.
Communities help you ask and answer questions, give feedback, and hear from experts with rich knowledge.
Майкрософт Эксель — одна из самых популярных электронных таблиц, используемых во всем мире как для личных, так и для деловых целей. Это универсальное место для хранения, организации и обработки данных организованным способом. MS Excel поставляется в основном с двумя расширениями, то есть в формате XLS и XLSX. Однако, помимо невероятной популярности, ошибки во время выполнения — обычная неприятность для очень многих пользователей Windows, и одной из самых распространенных является ошибка. Ошибка выполнения 1004.
В этом руководстве мы собираемся обсудить эту распространенную ошибку времени выполнения 1004 и некоторые из лучших исправлений для ее легкого решения.
Что такое ошибка времени выполнения 1004 в Excel?
Ошибка выполнения 1004 — это код ошибки, относящийся к Microsoft Visual Basic, который, как известно, беспокоит пользователей Microsoft Excel. С этой ошибкой сталкиваются любые версии MS Excel, такие как Excel 2007, 2010, 2013, 2016, 2019. Ни одна версия Microsoft Excel не застрахована от угрозы Runtime Error 1004.
С этой ошибкой в основном сталкиваются пользователи, когда они работают с файлом Excel или пытаются создать макрос в документе Excel. Это может вызвать серьезные проблемы при работе с приложениями Visual Basic и привести к полному сбою программы или даже всей системы; иногда это может привести к зависанию системы, запрещая пользователям что-либо делать в своей системе.
Типы сообщений об ошибках
Сообщения об ошибках, которые больше всего связаны с этой ошибкой времени выполнения, следующие:
- VB: ошибка времени выполнения ‘1004’: ошибка приложения или объекта
- Ошибка выполнения Excel VBA 1004 «Ошибка выбора метода класса Range»
- ошибка времени выполнения 1004 диапазон метода объекта _global не удалось Visual Basic
- Макрос Excel «Ошибка выполнения» 1004?
- Ошибка выполнения 1004 не удалось открыть метод объектных книг
- Ошибка времени выполнения «1004»: сбой метода «Рейнджер» объекта «Рабочий лист»
- «Сбой метода в ПРИЛОЖЕНИИ ПРИЛОЖЕНИЯ ОБЪЕКТНОЙ программы».
Если вы столкнулись с какой-либо из этих ошибок, вы можете исправить ее с помощью нашего руководства.
Каковы причины?
Ошибка 1004 — это общий код, связанный с MS Excel, но не связанный с одной точной причиной. Следовательно, в этом случае точная причина, по которой может появиться эта ошибка, будет варьироваться от случая к случаю и от обстоятельств к обстоятельствам. От проблем с конфигурацией до проблем с программным обеспечением, ниже мы перечислили краткий обзор распространенных причин ошибки времени выполнения 1004 в Excel:
- Значок рабочего стола MS Excel может быть поврежден
- Файл VBA Excel конфликтует с другим приложением
- Из-за ошибки, указанной в приложении или объекте
- Из-за отсутствия зависимого файла
- Из-за вируса, трояна или вредоносного ПО
- Из-за неверных ключей реестра и так далее.
Это были некоторые из наиболее частых причин получения ошибки времени выполнения 1004 в MS Excel; Теперь давайте разберемся с различными исправлениями.
Здесь мы подробно описали как ручные, так и автоматические решения для исправления ошибки выполнения 1004. Вы можете использовать любой из следующих методов, чтобы решить проблему.
- Создать новый шаблон Excel
- Запустите сканирование на вирусы
- Для VB: ошибка времени выполнения ‘1004’, измените размер записей легенды
Давайте подробно рассмотрим каждый из этих методов.
1]Создайте новый шаблон Excel
В некоторых случаях для устранения этой проблемы достаточно просто вставить новый лист из шаблона вместо создания копии существующего листа. Вот что вам нужно сделать:
1]Откройте MS Excel в вашей системе
2]Нажмите ‘CTRL + N‘для создания нового листа Microsoft Excel или просто выберите’Пустая книга‘с первого экрана.
3]После этого удалите все листы в книге, кроме одного.
4]Теперь отформатируйте оставшуюся книгу. Также обратите внимание, что эту книгу можно изменить в соответствии с вашими индивидуальными потребностями.
5]В конце перейдите к ‘Файл> Сохранить как‘, чтобы сохранить новый рабочий лист в формате файла шаблона Excel (.xltx или .xlt).
6]После успешного создания шаблона вы можете вставить его программно, используя следующую строку кода:
Таблицы.Добавить Тип: = путь имя файла
Пожалуйста, обрати внимание — Не забудьте заменить новое имя файла на настоящее имя документа.
2]Запустите сканирование на вирусы
Очень важно сканировать компьютерную систему на наличие вредоносных программ и вирусов, поскольку они могут повредить файлы и важные документы и показать ошибку времени выполнения 1004 в MS Excel. Иногда очень помогает хорошая антивирусная программа.
3]Для VB: ошибка времени выполнения «1004», измените размер записей легенды.
Если вы столкнулись с ошибкой времени выполнения 1004 при запуске макроса Microsoft Visual Basic для приложений (VBA), вы можете использовать этот метод для временного решения.
Обычно эта ошибка возникает при попытке запустить макрос VBA, который использует метод LegendEntries для внесения изменений в записи легенды на диаграмме Microsoft Excel. На этот раз вы можете получить следующее сообщение об ошибке:
Ошибка времени выполнения ‘1004’: ошибка приложения или объекта
Эта ошибка возникает, когда диаграмма Excel содержит больше записей легенды, чем имеется место для отображения записей легенды на диаграмме Excel. В этом случае Microsoft Excel может усекать записи легенды.
Чтобы обойти это поведение, создайте макрос, который уменьшает размер шрифта текста легенды диаграммы Excel до того, как макрос VBA внесет изменения в легенду диаграммы, а затем восстановите размер шрифта легенды диаграммы, чтобы он был похож на следующий пример макроса. .
Sub ResizeLegendEntries() With Worksheets("Sheet1").ChartObjects(1).Activate ' Store the current font size fntSZ = ActiveChart.Legend.Font.Size 'Temporarily change the font size. ActiveChart.Legend.Font.Size = 2 'Place your LegendEntries macro code here to make 'the changes that you want to the chart legend. ' Restore the font size. ActiveChart.Legend.Font.Size = fntSZ End With End Sub
Мы надеемся, что эта статья поможет вам исправить ошибку времени выполнения 1004 в Microsoft Excel. Это руководство дает вам как ручное, так и автоматическое решение, чтобы избавиться от этой ошибки; вы можете использовать любое решение в зависимости от ваших потребностей.
Читать дальше: Клавиши со стрелками не работают в Microsoft Excel.
Не так давно очередной раз столкнулся с ошибками приложения Excel при попытке включения макросов после открытия файлов .xlsm. Вспомнил, что подобные проблемы преследуют пользователей довольно давно, но чаще всего они наблюдались с Excel 2013 и Excel 2016. Характерные особенности этой группы ошибок следующие:
- Приложение Excel закрывается при открытии файла с макросами (при включенном режиме безопасности Включить все макросы);
- Ошибка приложения Excel возникает при попытке включить содержимое (нажатии соответствующей кнопки);
- Ошибка приложения Excel возникает при сохранении файла с макросами;
Ну и по горячим следам очередного инцидента, дабы не откладывать на потом, решил для себя собрать небольшой хаб по ошибкам приложения Excel с последующей модификацией, дабы опять не терять время на поиск информации в Сети и на составление облака причин.
Суть в том, что в процессе открытия файла xlsm, и при отключенных макросах, в верхней части основного окна (над таблицей), высвечивается строка уведомления: ПРЕДУПРЕЖДЕНИЕ СИСТЕМЫ БЕЗОПАСНОСТИ Запуск макросов отключен, с кнопкой включения содержимого (макросов). Как только пользователь её нажимает, Excel попросту аварийно завершается (падает) с ошибкой Программа Microsoft Excel не работает и характерным окном уведомления:
При этом было замечено, что непосредственно перед возникновением ошибки приложения Excel никаких системных обновлений и обновлений пакета Office не устанавливалось. Возможно, каким-то образом задействованы последние обновления на Office, но прямой связи я не заметил, а подробного исследования проблемы не проводил. При этом зависимости от версии операционной системы (мною лично сбои наблюдались на Windows 10 LTSC и Windows 7 Professional) так же выявлено не было. При анализе аварийного дампа приложения (*.hdmp) обычно можно увидеть подобную информацию исключения (вывод урезан):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
. . . EXCEPTION_RECORD: (.exr —1) ExceptionAddress: 00007ff86a1e05ac (VBE7+0x00000000001405ac) ExceptionCode: c0000005 (Access violation) ExceptionFlags: 00000000 NumberParameters: 2 Parameter[0]: 0000000000000001 Parameter[1]: 0000000000000010 Attempt to write to address 0000000000000010 DEFAULT_BUCKET_ID: NULL_CLASS_PTR_WRITE PROCESS_NAME: EXCEL.EXE ERROR_CODE: (NTSTATUS) 0xc0000005 — <Unable to get error code text> EXCEPTION_CODE: (NTSTATUS) 0xc0000005 — <Unable to get error code text> EXCEPTION_CODE_STR: c0000005 EXCEPTION_PARAMETER1: 0000000000000001 EXCEPTION_PARAMETER2: 0000000000000010 WRITE_ADDRESS: 0000000000000010 . . . |
обычно это NTSTATUS с кодом c0000005 — Access violation, доступ запрещен. И чаще всего в дампе можно увидеть такой вот стек потока (вывод оптимизирован для улучшения представления):
. . . STACK_TEXT: 000000b9`1acfdd00 000001d3`2fb24e90 : 000001d3`5a0e0ef0 00000000`00000000 : VBE7+0x1405ac 000000b9`1acfdd08 000001d3`24c1fe20 : 00000000`00000000 000001d3`2fda9640 : 0x000001d3`2fb24e90 000000b9`1acfdd10 000001d3`6cf35760 : 000001d3`2fda9640 000001d3`045c9b30 : 0x000001d3`24c1fe20 000000b9`1acfdd18 000001d3`5a0e0ef0 : 000001d3`045c9b30 000001d3`2fcbb2b0 : 0x000001d3`6cf35760 000000b9`1acfdd20 00000000`00000000 : 000001d3`2fcbb2b0 000001d3`2fcbb318 : 0x000001d3`5a0e0ef0 . . . |
из которого единственное что понятно, так это то, что падение Excel происходит в недрах функций библиотеки vbe7.dll (среда исполнения VBA), подгруженной в адресное пространство процесса. Это указывает на проблемы с обработчиком VBA-скриптов, в контексте Excel чаще именуемых макросами.
НЕРЕШЕННОЕ: при отладке приложений из комплекта MS Office, вы не увидите имен функций в стеке вызовов, поскольку отсутствуют отладочные символы как к основным исполняемым файлам (Excel/Word/Outlook), так и к многочисленным библиотекам. Интересно, есть ли какое-либо решение?
VBA
Так что же такое VBA и для чего он предназначается?
VBA (Visual Basic for Application) — язык макропрограммирования, основанный на языке Visual Basic.
В приложениях, входящих в комплект MS Office, таких как Excel, Word, PowerPoint и Access, VBA используется для автоматизации множества рутинных задач (напр.: повторяющихся однотипных действий), позволяет создавать формы для общения с пользователем и предлагает множество иного богатого функционала. При помощи VBA доступно управление электронной таблицей посредством объектно-ориентированной модели кода/данных, при помощи VBA-кода входные данные таблиц могут быть обработаны и представлены в итоговых (результирующих) таблицах и диаграммах (графиках). Таблица становится интерфейсом кода, позволяя легко работать, изменять его и управлять расчётами. На выходе VBA проект, используемый в структурах описанных выше приложений (электронные таблицы Excel, презентации PowerPoint, базы Access), компилируется в специальный бинарный исполняемый файл, который размещается внутри файла основного формата. Применительно к Excel это файл vbaProject.bin, который располагается внутри *.xslm-файла в директории /xl, представляющий собой бинарный исполняемый файл проекта, содержащий макрос в откомпилированном (готовом к исполнению) виде.
Наиболее вероятной причиной сбоя является повреждение блока кода VBA, содержащегося в книге Excel. Об истоках этого остается только догадываться, возможно что в структуре .xlsm-файла, в процессе работы с документом, происходят какие-то [непредвиденные разработчиками] изменения, способные приводить блок кода в неработоспособное состояние.
Решение 1: вставка нового листа
Выполните приведенную последовательность действий:
- Открываем [проблемный] .xlsm-файл (файл с макросами).
- Не нажимаем кнопку Включить содержимое.
- Добавляем в книгу Excel новый лист: правая кнопка мыши на ярлыках Лист1/Лист2/Лист3 → Вставить → Лист.
- Сохраняем электронную таблицу. Закрываем Excel.
- Открываем проблемный файл заново и включаем макросы.
Решение 2: перекомпиляция проекта
Выполните последовательность действий:
- Запускаем и открываем новую книгу Excel (не ваш проблемный файл).
- Открываем меню Файл — выбираем Параметры — далее открываем Центр управления безопасностью и заходим в Параметры центра управления безопасностью.
- В разделе Параметры макросов — выставляем чекбокс Отключить все макросы с уведомлением.
- В разделе Надежные расположения — выставляем чекбокс Отключить все надежные расположения.
- В разделе Надежные документы — выставляем чекбокс Отключить надежные документы.
- Жмем везде OK. Закрываем Excel.
- Открываем [проблемный] .xlsm-файл (файл с макросами).
- Не нажимаем кнопку Включить содержимое.
- Открывает редактор Visual Basic при помощи комбинации клавиш Alt+F11. Либо можно использовать обходной маневр: в настройках включаем меню Разработчик, после этого в появившемся сверху в ленте меню Разработчик выбираем пункт Visual Basic.
- В открывшемся окне редактора Visual Basic (VBA редактор) пересохраняем проект: для этого жмем на панели инструментов кнопку Сохранить (изображение дискетки или комбинация Ctrl+S).
- Выбираем из меню Debug — выбираем пункт меню Compile VBA Project:
- Еще раз сохраняем проект кнопкой Сохранить.
- Закрываем редактор Visual Basic.
- Сохраняем файл Excel через меню Файл — опцию Сохранить (или нажатием на значок дискетки в левом верхнем углу, либо комбинация клавиш Ctrl+S).
- Возвращаем все установки безопасности, сделанные на предыдущих шагах (пункты 2-5).
- Закрываем xlsm-файл.
- Заново открываем [проблемный] файл, в верхней части, в строке статуса — включаем макросы посредством кнопки Включить содержимое.
Решение 3: добавление модуля
Дополнительное решение состоит в том, что бы внести изменения в макрос без перекомпиляции.
- Открываем [проблемный] .xlsm-файл (файл с макросами).
- Не нажимаем кнопку Включить содержимое.
- Открывает редактор Visual Basic (при помощи комбинации клавиш Alt+F11).
- Открываем меню Tools → пункт Options. В открывшемся окне переходим на вкладку General и деактивируем чекбокс Compile on Demand:
Закрываем окно Опции нажатием клавиши OK.
- В левом фрейме окна проекта (Project) спускаемся вниз, находим раздел Modules, жмем на нём правую кнопку → пункт Insert → Module:
- Далее просто закрываем окно редактора Visual Basic, сохраняем основной xslm-документ и закрываем Excel.
- Заново открываем [проблемный] файл, в верхней части, в строке статуса — включаем макросы посредством кнопки Включить содержимое.
На чтение 25 мин. Просмотров 16.4k.
Эта статья содержит полное руководство по обработке ошибок 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 с ошибкой, вы можете обновить ошибку и сбросить ее.
- Вы можете использовать журнал для записи информации о приложении, когда оно запущено.
Download PC Repair Tool to quickly find & fix Windows errors automatically
While using Microsoft Visual Basic for Applications on Excel, if you get Run-time error, Class not registered, here is how you can fix the issue. It is pretty common when there are some issues with the code or Office installation. That is why you can follow these tips and tricks to get rid of this problem.
You can run various codes via Visual Basic on an Excel spreadsheet to get different things done within moments and in automation. However, while running such a code, if you get the aforementioned error, you won’t be able to do what you were looking forward to. If so, you can follow the subsequent solutions to get rid of the error, as mentioned above.
To fix Microsoft Visual Basic Run-time error Class not registered, follow these steps:
- Check the code
- Update Excel/Office
- Turn on trust access to VBA
- Repair Microsoft Office
To learn more about these steps, continue reading.
1] Check the code
It is the very first thing you need to check when you are getting the aforementioned error in Excel. If the entered or written code is wrong, the argument is missing, etc., you won’t be able to run it on your spreadsheet. As a result, you might get the error as said above. That is why it is recommended to verify the code before running it again or heading to other solutions.
Read: How to create Custom Excel Functions using VBA
2] Update Excel/Office
If you haven’t updated Excel or Office for a very long time, it is recommended to do that. At times, Microsoft might change various things, and that could be a reason why you are getting such an error. To update Office, do the following:
- Open Excel on your computer.
- Click on the Account.
- Expand the Update Options.
- Click the Update Now option.
Then, it will search for a pending update and install it accordingly.
3] Turn on Trust access to VBA
When you are getting this error, you must check if this setting is turned on or not. If not, it is suggested to enable it on your computer. To turn on trust access to the VBA project, follow these steps:
- Open Excel and click on Options.
- Switch to the Trust Center tab.
- Click the Trust Center Settings button.
- Go to the Macro Settings tab.
- Tick the Trust access to the VBA project object model checkbox.
- Click the OK button.
Then, restart Excel and check if the problem remains or not.
4] Repair Microsoft Office
It is the last thing you need to do in order to troubleshoot the error. To repair Office on Windows 11/10, do the following:
- Press Win+I to open Windows Settings.
- Go to Apps > Apps & features.
- Click the three-dotted button of Microsoft 365.
- Select the Modify option.
- Click the Yes button in the UAC prompt.
- Choose the Online Repair option.
- Click the Repair button.
Once the process is done, you can restart your computer and check if the problem is resolved or not.
Apart from trying these solutions, you can also run the System File Checker. At times, an internal conflict can cause the above-mentioned error. If so, you can fix it with the help of SFC Scan.
Related:
- How to fix Class not registered error in Explorer.exe
- Class Not Registered error in Outlook
- Class not registered error while opening image
- Class not registered Chrome.exe
How do I fix Runtime error in Excel VBA?
To fix the Run-time error in Excel VBA, you need to follow the above-mentioned solutions. You should start the troubleshooting process by verifying the code. However, if nothing works, you must repair the Office installation. In that case, select the Online Repair option instead of Quick Repair.
Read: How to fix Runtime Error 1004 in Microsoft Excel
How do I bypass VBA error in Excel?
There is no way to bypass the VBA error in Excel if you want to use the code. You must resolve the issue in order to use it without any error. A detailed guide of four solutions as mentioned above, and it is recommended to follow all of them to troubleshoot the VBA error in Excel.
Related: How to fix VBA error 400 in Excel.
When he is not writing about Microsoft Windows or Office, Sudip likes to work with Photoshop. He has managed the front end and back end of many websites over the years. He is currently pursuing his Bachelor’s degree.
Two main purposes for error handling:
- Trap errors you can
predict but can’t control the user
from doing (e.g. saving a file to a
thumb drive when the thumb drives
has been removed) - For unexpected errors, present user with a form
that informs them what the problem
is. That way, they can relay that
message to you and you might be able
to give them a work-around while you
work on a fix.
So, how would you do this?
First of all, create an error form to display when an unexpected error occurs.
It could look something like this (FYI: Mine is called frmErrors):
Notice the following labels:
- lblHeadline
- lblSource
- lblProblem
- lblResponse
Also, the standard command buttons:
- Ignore
- Retry
- Cancel
There’s nothing spectacular in the code for this form:
Option Explicit
Private Sub cmdCancel_Click()
Me.Tag = CMD_CANCEL
Me.Hide
End Sub
Private Sub cmdIgnore_Click()
Me.Tag = CMD_IGNORE
Me.Hide
End Sub
Private Sub cmdRetry_Click()
Me.Tag = CMD_RETRY
Me.Hide
End Sub
Private Sub UserForm_Initialize()
Me.lblErrorTitle.Caption = "Custom Error Title Caption String"
End Sub
Private Sub UserForm_QueryClose(Cancel As Integer, CloseMode As Integer)
'Prevent user from closing with the Close box in the title bar.
If CloseMode <> 1 Then
cmdCancel_Click
End If
End Sub
Basically, you want to know which button the user pressed when the form closes.
Next, create an Error Handler Module that will be used throughout your VBA app:
'****************************************************************
' MODULE: ErrorHandler
'
' PURPOSE: A VBA Error Handling routine to handle
' any unexpected errors
'
' Date: Name: Description:
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
'03/22/2010 Ray Initial Creation
'****************************************************************
Option Explicit
Global Const CMD_RETRY = 0
Global Const CMD_IGNORE = 1
Global Const CMD_CANCEL = 2
Global Const CMD_CONTINUE = 3
Type ErrorType
iErrNum As Long
sHeadline As String
sProblemMsg As String
sResponseMsg As String
sErrorSource As String
sErrorDescription As String
iBtnCap(3) As Integer
iBitmap As Integer
End Type
Global gEStruc As ErrorType
Sub EmptyErrStruc_S(utEStruc As ErrorType)
Dim i As Integer
utEStruc.iErrNum = 0
utEStruc.sHeadline = ""
utEStruc.sProblemMsg = ""
utEStruc.sResponseMsg = ""
utEStruc.sErrorSource = ""
For i = 0 To 2
utEStruc.iBtnCap(i) = -1
Next
utEStruc.iBitmap = 1
End Sub
Function FillErrorStruct_F(EStruc As ErrorType) As Boolean
'Must save error text before starting new error handler
'in case we need it later
EStruc.sProblemMsg = Error(EStruc.iErrNum)
On Error GoTo vbDefaultFill
EStruc.sHeadline = "Error " & Format$(EStruc.iErrNum)
EStruc.sProblemMsg = EStruc.sErrorDescription
EStruc.sErrorSource = EStruc.sErrorSource
EStruc.sResponseMsg = "Contact the Company and tell them you received Error # " & Str$(EStruc.iErrNum) & ". You should write down the program function you were using, the record you were working with, and what you were doing."
Select Case EStruc.iErrNum
'Case Error number here
'not sure what numeric errors user will ecounter, but can be implemented here
'e.g.
'EStruc.sHeadline = "Error 3265"
'EStruc.sResponseMsg = "Contact tech support. Tell them what you were doing in the program."
Case Else
EStruc.sHeadline = "Error " & Format$(EStruc.iErrNum) & ": " & EStruc.sErrorDescription
EStruc.sProblemMsg = EStruc.sErrorDescription
End Select
GoTo FillStrucEnd
vbDefaultFill:
'Error Not on file
EStruc.sHeadline = "Error " & Format$(EStruc.iErrNum) & ": Contact Tech Support"
EStruc.sResponseMsg = "Contact the Company and tell them you received Error # " & Str$(EStruc.iErrNum)
FillStrucEnd:
Exit Function
End Function
Function iErrorHandler_F(utEStruc As ErrorType) As Integer
Static sCaption(3) As String
Dim i As Integer
Dim iMCursor As Integer
Beep
'Setup static array
If Len(sCaption(0)) < 1 Then
sCaption(CMD_IGNORE) = "&Ignore"
sCaption(CMD_RETRY) = "&Retry"
sCaption(CMD_CANCEL) = "&Cancel"
sCaption(CMD_CONTINUE) = "Continue"
End If
Load frmErrors
'Did caller pass error info? If not fill struc with the needed info
If Len(utEStruc.sHeadline) < 1 Then
i = FillErrorStruct_F(utEStruc)
End If
frmErrors!lblHeadline.Caption = utEStruc.sHeadline
frmErrors!lblProblem.Caption = utEStruc.sProblemMsg
frmErrors!lblSource.Caption = utEStruc.sErrorSource
frmErrors!lblResponse.Caption = utEStruc.sResponseMsg
frmErrors.Show
iErrorHandler_F = frmErrors.Tag ' Save user response
Unload frmErrors ' Unload and release form
EmptyErrStruc_S utEStruc ' Release memory
End Function
You may have errors that will be custom only to your application. This would typically be a short list of errors specifically only to your application.
If you don’t already have a constants module, create one that will contain an ENUM of your custom errors. (NOTE: Office ’97 does NOT support ENUMS.). The ENUM should look something like this:
Public Enum CustomErrorName
MaskedFilterNotSupported
InvalidMonthNumber
End Enum
Create a module that will throw your custom errors.
'********************************************************************************************************************************
' MODULE: CustomErrorList
'
' PURPOSE: For trapping custom errors applicable to this application
'
'INSTRUCTIONS: To use this module to create your own custom error:
' 1. Add the Name of the Error to the CustomErrorName Enum
' 2. Add a Case Statement to the raiseCustomError Sub
' 3. Call the raiseCustomError Sub in the routine you may see the custom error
' 4. Make sure the routine you call the raiseCustomError has error handling in it
'
'
' Date: Name: Description:
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
'03/26/2010 Ray Initial Creation
'********************************************************************************************************************************
Option Explicit
Const MICROSOFT_OFFSET = 512 'Microsoft reserves error values between vbObjectError and vbObjectError + 512
'************************************************************************************************
' FUNCTION: raiseCustomError
'
' PURPOSE: Raises a custom error based on the information passed
'
'PARAMETERS: customError - An integer of type CustomErrorName Enum that defines the custom error
' errorSource - The place the error came from
'
' Returns: The ASCII vaule that should be used for the Keypress
'
' Date: Name: Description:
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
'03/26/2010 Ray Initial Creation
'************************************************************************************************
Public Sub raiseCustomError(customError As Integer, Optional errorSource As String = "")
Dim errorLong As Long
Dim errorDescription As String
errorLong = vbObjectError + MICROSOFT_OFFSET + customError
Select Case customError
Case CustomErrorName.MaskedFilterNotSupported
errorDescription = "The mask filter passed is not supported"
Case CustomErrorName.InvalidMonthNumber
errorDescription = "Invalid Month Number Passed"
Case Else
errorDescription = "The custom error raised is unknown."
End Select
Err.Raise errorLong, errorSource, errorDescription
End Sub
You are now well equipped to trap errors in your program. You sub (or function), should look something like this:
Public Sub MySub(monthNumber as Integer)
On Error GoTo eh
Dim sheetWorkSheet As Worksheet
'Run Some code here
'************************************************
'* OPTIONAL BLOCK 1: Look for a specific error
'************************************************
'Temporarily Turn off Error Handling so that you can check for specific error
On Error Resume Next
'Do some code where you might expect an error. Example below:
Const ERR_SHEET_NOT_FOUND = 9 'This error number is actually subscript out of range, but for this example means the worksheet was not found
Set sheetWorkSheet = Sheets("January")
'Now see if the expected error exists
If Err.Number = ERR_SHEET_NOT_FOUND Then
MsgBox "Hey! The January worksheet is missing. You need to recreate it."
Exit Sub
ElseIf Err.Number <> 0 Then
'Uh oh...there was an error we did not expect so just run basic error handling
GoTo eh
End If
'Finished with predictable errors, turn basic error handling back on:
On Error GoTo eh
'**********************************************************************************
'* End of OPTIONAL BLOCK 1
'**********************************************************************************
'**********************************************************************************
'* OPTIONAL BLOCK 2: Raise (a.k.a. "Throw") a Custom Error if applicable
'**********************************************************************************
If not (monthNumber >=1 and monthnumber <=12) then
raiseCustomError CustomErrorName.InvalidMonthNumber, "My Sub"
end if
'**********************************************************************************
'* End of OPTIONAL BLOCK 2
'**********************************************************************************
'Rest of code in your sub
goto sub_exit
eh:
gEStruc.iErrNum = Err.Number
gEStruc.sErrorDescription = Err.Description
gEStruc.sErrorSource = Err.Source
m_rc = iErrorHandler_F(gEStruc)
If m_rc = CMD_RETRY Then
Resume
End If
sub_exit:
'Any final processing you want to do.
'Be careful with what you put here because if it errors out, the error rolls up. This can be difficult to debug; especially if calling routine has no error handling.
Exit Sub 'I was told a long time ago (10+ years) that exit sub was better than end sub...I can't tell you why, so you may not want to put in this line of code. It's habit I can't break :P
End Sub
A copy/paste of the code above may not work right out of the gate, but should definitely give you the gist.
“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.)
When he is not writing about Microsoft Windows or Office, Sudip likes to work with Photoshop. He has managed the front end and back end of many websites over the years. He is currently pursuing his Bachelor’s degree.
Two main purposes for error handling:
- Trap errors you can
predict but can’t control the user
from doing (e.g. saving a file to a
thumb drive when the thumb drives
has been removed) - For unexpected errors, present user with a form
that informs them what the problem
is. That way, they can relay that
message to you and you might be able
to give them a work-around while you
work on a fix.
So, how would you do this?
First of all, create an error form to display when an unexpected error occurs.
It could look something like this (FYI: Mine is called frmErrors):
Notice the following labels:
- lblHeadline
- lblSource
- lblProblem
- lblResponse
Also, the standard command buttons:
- Ignore
- Retry
- Cancel
There’s nothing spectacular in the code for this form:
Option Explicit
Private Sub cmdCancel_Click()
Me.Tag = CMD_CANCEL
Me.Hide
End Sub
Private Sub cmdIgnore_Click()
Me.Tag = CMD_IGNORE
Me.Hide
End Sub
Private Sub cmdRetry_Click()
Me.Tag = CMD_RETRY
Me.Hide
End Sub
Private Sub UserForm_Initialize()
Me.lblErrorTitle.Caption = "Custom Error Title Caption String"
End Sub
Private Sub UserForm_QueryClose(Cancel As Integer, CloseMode As Integer)
'Prevent user from closing with the Close box in the title bar.
If CloseMode <> 1 Then
cmdCancel_Click
End If
End Sub
Basically, you want to know which button the user pressed when the form closes.
Next, create an Error Handler Module that will be used throughout your VBA app:
'****************************************************************
' MODULE: ErrorHandler
'
' PURPOSE: A VBA Error Handling routine to handle
' any unexpected errors
'
' Date: Name: Description:
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
'03/22/2010 Ray Initial Creation
'****************************************************************
Option Explicit
Global Const CMD_RETRY = 0
Global Const CMD_IGNORE = 1
Global Const CMD_CANCEL = 2
Global Const CMD_CONTINUE = 3
Type ErrorType
iErrNum As Long
sHeadline As String
sProblemMsg As String
sResponseMsg As String
sErrorSource As String
sErrorDescription As String
iBtnCap(3) As Integer
iBitmap As Integer
End Type
Global gEStruc As ErrorType
Sub EmptyErrStruc_S(utEStruc As ErrorType)
Dim i As Integer
utEStruc.iErrNum = 0
utEStruc.sHeadline = ""
utEStruc.sProblemMsg = ""
utEStruc.sResponseMsg = ""
utEStruc.sErrorSource = ""
For i = 0 To 2
utEStruc.iBtnCap(i) = -1
Next
utEStruc.iBitmap = 1
End Sub
Function FillErrorStruct_F(EStruc As ErrorType) As Boolean
'Must save error text before starting new error handler
'in case we need it later
EStruc.sProblemMsg = Error(EStruc.iErrNum)
On Error GoTo vbDefaultFill
EStruc.sHeadline = "Error " & Format$(EStruc.iErrNum)
EStruc.sProblemMsg = EStruc.sErrorDescription
EStruc.sErrorSource = EStruc.sErrorSource
EStruc.sResponseMsg = "Contact the Company and tell them you received Error # " & Str$(EStruc.iErrNum) & ". You should write down the program function you were using, the record you were working with, and what you were doing."
Select Case EStruc.iErrNum
'Case Error number here
'not sure what numeric errors user will ecounter, but can be implemented here
'e.g.
'EStruc.sHeadline = "Error 3265"
'EStruc.sResponseMsg = "Contact tech support. Tell them what you were doing in the program."
Case Else
EStruc.sHeadline = "Error " & Format$(EStruc.iErrNum) & ": " & EStruc.sErrorDescription
EStruc.sProblemMsg = EStruc.sErrorDescription
End Select
GoTo FillStrucEnd
vbDefaultFill:
'Error Not on file
EStruc.sHeadline = "Error " & Format$(EStruc.iErrNum) & ": Contact Tech Support"
EStruc.sResponseMsg = "Contact the Company and tell them you received Error # " & Str$(EStruc.iErrNum)
FillStrucEnd:
Exit Function
End Function
Function iErrorHandler_F(utEStruc As ErrorType) As Integer
Static sCaption(3) As String
Dim i As Integer
Dim iMCursor As Integer
Beep
'Setup static array
If Len(sCaption(0)) < 1 Then
sCaption(CMD_IGNORE) = "&Ignore"
sCaption(CMD_RETRY) = "&Retry"
sCaption(CMD_CANCEL) = "&Cancel"
sCaption(CMD_CONTINUE) = "Continue"
End If
Load frmErrors
'Did caller pass error info? If not fill struc with the needed info
If Len(utEStruc.sHeadline) < 1 Then
i = FillErrorStruct_F(utEStruc)
End If
frmErrors!lblHeadline.Caption = utEStruc.sHeadline
frmErrors!lblProblem.Caption = utEStruc.sProblemMsg
frmErrors!lblSource.Caption = utEStruc.sErrorSource
frmErrors!lblResponse.Caption = utEStruc.sResponseMsg
frmErrors.Show
iErrorHandler_F = frmErrors.Tag ' Save user response
Unload frmErrors ' Unload and release form
EmptyErrStruc_S utEStruc ' Release memory
End Function
You may have errors that will be custom only to your application. This would typically be a short list of errors specifically only to your application.
If you don’t already have a constants module, create one that will contain an ENUM of your custom errors. (NOTE: Office ’97 does NOT support ENUMS.). The ENUM should look something like this:
Public Enum CustomErrorName
MaskedFilterNotSupported
InvalidMonthNumber
End Enum
Create a module that will throw your custom errors.
'********************************************************************************************************************************
' MODULE: CustomErrorList
'
' PURPOSE: For trapping custom errors applicable to this application
'
'INSTRUCTIONS: To use this module to create your own custom error:
' 1. Add the Name of the Error to the CustomErrorName Enum
' 2. Add a Case Statement to the raiseCustomError Sub
' 3. Call the raiseCustomError Sub in the routine you may see the custom error
' 4. Make sure the routine you call the raiseCustomError has error handling in it
'
'
' Date: Name: Description:
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
'03/26/2010 Ray Initial Creation
'********************************************************************************************************************************
Option Explicit
Const MICROSOFT_OFFSET = 512 'Microsoft reserves error values between vbObjectError and vbObjectError + 512
'************************************************************************************************
' FUNCTION: raiseCustomError
'
' PURPOSE: Raises a custom error based on the information passed
'
'PARAMETERS: customError - An integer of type CustomErrorName Enum that defines the custom error
' errorSource - The place the error came from
'
' Returns: The ASCII vaule that should be used for the Keypress
'
' Date: Name: Description:
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
'03/26/2010 Ray Initial Creation
'************************************************************************************************
Public Sub raiseCustomError(customError As Integer, Optional errorSource As String = "")
Dim errorLong As Long
Dim errorDescription As String
errorLong = vbObjectError + MICROSOFT_OFFSET + customError
Select Case customError
Case CustomErrorName.MaskedFilterNotSupported
errorDescription = "The mask filter passed is not supported"
Case CustomErrorName.InvalidMonthNumber
errorDescription = "Invalid Month Number Passed"
Case Else
errorDescription = "The custom error raised is unknown."
End Select
Err.Raise errorLong, errorSource, errorDescription
End Sub
You are now well equipped to trap errors in your program. You sub (or function), should look something like this:
Public Sub MySub(monthNumber as Integer)
On Error GoTo eh
Dim sheetWorkSheet As Worksheet
'Run Some code here
'************************************************
'* OPTIONAL BLOCK 1: Look for a specific error
'************************************************
'Temporarily Turn off Error Handling so that you can check for specific error
On Error Resume Next
'Do some code where you might expect an error. Example below:
Const ERR_SHEET_NOT_FOUND = 9 'This error number is actually subscript out of range, but for this example means the worksheet was not found
Set sheetWorkSheet = Sheets("January")
'Now see if the expected error exists
If Err.Number = ERR_SHEET_NOT_FOUND Then
MsgBox "Hey! The January worksheet is missing. You need to recreate it."
Exit Sub
ElseIf Err.Number <> 0 Then
'Uh oh...there was an error we did not expect so just run basic error handling
GoTo eh
End If
'Finished with predictable errors, turn basic error handling back on:
On Error GoTo eh
'**********************************************************************************
'* End of OPTIONAL BLOCK 1
'**********************************************************************************
'**********************************************************************************
'* OPTIONAL BLOCK 2: Raise (a.k.a. "Throw") a Custom Error if applicable
'**********************************************************************************
If not (monthNumber >=1 and monthnumber <=12) then
raiseCustomError CustomErrorName.InvalidMonthNumber, "My Sub"
end if
'**********************************************************************************
'* End of OPTIONAL BLOCK 2
'**********************************************************************************
'Rest of code in your sub
goto sub_exit
eh:
gEStruc.iErrNum = Err.Number
gEStruc.sErrorDescription = Err.Description
gEStruc.sErrorSource = Err.Source
m_rc = iErrorHandler_F(gEStruc)
If m_rc = CMD_RETRY Then
Resume
End If
sub_exit:
'Any final processing you want to do.
'Be careful with what you put here because if it errors out, the error rolls up. This can be difficult to debug; especially if calling routine has no error handling.
Exit Sub 'I was told a long time ago (10+ years) that exit sub was better than end sub...I can't tell you why, so you may not want to put in this line of code. It's habit I can't break :P
End Sub
A copy/paste of the code above may not work right out of the gate, but should definitely give you the gist.
“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.)
“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.)