При выполнении макросов Excel могут возникнуть ошибки, которые в VBA делят на три категории:
- Ошибки компиляции
- Ошибки выполнения
- Логические ошибки (баги)
Далее мы поговорим о каждом из трёх типов ошибок VBA подробно.
Содержание
- Ошибки компиляции
- Ошибки выполнения
- Перехват ошибок выполнения
- Логические ошибки
Ошибки компиляции
Компилятор VBA рассматривает ошибки компиляции как недопустимые и выделяет их в коде ещё до того, как дело дойдёт до запуска макроса.
Если при написании кода допущена синтаксическая ошибка, то редактор VBA сигнализирует об этом немедленно: либо при помощи окна с сообщением, либо выделяя ошибку красным цветом, в зависимости от статуса режима Auto Syntax Check.
Примечание: При включённом режиме Auto Syntax Check каждый раз, при появлении в редакторе Visual Basic во введённом коде синтаксической ошибки, будет показано соответствующее сообщение. Если же этот режим выключен, то редактор VBA продолжит сообщать о синтаксических ошибках, просто выделяя их красным цветом. Опцию Auto Syntax Check можно включить/выключить в меню Tools > Options редактора Visual Basic.
В некоторых случаях ошибка компиляции может быть обнаружена при выполнении компиляции кода, непосредственно перед тем, как макрос будет выполнен. Обычно ошибку компиляции несложно обнаружить и исправить, потому что компилятор VBA даёт информацию о характере и причине ошибки.
Например, сообщение «Compile error: Variable not defined» при попытке запустить выполнение кода VBA говорит о том, что происходит попытка использовать или обратиться к переменной, которая не была объявлена для текущей области (такая ошибка может возникнуть только если используется Option Explicit).
Ошибки выполнения
Ошибки выполнения возникают в процессе выполнения кода и приводят к остановке выполнения программы. Этот тип ошибок VBA, как правило, также не сложно обнаружить и исправить, так как сообщается информация о характере ошибки и место в коде, где произошла остановка.
Примером такой ошибки может служить попытка выполнить деление на ноль. В результате будет показано сообщение «Run-time error ’11’: Division by zero«.
В зависимости от структуры проекта VBA, может быть предложено выполнить отладку кода (как показано на рисунке ниже). В этом случае при нажатии на кнопку Debug (в окне сообщения о необходимости отладки) будет выделена цветом строка кода, которая стала причиной ошибки VBA.
Получив такое сообщение и видя выделенную строку кода, как в приведённом выше примере, обнаружить причину ошибки будет совсем не сложно.
В случае если код сложнее, чем в нашем примере, то, чтобы получить больше информации о причине возникновения ошибки VBA, можно проверить значения используемых переменных. В редакторе VBA для этого достаточно навести указатель мыши на имя переменной, или можно открыть окно отслеживания локальных переменных (в меню редактора View > Locals Window).
Коды различных ошибок выполнения расшифрованы на сайте Microsoft Support (на английском). Наиболее часто встречающиеся ошибки VBA перечислены в этой таблице:
| 5 | Недопустимый вызов процедуры (Invalid procedure call) |
| 7 | Недостаточно памяти (Out of memory) |
| 9 | Индекс вне заданного диапазона (Subscript out of range)
Эта ошибка возникает при попытке обратиться к элементу массива за пределами заданного размера массива – например, если объявлен массив с индексами от 1 до 10, а мы пытаемся обратиться к элементу этого же массива с индексом 11. |
| 11 | Деление на ноль (Division by zero) |
| 13 | Несоответствие типа (Type mismatch)
Эта ошибка возникает при попытке присвоить переменной значение не соответствующего типа – например, объявлена переменная i типа Integer, и происходит попытка присвоить ей значение строкового типа. |
| 53 | Файл не найден (File not found)
Иногда возникает при попытке открыть не существующий файл. |
Перехват ошибок выполнения
Не все ошибки выполнения бывают вызваны недочётами в коде. Например, ошибки VBA не удастся избежать, если для работы макроса необходимо открыть файл с данными, а этого файла не существует. В таких случаях признаком профессионализма будет перехват ошибок и написание кода VBA, который будет выполняться при их возникновении. Таким образом, вместо неприятных сбоев будет происходить изящное завершение работы макроса.
Для того, чтобы помочь справиться с возникающими ошибками, VBA предоставляет разработчику операторы On Error и Resume. Эти операторы отслеживают ошибки и направляют выполнение макроса в специальный раздел кода VBA, в котором происходит обработка ошибки. После выполнения кода обработки ошибки, работа программы может быть продолжена с того места, где возникла ошибка, или макрос может быть остановлен полностью. Далее это показано на примере.
'Процедура Sub присваивает переменным Val1 и Val2 значения,
'хранящиеся в ячейках A1 и B1 рабочей книги Data.xlsx расположенной в каталоге C:Documents and Settings
Sub Set_Values(Val1 As Double, Val2 As Double)
Dim DataWorkbook As Workbook
On Error GoTo ErrorHandling
'Открываем рабочую книгу с данными
Set DataWorkbook = Workbooks.Open("C:Documents and SettingsData")
'Присваиваем переменным Val1 и Val2 данные из рабочей книги DataWorkbook
Val1 = Sheets("Лист1").Cells(1, 1)
Val2 = Sheets("Лист1").Cells(1, 2)
DataWorkbook.Close
Exit Sub
ErrorHandling:
'Если файл не найден, предлагаем пользователю разместить его в
'нужном месте и продолжить работу
MsgBox "Рабочая книга не найдена! " & _
"Пожалуйста добавьте книгу Data.xlsx в каталог C:Documents and Settings и нажмите OK."
Resume
End Sub
В этом коде производится попытка открыть файл Excel с именем Data. Если файл не найден, то пользователю будет предложено поместить этот файл в нужную папку. После того, как пользователь сделает это и нажмёт ОК, выполнение кода продолжится, и попытка открыть этот файл повторится. При желании вместо попытки открыть нужный файл, выполнение процедуры Sub может быть прервано в этом месте при помощи команды Exit Sub.
Логические ошибки
Логические ошибки (или баги) возникают в процессе выполнения кода VBA, но позволяют ему выполняться до самого завершения. Правда в результате могут выполняться не те действия, которые ожидалось, и может быть получен неверный результат. Такие ошибки обнаружить и исправить труднее всего, так как компилятор VBA их не распознаёт и не может указать на них так, как это происходит с ошибками компиляции и выполнения.
Например, при создании макроса в процедуре случайно были просуммированы не те переменные, которые требовалось просуммировать. Результат будет ошибочным, но макрос будет продолжать выполняться до завершения.
Редактор Excel VBA предоставляет набор инструментов отладки, которые помогут найти и исправить логические ошибки в коде VBA. В данной статье мы не будем рассматривать подробно эти инструменты. Любознательный пользователь может найти обзор инструментов отладки VBA на сайте Microsoft Help & Support (на английском).
Оцените качество статьи. Нам важно ваше мнение:
Обработка ошибок
Если вы когда-нибудь учились водить автомобиль, то наверняка вспомните, что при первой посадке на водительское сиденье все внимание было приковано к трем деталям: рулю, педалям и рычагу переключения передач. Происходящее вне автомобиля уходило на второй план, так как вначале нужно было стронуться с места. По мере практики навыки вождения улучшались и эти три детали постепенно уходили на задний план. Как ни странно, но руль и рычаг переключения передач всегда оказывались там, куда вы не смотря протягивали руки, а ноги сами находили педали. Теперь все внимание стало занимать происходящее на дороге. Иными словами, вы стали опытным водителем.
В программировании все абсолютно также. Начинающие программисты больше обращают внимание на первые попавшиеся на глаза операторы, функции и другие элементы языка, а сам алгоритм уходит на задний план. Если программа скомпилировалась без ошибок, то это уже большое счастье, хотя это еще не означает, что программа работает правильно. По мере практики мышление программиста меняется, он начинает обращать внимание на мелочи, на форматирование программы, использует более эффективные алгоритмы и в результате всего этого допускает меньше ошибок. Подводя итоги, можно сказать, что начинающий программист просто пишет программу, а опытный программист пытается найти оптимальный алгоритм и предусмотреть поведение программы в различных ситациях. Однако, от ошибок никто не застрахован, поэтому очень важно знать как быстро найти ошибку.
Типы ошибок
Существуют три типа ошибок в программе:
- синтаксические — это ошибки в имени оператора или подпрограммы, отсутствие закрывающей или открывающей кавычек и т. д., то есть ошибки в синтаксисе языка. Как правило, компилятор предупредит о наличии ошибки, а программа не будет выполняться совсем;
- логические — это ошибки в логике работы программы, которые можно выявить только по результатам работы программы. Как правило, компилятор не предупреждает о наличии ошибки, а программа будет выполняться, так как не содержит синтаксических ошибок. Такие ошибки достаточно трудно выявить;
- ошибки времени выполнения — это ошибки, которые возникают во время работы программы. В одних случаях ошибки времени выполнения являются следствием логических ошибок, а в других случаях причиной являются внешние события, например, нехватка оперативной памяти, отсутствие прав для записи в файл и др.
Инструкция On Error
Ошибки времени выполнения можно перехватывать внутри подпрограммы. Для этого используется инструкция On Error, которая имеет три формата:
On Error GoTo <Метка>— при возникновении ошибки управление передается инструкции, помеченной меткой<Метка>. Метка должна быть допустимым идентификатором, к которому предъявляются такие же требования как и к переменным. Внутри подпрограммы метка указывается в самом начале помечаемой строки и после метки ставится двоеточие. В качестве примера создадим функцию для деления двух целых чисел. Внутри функции предусмотрим обработку ошибки деления на0:
Function Деление(x As Integer, y As Integer) As Double
On Error GoTo ПриОшибке
Деление = x / y
Exit Function
ПриОшибке:
Деление = 0
End Function
Если при вызове функции во втором параметре передать значение 0, то управление будет передано в строку, помеченную с помощью метки ПриОшибке. Обратите внимание на то, что метка расположена после инструкции Exit Function. В этом случае код после инструкции Exit Function будет выполнен только в том случае, если возникнет ошибка;
On Error Resume Next— при возникновении ошибки управление передается следующей инструкции;On Error GoTo 0— отключает перехват ошибок.
Если внутри подпрограммы не предусмотрен перехват ошибки, то при возникновении ошибки работа программы прерывается и выводится стандартное окно с описанием и несколькими кнопками: Continue (продолжить), End (завершить выполнение программы), Debug (перейти в режим отладки) и Help (вывод справки).
Инструкция Resume
Инструкция Resume позволяет указать куда следует переходить после обработки ошибки. Инструкция имеет несколько форматов:
Resume [0]— управление передается инструкции, вызвавшей ошибку;Resume Next— управление передается инструкции, следующей за инструкцией, вызвавшей ошибку;Resume <Метка>— управление передается инструкции, помеченной меткой<Метка>.
Если инструкция Resume не указана, то выполняется только код внутри обработчика ошибки и производится выход из подпрограммы.
Получение информации об ошибке и генерация ошибки
Вся информация о последней ошибке доступна через объект Err. Объект содержит следующие свойства:
Number— код ошибки, например, код11для ошибки деления на0. Если ошибки не произошло, то свойство содержит значение0;Description— описание ошибки, например, строка"Division by zero"для ошибки деления на0. Пример вывода кода и описания ошибки:
Debug.Print Err.Number; Err.Description
Source— название текущего проекта;HelpFile— путь к файлу справки;HelpContext— идентификатор раздела в справочном файле;LastDLLError— системный код ошибки при работе с DLL.
Объект Err содержит следующие методы:
Clear()— очищает всю информацию о последней ошибке. Этот метод следует вызвать после успешной обработки ошибки. Информация об ошибке автоматически очищается при выходе из подпрограммы и ряде других случаев;Raise()— позволяет сгенерировать ошибку в программе. Формат метода:
Raise Number[, Source][, Description][, HelpFile][, HelpContext]
В параметре Number указывается код генерируемой ошибки (целое число от 0 до 65 535). Коды от 0 до 512 зарезервированы под системные ошибки, а остальные коды можно использовать под пользовательские ошибки. Чтобы сгенерировать ошибку с пользовательским кодом необходимо сложить код с константой vbObjectError. Остальные параметры являются необязательными и полностью аналогичны одноименным свойствам объекта Err. Пример генерации и обработки пользовательской ошибки:
Sub ГенерацияОшибки()
On Error GoTo ПриОшибке
Err.Raise vbObjectError + 513
Exit Sub
ПриОшибке:
Debug.Print Err.Number; Err.Description
' -2147220991 Automation error
End Sub
Способы поиска ошибок в программе
В предыдущих разделах мы научились обрабатывать ошибки времени выполнения. Однако, наибольшее количество времени программист затрачивает на другой тип ошибок — логические ошибки. В этом случае программа компилируется без ошибок, но результат выполнения программы не соответствует ожидаемому результату. Ситуация еще более осложняется, когда неверный результат проявляется лишь периодически, а не постоянно. Инсценировать такую же ситуацию, чтобы получить этот же неверный результат, бывает крайне сложно и занимает очень много времени. В этом разделе мы рассмотрим лишь «дедовские» (но по прежнему актуальные) способы поиска ошибок, а современные способы отладки приложений, доступные в VBA, изучим в следующем разделе.
Первое, на что следует обратить внимание, — на объявления переменных. Например, рассмотрим простой пример:
Как вы думаете, какое значение отобразится в окне Immediate после выполнения этого кода? Думаете, что число 10? Не факт! Вот тут-то и кроется проблема не видная на первый взгляд. В первой инструкции присваивается значение переменной x, имя которой набрано на английской раскладке клавиатуры, а вот во второй инструкции выводится значение переменной x, имя которой набрано на русской раскладке клавиатуры. В результате значение присваивается одной переменной, а выводится значение другой переменной. Такие ситуации очень часто встречаются в программах на языке VBA, так как объявлять переменную не обязательно. Чтобы избежать такой ситуации следует обязательно объявлять переменные явным образом. Контроль за соблюдением этого правила можно возложить на компилятор, добавив в начале модуля следующую инструкцию:
При наличии инструкции компилятор производит проверку объявления всех переменных. Если переменная не была объявлена явным образом, то компилятор выведет сообщение об ошибке и выполнение программы будет остановлено. Таким образом, код должен выглядеть следующим образом:
Option Explicit
...
Dim x As Integer
x = 10
Debug.Print x ' 10
Далее следует обратить внимание на форматирование кода. Начинающие программисты обычно не обращают на это никакого внимания, считая этот процесс лишним. А на самом деле зря! Компилятору абсолютно все равно, разместите вы все инструкции на одной строке или выполните форматирование кода. Однако, при поиске ошибок форматирование кода позволит найти ошибку гораздо быстрее.
Перед всеми инструкциями внутри блока должно быть расположено одинаковое количество пробелов. Обычно используют три или четыре пробела. От применения символов табуляции лучше отказаться. Если все же используете, то не следует в одном файле совмещать и пробелы и табуляцию. Для вложенных блоков количество пробелов умножают на уровень вложенности. Если для блока первого уровня вложенности использовалось три пробела, то для блока второго уровня вложенности должно использоваться шесть пробелов, для третьего уровня — девять пробелов и т. д. Пример форматирования вложенных блоков приведен в листинге 11.1.
Dim Массив As Variant, i As Integer, j As Integer
Массив = Array(Array(0, 1), Array(2, 3), Array(4, 5))
For i = 0 To 2
For j = 0 To 1
Debug.Print Массив(i)(j)
Next
Next
Длина одной строки не должна содержать более 80 символов. Если количество символов больше, то следует выполнить переход на новую строку. При этом продолжение смещается относительно основной инструкции на величину отступа или выравнивается по какому-либо элементу. Иначе приходится пользоваться горизонтальной полосой прокрутки, а это очень неудобно при поиске ошибок.
Если программа слишком большая, то следует задуматься о разделении программы на отдельные подпрограммы или классы, которые выполняют логически законченные действия. Помните, что отлаживать отдельную подпрограмму гораздо легче, чем «спагетти»-код. Причем прежде чем вставить подпрограмму (или класс) в основную программу ее следует протестировать в отдельном проекте, передавая подпрограмме различные значения и проверяя результат ее выполнения.
Обратите внимание на то, что форматирование кода должно выполняться при написании кода, а не во время поиска ошибок. Этим вы сократите время поиска ошибки и скорее всего заметите ошибку еще на этапе написания. Если все же ошибка возникла, то вначале следует инсценировать ситуацию, при которой ошибка проявляется. После этого можно начать поиск ошибки.
Причиной периодических ошибок чаще всего являются внешние данные. Например, если числа получаются от пользователя, а затем производится деление чисел, то вполне возможна ситуация, при которой пользователь введет число 0. Деление на ноль приведет к ошибке. Следовательно, все данные, которые поступают от пользователей, должны проверяться на соответствие допустимым значениям. Если данные не соответствуют, то нужно вывести сообщение об ошибке, а затем повторно запросить новое число или прервать выполнение всей программы. Кроме того, нужно обработать возможность того, что пользователь может ввести вовсе не число, а строку.
Метод Print() объекта Debug удобно использовать для вывода промежуточных значений. В этом случае значения переменных вначале выводятся в самом начале программы и производится проверка соответствия значений. Если значения соответствуют, то инструкция с методом Print() перемещается на следующую строку программы и опять производится проверка и т. д. Если значения не совпали, то ошибка возникает в инструкции, расположенной перед инструкцией с методом Print(). Если это пользовательская подпрограмма, то проверку значений производят внутри подпрограммы, каждый раз перемещая инструкцию с выводом значений. На одном из этих многочисленных этапов ошибка обычно обнаруживается. В больших программах можно логически догадаться о примерном расположении инструкции с ошибкой и начать поиск ошибки оттуда, а не с самого начала программы.
Инструкции для вывода промежуточных значений можно расставить уже при написании программы, не дожидаясь возникновения ошибки. В этом случае в начале программы объявляется константа с помощью инструкции #Const, а внутри программы производится проверка значения константы:
Проверить значение константы позволяет следующая конструкция:
#If MY_DEBUG Then
' Здесь размещаем инструкции вывода значений
#End If
Таким образом, меняя значение константы MY_DEBUG с 1 на 0, можно отлючать вывод всех промежуточных значений.
Сделать поиск ошибок более эффективным позволяет отладчик, встроенный в редактор VBA. С его помощью можно выполнять программу по шагам, при этом контролируя значения переменных на каждом шагу. Отладчик позволяет также проверить, соответствует ли порядок выполнения инструкций разработанному ранее алгоритму.
Прежде чем начать отладку необходимо пометить строки внутри программы с помощью точек останова. Для добавления точки останова делаем строку активной, а затем из меню Debug выбираем пункт Toggle Breakpoint. Слева от строки появится кружок, обозначающий точку останова. Добавить точку останова можно еще быстрее. Для этого достаточно щелкнуть слева от строки левой кнопкой мыши. Повторный щелчок позволяет удалить точку останова. Кроме того, для добавления или удаления точки отстанова можно воспользоваться клавишей <F9>. Чтобы удалить все точки останова следует из меню View выбрать пункт Clear All Breakpoints.
Когда точки останова расставлены можно начать отладку. Для этого запускаем программу на выполнение обычным способом. При достижении точки останова выполнение программы прерывается и отладчик ожидает дальнейших действий программиста. Инструкция, которая будет выполняться на следующем шаге, помечается желтой стрелкой слева от строки.
В режиме прерывания можно посмотреть значения различных переменных в окне Locals. Если окно не отображается, то отобразить его можно выбрав в меню View пункт Locals Window. Посмотреть значение переменной можно также если навести указатель мыши на переменную. Значение переменной отобразится во всплывающей подсказке.
При отладке можно контролировать значения отдельных переменных, а не всех сразу. Для этого следует выделить название переменной и из меню Debug выбрать пункт Add Watch. Можно также выделить название переменной и из контектного меню выбрать пункт Add Watch. В открывшемся окне устанавливаем флажок Watch Expression и нажимаем кнопку OK. Значение переменной будет отображаться в окне Watches. Чтобы отобразить окно Watches из меню View выбираем пункт Watch Window. Чтобы отменить отслеживание нужно выделить строку в окне Watches и нажать клавишу <Delete>.
Для пошагового выполнения программы предназначены следующие пункты в меню Debug или соответствующие кнопки на панели инструментов Debug (View | Toolbars | Debug):
- Step Into (клавиша <F8>) — выполняет переход к следующей инструкции;
- Step Over — выполняет одну инструкцию. Если в этой инструкции производится вызов подпрограммы, то подпрограмма выполняется за один шаг и отладчик переходит в режим ожидания после выхода из подпрограммы;
- Step Out — при заходе в подпрограмму этот пункт позволяет выполнить подпрограмму за один шаг и выйти из нее. Отладчик переходит в режим прерывания после выхода из подпрограммы;
- Run To Cursor — выполняет переход к инструкции, в которой расположен курсор.
Если необходимо посмотреть последовательность вызова подпрограмм, то следует открыть окно Call Stack, выбрав в меню View пункт Call Stack.
Подача звукового сигнала
При возникновении ошибки или при неправильном вводе данных имеет смысл привлечь внимание пользователя звуковым сигналом. Сгенерировать звуковой сигнал позволяет инструкция Beep. Пример:
Dim Результат
Beep
Результат = InputBox("Необходимо ввести значение")
Статьи по Visual Basic for Applications (VBA)
На чтение 25 мин. Просмотров 14.3k.
Эта статья содержит полное руководство по обработке ошибок VBA. Если вы ищете краткое резюме, посмотрите таблицу быстрого руководства в первом разделе.
Если вы ищете конкретную тему по обработке ошибок VBA, ознакомьтесь с приведенным ниже содержанием.
Если вы новичок в VBA, то вы можете прочитать пост от начала до конца, так как он выложен в логическом порядке.
Содержание
- Краткое руководство по обработке ошибок
- Введение
- Ошибки VBA
- Заявление об ошибке
- Err объект
- Логирование
- Другие элементы, связанные с ошибками
- Простая стратегия обработки ошибок
- Полная стратегия обработки ошибок
- Обработка ошибок в двух словах
Краткое руководство по обработке ошибок
| Пункт | Описание |
| On Error Goto 0 | При возникновении ошибки код останавливается и отображает ошибку. |
| On Error Resume Next | Игнорирует ошибку и продолжает. |
| On Error Goto [Label] | Переход к определенной метке при возникновении ошибки. Это позволяет нам справиться с ошибкой. |
| Err Object | При возникновении ошибки информация об ошибке сохраняется здесь. |
| Err.Number | Номер ошибки. (Полезно, только если вам нужно проверить, произошла ли конкретная ошибка.) |
| Err.Description | Содержит текст ошибки. |
| Err.Source | Вы можете заполнить это, когда используете Err.Raise. |
| Err.Raise | Функция, которая позволяет генерировать вашу собственную ошибку. |
| Error Function | Возвращает текст ошибки из номера ошибки. Вышло из употребления. |
| Error Statement | Имитирует ошибку. Вместо этого используйте Err.Raise. |
Введение
Обработка ошибок относится к коду, который написан для обработки ошибок, возникающих во время работы вашего приложения. Эти ошибки обычно вызваны чем-то вне вашего контроля, например отсутствующим файлом, недоступностью базы данных, недействительными данными и т.д.
Если мы считаем, что ошибка может произойти в какой-то
момент, рекомендуется написать специальный код для обработки ошибки, если она
возникнет, и устранить ее.
Для всех остальных ошибок мы используем общий код для их
устранения. Это где оператор обработки ошибок VBA вступает в игру. Они
позволяют нашему приложению корректно обрабатывать любые ошибки, которые мы не
ожидали.
Чтобы понять обработку ошибок, мы должны сначала понять
различные типы ошибок в VBA.
Ошибки VBA
В VBA есть три типа ошибок
- Синтаксис
- Компиляция
- Время выполнения
Мы используем обработку ошибок для устранения ошибок во
время выполнения. Давайте посмотрим на каждый из этих типов ошибок, чтобы было
ясно, что такое ошибка во время выполнения.
Синтаксические ошибки
Если вы использовали VBA в течение какого-то времени, вы
увидите синтаксическую ошибку. Когда вы набираете строку и нажимаете return,
VBA оценивает синтаксис и, если он неверен, выдает сообщение об ошибке.
Например, если вы введете If и забудете ключевое слово Then,
VBA отобразит следующее сообщение об ошибке.
Некоторые примеры синтаксических ошибок
' then отсутствует
If a > b
' не хватает = после i
For i 2 To 7
' отсутствует правая скобка
b = left("АБВГ",1
Синтаксические ошибки относятся только к одной строке. Они
возникают, когда синтаксис одной строки неверен.
Примечание. Диалоговое окно «Ошибка синтаксиса» можно отключить, выбрав «Сервис» -> «Параметры» и отметив «Автосинтаксическая проверка». Строка по-прежнему будет отображаться красным цветом в случае ошибки, но диалоговое окно не появится.
Ошибки компиляции
Ошибки компиляции происходят более чем в одной строке.
Синтаксис в одной строке правильный, но неверный, если учесть весь код проекта.
Примеры ошибок компиляции:
- Оператор If без соответствующего оператора End If
- For без Next
- Select без End Select
- Вызов Sub или Function, которые не существуют
- Вызов Sub или Function с неверными параметрами
- Присвоение Sub или Function того же имени, что и для модуля
- Переменные не объявлены (Option Explicit должен присутствовать в верхней части модуля)
На следующем снимке экрана показана ошибка компиляции,
которая возникает, когда цикл For не имеет соответствующего оператора Next.
Использование Debug-> Compile
Чтобы найти ошибки компиляции, мы используем Debug->
Compile VBA Project из меню Visual Basic.
Когда вы выбираете Debug-> Compile, VBA отображает первую
обнаруженную ошибку.
Когда эта ошибка исправлена, вы можете снова запустить
Compile, и VBA найдет следующую ошибку.
Debug-> Compile также будет включать синтаксические
ошибки в поиск, что очень полезно.
Если ошибок не осталось и вы запускаете Debug-> Compile,
может показаться, что ничего не произошло. Однако «Компиляция» будет недоступна
в меню «Отладка». Это означает, что ваше приложение не имеет ошибок компиляции
в текущий момент.
Debug->Compile Error Summary
Debug-> Compile находит ошибки компиляции (проекта).
Он также найдет синтаксические ошибки.
Он находит одну ошибку каждый раз, когда вы ее используете.
Если нет ошибок компиляции, оставленная опция Компиляция
будет отображаться серым цветом в меню.
Debug-> Compile Usage
Вы должны всегда использовать Debug-> Compile, прежде чем
запускать свой код. Это гарантирует, что ваш код не будет иметь ошибок
компиляции при запуске.
Если вы не запускаете Debug-> Compile, то VBA может
обнаружить ошибки компиляции при запуске. Их не следует путать с ошибками
времени выполнения.
Ошибки во время выполнения
Ошибки во время выполнения возникают, когда ваше приложение
работает. Обычно они находятся вне вашего контроля, но могут быть вызваны
ошибками в вашем коде.
Например, представьте, что ваше приложение читает из внешней
рабочей книги. Если этот файл будет удален, то VBA отобразит ошибку, когда ваш
код попытается открыть его.
Другие примеры ошибок времени выполнения
- база данных недоступна
- пользователь вводит неверные данные
- ячейка, содержащая текст вместо числа
Как мы уже видели, целью обработки ошибок является обработка
ошибок времени выполнения, когда они возникают.
Ожидаемые и неожиданные ошибки
Когда мы думаем, что может произойти ошибка во время
выполнения, мы помещаем код на место для ее обработки. Например, мы обычно
помещаем код на место, чтобы иметь дело с файлом, который не найден.
Следующий код проверяет, существует ли файл, прежде чем он
пытается его открыть. Если файл не существует, отображается сообщение, удобное
для пользователя, и код выходит из подпрограммы.
Sub OtkritFail()
Dim sFile As String
sFile = "C:ДокументыОтчет.xlsx"
' Используйте Dir, чтобы проверить, существует ли файл
If Dir(sFile) = "" Then
' если файл не существует, отобразить сообщение
MsgBox "Файл не найден" & sFile
Exit Sub
End If
' Код достигнет только если файл существует
Workbooks.Open sFile
End Sub
Когда мы думаем, что в какой-то момент может произойти
ошибка, рекомендуется добавить код для обработки ситуации. Мы обычно называем
эти ошибки ожидаемыми.
Если у нас нет специального кода для обработки ошибки, это
считается неожиданной ошибкой. Мы используем операторы обработки ошибок VBA для
обработки непредвиденных ошибок.
Ошибки времени выполнения, которые не являются ошибками VBA
Прежде чем мы рассмотрим VBA Handling, мы должны упомянуть
один тип ошибок. Некоторые ошибки во время выполнения не рассматриваются как
ошибки VBA, а только пользователем.
Позвольте мне объяснить это на примере. Представьте, что у
вас есть приложение, которое требует, чтобы вы добавили значения в переменные a
и b
Допустим, вы по ошибке используете звездочку вместо знака
плюс
Это не ошибка VBA. Ваш синтаксис кода является совершенно
законным. Однако, с вашей точки зрения, это ошибка.
Эти ошибки не могут быть обработаны с помощью обработки ошибок, поскольку они, очевидно, не будут генерировать никаких ошибок. Вы можете справиться с этими ошибками, используя Unit Testing and Assertions.
Заявление об ошибке
Как мы видели, есть два способа обработки ошибок во время
выполнения
- Ожидаемые ошибки — напишите конкретный код для
их обработки. - Неожиданные ошибки — используйте операторы
обработки ошибок VBA для их обработки.
Оператор VBA On Error используется для обработки ошибок.
Этот оператор выполняет некоторые действия при возникновении ошибки во время
выполнения.
Есть четыре различных способа использовать это утверждение
- On Error Goto 0 — код останавливается на строке с ошибкой и отображает сообщение.
- On Error Resume Next — код перемещается на следующую строку. Сообщение об ошибке не отображается.
- On Error Goto [label] — код перемещается на определенную строку или метку. Сообщение об ошибке не отображается. Это тот, который мы используем для обработки ошибок.
- On Error Goto -1 — очищает текущую ошибку.
Давайте посмотрим на каждое из этих утверждений по очереди.
On Error Goto 0
Это поведение по умолчанию VBA. Другими словами, если вы не
используете On Error, это поведение вы увидите.
При возникновении ошибки VBA останавливается на строке с
ошибкой и отображает сообщение об ошибке. Приложение требует вмешательства
пользователя с кодом, прежде чем оно сможет продолжить. Это может быть
исправление ошибки или перезапуск приложения. В этом случае обработка ошибок не
происходит.
Давайте посмотрим на пример. В следующем коде мы не
использовали строку On Error, поэтому VBA будет использовать поведение On Error
Goto 0 по умолчанию.
Sub IspDefault()
Dim x As Long, y As Long
x = 6
y = 6 / 0
x = 7
End Sub
Вторая строка присваивания приводит к ошибке деления на ноль. Когда мы запустим этот код, мы получим сообщение об ошибке, показанное на скриншоте ниже.
Когда появляется ошибка, вы можете выбрать End или Debug
Если вы выберете Конец, то приложение просто остановится.
Если вы выберете Отладить, приложение остановится на строке
ошибки, как показано на скриншоте ниже.
Это нормально, когда вы пишете код VBA, поскольку он
показывает вам точную строку с ошибкой.
Это поведение не подходит для приложения, которое вы
передаете пользователю. Эти ошибки выглядят непрофессионально и делают
приложение нестабильным.
Подобная ошибка, по сути, приводит к сбою приложения.
Пользователь не может продолжить работу без перезапуска приложения. Они могут
вообще не использовать его, пока вы не исправите для них ошибку.
Используя On Error Goto [label], мы можем дать пользователю
более контролируемое сообщение об ошибке. Это также предотвращает остановку
приложения. Мы можем заставить приложение работать предопределенным образом.
On Error Resume Next
Использование On Error Resume Next указывает VBA
игнорировать ошибку и продолжать работу.
Есть конкретные случаи, когда это полезно. Большую часть
времени вы должны избегать его использования.
Если мы добавим Resume Next к нашему примеру Sub, то VBA
проигнорирует ошибку деления на ноль
Sub UsingResumeNext()
On Error Resume Next
Dim x As Long, y As Long
x = 6
y = 6 / 0
x = 7
End Sub
Это не очень хорошая идея, чтобы сделать это. Если вы
игнорируете ошибку, то поведение может быть непредсказуемым. Ошибка может
повлиять на приложение несколькими способами. Вы можете получить неверные
данные. Проблема в том, что вы не знаете, что что-то пошло не так, потому что
вы подавили ошибку.
Приведенный ниже код является примером использования Resume
Next.
Sub OtprSoobsch()
On Error Resume Next
' Требуется ссылка:
' Библиотека объектов Microsoft Outlook 15.0
Dim Outlook As Outlook.Application
Set Outlook = New Outlook.Application
If Outlook Is Nothing Then
MsgBox " Не удается создать сеанс Microsoft Outlook." _
& " Письмо не будет отправлено."
Exit Sub
End If
End Sub
В этом коде мы проверяем, доступен ли Microsoft Outlook на компьютере. Все,
что мы хотим знать — это доступно или нет. Нас не интересует конкретная ошибка.
В приведенном выше коде мы продолжаем, если есть ошибка.
Затем в следующей строке мы проверяем значение переменной Outlook. Если произошла ошибка, тогда
значение этой переменной будет установлено равным Nothing.
Это пример того, когда Резюме может быть полезным. Дело в
том, что, хотя мы используем Resume,
мы все равно проверяем наличие ошибки. Подавляющее большинство времени вам не
нужно будет использовать Resume.
On Error Goto [label]
Вот как мы используем обработку ошибок в VBA. Это эквивалент функциональности Try and Catch, которую вы видите на
таких языках, как C # и
Java.
При возникновении ошибки вы отправляете ошибку на
определенный ярлык. Обычно это внизу саба.
Давайте применим это к подводной лодке, которую мы
использовали
Sub IspGotoLine()
On Error Goto eh
Dim x As Long, y As Long
x = 6
y = 6 / 0
x = 7
Done:
Exit Sub
eh:
MsgBox "Произошла следующая ошибка: " & Err.Description
End Sub
Снимок экрана ниже показывает, что происходит при возникновении ошибки.
VBA переходит на метку eh, потому что мы указали это в
строке «Перейти к ошибке».
Примечание 1: Метка, которую мы используем в операторе On… Goto, должна быть в текущей Sub / Function. Если нет, вы получите ошибку компиляции.
Примечание 2: Когда возникает ошибка при использовании On Error Goto [label], обработка ошибок возвращается к поведению по умолчанию, т.е. код остановится на строке с ошибкой и отобразит сообщение об ошибке. См. Следующий раздел для получения дополнительной информации об этом.
On Error Goto -1
Это утверждение отличается от других трех. Он используется
для очистки текущей ошибки, а не для настройки конкретного поведения.
При возникновении ошибки с помощью функции On Error Goto [label] поведение обработки ошибки возвращается к поведению по умолчанию, т.е. On Error Goto 0 . Это означает, что если произойдет другая ошибка, код остановится на текущей строке.
Это поведение относится только к текущей подпрограмме. Как
только мы выйдем из саба, ошибка будет очищена автоматически.
Посмотрите на код ниже. Первая ошибка приведет к переходу
кода на метку eh. Вторая ошибка остановится на строке с ошибкой 1034.
Sub DveOshibki()
On Error Goto eh
' генерировать ошибку «Несоответствие типов»
Error (13)
Done:
Exit Sub
eh:
' генерировать «определенную приложением» ошибку
Error (1034)
End Sub
Если мы добавим дальнейшую обработку ошибок, она не будет
работать, поскольку ловушка ошибок не была очищена.
В коде ниже мы добавили строку
после того как мы поймаем первую ошибку.
Это не имеет никакого эффекта, так как ошибка не была
очищена. Другими словами, код остановится на строке с ошибкой и отобразит
сообщение.
Sub DveOshibki()
On Error Goto eh
' генерировать ошибку «Несоответствие типов»
Error (13)
Done:
Exit Sub
eh:
On Error Goto eh_other
' генерировать «определенную приложением» ошибку
Error (1034)
Exit Sub
eh_other:
Debug.Print "ehother " & Err.Description
End Sub
Для устранения ошибки мы используем On Error Goto -1.
Думайте об этом как об установке ловушки для мыши. Когда ловушка сработает, вам
нужно установить ее снова.
В приведенном ниже коде мы добавляем эту строку, и вторая
ошибка теперь приведет к переходу кода на метку eh_other.
Sub DveOshibki()
On Error Goto eh
' генерировать ошибку «Несоответствие типов»
Error (13)
Done:
Exit Sub
eh:
' явная ошибка
On Error Goto -1
On Error Goto eh_other
' генерировать «определенную приложением» ошибку
Error (1034)
Exit Sub
eh_other:
Debug.Print "ehother " & Err.Description
End Sub
Примечание 1. Вероятно, в редких случаях полезно использовать On Error Goto -1. Мне лично никогда не приходилось пользоваться этой линией. Помните, что как только вы выйдете из Sub, ошибка все равно будет очищена.
Примечание 2. у объекта Err есть член Clear. Использование Clear очищает текст и цифры в объекте Err, но НЕ сбрасывает ошибку.
Использование On Error
Как мы уже видели, VBA будет делать одну из трех вещей при возникновении ошибки:
- Остановитесь и отобразите ошибку.
- Игнорируйте ошибку и продолжайте.
- Перейти к определенной строке.
VBA всегда будет настроен на одно из этих действий. Когда вы
используете On Error, VBA изменит ваше поведение и забудет о любом предыдущем.
В следующем подпункте VBA изменяет поведение ошибки каждый
раз, когда мы используем оператор On Error
Sub ErrorSostoyaniya()
Dim x As Long
' Перейти на этикетке, если ошибка
On Error Goto eh
' это проигнорирует ошибку в следующей строке
On Error Resume Next
x = 1 / 0
' это отобразит сообщение об ошибке в следующей строке
On Error Goto 0
x = 1 / 0
Done:
Exit Sub
eh:
Debug.Print Err.Description
End Sub
Err объект
При возникновении ошибки вы можете просмотреть детали
ошибки, используя объект Err.
При возникновении ошибки времени выполнения VBA
автоматически заполняет объект Err деталями.
Приведенный ниже код выведет «Error Number: 13 Type
Mismatch», которое возникает, когда мы пытаемся поместить строковое значение в
длинное целое число.
Sub IspErr()
On Error Goto eh
Dim total As Long
total = "aa"
Done:
Exit Sub
eh:
Debug.Print "Номер ошибки: " & Err.Number _
& " " & Err.Description
End Sub
Err.Description предоставляет подробную информацию об ошибке, которая происходит. Это текст, который вы обычно видите, когда возникает ошибка, например, «Несоответствие типов»
Err.Number — это идентификационный номер ошибки, например, номер ошибки для «Несоответствие типов» — 13. Единственное время, когда вам действительно нужно это, если вы проверяете, что произошла конкретная ошибка, и это необходимо только в редких случаях.
Свойство Err.Source кажется отличной идеей, но оно не работает при ошибке VBA. Источник вернет имя проекта, которое вряд ли сузит место возникновения ошибки. Однако, если вы создаете ошибку с помощью Err.Raise, вы можете установить источник самостоятельно, и это может быть очень полезно.
Получение номера строки
Функция Erl используется для возврата номера строки, где
произошла ошибка.
Это часто вызывает путаницу. В следующем коде Erl вернет ноль.
Sub IspErr()
On Error Goto eh
Dim val As Long
val = "aa"
Done:
Exit Sub
eh:
Debug.Print Erl
End Sub
Это потому, что нет номеров строк. Большинство людей не
понимают этого, но VBA позволяет вам иметь номера строк.
Если мы изменим подпрограмму, указав номер строки, она теперь выведет 20.
Sub IspErr()
10 On Error Goto eh
Dim val As Long
20 val = "aa"
Done:
30 Exit Sub
eh:
40 Debug.Print Erl
End Sub
Добавление номеров строк в код вручную затруднительно.
Однако есть инструменты, которые позволят вам легко добавлять и удалять номера
строк в подпрограмме.
Когда вы закончите работу над проектом и передадите его
пользователю, в этот момент может быть полезно добавить номера строк. Если вы
используете стратегию обработки ошибок в последнем разделе этого поста, то VBA
сообщит строку, где произошла ошибка.
Использование Err.Raise
Err.Raise позволяет нам создавать ошибки. Мы можем
использовать его для создания пользовательских ошибок для нашего приложения,
что очень полезно. Это эквивалент оператора Throw в Java C #.
Формат следующий
Err.Raise [error number], [error source], [error description]
Давайте посмотрим на простой пример. Представьте, что мы
хотим убедиться, что в ячейке есть запись длиной 5 символов. Мы могли бы иметь конкретное сообщение для
этого
Public Const ERROR_INVALID_DATA As Long = vbObjectError + 513
Sub ReadWorksheet()
On Error Goto eh
If Len(Sheet1.Range("A1")) <> 5 Then
Err.Raise ERROR_INVALID_DATA, "ReadWorksheet" _
, "Значение в ячейке A1 должно иметь ровно 5 символов."
End If
' продолжить, если ячейка имеет действительные данные
Dim id As String
id = Sheet1.Range("A1")
Done:
Exit Sub
eh:
' Err.Raise отправит код сюда
MsgBox " Обнаружена ошибка: " & Err.Description
End Sub
Когда мы создаем ошибку, используя Err.Raise, нам нужно присвоить ей номер. Мы можем использовать любое
число от 513 до 65535 для нашей ошибки. Мы должны использовать vbObjectError с номером,
например
Err.Raise vbObjectError + 513
Использование Err.Clear
Err.Clear используется для очистки текста и чисел из объекта
Err.Object. Другими словами, он очищает описание и номер.
Редко вам понадобится его использовать, но давайте
рассмотрим пример, где вы могли бы.
В приведенном ниже коде мы подсчитываем количество ошибок,
которые могут возникнуть. Для простоты мы генерируем ошибку для каждого
нечетного числа.
Мы проверяем номер ошибки каждый раз, когда проходим цикл.
Если число не равно нулю, то произошла ошибка. Как только мы посчитаем ошибку,
нам нужно установить номер ошибки на ноль, чтобы он был готов проверить
следующую ошибку.
Sub IspErrClear()
Dim count As Long, i As Long
' Продолжите, если ошибка, так как мы проверим номер ошибки
On Error Resume Next
For i = 0 To 9
' генерировать ошибку для каждого второго
If i Mod 2 = 0 Then Error (13)
' Проверьте на ошибку
If Err.Number <> 0 Then
count = count + 1
Err.Clear ' Очистить Err, как только он считается
End If
Next
Debug.Print " Количество ошибок было: " & count
End Sub
Примечание: Err.Clear сбрасывает текст и цифры в объекте ошибки, но не очищает ошибку — см. On Error Goto -1 для получения дополнительной информации об очистке фактической ошибки.
Логирование
Ведение журнала означает запись информации из вашего
приложения, когда оно запущено. При возникновении ошибки вы можете записать
детали в текстовый файл, чтобы у вас была запись об ошибке.
Код ниже показывает очень простую процедуру регистрации
Sub Logger(sType As String, sSource As String, sDetails As String)
Dim sFilename As String
sFilename = "C:templogging.txt"
' Архивный файл определенного размера
If FileLen(sFilename) > 20000 Then
FileCopy sFilename _
, Replace(sFilename, ".txt", Format(Now, "ddmmyyyy hhmmss.txt"))
Kill sFilename
End If
' Откройте файл для записи
Dim filenumber As Variant
filenumber = FreeFile
Open sFilename For Append As #filenumber
Print #filenumber, CStr(Now) & "," & sType & "," & sSource _
& "," & sDetails & "," & Application.UserName
Close #filenumber
End Sub
Вы можете использовать это так:
' Создать уникальный номер ошибки
Public Const ERROR_DATA_MISSING As Long = vbObjectError + 514
Sub CreateReport()
On Error Goto eh
If Sheet1.Range("A1") = "" Then
Err.Raise ERROR_DATA_MISSING, "CreateReport", "Данные отсутствуют в ячейке A1"
End If
' другой код здесь
Done:
Exit Sub
eh:
Logger "Error", Err.Source, Err.Description
End Sub
Журнал не только для записи ошибок. Вы можете записывать
другую информацию во время работы приложения. При возникновении ошибки вы
можете проверить последовательность событий до того, как произошла ошибка.
Ниже приведен пример регистрации. То, как вы реализуете
журналирование, зависит от характера приложения и его полезности.
Sub ReadingData()
Logger "Information", "ReadingData()", "Starting to read data."
Dim coll As New Collection
' Read data
Set coll = ReadData
If coll.Count < 10 Then
Logger "Warning", "ReadingData()", "Number of data items is low."
End If
Logger "Information", "ReadingData()", "Number of data items is " & coll.Count
Logger "Information", "ReadingData()", "Finished reading data."
End Sub
Наличие большого количества информации при работе с ошибкой
может быть очень полезным. Часто пользователь может не дать вам точную информацию
об ошибке, которая произошла. Глядя на журнал, вы можете получить более точную
информацию об информации.
Другие элементы, связанные с ошибками
В этом разделе рассматриваются некоторые другие инструменты
обработки ошибок, которые есть в VBA. Эти элементы считаются устаревшими, но я
включил их, поскольку они могут существовать в устаревшем коде.
Функция ошибки
Функция Error используется для печати описания ошибки с
заданным номером ошибки. Он включен в VBA для обеспечения обратной
совместимости и не нужен, поскольку вместо него можно использовать описание
Err.Description.
Ниже приведены некоторые примеры
' Распечатать текст «Деление на ноль» Debug.Print Error(11) ' Распечатать текст "Несоответствие типов" Debug.Print Error(13) ' Распечатать текст "Файл не найден" Debug.Print Error(53)
Заявление об ошибке
Заявление об ошибке позволяет имитировать ошибку. Он включен
в VBA для обратной совместимости. Вместо этого вы должны использовать
Err.Raise.
В следующем коде мы моделируем ошибку «Разделить на ноль».
Sub ZayavlObOshibke()
On Error Goto eh
' Это создаст деление на ноль ошибок
Error 11
Exit Sub
eh:
Debug.Print Err.Number, Err.Description
End Sub
Это утверждение включено в VBA для обратной совместимости.
Вместо этого вы должны использовать Err.Raise.
Простая стратегия обработки ошибок
Со всеми различными опциями вы можете быть озадачены тем,
как использовать обработку ошибок в VBA. В этом разделе я покажу вам, как
реализовать простую стратегию обработки ошибок, которую вы можете использовать
во всех своих приложениях.
Основная реализация
Это простой обзор нашей стратегии
- Поместите строку On Error Goto Label в начале нашего верхнего Sub.
- Поместите Label у обработки ошибок в конце нашего верхнего
Sub. - Если происходит ожидаемая ошибка, обработайте ее и продолжайте.
- Если приложение не может продолжить работу, используйте Err.Raise для перехода к метке обработки ошибок.
- В случае непредвиденной ошибки код автоматически перейдет к метке обработки ошибок.
На следующем рисунке показан обзор того, как это выглядит
Следующий код показывает простую реализацию этой стратегии
Public Const ERROR_NO_ACCOUNTS As Long = vbObjectError + 514
Sub BuildReport()
On Error Goto eh
' Если ошибка в ReadAccounts, то перейти к ошибке
ReadAccounts
' Сделай что-нибудь с кодом
Done:
Exit Sub
eh:
' Все ошибки будут прыгать сюда
MsgBox Err.Source & ": Произошла следующая ошибка " & Err.Description
End Sub
Sub ReadAccounts()
' ОЖИДАЕМАЯ ОШИБКА - Может обрабатываться кодом
' Приложение может обрабатывать A1 равным нулю
If Sheet1.Range("A1") = 0 Then
Sheet1.Range("A1") = 1
End If
' ОЖИДАЕМАЯ ОШИБКА - не может быть обработана кодом
' Приложение не может быть продолжено, если нет учетной записи
If Dir("C:ДокументыОтчет.xlsx") = "" Then
Err.Raise ERROR_NO_ACCOUNTS, "UsingErr" _
, "There are no accounts present for this month."
End If
' НЕОЖИДАННАЯ ОШИБКА - не может быть обработана кодом
' Если ячейка B3 содержит текст, мы получим ошибку несоответствия типов
Dim total As Long
total = Sheet1.Range("B3")
' продолжить и читать счета
End Sub
Это хороший способ реализации обработки ошибок, потому что
- Нам не нужно добавлять код обработки ошибок в
каждую подпрограмму. - Если возникает ошибка, то VBA корректно
завершает работу приложения.
Полная стратегия обработки ошибок
Стратегия выше имеет один недостаток. Он не сообщает вам,
где произошла ошибка. VBA не наполняет Err.Source чем-либо полезным, поэтому мы
должны сделать это сами.
В этом разделе я собираюсь представить более полную
стратегию ошибок. Я написал два сабвуфера, которые выполняют всю тяжелую
работу, поэтому все, что вам нужно сделать, это добавить их в свой проект.
Целью этой стратегии является предоставление вам стека * и
номера строки в случае возникновения ошибки.
* Стек — это список вспомогательных функций, которые
использовались в данный момент при возникновении ошибки.
Это наша стратегия
- Разместите обработку ошибок во всех
подпрограммах. - Когда происходит ошибка, обработчик ошибок
добавляет подробности к ошибке и вызывает ее снова. - Когда ошибка достигает самой верхней
подпрограммы, она отображается.
Мы просто «всплываем» из-за ошибки. Следующая диаграмма
показывает простое визуальное представление о том, что происходит, когда в Sub3
возникает ошибка
Единственная грязная часть этого — правильное форматирование
строк. Я написал две подводные лодки, которые справляются с этим, поэтому он
позаботится о вас.
Это две вспомогательные подводные лодки
Option Explicit
Public Const MARKER As String = "NOT_TOPMOST"
' Вызывает ошибку и добавляет номер строки и имя текущей процедуры
Sub RaiseError(ByVal errorno As Long, ByVal src As String _
, ByVal proc As String, ByVal desc As String, ByVal lineno As Long)
Dim sLineNo As Long, sSource As String
' Если маркера нет, тогда RaiseError вызывается впервые.
If Left(src, Len(MARKER)) <> MARKER Then
' Добавить номер строки ошибки, если она есть
If lineno <> 0 Then
sSource = vbCrLf & "Line no: " & lineno & " "
End If
' Добавить маркер и процедуру к источнику
sSource = MARKER & sSource & vbCrLf & proc
Else
' Если ошибка уже возникла, просто добавьте имя процедуры
sSource = src & vbCrLf & proc
End If
' Если код останавливается здесь, убедитесь, что DisplayError находится в верхней части Sub
Err.Raise errorno, sSource, desc
End Sub
' Отображает ошибку, когда она достигает самого верхнего sub
' Примечание: вы можете добавить вызов для входа из этого подпункта
Sub DisplayError(ByVal src As String, ByVal desc As String _
, ByVal sProcname As String)
' Удалить маркер
src = Replace(src, MARKER, "")
Dim sMsg As String
sMsg = " Произошла следующая ошибка: " & vbCrLf & Err.Description _
& vbCrLf & vbCrLf & " Расположение ошибки: "
sMsg = sMsg + src & vbCrLf & sProcname
' Показать сообщение
MsgBox sMsg, Title:="Ошибка "
End Sub
Пример использования этой стратегии
Вот простое кодирование, которое использует эти Sub. В этой стратегии мы не размещаем какой-либо код в верхнем подпрограмме. Мы только вызываем подводные лодки.
Sub Topmost()
On Error Goto EH
Level1
Done:
Exit Sub
EH:
DisplayError Err.source, Err.Description, "Module1.Topmost"
End Sub
Sub Level1()
On Error Goto EH
Level2
Done:
Exit Sub
EH:
RaiseError Err.Number, Err.source, "Module1.Level1", Err.Description, Erl
End Sub
Sub Level2()
On Error Goto EH
' Ошибка здесь
Dim a As Long
a = "7 / 0"
Done:
Exit Sub
EH:
RaiseError Err.Number, Err.source, "Module1.Level2", Err.Description, Erl
End Sub
Результат выглядит так
Если в вашем проекте есть номера строк, результат будет содержать номер строки ошибки.
Примечание: вы можете получить следующую ошибку при использовании этого кода:
“Programmatic Access to Visual Basic Project is not trusted”
Чтобы решить эту проблему, выполните следующие действия.
- Перейдите в раздел «Разработчик» на ленте и
нажмите «Macro Security», которая находится под кодом. - Нажмите «Настройка макроса» в левом списке.
- Поставьте флажок в поле «Доверительный доступ к
объектной модели проекта VBA». - Нажмите Ok.
Обработка ошибок в двух словах
- Обработка ошибок используется для обработки ошибок, возникающих во время работы приложения.
- Вы пишете определенный код для обработки ожидаемых ошибок. Вы используете оператор обработки ошибок VBA
On Error Goto [label] для отправки VBA на метку при возникновении непредвиденной ошибки. - Вы можете получить подробную информацию об ошибке из Err.Description.
- Вы можете создать свою собственную ошибку, используя Err.Raise.
- Использование одного оператора On Error в самой верхней подпрограмме перехватит все ошибки в подпрограммах, которые вызываются отсюда.
- Если вы хотите записать имя Sub с ошибкой, вы можете обновить ошибку и сбросить ее.
- Вы можете использовать журнал для записи информации о приложении, когда оно запущено.
Итак,
в самом общем случае VBA-программа
представляет собой определенную
последовательность команд, которые
выполняются по порядку, одна за другой,
при каждом запуске программы. Сама по
себе любая VBA-программа
является совершенно бесполезной, если
не уметь её запускать на выполнение.
Один
способ мы уже знаем: VBA-программу
можно выполнить в окне редактора VBA,
выбрав команду меню Run=>Run
…, щелкнув на кнопке Run
… панели инструментов Standard
или нажав <F5>.
Несомненно,
это очень удобно при тестировании
программы, но совершенно не подходит
для повседневной работы с ней. Запускать
программу, готовую к выполнению, нужно
(и гораздо удобнее) из того приложения,
в котором вы работаете. При этом
организовать ее запуск в приложении
можно будет с помощью кнопки на панели
инструментов, нажатия определенной
комбинации клавиш, выбора команды меню
или даже, предусмотрев ее автоматический
запуск при открытии документа.
Повторим:
макрос — это та же VBA-программа,
а макрос, написанный самостоятельно
(без использования специальных функций
Microsoft
Office),
— это процедура. Поэтому выполнить
VBA-программу
фактически означает выполнить макрос
или процедуру.
Программа
может включать как одну, так и несколько
процедур, но только одна из этих процедур
будет выполняться первой
при вызове
программы на выполнение — имя этой
первой выполняемой процедуры можно
считать именем всей программы. Эта
первая процедура может вызывать другие
процедуры, но для выполнения всей
программы
вполне необходимо и достаточно запускать
на выполнение только первую процедуру,
а все остальные будут выполняться
автоматически, по мере необходимости,
непосредственно по ходу решения задачи.
При
вызове программы на выполнение из
диалогового окна Макрос следует найти
в этом окне ее имя:
1)
откройте диалоговое окно Макрос в том
VBA-приложении,
в котором будет выполняться ваша
программа, т.е. перейдите на ленте
приложения (для Office
2007) на вкладку Вид, раскройте в группе
Макросы меню и выберите в нем команду
Макросы. Вид диалогового окна Макрос
приложения был показан ранее, однако
некоторые детали в нем могут несколько
отличаться, в зависимости от используемого
VBА-приложения.
2)
в диалоговом окне Макрос
выбираем из списка доступных VBA-программ
(или макросов) имя требуемой программы
и щелкаем по кнопке Выполнить.
3)
если в приведенном в окне списке макросов
интересующая вас программа (или макрос)
отсутствует, откройте раскрывающийся
список Макросы
из
(для Word)
и выберите в нем вместо принимаемого
по умолчанию значения Активных
шаблонов
то, которое описывает документ, в котором
хранится интересующая вас программа.
Для приложения Excel
подобный список называется Находится
в
— по умолчанию в нем выбрано значение
Все открытые
книги.
9.5. Обработка ошибок
При
написании кода VBA-программы
безусловно могут быть допущены ошибки
или случайные описки. Многие из подобных
случайных ошибок редактор VBA
автоматически отслеживает непосредственно
во время написания или редактирования
программного кода. Более сложные
логические ошибки можно обнаружить
компилятором при выполнении процедуры
— он проверяет код процедуры на наличие
ошибок непосредственно перед
преобразованием программы в форму,
понятную для компьютера. Если операция
компиляции не будет успешной, появится
окно с уведомлением об ошибке.
Данный
уровень проверки намного строже, чем
обычная проверка синтаксиса в каждой
строке кода, так как на этом этапе
проверяется правильность ссылок и тип
переменных, а каждый оператор проверяется
на корректность всех его параметров.
Однако
ту часть ошибок, которые все еще остались
необнаруженными компилятором придется
отыскивать самостоятельно. Самыми
простыми ошибками, с которыми вы
непременно
столкнетесь при написании процедур
VBA,
являются ошибки
синтаксиса (syntax
error).
Если при написании программного кода
была допущена синтаксическая ошибка,
редактор VBA
сообщит об этом сразу, не дожидаясь
момента выполнения программы.
Всякий
раз, когда редактор VBA
не сможет понять и корректно интерпретировать
введенную в строку последовательность
символов в качестве того или иного
оператора, этот текст будет выделен
красным цветом. При попытке перейти с
такой строки на другую, редактор VBA
выдаст сообщение о наличии ошибки с
теми или иными разъяснениями. Для того
чтобы описанный выше режим был
активизирован, следует выбрать команду
меню Tools
=> Options
редактора
VBA
и в раскрывшемся диалоговом окне Option
(Параметры) на вкладке Editor
(Редактор)
установить флажок опции Auto
Syntax
Check
(автоматическая проверка синтаксиса).
Обнаруживая
многие ошибки синтаксиса, редактор VBA
информирует о пропущенных запятых,
кавычках и т.д. Однако некоторые
синтаксические ошибки редактор может
обнаружить только тогда, когда программа
начнет выполняться — например, если в
операторе была указана ссылка на
несуществующую в программе метку.
Сообщение о такой ошибке будет выдано,
когда начнется выполнение программы.
Подобные
ошибки следует исправлять сразу же, как
только редактор VBA
их обнаруживает. В некоторых боле сложных
случаях редактор VBA
не может определить, что именно неверно
в синтаксис данного оператора, и только
сообщает о наличии неопознанной им
ошибки.
Кроме
ошибок компиляции, т.е. синтаксических
ошибок, существуют еще и логические
ошибки —
неточности и несоответствия, допущенные
при разработке самого алгоритма,
воплощённого в программе. При наличии
подобных ошибок программа делает не
то, что было запланировано, или делает
что-то не так, как это ожидалось. Причиной
таких несоответствий чаще всего являются
ошибки, заложенные в неверной логике
алгоритма программы. Тогда не следует
искать ошибки в записи операторов;
необходимо еще раз тщательно продумать
саму структуру программы и уточнить
алгоритм ее поведения. Когда правильное
решение будет найдено, вы обязательно
получите требуемый результат.
Существует
еще третий вид ошибок — это ошибки
выполнения. Такие ошибки приводят к
останову выполнения программы вследствие
непредсказуемых ошибок в обрабатываемых
данных или в действиях пользователя.
Они вызывают возникновение непредусмотренных
в программе ситуаций. Такие виды ошибок
далеко не всегда поддаются легкому
обнаружению и исправлению. Здесь на
помощь к разработчику приходят различные
методы тестирования программ с последующей
отладкой.
Вывод:
чем тщательнее будет проведено
тестирование, тем устойчивее и надежнее
будет работать написанная вами программа.
Тестовые задания
Ниже
приведено несколько тестовых заданий,
предназначенных для закрепления
изложенного в этой главе материала. В
каждом задании вам предлагается вопрос
и несколько вариантов ответа на него,
один (или несколько) из которых является
правильным, остальные — нет. Укажите
правильный ответ.
|
№ п/п |
Вопросы |
Предлагаемые |
|
1 |
Общий цикл |
а) анализ задачи,
б) проектирование
в) анализ задачи,
г) анализ задачи, |
|
2 |
Программными |
а) проекты,
б) проекты,
в) программы,
г) проекты, |
|
3 |
Обмен программными |
а) копирования
б) экспорта и
в) совместного
г) пересылки и |
|
4 |
Запуск VBA-программ |
а) ярлыка на
б) сочетания
в) кнопки на
г) команды в меню
д) команды в меню |
|
5 |
Редактор VBA |
а) орфографические, б) синтаксические, в) логические, г) структурные. |
|
6 |
Комментарии в |
а) для повышения
б) для пояснения
в) для защиты
г) для описания |
Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]
- #
- #
- #
- #
- #
- #
- #
- #
- #
- #
- #
Содержание
- Типы ошибок VBA в Excel
- Использование отладки для поиска ошибок компиляции / синтаксиса
- Настройка параметров ошибок (обработанные и необработанные ошибки)
- Обработка ошибок VBA с помощью операторов «при ошибке»
- Объект ошибки
- Рекомендации по обработке ошибок VBA
Независимо от того, насколько вы опытны в программировании на VBA, ошибки всегда будут частью этого.
Разница между новичком и опытным программистом VBA заключается в том, что опытные программисты знают, как эффективно обрабатывать и использовать ошибки.
В этом руководстве я покажу вам различные способы эффективной обработки ошибок в Excel VBA.
Прежде чем мы перейдем к обработке ошибок VBA, давайте сначала разберемся с различными типами ошибок, с которыми вы, вероятно, столкнетесь при программировании в Excel VBA.
В Excel VBA есть четыре типа ошибок:
- Синтаксические ошибки
- Ошибки компиляции
- Ошибки времени выполнения
- Логические ошибки
Давайте быстро поймем, что это за ошибки и когда вы с ними столкнетесь.
Ошибка синтаксиса
Синтаксическая ошибка, как следует из названия, возникает, когда VBA обнаруживает что-то не так с синтаксисом в коде.
Например, если вы забудете часть необходимого оператора / синтаксиса, вы увидите ошибку компиляции.
В приведенном ниже коде, как только я нажимаю Enter после второй строки, я вижу ошибку компиляции. Это потому, что Заявление ЕСЛИ необходимо иметь «Затем‘, Которая отсутствует в приведенном ниже коде.
Примечание: Когда вы вводите код в Excel VBA, он проверяет каждое предложение, как только вы нажимаете клавишу ВВОД. Если VBA обнаруживает, что в синтаксисе чего-то не хватает, он мгновенно отображает сообщение с текстом, который может помочь вам понять недостающую часть.
Чтобы убедиться, что вы видите синтаксическую ошибку всякий раз, когда чего-то не хватает, вам необходимо убедиться, что проверка автосинтаксиса включена. Для этого нажмите «Инструменты», а затем «Параметры». Убедитесь, что в диалоговом окне параметров включена опция «Автоматическая проверка синтаксиса».
Если опция «Автоматическая проверка синтаксиса» отключена, VBA по-прежнему будет выделять строку с синтаксической ошибкой красным цветом, но не будет отображать диалоговое окно с ошибкой.
Ошибка компиляции
Ошибки компиляции возникают, когда что-то отсутствует, что необходимо для запуска кода.
Например, в приведенном ниже коде, как только я попытаюсь запустить код, он покажет следующую ошибку. Это происходит, поскольку я использовал оператор IF Then, не закрывая его обязательным «End If».
Синтаксическая ошибка также является разновидностью ошибки компиляции. Синтаксическая ошибка возникает, как только вы нажимаете клавишу ВВОД, и VBA определяет, что чего-то не хватает. Ошибка компиляции также может возникать, когда VBA не находит ничего недостающего при вводе кода, но это происходит при компиляции или выполнении кода.
VBA проверяет каждую строку при вводе кода и выделяет синтаксическую ошибку, как только строка оказывается неверной и вы нажимаете клавишу ВВОД. С другой стороны, ошибки компиляции выявляются только тогда, когда весь код анализируется VBA.
Ниже приведены несколько сценариев, при которых вы столкнетесь с ошибкой компиляции:
- Использование оператора IF без конечного IF
- Использование оператора For с оператором Next
- Использование оператора Select без использования End Select
- Не объявлять переменную (это работает только при включенном Option Explicit)
- Вызов несуществующей подпрограммы / функции (или с неправильными параметрами)
Примечание о «Option Explicit»: Когда вы добавляете «Option Explicit», вам нужно будет объявить все переменные перед запуском кода. Если есть переменная, которая не была объявлена, VBA выдаст ошибку. Это хорошая практика, поскольку она показывает ошибку, если у вас есть переменная с ошибкой. Вы можете узнать больше о Option Explicit здесь.
Ошибки времени выполнения
Ошибки времени выполнения — это те, которые возникают во время выполнения кода.
Ошибки времени выполнения будут возникать только тогда, когда будут устранены все синтаксические ошибки и ошибки компиляции.
Например, если вы запускаете код, который должен открывать книгу Excel, но эта книга недоступна (либо удалена, либо изменено имя), ваш код выдаст ошибку во время выполнения.
Когда возникает ошибка времени выполнения, код останавливается и отображается диалоговое окно ошибки.
Сообщение в диалоговом окне «Ошибка выполнения» немного более полезно. Он пытается объяснить проблему, что может помочь вам ее исправить.
Если вы нажмете кнопку «Отладка», будет выделена часть кода, которая приводит к ошибке.
Если вы исправили ошибку, вы можете нажать кнопку «Выполнить» на панели инструментов (или нажать F5), чтобы продолжить выполнение кода с того места, где он был оставлен.
Или вы также можете нажать кнопку «Конец», чтобы выйти из кода.
Важный: Если вы нажмете кнопку «Конец» в диалоговом окне, код будет остановлен на той строке, в которой он встречается. Однако все предыдущие строки кода были бы выполнены.
Логические ошибки
Логические ошибки не остановят ваш код, но могут привести к неверным результатам. Это также могут быть самые сложные типы ошибок для устранения.
Эти ошибки не выделяются компилятором, и их нужно устранять вручную.
Один из примеров логической ошибки (с которой я часто сталкиваюсь) — это бесконечный цикл.
Другой пример может быть, когда он дает неправильный результат. Например, вы можете использовать неправильную переменную в коде или добавить две переменные, если одна из них неверна.
Я использую несколько способов устранения логических ошибок:
- Вставьте окно сообщения в какое-либо место в коде и выделите значения / данные, которые могут помочь понять, идет ли eberything, как ожидалось.
- Вместо того, чтобы запускать код за один раз, просматривайте каждую строку одну за другой. Для этого щелкните в любом месте кода и нажмите F8. вы могли бы заметить, что каждый раз, когда вы нажимаете F8, выполняется одна строка. Это позволяет просматривать код по одной строке за раз и определять логические ошибки.
Использование отладки для поиска ошибок компиляции / синтаксиса
Когда вы закончите работу с кодом, рекомендуется сначала скомпилировать его перед запуском.
Чтобы скомпилировать код, выберите параметр «Отладка» на панели инструментов и нажмите «Скомпилировать VBAProject».
Когда вы компилируете проект VBA, он просматривает код и выявляет ошибки (если таковые имеются).
Если он обнаружит ошибку, он покажет вам диалоговое окно с ошибкой. Он обнаруживает ошибки одну за другой. Поэтому, если он обнаружит ошибку, и вы ее исправили, вам нужно снова запустить компиляцию, чтобы найти другие ошибки (если они есть).
Если в вашем коде нет ошибок, параметр Compile VBAProject будет неактивен.
Обратите внимание, что при компиляции будут обнаружены только ошибки «Синтаксис» и «Компиляция». Он НЕ найдет ошибок времени выполнения.
Когда вы пишете код VBA, вы не хотите, чтобы ошибки возникали. Чтобы избежать этого, вы можете использовать множество методов обработки ошибок.
В следующих нескольких разделах этой статьи я расскажу о методах, которые вы можете использовать для обработки ошибок VBA в Excel.
Настройка параметров ошибок (обработанные и необработанные ошибки)
Прежде чем вы начнете работать со своим кодом, вам необходимо проверить один параметр в Excel VBA.
Перейдите на панель инструментов VBA и нажмите Инструменты, а затем нажмите Параметры.
В диалоговом окне «Параметры» перейдите на вкладку «Общие» и убедитесь, что в группе «Перехват ошибок» установлен флажок «Прерывание по необработанным ошибкам».
Позвольте мне объяснить три варианта:
- Прервать все ошибки: Это остановит ваш код на всех типах ошибок, даже если вы использовали методы для обработки этих ошибок.
- Модуль Break in Class: Это остановит ваш код на всех необработанных ошибках, и в то же время, если вы используете такие объекты, как пользовательские формы, он также сломается внутри этих объектов и выделит точную строку, вызвавшую ошибку.
- Перерыв в связи с необработанными ошибками: Это остановит ваш код только для тех ошибок, которые не обрабатываются. Это настройка по умолчанию, так как она обеспечивает уведомление о любых необработанных ошибках. Если вы используете такие объекты, как пользовательские формы, при этом не будет выделена строка, вызывающая ошибку в объекте, а будет выделена только строка, относящаяся к этому объекту.
Примечание: Если вы работаете с такими объектами, как пользовательские формы, вы можете изменить этот параметр на «Прерывание по модулям класса». Разница между №2 и №3 заключается в том, что при использовании Break в модуле класса вы перейдете к определенной строке в объекте, вызывающем ошибку. Вы также можете выбрать этот вариант вместо «Прерывание по необработанным ошибкам».
Вкратце: если вы только начинаете работу с Excel VBA, убедитесь, что установлен флажок «Прерывание при необработанных ошибках».
Обработка ошибок VBA с помощью операторов «при ошибке»
Когда ваш код обнаруживает ошибку, вы можете сделать следующее:
- Игнорируйте ошибку и позвольте коду продолжить
- Имейте код обработки ошибок и запускайте его при возникновении ошибки.
Оба этих метода обработки ошибок гарантируют, что конечный пользователь не увидит ошибку.
Есть несколько операторов «При ошибке», которые вы можете использовать для этого.
При ошибке Возобновить Далее
Когда вы используете в своем коде «Возобновить после ошибки», любая обнаруженная ошибка будет проигнорирована, и код продолжит работу.
Этот метод обработки ошибок используется довольно часто, но при его использовании нужно соблюдать осторожность. Поскольку он полностью игнорирует любые ошибки, которые могут возникнуть, вы не сможете определить ошибки, которые необходимо исправить.
Например, если выполнить приведенный ниже код, он вернет ошибку.
Sub AssignValues () x = 20/4 y = 30/0 End Sub
Это происходит потому, что вы не можете разделить число на ноль.
Но если я использую в этом коде оператор «On Error Resume Next» (как показано ниже), он проигнорирует ошибку, и я не узнаю, что есть проблема, которую необходимо исправить.
Sub AssignValues () При ошибке Возобновить След. X = 20/4 y = 30/0 Конец Sub
On Error Resume Next следует использовать только в том случае, если вы четко знаете, какие ошибки ожидаются от вашего кода VBA, и можете их игнорировать.
Например, ниже приведен код события VBA, который мгновенно добавит значение даты и времени в ячейку A1 только что вставленного листа (этот код добавляется на лист, а не в модуль).
Private Sub Workbook_NewSheet (ByVal Sh As Object) Sh.Range ("A1") = Format (Теперь, "дд-ммм-гггг чч: мм: сс") End Sub
Хотя в большинстве случаев это отлично работает, при добавлении листа диаграммы вместо листа будет отображаться ошибка. Поскольку на листе диаграммы нет ячеек, код выдает ошибку.
Итак, если я использую в этом коде оператор «При ошибке возобновить следующий», он будет работать, как ожидалось, с листами и ничего не будет делать с листами диаграмм.
Private Sub Workbook_NewSheet (ByVal Sh As Object) При ошибке Возобновить Далее Sh.Range ("A1") = Format (Теперь, "dd-mmm-yyyy hh: mm: ss") End Sub
Примечание. Оператор «Возобновить следующее при ошибке» лучше всего использовать, когда вы знаете, с какими ошибками вы, скорее всего, столкнетесь. А затем, если вы считаете, что эти ошибки можно игнорировать, вы можете использовать это.
Вы можете вывести этот код на следующий уровень, проанализировав, была ли ошибка, и отобразив соответствующее сообщение для нее.
В приведенном ниже коде будет отображаться окно сообщения, которое будет информировать пользователя о том, что рабочий лист не вставлен.
Private Sub Workbook_NewSheet (ByVal Sh As Object) При ошибке Возобновить Далее Sh.Range ("A1") = Format (Теперь, "dd-mmm-yyyy hh: mm: ss") Если Err.Number 0, то MsgBox "Похоже на вас вставлен лист диаграммы "& vbCrLf &" Error - "& Err.Description End If End Sub
«Err.Number» используется для получения номера ошибки, а «Err.Description» используется для получения описания ошибки. Они будут рассмотрены позже в этом руководстве.
При ошибке GoTo 0
«On Error GoTo 0» остановит код в строке, которая вызывает ошибку, и отобразит окно сообщения, описывающее ошибку.
Проще говоря, он включает поведение проверки ошибок по умолчанию и показывает сообщение об ошибке по умолчанию.
Тогда зачем вообще его использовать?
Обычно вам не нужно использовать «On Error Goto 0», но это может быть полезно, когда вы используете его вместе с «On Error Resume Next».
Позволь мне объяснить!
Приведенный ниже код выберет все пустые ячейки в выделенном фрагменте.
Подложка SelectFormulaCells () Selection.SpecialCells (xlCellTypeBlanks) .Select End Sub
Но он покажет ошибку, если в выбранных ячейках нет пустых ячеек.
Поэтому, чтобы не отображать ошибку, вы можете использовать «Возобновить при ошибке».
Теперь он также покажет любую ошибку, когда вы запустите приведенный ниже код:
Sub SelectFormulaCells () При ошибке Возобновить следующий выбор. SpecialCells (xlCellTypeBlanks). Выберите End Sub
Все идет нормально!
Проблема возникает, когда есть часть кода, в которой может произойти ошибка, и поскольку вы используете «При ошибке возобновить следующее», код просто проигнорирует ее и перейдет к следующей строке.
Например, в приведенном ниже коде не будет сообщения об ошибке:
Sub SelectFormulaCells () При ошибке Возобновить следующий выбор.SpecialCells (xlCellTypeBlanks) .Select '… дополнительный код, который может содержать ошибку End Sub
В приведенном выше коде есть два места, где может произойти ошибка. В первом месте мы выбираем все пустые ячейки (используя Selection.SpecialCells), а во втором — оставшийся код.
Хотя ожидается первая ошибка, никаких ошибок после нее нет.
Здесь на помощь приходит On Error Goto 0.
Когда вы его используете, вы сбрасываете настройку ошибки на значение по умолчанию, где она начинает показывать ошибки при их обнаружении.
Например, в приведенном ниже коде не будет ошибки, если нет пустых ячеек, но будет сообщение об ошибке из-за ’10 / 0 ‘
Sub SelectFormulaCells () При ошибке Возобновить следующий выбор. SpecialCells (xlCellTypeBlanks). Select On Error GoTo 0 '… больше кода, который может содержать ошибку End Sub
При ошибке Перейти к [ярлык]
Два вышеуказанных метода — «При ошибке возобновить следующее» и «При ошибке перейти к 0» — не позволяют нам по-настоящему обработать ошибку. Один заставляет код игнорировать ошибку, а второй возобновляет проверку ошибок.
On Error Go [Label] — это способ, с помощью которого вы можете указать, что вы хотите делать, если в вашем коде есть ошибка.
Ниже приведена структура кода, в которой используется этот обработчик ошибок:
Sub Test () On Error GoTo Label: X = 10/0 'эта строка вызывает ошибку' … ваш оставшийся код идет сюда Exit Sub Label: 'код для обработки ошибки End Sub
Обратите внимание, что перед меткой обработки ошибок находится подпрограмма выхода. Это гарантирует, что в случае отсутствия ошибок подпрограмма будет закрыта, а код «Label» не будет выполнен. Если вы не используете Exit Sub, он всегда будет выполнять код «Label».
В приведенном ниже примере кода при возникновении ошибки код перескакивает и выполняет код в разделе обработчика (и показывает окно сообщения).
Sub Errorhandler () При ошибке GoTo ErrMsg X = 12 Y = 20/0 Z = 30 Exit Sub ErrMsg: MsgBox «Похоже, произошла ошибка» & vbCrLf & Err.Description End Sub
Обратите внимание, что при возникновении ошибки код уже был запущен и выполнил строки перед строкой, вызвавшей ошибку. В приведенном выше примере код устанавливает значение X как 12, но поскольку ошибка возникает в следующей строке, он не устанавливает значения для Y и Z.
Как только код перейдет к коду обработчика ошибок (ErrMsg в этом примере), он продолжит выполнение всех строк в коде обработчика ошибок и ниже и завершит выполнение подпрограммы.
При ошибке Goto -1
Это немного сложно, и в большинстве случаев вы вряд ли им воспользуетесь.
Но я все же расскажу об этом, поскольку я столкнулся с ситуацией, когда это было необходимо (не стесняйтесь игнорировать и переходить к следующему разделу, если вы ищете только основы).
Прежде чем я углублюсь в механику этого, позвольте мне попытаться объяснить, где это может быть полезно.
Предположим, у вас есть код, в котором обнаружена ошибка. Но все в порядке, поскольку у вас есть один обработчик ошибок. Но что происходит, когда в коде обработчика ошибок появляется еще одна ошибка (да… что-то вроде начального фильма).
В таком случае вы не можете использовать второй обработчик, так как первая ошибка не была устранена. Итак, хотя вы обработали первую ошибку, она все еще существует в памяти VBA. А в памяти VBA есть место только для одной ошибки, а не для двух или более.
В этом сценарии вы можете использовать On Error Goto -1.
Он очищает ошибку и освобождает память VBA для обработки следующей ошибки.
Хватит разговоров!
Теперь позвольте мне объяснить на примерах.
Предположим, у меня есть приведенный ниже код. Это вызовет ошибку, так как есть деление на ноль.
Дополнительный обработчик ошибок () X = 12 Y = 20/0 Z = 30 End Sub
Чтобы справиться с этим, я использую код обработчика ошибок (с именем ErrMsg), как показано ниже:
Sub Errorhandler () При ошибке GoTo ErrMsg X = 12 Y = 20/0 Z = 30 Exit Sub ErrMsg: MsgBox «Похоже, произошла ошибка» & vbCrLf & Err.Description End Sub
Теперь все снова хорошо. Как только возникает ошибка, используется обработчик ошибок и отображается окно сообщения, как показано ниже.
Теперь я расширяю код, чтобы у меня было больше кода в обработчике ошибок или после него.
Sub Errorhandler () При ошибке GoTo ErrMsg X = 12 Y = 20/0 Z = 30 Exit Sub ErrMsg: MsgBox «Кажется, произошла ошибка» & vbCrLf & Err.Description A = 10/2 B = 35/0 End Sub
Поскольку первая ошибка была обработана, а вторая нет, я снова вижу ошибку, как показано ниже.
По-прежнему все хорошо. Код ведет себя так, как мы и ожидали.
Поэтому для обработки второй ошибки я использую другой обработчик ошибок (ErrMsg2).
Sub Errorhandler () При ошибке GoTo ErrMsg X = 12 Y = 20/0 Z = 30 Выход Sub ErrMsg: MsgBox «Похоже, произошла ошибка» & vbCrLf & Err.Description On Error GoTo ErrMsg2 A = 10/2 B = 35 / 0 Exit Sub ErrMsg2: MsgBox "Кажется, снова произошла ошибка" & vbCrLf & Err.Description End Sub
И вот где это не работает должным образом.
Если вы запустите приведенный выше код, он все равно будет выдавать ошибку времени выполнения, даже после того, как будет установлен второй обработчик ошибок.
Это происходит из-за того, что мы не удалили первую ошибку из памяти VBA.
Да, мы справились! Но все еще остается в памяти.
И когда VBA обнаруживает другую ошибку, он все равно зависает с первой ошибкой, и, следовательно, второй обработчик ошибок не используется. Код останавливается на строке, вызвавшей ошибку, и показывает сообщение об ошибке.
Чтобы очистить память VBA и удалить предыдущую ошибку, вам необходимо использовать «On Error Goto -1».
Поэтому, если вы добавите эту строку в приведенный ниже код и запустите ее, она будет работать должным образом.
Sub Errorhandler () При ошибке GoTo ErrMsg X = 12 Y = 20/0 Z = 30 Выход Sub ErrMsg: MsgBox «Похоже, произошла ошибка» & vbCrLf & Err.Description On Error GoTo -1 При ошибке GoTo ErrMsg2 A = 10 / 2 B = 35/0 Выход из подпрограммы ErrMsg2: MsgBox «Похоже, снова произошла ошибка» & vbCrLf & Err.Description End Sub
Примечание: Ошибка автоматически очищается после завершения подпрограммы.Таким образом, «On Error Goto -1» может быть полезен, когда вы получаете две или более двух ошибок в одной и той же подпрограмме.
Объект ошибки
Когда в коде возникает ошибка, для получения подробных сведений об ошибке (например, номера ошибки или описания) используется объект Err.
Свойства объекта Err
Объект Err имеет следующие свойства:
| Свойство | Описание |
| Номер | Число, представляющее тип ошибки. Если ошибки нет, это значение равно 0. |
| Описание | Краткое описание ошибки |
| Источник | Название проекта, в котором произошла ошибка |
| HelpContext | Идентификатор контекста справки для ошибки в файле справки |
| HelpFile | Строка, представляющая расположение папки и имя файла справки. |
Хотя в большинстве случаев вам не нужно использовать объект Err, иногда он может быть полезен при обработке ошибок в Excel.
Например, предположим, что у вас есть набор данных, как показано ниже, и для каждого числа в выделенном фрагменте вы хотите вычислить квадратный корень в соседней ячейке.
Приведенный ниже код может это сделать, но поскольку в ячейке A5 есть текстовая строка, он показывает ошибку, как только это происходит.
Sub FindSqrRoot () Dim rng As Range Set rng = Selection For Each cell In rng cell.Offset (0, 1) .Value = Sqr (cell.Value) Следующая ячейка End Sub
Проблема с этим типом сообщений об ошибках заключается в том, что они ничего не говорят о том, что пошло не так и где возникла проблема.
Вы можете использовать объект Err, чтобы сделать эти сообщения об ошибках более значимыми.
Например, если я сейчас использую приведенный ниже код VBA, он остановит код, как только возникнет ошибка, и покажет окно сообщения с адресом ячейки, в которой есть проблема.
Sub FindSqrRoot () Dim rng As Range Set rng = Selection For each cell In rng On Error GoTo ErrHandler cell.Offset (0, 1) .Value = Sqr (cell.Value) Следующая ячейка ErrHandler: MsgBox "Номер ошибки:" & Err .Number & vbCrLf & _ "Описание ошибки:" & Err.Description & vbCrLf & _ "Ошибка в:" & cell.Address End Sub
Приведенный выше код предоставит вам гораздо больше информации, чем простое «Несоответствие типов», особенно адрес ячейки, чтобы вы знали, где произошла ошибка.
Вы можете дополнительно уточнить этот код, чтобы убедиться, что ваш код работает до конца (вместо прерывания при каждой ошибке), а затем выдает вам список адресов ячеек, в которых возникает ошибка.
Следующий код сделает это:
Sub Найти ErrorCells & vbCrLf & cell.Address On Error GoTo -1 End If Следующая ячейка MsgBox «Ошибка в следующих ячейках» & ErrorCells Exit Sub End Sub
Приведенный выше код выполняется до конца и дает квадратный корень из всех ячеек, в которых есть числа (в соседнем столбце). Затем отображается сообщение, в котором перечислены все ячейки, в которых произошла ошибка (как показано ниже):
Методы объекта Err
Хотя свойства Err полезны для отображения полезной информации об ошибках, есть также два метода Err, которые могут помочь вам с обработкой ошибок.
| Метод | Описание |
| Прозрачный | Очищает все настройки свойств объекта Err |
| Поднимать | Генерирует ошибку времени выполнения |
Давайте быстро узнаем, что это такое и как / зачем их использовать с VBA в Excel.
Err Clear Method
Предположим, у вас есть набор данных, показанный ниже, и вы хотите получить квадратный корень из всех этих чисел в соседнем столбце.
Следующий код получит квадратные корни из всех чисел в соседнем столбце и покажет сообщение о том, что произошла ошибка для ячеек A5 и A9 (поскольку в них есть текст).
Sub Найти ErrorCells & vbCrLf & cell.Address Err.Clear End If Next cell MsgBox «Ошибка в следующих ячейках» & ErrorCells End Sub
Обратите внимание, что я использовал метод Err.Clear в операторе If Then.
После того, как ошибка возникла и была перехвачена условием If, метод Err.Clear сбрасывает номер ошибки обратно на 0. Это гарантирует, что условие IF перехватывает ошибки только для тех ячеек, в которых оно возникло.
Если бы я не использовал метод Err.Clear, при возникновении ошибки она всегда была бы истинной в условии IF, и номер ошибки не был сброшен.
Другой способ сделать это — использовать On Error Goto -1, который полностью сбрасывает ошибку.
Примечание: Err.Clear отличается от On Error Goto -1. Err.Clear очищает только описание ошибки и номер ошибки. он не сбрасывает его полностью. Это означает, что если в том же коде есть еще один экземпляр ошибки, вы не сможете обработать его до его сброса (что можно сделать с помощью «On Error Goto -1», а не «Err.Clear»).
Err Raise Method
Метод Err.Raise позволяет вызвать ошибку времени выполнения.
Ниже приведен синтаксис использования метода Err.Raise:
Err.Raise [номер], [источник], [описание], [файл справки], [контекст помощи]
Все эти аргументы являются необязательными, и вы можете использовать их, чтобы сделать ваше сообщение об ошибке более значимым.
Но зачем вам самому создавать ошибку?
Хороший вопрос!
Вы можете использовать этот метод, когда есть экземпляр ошибки (что означает, что в любом случае произойдет ошибка), а затем вы используете этот метод, чтобы сообщить пользователю больше об ошибке (вместо менее полезного сообщения об ошибке, которое показывает VBA. по умолчанию).
Например, предположим, что у вас есть набор данных, показанный ниже, и вы хотите, чтобы все ячейки имели только числовые значения.
Sub RaiseError () Dim rng As Range Set rng = Selection On Error GoTo ErrHandler For each Cell in rng If Not (IsNumeric (Cell.Value)) Then Err.Raise vbObjectError + 513, Cell.Address, "Not a number", " Test.html "End If Next Cell ErrHandler: MsgBox Err.Description & vbCrLf & Err.HelpFile End Sub
В приведенном выше коде будет отображаться сообщение об ошибке с указанным описанием и файлом контекста.
Лично я никогда не использовал Err.Raise, так как в основном работаю только с Excel. Но для тех, кто использует VBA для работы с Excel вместе с другими приложениями, такими как Outlook, Word или PowerPoint, это может быть полезно.
Вот подробная статья о методе Err.Raise, если вы хотите узнать больше.
Рекомендации по обработке ошибок VBA
Независимо от того, насколько квалифицированно вы пишете код VBA, ошибки всегда будут его частью. Лучшие кодировщики — это те, кто умеет правильно обрабатывать эти ошибки.
Вот несколько рекомендаций, которые вы можете использовать при обработке ошибок в Excel VBA.
- Используйте «On Error Go [Label]» в начале кода. Это гарантирует, что любая ошибка, которая может произойти оттуда, будет обработана.
- Используйте «Возобновить при ошибке» ТОЛЬКО в том случае, если вы уверены в том, какие ошибки могут произойти. Используйте его только с ожидаемой ошибкой. Если вы используете его с неожиданными ошибками, он просто проигнорирует его и двинется вперед. Вы можете использовать «On Error Resume Next» с «Err.Raise», если хотите игнорировать определенный тип ошибки и улавливать остальные.
- При использовании обработчиков ошибок убедитесь, что вы используете Exit Sub перед обработчиками. Это гарантирует, что код обработчика ошибок будет выполняться только при возникновении ошибки (иначе он будет выполняться всегда).
- Используйте несколько обработчиков ошибок для перехвата различных типов ошибок. Наличие обработчика множественных ошибок гарантирует, что ошибка будет исправлена должным образом. Например, вы хотите обрабатывать ошибку «несоответствие типа» иначе, чем ошибку времени выполнения «Деление на 0».
Надеюсь, вы нашли эту статью в Excel полезной!
Вот еще несколько руководств по Excel VBA, которые могут вам понравиться:
- Типы данных Excel VBA — полное руководство
- Циклы Excel VBA — для «Далее», «Сделать пока», «Сделать до», «Для каждого»
- События Excel VBA — простое (и полное) руководство
- Редактор Excel Visual Basic — как открыть и использовать в Excel
Обработка ошибок Excel VBA
В VBA, когда мы работаем с кодами, мы можем столкнуться со многими различными типами ошибок, и способ устранения этих ошибок известен как обработка ошибок, теперь могут быть некоторые ошибки, которые сделаны в синтаксисе, который сам выделяет это, но когда есть какая-то ошибка который выходит за пределы диапазона или что-то, чего не существует Excel дает нам всплывающее окно для того же самого, важно знать, какой код ошибки для какой ошибки, чтобы идентифицировать ошибку в коде.
В Excel VBA при выполнении любого набора кодов мы получаем какие-то ошибки. Некоторые из этих ошибок являются синтаксическими; некоторые из них являются неисполняемыми ошибками. Синтаксическая ошибка, сделанная пользователем, выделяется красным цветом самим Excel. Но когда возникает какая-либо другая ошибка времени выполнения, как мы с ней справимся и как выйти за рамки этого, мы рассмотрим в этой статье.
Помимо синтаксических ошибок, другие ошибки времени выполнения необходимо обрабатывать при выполнении любого набора кодов. Во-первых, позвольте мне привести пример того, как возникает другая ошибка времени выполнения. Взгляните на приведенный ниже код,
Это пример кода, который при выполнении вернет то, что написано в функции msgbox. Но, как мы видим, во второй строке кода есть 4/0, что невозможно с математической точки зрения, поэтому он вернет ошибку времени выполнения. Давайте выполним приведенный выше код и увидим ошибку, которую мы получим.
Это ошибка, которую мы получаем при выполнении данного кода. Теперь, как мы обрабатываем эту ошибку, производится обработкой ошибок.
Существует два метода обработки ошибок:
- При ошибке Перейти к и
- При ошибке Возобновить дальше.
Объяснение
Как объяснялось выше, мы получаем много типов ошибок в VBA. Некоторые из них являются синтаксисом, а некоторые — временем выполнения. Синтаксические ошибки уже выделены красным цветом, например, см. скриншот ниже,
В то время как другие ошибки времени выполнения. По сути, Excel выполняет следующие три действия: либо показывает ошибку, либо игнорирует эту ошибку, либо показывает определенный набор инструкций. Для выполнения таких задач нам нужно давать инструкции, и это называется обработкой ошибок.
Как обрабатывать ошибки в коде VBA?
Вы можете скачать этот шаблон Excel для обработки ошибок VBA здесь — Шаблон Excel для обработки ошибок VBA
Пример №1
В качестве первого примера возьмем первый код, который мы взяли в качестве демонстрации. В приведенном выше примере мы видели, что код выдает ошибку времени выполнения во второй функции msgbox.
Напишите следующий код после открытия подфункции,
Код:
Sub Sample() On Error Resume Next MsgBox 4 / 2 MsgBox 4 / 0 MsgBox 4 / 1 End Sub
Теперь, когда мы выполняем приведенный выше код, мы видим, что строка кода с ошибкой не выполняется. Excel пропускает эту строку и возобновляет работу на следующей строке.
Существует еще один способ обработки ошибки — VBA. Заявление о переходеОператор VBA GoTo позволяет перейти к строке кода, пропуская все ошибки между ними. Существует два типа операторов GOTO: один — выбрать любой диапазон рабочего листа в указанной книге, а другой — обработчик ошибок.читать далее. Мы предоставляем Excel в качестве места назначения для перехода при обнаружении ошибки. Вместо предыдущего кода обработки ошибок мы вставили, запишите следующий код,
Код:
Sub Sample() On Error GoTo az MsgBox 4 / 2 MsgBox 4 / 0 MsgBox 4 / 1 End Sub
Мы даем Excel Az в качестве пункта назначения, к которому можно перейти, если он обнаружит ошибку. Теперь после msgbox напишите еще один код, как показано ниже,
Код:
Sub Sample() On Error GoTo az MsgBox 4 / 2 MsgBox 4 / 0 MsgBox 4 / 1 Done: Exit Sub
Теперь нам нужно определить пункт назначения az как то, что он должен делать, когда Excel находит ошибку в коде.
Код:
Sub Sample() On Error GoTo az MsgBox 4 / 2 MsgBox 4 / 0 MsgBox 4 / 1 Done: Exit Sub az: MsgBox "This is an error " & Err.Description End Sub
Теперь, когда мы запускаем этот код, мы видим отображаемый результат.
Это первый результат окна сообщения, и, поскольку мы знаем, что у нас есть ошибка в следующей строке нашего кода, давайте посмотрим результат, который даст Excel.
err.description выше в коде помогает нам точно показать, какая ошибка произошла в нашем коде.
Пример #2
Мы научились обрабатывать ошибки в наших кодах. Давайте посмотрим на другой пример того, как обрабатывать ошибки. Рассмотрим следующий код в качестве нашего второго примера.
У нас есть чем-то похожая ошибка из примера 1. Ошибка в строке d = i/b. Теперь мы будем обрабатывать эти ошибки, используя два описанных выше метода.
Напишите следующий код после открытия подфункции,
Код:
Sub Sample2() On Error Resume Next bx Dim i As Integer, b As Integer, c As Integer, d As Integer i = 2 b = 0 c = i + b MsgBox c d = i / b MsgBox d End Sub
Теперь, когда мы выполняем наш код, мы видим, что он игнорирует вторую строку и просто отображает значение для C.
Вышеупомянутый обработчик ошибок был следующим для возобновления, и теперь мы будем использовать Go to, в котором мы скажем, что превосходим пункт назначения для перехода, когда он обнаруживает ошибку. Запишите следующий код,
Код:
Sub Sample2() On Error GoTo bx Dim i As Integer, b As Integer, c As Integer, d As Integer i = 2 b = 0 c = i + b MsgBox c d = i / b MsgBox d
bx — это пункт назначения, который выдается при возникновении ошибки после того, как msgbox D запишет следующий код:
Код:
Sub Sample2() On Error GoTo bx Dim i As Integer, b As Integer, c As Integer, d As Integer i = 2 b = 0 c = i + b MsgBox c d = i / b MsgBox d DOne: Exit Sub
Теперь нам нужно определить пункт назначения Bx, что он должен делать при обнаружении ошибки. Поэтому запишите следующий код:
Код:
Sub Sample2() On Error GoTo bx Dim i As Integer, b As Integer, c As Integer, d As Integer i = 2 b = 0 c = i + b MsgBox c d = i / b MsgBox d DOne: Exit Sub bx: MsgBox " This is another Error " & Err.Description End Sub
Теперь, когда мы выполняем код, мы видим, что Excel сначала дает нам значение для C.
Теперь на другом этапе он даст нам подсказку, которую мы ему предоставили, когда он обнаружит ошибку.
Вот как мы обрабатываем обычную среду выполнения ошибки в экселеОшибки в Excel распространены и часто возникают во время применения формул. Список из девяти наиболее распространенных ошибок Excel: #DIV/0, #N/A, #NAME?, #NULL!, #NUM!, #REF!, #VALUE!, #####, Circular Reference.читать далее VBA.
То, что нужно запомнить
Есть несколько вещей, которые нам нужно помнить об обработке ошибок:
- При следующем возобновлении ошибки игнорирует ошибку.
- On Error GoTo Отображает пункт назначения excel при обнаружении ошибки.
- Описание используется для отображения точной ошибки, возникшей у пользователя.
УЗНАТЬ БОЛЬШЕ >>
Post Views: 676
Коды ошибок vba excel
Поискав по рунету материал на тему обработки ошибок в VBA, не увидал на первых двух страницах результатов поиска чего-то, что мне понравилось. Может плохо смотрел, но решил написать на эту тему свою статью.
Простите, но — немного словоблудия 🙂
Ошибки в программе
Ошибки времени исполнения программы возникают, когда среда программирования не может выполнить то, что вы хотите. Таких ситуаций может быть много. Например:
Вы обращаетесь к объекту по имени, а объекта с таким именем в коллекции нет
Вы хотите выделить ячеку на одном листе, а этот лист в данный момент не является активным (типичнейшая ошибка новичков в Excel VBA)
Вы хотите удалить отфильтрованные автофильтром строки, а фильтр вообще не вернул записей и удалять нечего
Вы ссылаетесь на элемент массива, который находится за пределами его границ.
Вы пытаетесь присвоить переменной значение, которое оно не может хранить. Например, переменной типа Long нельзя присвоить строковую константу или переменной типа Integer присвоить знанчение превышающее число 32767 .
На любую из этих и сотни других ситуаций среда выполнения реагирует стандартно — прерывает ход выполнения программы на том операторе, где возникла ошибка или, как ещё принято говорить, исключение. На экран выводится информация о возникшей ошибке и предлагаются стандартные варианты для продолжения работы:
Continue (продолжить) — этот пункт во время возникновения ошибки всегда не активен. Он активен, когда по ходу выполнения программы вы использовали оператор Stop . Кстати это очень полезный оператор для отладки программы.
End (завершить) — завершение исполнения программы
Debug (отладка) — переход в режим отладки, в котором можно посмотреть, на каком операторе возникла ошибка, что содержат переменные, можно даже перетащить жёлтую полоску, подсвечивающую текущий оператор, назад, и модифицировать знанчение переменных через окно Immediate window (впрочем это экзотика). В общем случае кнопка Debug позволяет посмотреть, где случилась ошибка и попытаться понять почему так случилось.
Если вы — автор программы, в которой случилась ошибка, то вы, должно быть, в начале будете рады увидеть подобное окно, ибо только так вы сможете отловить основные ошибки, скрытые в вашем коде. Однако, если эту ошибку видит пользователь, то для него это, мягко говоря, безрадостное и малопонятное зрелище. Ещё хуже, если за эту программу вам заплатили деньги. Поэтому в среде худо-бедно профессиональных программистов принято предусматривать обработку ошибок в своих программах.
Почему вообще в коде возникают ошибки?
Много ошибок во время написания кода возникает по невнимательности или не совсем адекватного понимания того, что делаешь. Таких ошибок, как правило, очень много, особенно у начинающих программистов, но эти ошибки довольно легко отловить и исправить, так как, пока вы их не исправите, ничего не работает. Ну, например, вы должны извлечь данные из 5-го столбца, а вы извлекаете из 6-го, а их там банально нет. Ясно, что вы это очень быстро заметите.
Вторая группа ошибок — это ошибки оптимиста. Когда программа написана в целом правильно, но алгоритм не готов к ударам судьбы в виде неожиданных действий со стороны пользователя, ошибок ввода-вывода (вы рассчитывали считать данные из файла, а файла с таким именем не оказалось, либо он заблокирован другим приложением), особенностей конфигурации компьютера (разные версии ОС или офиса, которые в некоторых мелочах отличаются).
Тонкие логические ошибки. Чем сложнее программа, тем больше шансов, что модель задачи в вашей голове, ваша программа и реальность не совсем согласованы между собой. Пока вы не достигните достаточного погружения в задачу вы такие ошибки не найдёте и не исправите. Порой на это уходит много времени. Но это характерно для сложных задач.
Ошибки на стыке вашего приложения и сервисов ОС, приводящие к неожиданным крахам приложения. Такого вообще возникать не должно, но как мы понимаем, и ОС и офис содержат ошибки, да и вы (что более вероятно) можете пользоваться системными вызовами не правильно. Подобные ошибки — сущий кошмар, особенно когда они проявляются лишь на некоторых конфигурациях, при определенных условиях, их трудно поймать и надёжно воспроизвести.
Задачи механизмов обработки ошибок
Обеспечить стабильную работу программы . Возникновение ошибки, появление которой вы не предусмотрели, приведёт в большинстве случаев к аварийному завершению всей программы или её части. При определенном уровне подобных ситуаций это ведёт к тому, что программой пользоваться становится невозможно.
Информирование . Мало обработать ошибку и предотвратить завершение программы. Надо ещё и адекватно проинформировать пользователя о причинах нестандартного поведения программы. Частно причиной ошибок в программе являются некорректные действия пользователя, поэтому важно сообщать ему о них.
Защита данных от повреждения . Программа обязана защищать от непреднамеренных повреждений результаты своей или пользовательской работы. Деструктивные действия должны быть снабжены соответствующими предупредительными диалоговыми окнами. Часто ошибка, не обработанная должным образом может повредить нужные данные.
Файл примера
Скачать
Код без обработки ошибок
Вот простой пример с потолка. Если вызвать Example_00 , то она прекрасно отработает без ошибок и вернёт это:
В функцию GetCalories передаётся строка с блюдом, а она должна вернуть его калорийность, сверившись с таблицей в A1:B7 .
Давайте поищем слабые места в этом коде. Первое, что должно прийти в голову — если мы ищем, то, что произойдёт, если мы не найдём? А произойдёт, конечно же, ошибка. Её инициирует метод Match .

