Самое тяжелые для разработчика ошибки — это ошибки времени выполнения, которые могут возникнуть по самым разным причинам: пользователь ввел недопустимое значение, файл с таким именем уже существует, сервер баз данных отказывается вставлять введенные пользователем значения, разорвано сетевое соединение и т. п. При возникновении ошибок времени выполнения обычно работа приложения аварийно завершается, а пользователю выдается встроенное сообщение, которое он вряд ли сможет расшифровать. Поэтому одна из самых трудоемких задач при создании программы на VBA - предусмотреть, какие ошибки могут возникнуть при работе пользователя и реализовать их обработку.
Общий принцип обработки ошибки выглядит так:
1. Перед опасным кодом (сохранение или открытие файла, возможность деления на ноль и т. п.) помещается команда:
On Error GoTo метка _ обработчика _ ошибки
например:
Dim a As Integer, b As Integer, c As Integer
On Error GoTo ErrorHandlerDivision
c = a / b
2. Далее в коде программы помещается метка обработчика ошибки и программный код обработки:
|
|
ErrorHandlerDivision:
MsgBox "Ошибка при делении"
3. Поскольку в такой ситуации код обработчика ошибки будет выполняться даже в том случае, если ошибки не было, есть смысл поставить перед меткой обработчика команду Exit Sub (если это подпроцедура) или Exit Function (если это функция). Полный код нашей мини-программы может выглядеть так:
Private Sub UserForm_Click()
Dim a As Integer, b As Integer, c As Integer
On Error GoTo ErrorHandlerDivision
c = a / b
Exit Sub
ErrorHandlerDivision:
MsgBox "Ошибка при делении"
End Sub
Как правило, если есть возможность исправить ошибку, то в обработчике ошибок ее исправляют (или предоставляют такую возможность пользователю), если нет — то выдают пользователю сообщение с объяснением и прекращают работу программы.
4. После выполнения кода обработчика ошибки вам нужно будет сделать выбор: либо продолжить выполнение той процедуры, в которой возникла ошибка, либо прекратить ее выполнение и передать управление вызвавшей ее процедуре. В вашем распоряжении три варианта:
- еще раз выполнить оператор, вызвавший ошибку (если обработчик ошибки может определить характер возникший проблемы). Для этого достаточно в обработчик ошибок вставить команду Resume;
- пропустить оператор, вызвавший ошибку. Для этой цели можно использовать команду Resume Next;
- продолжить выполнение с определенного места в программе. Для этого используется команда Resume метка. Синтаксис работы с меткой — такой же, как в операторе GoTo.
Отметим еще несколько моментов, которые связаны с обработкой ошибок:
- чтобы вернуться в нормальный режим работы после прохождения опасного участка кода (отменить обработку ошибок), можно воспользоваться командой:
|
|
On Error GoTo 0
- в вашем распоряжении имеется также команда On Error Resume Next. Она предписывает компилятору просто игнорировать все возникающие ошибки и переходить к выполнению следующего оператора. На практике очень часто перед выполнением опасного оператора используется эта команда, а затем при помощи конструкции Select Case проверяется номер возникшей ошибки (через свойства объекта Err), и в зависимости от этого организуется дальнейшее выполнение программы.
Рассмотрим чуть подробнее специальный объект Err. У этого объекта есть два главных свойства и два метода.
- Number — это свойство показывает номер ошибки. Обычно оно и проверяется в обработчике ошибок, чтобы выяснить, какая именно ошибка возникла. Если номер ошибки равен 0, то ошибки не было.
- Description — текстовое описание возникшей ошибки. Именно оно по умолчанию возвращается пользователю (хотя пользователь вряд ли в нем что-либо поймет). Скорее это информация для разработчика.
- Clear() — этот метод очищает объект Err от старой информации об ошибках. То же самое делает и команда On Error GoTo 0.
- Raise() — позволяет сгенерировать ошибку в программе, передав ей номер и описание. Очень полезная возможность для проверки поведения программы, если смоделировать ситуацию с реальной ошибкой трудно.
Надо сказать, что обработка ошибок — это очень надежный, но и очень ресурсоемкий метод работы. Если в вашей программе есть возможность обойтись без генерации и перехвата ошибок (например, проверять вводимое пользователем значение при помощи встроенных функций), то лучше так и делать. В то же время наличие обработчиков ошибок, чтобы справляться с действительно аварийными ситуациями, - это большой плюс вашей программе (а зачастую и просто необходимость).