Ещё одно слабое место этой подпрограммы: функция возвращает вещественный тип Double , и даже, если поиск оказался удачным, то в Cells(intRow, 2) может случайно находиться текстовая строка, а потому, когда вы числовому типу попытаетесь присвоить строковый тип, также произойдёт ошибка. И, если вы второй ошибки сможете избежать за счёт дополнительного оператора if с проверкой через IsNumber (), то избежать первой ошибки таким способом нельзя. Что же делать? А вот тут на сцену выходят операторы обработки ошибок.
Есть 2 подхода к обработке ошибок: автономный подход и выносной . Эти термины я придумал только что, чтобы проще было их обсуждать.
Автономный подход
Смысл автономного подхода в том, чтобы не выносить сор из избы. Если в подпрограмме возникла ошибка, то мы должны предположить, на каком месте она возникнет и поджидать её там с дубиной. С ошибкой, в этом случае, разбираются обычно в операторе, идущем сразу после потенциально опасного места. Давайте смотреть, как это может выглядеть:
Итак, что тут сделано:
Сразу после объявления функции GetCalories_v1 идёт оператор on error resume next , который в случае возникновения в каком-либо месте ошибки, предписывает VBA просто передавать управление на следующий оператор, идущий после ошибочного.
Мы объявили переменные. Необъявленные переменные получают тип Variant и значение по умолчанию Empty . Объявленные переменные числовых типов инициируются нулём, строковые — пустой строкой, то есть я наперёд знаю, что они содержат, а это хорошо для обработки ошибок.
На вызове метода WorksheetFunction.Match у нас возникает ошибка, так как искомого значения в таблице нет. А это, между прочим, был оператор присваивания ( = ). Прежде, чем левой части оператора присваивания ( intRow ) что-то будет присвоено, необходимо вычислить правую часть оператора присваивания ( WorksheetFunction.Match . ), а поскольку в процессе этого вычисления возникает ошибка, то переменная intRow остаётся такой, какой была! А, как я уже сказал, VBA автоматически её инициализирует нулём до начала исполнения подпрограммы. Получается, что, если в этом операторе возникнет ошибка, то в intRow будет ноль. Если ошибки во время поиска не возникнет, то ноля там не будет ни при каких раскладах, так как строки на листе нумеруются с единицы.
И вот этот ноль мы и контролируем, добавляя оператор If . Если intRow больше нуля, то WorksheetFunction.Match отработала штатно, а если нет — то работу подпрограммы надо прерывать, но об этом чуть позже.
Далее мы помним, что Cells(intRow, 2) может теоретически вернуть строковое значение, которое вызовет ошибку Type missmatch при присвоении переменной типа Double ( GetCalories_v1 ), поэтому мы вставляем дополнительную проверку промежуточной переменной varTemp тому, что она числовая. И если это так, то присваиваем GetCalories_v1 значение из varTemp .
В случае возникновения любой ошибки внутри GetCalories_v1 она просто вернёт ноль. Почему ноль? Потому что переменная GetCalories_v1 тоже инициализируется нулём и об этом не надо заботиться, а в случае ошибки она останется в неприкосновенности.
Соответственно родительский код (в нашем случае его роль играет процедура Example_01 ) должен проверить, а не вернёт ли GetCalories_v1 ноль, и быть готовым к этой ситуации.
А вот теперь тонкий момент, который не все понимают. Почему я использовал промежуточные переменные intRow и varTemp ? Вроде бы есть очевидный ответ — чтобы не вычислять значение выражений с Match и Cells 2 раза. Отчасти это, конечно, так. Но это, в данном случае, не главная причина. Главная причина в том, что такой код
вызовет неправильное поведение программы. Если у нас Match вызовет исключение, то VBA передаст управление на СЛЕДУЮЩИЙ оператор, а следующий оператор в данном случае это то, что идёт после Then — присваивание переменной varTemp значения. Таким образом наша проверка на наличие ошибки сработает с точностью до наоборот, передав управление в ту часть кода, которая должна быть защищена от ситуации, когда Match не нашла строку в таблице. Вот почему важно в операторе If не иметь ничего такого, что могло бы вызвать ошибку.
Как видите, в этом подходе мне зачастую даже нет необходимости проверять объект Err , чтобы понять, что произошла ошибка, так как я ориентируюсь на то, что промежуточные переменные остаются неинициализированными, что является показателем наличия ошибки.
Выносной подход
Данный метод основан на том, что, когда возникает ошибка, то VBA передаёт управление на специальный участок кода — обработчик ошибок, который обычно размещают в конце подпрограммы. Это может выглядеть так:
Обратите внимание, что:
Оператор on error теперь в случае ошибки предписывает передавать управление на метку ErrorHandler , которая объявлена в конце кода процедуры GetCalories_v2
В коде мы никак не заботимся о каких-либо проверках. Возникла ошибка? Иди на метку — там разберутся.
Если ошибки не случилось, то, чтобы программа не стала исполнять строчки, предназначенные для обработки ошибок, перед меткой ErrorHandler обычно ставят оператор Exit Sub или Exit Function (в зависимости от типа подпрограммы).
Принципиальный момент — наличие оператора On Error Resume Next сразу после метки ErrorHandler . Дело в том, что после того, как вы перешли на метку ErrorHandler , очень опасно иметь действующим оператор On Error GoTo ErrorHandler , так как, если у вас в обработчике ошибки случится любая ошибка, то управление будет передано опять на метку и, как нетрудно понять, образуется бесконечный цикл. Поэтому сразу после метки мы возможность возникновения цикла ликвидируем оператором On Error Resume Next .
Что лучше?
Какой метод лучше применять зависит от ваших предпочтений и конкретных ситуаций. Грамотную обработку ошибок можно сделать и так и эдак. Вот несколько соображений по преимуществам и недостакам данных подходов:
excel-vba Обработка ошибок
пример
Хорошая обработка ошибок не позволяет конечным пользователям видеть ошибки времени выполнения VBA и помогает разработчику легко диагностировать и исправлять ошибки.
Существует три основных метода обработки ошибок в VBA, два из которых следует избегать для распределенных программ, если это специально не требуется в коде.
По ошибке GoTo 0
Если в вашем коде не установлена ошибка, On Error GoTo 0 является обработчиком ошибок по умолчанию. В этом режиме любые ошибки времени выполнения запускают типичное сообщение об ошибке VBA, позволяющее либо закончить код, либо ввести режим debug , идентифицируя источник. При написании кода этот метод является самым простым и полезным, но его всегда следует избегать для кода, который распространяется среди конечных пользователей, поскольку этот метод очень непригляден и затруднен для понимания конечными пользователями.
On Error Resume Next VBA будет игнорировать любые ошибки, возникающие во время выполнения для всех строк, следующих за вызовом ошибки, до тех пор, пока обработчик ошибок не будет изменен. В очень конкретных случаях эта строка может быть полезна, но ее следует избегать за пределами этих случаев. Например, при запуске отдельной программы из макроса Excel вызов On Error Resume Next может быть полезен, если вы не уверены, открыта ли программа или нет:
Если бы мы не использовали GetObject вызов On Error Resume Next и приложение Powerpoint еще не было открыто, метод GetObject бы ошибку. Таким образом, для устранения двух экземпляров приложения необходимо было On Error Resume Next .
Примечание. Также рекомендуется сразу же сбросить обработчик ошибок, как только вам больше не понадобится On Error Resume Next вызова»
Вкл. Ошибка GoTo
Этот метод обработки ошибок рекомендуется для всего кода, который распространяется среди других пользователей. Это позволяет программисту точно контролировать, как VBA обрабатывает ошибку, отправив код в указанную строку. Тег можно заполнить любой строкой (включая числовые строки) и отправить код в соответствующую строку, за которой следует двоеточие. Несколько блоков обработки ошибок можно использовать, выполняя различные вызовы On Error GoTo
Примечание. Важно, чтобы строка Exit Sub была помещена над первым обработчиком ошибок и перед каждым последующим обработчиком ошибок, чтобы предотвратить естественный переход кода в блок без вызываемой ошибки. Таким образом, лучше всего использовать функцию и читаемость для размещения обработчиков ошибок в конце блока кода.
Если вы выйдете из своего метода с кодом обработки ошибок, убедитесь, что вы очистили:
- Отменить все, что частично завершено
- Закрыть файлы
- Сбросить обновление экрана
- Сбросить режим расчета
- Сбросить события
- Сбросить указатель мыши
- Вызов метода выгрузки для экземпляров объектов, которые сохраняются после End Sub
- Сброс строки состояния
Типы ошибок в VBA
При выполнении макросов Excel могут возникнуть ошибки, которые в VBA делят на три категории:
Далее мы поговорим о каждом из трёх типов ошибок VBA подробно.
Ошибки компиляции
Компилятор VBA рассматривает ошибки компиляции как недопустимые и выделяет их в коде ещё до того, как дело дойдёт до запуска макроса.
Если при написании кода допущена синтаксическая ошибка, то редактор VBA сигнализирует об этом немедленно: либо при помощи окна с сообщением, либо выделяя ошибку красным цветом, в зависимости от статуса режима Auto Syntax Check.
Примечание: При включённом режиме Auto Syntax Check каждый раз, при появлении в редакторе Visual Basic во введённом коде синтаксической ошибки, будет показано соответствующее сообщение. Если же этот режим выключен, то редактор VBA продолжит сообщать о синтаксических ошибках, просто выделяя их красным цветом. Опцию Auto Syntax Check можно включить/выключить в меню Tools > Options редактора Visual Basic.
В некоторых случаях ошибка компиляции может быть обнаружена при выполнении компиляции кода, непосредственно перед тем, как макрос будет выполнен. Обычно ошибку компиляции несложно обнаружить и исправить, потому что компилятор VBA даёт информацию о характере и причине ошибки.
Например, сообщение “Compile error: Variable not defined” при попытке запустить выполнение кода VBA говорит о том, что происходит попытка использовать или обратиться к переменной, которая не была объявлена для текущей области (такая ошибка может возникнуть только если используется Option Explicit).
Ошибки выполнения
Ошибки выполнения возникают в процессе выполнения кода и приводят к остановке выполнения программы. Этот тип ошибок VBA, как правило, также не сложно обнаружить и исправить, так как сообщается информация о характере ошибки и место в коде, где произошла остановка.
Примером такой ошибки может служить попытка выполнить деление на ноль. В результате будет показано сообщение “Run-time error ’11’: Division by zero“.
В зависимости от структуры проекта VBA, может быть предложено выполнить отладку кода (как показано на рисунке ниже). В этом случае при нажатии на кнопку Debug (в окне сообщения о необходимости отладки) будет выделена цветом строка кода, которая стала причиной ошибки VBA.
Получив такое сообщение и видя выделенную строку кода, как в приведённом выше примере, обнаружить причину ошибки будет совсем не сложно.
В случае если код сложнее, чем в нашем примере, то, чтобы получить больше информации о причине возникновения ошибки VBA, можно проверить значения используемых переменных. В редакторе VBA для этого достаточно навести указатель мыши на имя переменной, или можно открыть окно отслеживания локальных переменных (в меню редактора View > Locals Window).
Коды различных ошибок выполнения расшифрованы на сайте Microsoft Support (на английском). Наиболее часто встречающиеся ошибки VBA перечислены в этой таблице:
11. Типы ошибок в программах. Перехват ошибок времени выполнения
Лабораторная работа 11.1 Перехват ошибок времени выполнения
Обработка ошибок в макросах VBA в Excel, ошибки времени выполнения (run-time errors)
Подготовка:
1. Создайте новый файл Excel и сохраните его как C:ErrorHandling. xls .
2. В ячейку A1 этого файла введите значение «Результат деления:».
3. Щелкните правой кнопкой мыши по любой панели инструментов или меню и в открывшемся списке доступных панелей инструментов выберите Элементы управления.
4. На панели инструментов Элементы управления нажмите кнопку Режим конструктора (верхняя левая кнопка) и в этом режиме поместите на лист Excel новую кнопку. Для этого нужно щелкнуть по объекту Кнопка на панели инструментов Элементы управления и на листе определить местонахождение и размеры этой кнопки.
5. Щелкните по созданной вами кнопке правой кнопкой мыши и в контекстном меню выберите Свойства. Определите для нее свойства по вашему усмотрению.
6. В режиме конструктора щелкните по кнопке правой кнопкой мыши и в контекстном меню выберите Исходный текст. Откроется редактор кода Visual Basic с созданной процедурой для события Click данной кнопки. Поместите в него следующий код :
Private Sub CommandButton1_Click()
Dim nNum1 As Integer
Dim nNum2 As Integer
Dim nResult As Integer
nNum 1 = InputBox («Введите первое число»)
nNum 2 = InputBox («Введите второе число»)
nResult = nNum1 / nNum2
7. Вернитесь на ваш лист Excel , выйдите из режима конструктора (щелкнув по кнопке Выход из режима конструктора на панели инструментов Элементы управления) и нажмите на созданную вами на листе кнопку. Убедитесь, что если вводить допустимые значения для делимого и делителя, то код работает правильно и выводит результат деления в ячейку B2.
Задание:
Измените эту программу таким образом, чтобы обеспечить защиту от ввода пользователем недопустимых значений (например, строковых значений делимого и делителя или значения делителя, равного 0).
Не обязательно оставлять код по приему значений от пользователя и выполнению деления в обработчике события Click вашей кнопки. Этот код при желании можно перенести во внешние процедуры или функции.
Решение:
Существует множество вариантов решения этой задачи. Примеры приведены далее.
Так, например, может выглядеть решение с обработкой кода ошибки и повторным вызовом функцией самой себя:
Private Sub CommandButton1_Click()
Public Sub subPrepare()
Dim nReturnCode As Integer
Dim nAnswer As Integer
Select Case nReturnCode
MsgBox («Делить на ноль нельзя!»)
nAnswer = MsgBox(«Повторить?», vbYesNo)
If nAnswer = vbYes Then
MsgBox (» Нужно число !»)
nAnswer = MsgBox(«Повторить?», vbYesNo)
If nAnswer = vbYes Then
MsgBox (» Неизвестная ошибка «)
nAnswer = MsgBox(«Повторить?», vbYesNo)
If nAnswer = vbYes Then
On Error Resume Next
Dim nNum1 As Integer
Dim nNum2 As Integer
Dim nResult As Integer
nNum1 = InputBox(» Введите первое число «)
nNum 2 = InputBox («Введите второе число»)
nResult = CInt(nNum1) / CInt(nNum2)
Select Case Err.Number
А вот решение с обработкой кода ошибки и циклом:
Private Sub CommandButton1_Click()
Dim nNum1 As Variant
Dim nNum2 As Variant
Dim nResult As Integer
Dim nError As Integer
nNum1 = InputBox(» Введите первое число :»)
On Error Resume Next
If Err.Number = 13 Then
MsgBox (» Нужно число «)
On Error GoTo 0
Loop While (nNum1 = «»)
nNum2 = InputBox(» Введите второе число :»)
On Error Resume Next
If Err.Number = 13 Then
MsgBox (» Нужно число «)
ElseIf nNum 2 = 0 Then
MsgBox («Делить на ноль нельзя!»)
On Error GoTo 0
Loop While (nNum2 = «»)
nResult = nNum1 / nNum2
Еще один вариант решения вообще не допускает возникновения ошибок:
Private Sub CommandButton1_Click()
Dim nNum1 As Variant
Dim nNum2 As Variant
Dim nResult As Integer
nNum 1 = InputBox («Введите первое число:»)
If IsNumeric(nNum1 & «») Then Exit Do
MsgBox «Нужно число»
nNum 2 = InputBox («Введите второе число:»)
Коды ошибок vba excel
Pearson Software Consulting Services
Error Handling In VBA
Error handling refers to the programming practice of anticipating and coding for error conditions that may arise when your program runs. Errors in general come in three flavors: compiler errors such as undeclared variables that prevent your code from compiling; user data entry error such as a user entering a negative value where only a positive number is acceptable; and run time errors, that occur when VBA cannot correctly execute a program statement. We will concern ourselves here only with run time errors. Typical run time errors include attempting to access a non-existent worksheet or workbook, or attempting to divide by zero. The example code in this article will use the division by zero error (Error 11) when we want to deliberately raise an error.
Your application should make as many checks as possible during initialization to ensure that run time errors do not occur later. In Excel, this includes ensuring that required workbooks and worksheets are present and that required names are defined. The more checking you do before the real work of your application begins, the more stable your application will be. It is far better to detect potential error situations when your application starts up before data is change than to wait until later to encounter an error situation.
If you have no error handling code and a run time error occurs, VBA will display its standard run time error dialog box. While this may be acceptable, even desirable, in a development environment, it is not acceptable to the end user in a production environment. The goal of well designed error handling code is to anticipate potential errors, and correct them at run time or to terminate code execution in a controlled, graceful method. Your goal should be to prevent unhandled errors from arising.
A note on terminology: Throughout this article, the term procedure should be taken to mean a Sub , Function , or Property procedure, and the term exit statement should be taken to mean Exit Sub , Exit Function , or Exit Property . The term end statement should be taken to mean End Sub , End Function , End Property , or just End .
The On Error Statement
The heart of error handling in VBA is the On Error statement. This statement instructs VBA what to do when an run time error is encountered. The On Error statement takes three forms.
On Error Goto 0
On Error Resume Next
On Error Goto :
The first form, On Error Goto 0 , is the default mode in VBA. This indicates that when a run time error occurs VBA should display its standard run time error message box, allowing you to enter the code in debug mode or to terminate the VBA program. When On Error Goto 0 is in effect, it is the same as having no enabled error handler. Any error will cause VBA to display its standard error message box.
The second form, On Error Resume Next , is the most commonly used and misused form. It instructs to VBA to essentially ignore the error and resume execution on the next line of code. It is very important to remember that On Error Resume Next does not in any way «fix» the error. It simply instructs VBA to continue as if no error occured. However, the error may have side effects, such as uninitialized variables or objects set to Nothing. It is the responsibility of your code to test for an error condition and take appropriate action. You do this by testing the value of Err.Number and if it is not zero execute appropriate code. For example,
On Error Resume Next
N = 1 / 0 ‘ cause an error
If Err.Number <> 0 Then
N = 1
End If
This code attempts to assign the value 1 / 0 to the variable N . This is an illegal operations, so VBA will raise an error 11 — Division By Zero — and because we have On Error Resume Next in effect, code continues to the If statement. This statement tests the value of Err.Number and assigns some other number to N .
The third form On Error of is On Error Goto : which tells VBA to transfer execution to the line following the specified line label. Whenever an error occurs, code execution immediately goes to the line following the line label. None of the code between the error and the label is executed, including any loop control statements.
On Error Goto ErrHandler:
N = 1 / 0 ‘ cause an error
‘
‘ more code
‘
Exit Sub
ErrHandler:
‘ error handling code
Resume Next
End Sub
Enabled And Active Error Handlers
An error handler is said to be enabled when an On Error statement is executed. Only one error handler is enabled at any given time, and VBA will behave according to the enabled error handler. An active error handler is the code that executes when an error occurs and execution is transferred to another location via a On Error Goto : statement.
Error Handling Blocks And On Error Goto
An error handling block, also called an error handler, is a section of code to which execution is tranferred via a On Error Goto : statement. This code should be designed either to fix the problem and resume execution in the main code block or to terminate execution of the procedure. You can’t use to the On Error Goto : statement merely skip over lines. For example, the following code will not work properly:
On Error GoTo Err1:
Debug.Print 1 / 0
‘ more code
Err1:
On Error GoTo Err2:
Debug.Print 1 / 0
‘ more code
Err2:
When the first error is raised, execution transfers to the line following Err1: . The error hander is still active when the second error occurs, and therefore the second error is not trapped by the On Error statement.
The Resume Statement
The Resume statement instructs VBA to resume execution at a specified point in the code. You can use Resume only in an error handling block; any other use will cause an error. Moreover, Resume is the only way, aside from exiting the procedure, to get out of an error handling block. Do not use the Goto statement to direct code execution out of an error handling block. Doing so will cause strange problems with the error handlers.
The Resume statement takes three syntactic form:
Resume
Resume Next
Resume
Used alone, Resume causes execution to resume at the line of code that caused the error. In this case you must ensure that your error handling block fixed the problem that caused the initial error. Otherwise, your code will enter an endless loop, jumping between the line of code that caused the error and the error handling block. The following code attempts to activate a worksheet that does not exist. This causes an error (9 — Subscript Out Of Range), and the code jumps to the error handling block which creates the sheet, correcting the problem, and resumes execution at the line of code that caused the error.
On Error GoTo ErrHandler:
Worksheets(«NewSheet»).Activate
Exit Sub
ErrHandler:
If Err.Number = 9 Then
‘ sheet does not exist, so create it
Worksheets.Add.Name = «NewSheet»
‘ go back to the line of code that caused the problem
Resume
End If
The second form of Resume is Resume Next . This causes code execution to resume at the line immediately following the line which caused the error. The following code causes an error (11 — Division By Zero) when attempting to set the value of N. The error handling block assigns 1 to the variable N, and then causes execution to resume at the statement after the statement that caused the error.
On Error GoTo ErrHandler:
N = 1 / 0
Debug.Print N
Exit Sub
ErrHandler:
N = 1
‘ go back to the line following the error
Resume Next
The third form of Resume is Resume : . This causes code execution to resume at a line label. This allows you to skip a section of code if an error occurs. For example,
On Error GoTo ErrHandler:
N = 1 / 0
‘
‘ code that is skipped if an error occurs
‘
Label1:
‘
‘ more code to execute
‘
Exit Sub
ErrHandler:
‘ go back to the line at Label1:
Resume Label1:
All forms of the Resume clear or reset the Err object.
Error Handling With Multiple Procedures
Every procedure need not have a error code. When an error occurs, VBA uses the last On Error statement to direct code execution. If the code causing the error is in a procedure with an On Error statement, error handling is as described in the above section. However, if the procedure in which the error occurs does not have an error handler, VBA looks backwards through the procedure calls which lead to the erroneous code. For example if procedure A calls B and B calls C, and A is the only procedure with an error handler, if an error occurs in procedure C, code execution is immediately transferred to the error handler in procedure A, skipping the remaining code in B.
A Note Of Caution
It is tempting to deal with errors by placing an On Error Resume Next statement at the top of the procedure in order to get the code to run without raising an error. This is very bad coding practice. Remember that using On Error Resume Next does not fix errors. It merely ignores them.
Типы ошибок в VBA
Смотрите также вероятностью 1/5 If момент возникновения ошибки / 0 j On Error Resume
- . Спасибо.
- = wdSeekCurrentPageHeader Do
- On Error GoTo
будет ошибочным, но этот файл повторится. = Workbooks.Open(«C:Documents and справиться с возникающими
Ошибки компиляции
попытке присвоить переменной расшифрованы на сайте случае при нажатии использовать или обратиться Visual Basic воПри выполнении макросов Excel Cells(i, 1).Value >
в цикле For = «test» If Next For iГрузить файлы запрещено Selection.WholeStory Selection.Copy ActiveWindow.ActivePane.View.NextHeaderFooter err1 ‘включаем первую макрос будет продолжать При желании вместо SettingsData») ‘Присваиваем переменным ошибками, VBA предоставляет значение не соответствующего Microsoft Support (на
на кнопку к переменной, которая введённом коде синтаксической могут возникнуть ошибки, 3 Then On у меня останавливалось Err Then Cells(i, = 1 To в организации, поэтому Loop footercopy: ActiveWindow.ActivePane.View.SeekView обработку ‘создаём исключение выполняться до завершения. попытки открыть нужный Val1 и Val2 разработчику операторы типа – например, английском). Наиболее частоDebug не была объявлена ошибки, будет показано которые в VBA Error GoTo errH2
выполнение кода и 2).Value = Err.Description: 10 If Cells(i, опишу пример. = wdSeekMainDocument Application.Run On Error GoToРедактор Excel VBA предоставляет файл, выполнение процедуры данные из рабочейOn Error объявлена переменная встречающиеся ошибки VBA
(в окне сообщения для текущей области соответствующее сообщение. Если делят на три x = 1 переходило на Next? Err.Clear: End If 1).Value > 3Есть книга со «footercopy» End Sub 0 ‘отключаем её набор инструментов отладки,Sub книги DataWorkbook Val1иi
Ошибки выполнения
перечислены в этой о необходимости отладки) (такая ошибка может же этот режим категории: / 0 EndКазанский Next End SubErr.Description Then If Err значениями на Листе1 Sub footercopy() On On Error GoTo которые помогут найти
может быть прервано = Sheets(«Лист1»).Cells(1, 1)Resumeтипа таблице: будет выделена цветом возникнуть только если выключен, то редактор
Ошибки компиляции If nxt: Next: Да уж наверно, будет выдавать последнюю Then Cells(i, 2).Value [A1:A5]={1;2;3;4;5} и макрос: Error GoTo ExitSub err2 ‘включаем вторую и исправить логические в этом месте Val2 = Sheets(«Лист1»).Cells(1,. Эти операторы отслеживаютInteger5 строка кода, которая
используется VBA продолжит сообщатьОшибки выполнения Exit Sub ‘Если раз не работает ошибку, а не = «Ошибка 1»:
Sub test() Dim ActiveWindow.ActivePane.View.SeekView = wdSeekCurrentPageFooter обработку ‘создаём исключение ошибки в коде при помощи команды 2) DataWorkbook.Close Exit ошибки и направляют, и происходит попыткаНедопустимый вызов процедуры (Invalid стала причиной ошибкиOption Explicit о синтаксических ошибках,Логические ошибки (баги) ошибка в условииResume первую. Err.Clear: Exit Sub i%, x# [B:B].ClearContents Do Selection.WholeStory Selection.Copy
Exit Sub ‘выход VBA. В даннойExit Sub Sub ErrorHandling: ‘Если выполнение макроса в присвоить ей значение procedure call)
| VBA. | ). просто выделяя их |
| Далее мы поговорим о | цикла, значит Netxнужен для того, |
| А почему в | x = 1 For i = ActiveWindow.ActivePane.View.NextHeaderFooter Loop ExitSub:
из процедуры err1: статье мы не. файл не найден, специальный раздел кода строкового типа.7Получив такое сообщение иОшибки выполнения возникают в красным цветом. Опцию каждом из трёх errH2: ‘If Err.Number чтобы выйти из моём варианте возникает |
| / 0 If | 1 To 10 ActiveWindow.ActivePane.View.SeekView = wdSeekMainDocument |
| MsgBox Err.Description ‘обрабатываем | будем рассматривать подробно
Логические ошибки (или баги) предлагаем пользователю разместить VBA, в котором53Недостаточно памяти (Out of видя выделенную строку процессе выполнения кодаAuto Syntax Check типов ошибок VBA > 0 Then состояния обработки ошибки |
| ошибка? | Err Then Cells(i, On Error GoTo
End SubЯ здесь первое исключение Exit эти инструменты. Любознательный |
Перехват ошибок выполнения
возникают в процессе его в ‘нужном происходит обработка ошибки.Файл не найден (File memory) кода, как в и приводят кможно включить/выключить в подробно. ‘проверка не нужна, и перейти вВроде всё верно 2).Value = «Ошибка errH1 If Cells(i, сделал вызов другого Sub ‘выход из пользователь может найти выполнения кода VBA, месте и продолжить
После выполнения кода not found)9 приведённом выше примере, остановке выполнения программы. менюКомпилятор VBA рассматривает ошибки т.к. без ошибки состояние нормальной работы. написано, но обработка 2″: Err.Clear: End 1).Value > 3 макроса, т.к. не процедуры err2: MsgBox обзор инструментов отладки но позволяют ему работу MsgBox «Рабочая обработки ошибки, работаИногда возникает при попыткеИндекс вне заданного диапазона обнаружить причину ошибки Этот тип ошибок
Tools компиляции как недопустимые мы бы сюдаЕсли при работе не срабатывает… If Next End Then On Error знал, как применить Err.Description ‘обрабатываем второе VBA на сайте выполняться до самого книга не найдена! программы может быть открыть не существующий (Subscript out of будет совсем не VBA, как правило,> и выделяет их не попали Cells(i, обработчика ошибок происходитКазанский Sub GoTo errH2 x обработку 2 ошибок, исключениеНо зачем? Microsoft Help & завершения. Правда в » & _ продолжена с того файл. range) сложно. также не сложноOptions в коде ещё
2).Value = «Ошибка ошибка, происходит останов: 1. Нет выходаЕвгений = 1 / которые должны по-любомуМожно и в Support (на английском). результате могут выполняться «Пожалуйста добавьте книгу места, где возниклаНе все ошибки выполненияЭта ошибка возникает приВ случае если код обнаружить и исправить,редактора Visual Basic. до того, как 2″ ‘ Err.Clear (есть правда возможность из обработчика ошибки: Т.е. выполняется условие, 0 End If произойти (это является одной метке обработатьУрок подготовлен для Вас
Логические ошибки
не те действия, Data.xlsx в каталог ошибка, или макрос бывают вызваны недочётами попытке обратиться к сложнее, чем в так как сообщаетсяВ некоторых случаях ошибка дело дойдёт до ‘End If Resume обойти его: — оператор Resume а только потом ‘Если ошибка в функциональностью макроса). несколько ошибок командой сайта office-guru.ru которые ожидалось, и C:Documents and Settings может быть остановлен в коде. Например,
элементу массива за нашем примере, то, информация о характере компиляции может быть запуска макроса. nxt ‘Если ошибкаOn Error Goto -12. Нет обхода
проверяется наличие ошибок, условии цикла, значитЕвгенийOn Error GoToИсточник: http://www.excelfunctions.net/VBA-Error.html может быть получен и нажмите OK.» полностью. Далее это ошибки VBA не пределами заданного размера чтобы получить больше ошибки и место обнаружена при выполненииЕсли при написании кода
перед условием цикла,, но это
обработчиков ошибок при
а не в
Netx errH2: If
office-guru.ru
Обработка ошибок
: Добрый день! errLabel Open «C:имя_файла»Перевел: Антон Андронов неверный результат. Такие
Resume End Sub показано на примере. удастся избежать, если массива – например,
информации о причине в коде, где компиляции кода, непосредственно
допущена синтаксическая ошибка, значит End errH1:
крайний случай), а
нормальном выполнении программы. момент её возникновения? Err.Number > 0Необходимо построить обработку For Input AsАвтор: Антон Андронов ошибки обнаружить иВ этом коде производится’Процедура Sub присваивает для работы макроса если объявлен массив возникновения ошибки VBA, произошла остановка. перед тем, как то редактор VBA ‘If Err.Number >
если ошибка происходитЕвгенийТак работает, спасибо!
Then Cells(i, 2).Value ошибок с двумя 0 Exit SubBusine2009 исправить труднее всего, попытка открыть файл переменным Val1 и необходимо открыть файл с индексами можно проверить значенияПримером такой ошибки может макрос будет выполнен. сигнализирует об этом
0 Then ‘проверка после Resume, то
: 1. Может я Только что делать, = «Ошибка 2″ разными метками выхода errLabel: Select Case: Можно в одной так как компилятор Excel с именем Val2 значения, ‘хранящиеся с данными, аот 1 до 10 используемых переменных. В служить попытка выполнить Обычно ошибку компиляции немедленно: либо при не нужна, т.к. вызывается обработчик ошибок, неправильно представлял работу если будет так: Err.Clear End If (всё в цикле): Err.Number … Case
CyberForum.ru
Обработка ошибок с двумя разными метками (VBA)
процедуре использовать 2 VBA их не
Data в ячейках A1 этого файла не, а мы пытаемся
редакторе VBA для деление на ноль. несложно обнаружить и помощи окна с без ошибки мы
который назначен в обработчика, но зачем Sub test() Dim Next ‘Если ошибка
1. Если возникает 52 MsgBox «Неправильный раза
. Если файл не и B1 рабочей существует. В таких
обратиться к элементу этого достаточно навести В результате будет исправить, потому что сообщением, либо выделяя бы сюда не данный момент. делать Resume, если i%, x#, j% перед условием цикла, ошибка до условия дискриптор файла» CaseOn Error GoToсоответственно может указать на найден, то пользователю книги Data.xlsx расположенной случаях признаком профессионализма этого же массива указатель мыши на показано сообщение « компилятор VBA даёт ошибку красным цветом, попали Cells(i, 2).ValueВаш код может есть GoTo? [B:B].ClearContents On Error значит End errH1: If, то просто 53 MsgBox «Файл
для одной части них так, как
будет предложено поместить в каталоге C:Documents будет перехват ошибок с индексом имя переменной, илиRun-time error ’11’: Division информацию о характере в зависимости от = «Ошибка 1″ выглядеть так: Sub2. Я для Resume Next For If Err.Number > переходим на End не найден» … кода и для это происходит с этот файл в
and Settings Sub и написание кода11 можно открыть окно by zero и причине ошибки.
статуса режима ‘End If End test() Dim i%, этого вставил условие i = 1 0 Then Cells(i, Sub. Case Else MsgBox другой части кода? ошибками компиляции и нужную папку. После Set_Values(Val1 As Double, VBA, который будет. отслеживания локальных переменных«.Например, сообщение «Auto Syntax Check Sub x# [B:B].ClearContents For If Err.Number > To 10 If 2).Value = «Ошибка2. Если возникает
«Другая ошибка» EndЕсли можно, то выполнения.
того, как пользователь Val2 As Double) выполняться при их
11 (в меню редактораВ зависимости от структурыCompile error: Variable not
.Евгений i = 1
0 Then … Cells(i, 1).Value > 1″ End If ошибка в условии Select напишите как. Буду
Например, при создании макроса сделает это и Dim DataWorkbook As возникновении. Таким образом,Деление на ноль (Division
View проекта VBA, может definedПримечание:: Спасибо за подробное To 10 On End If 3 Then If End Sub
If, то переходимBusine2009 очень признательным.
в процедуре случайно нажмёт Workbook On Error вместо неприятных сбоев by zero)>
быть предложено выполнить» при попытке запуститьПри включённом режиме объяснение, всё работает Error GoTo errH1Евгений Err Then Cells(i,KuklP на Netx.: Вот конкретный пример:Abu были просуммированы неОК
GoTo ErrorHandling ‘Открываем будет происходить изящное13Locals Window отладку кода (как выполнение кода VBAAuto Syntax CheckА то у x = 1: Задам немного другой 2).Value = Err.Description:: Так не проще?:Прошу помочь разобратьсяSub HeaderCopy() On: Можно! те переменные, которые, выполнение кода продолжится, рабочую книгу с завершение работы макроса.Несоответствие типа (Type mismatch)). показано на рисунке говорит о том,каждый раз, при Уокенбаха такого не / Int(Rnd * вопрос: как сделать Err.Clear: Exit SubSub test() Dim почему на срабатывает Error GoTo footercopyМожно так требовалось просуммировать. Результат и попытка открыть данными Set DataWorkbookДля того, чтобы помочьЭта ошибка возникает приКоды различных ошибок выполнения ниже). В этом что происходит попытка появлении в редакторе
написано 5) ‘ошибка с так, что в
x = 1 i%, x# [B:B].ClearContents макрос
planetaexcel.ru
Selection.HomeKey Unit:=wdStory ActiveWindow.ActivePane.View.SeekView



















































