Обработка ошибок – это определение реакции на выполнение ошибок, которые возникают при выполнении программы. Причины ошибок могут быть как в самой программе, так и вне ее (например, может отсутствовать нужный файл). Все ошибки можно отнести к трем категориям: ошибки компиляции, возникающие, когда VBA не может интерпретировать введенный текст; ошибки выполнения, возникающие после успешной компиляции, при выполнении программы (причиной этих ошибок могут быть, например, неправильные данные, введенные пользователем), и логические ошибки, которые не распознаются VBA и не приводят к прекращению выполнения программы, но ведут к получению неверных результатов. Логические ошибки можно выявить с помощью средств отладки (пошагового выполнения программы, отслеживания контролируемых значений и т.п.).
В VBA есть несколько средств обработки ошибок:
– оператор On Error,
– оператор Resume,
– оператор Error,
– функция IsError,
– функция CVErr,
– объект Err.
Оператор On Error предназначен для обработки ошибок, он задает действия, которые должны быть выполнены при возникновении ошибки. Если в программе не выполнена инструкция On Error, то любая ошибка выполнения является фатальной; это означает, что выводится сообщение об ошибке и выполнение программы прекращается. Этот оператор заставляет программу реагировать на ошибку различным образом.
Подпрограмма обработки ошибок не может быть процедурой Sub или Function. Эта подпрограмма должна быть частью программы, которая отмечается с помощью метки строки или номера строки.
Оператор
On Error GoTo Метка
можно использовать как общий обработчик ошибок (в случае возникновения ошибки управление будет передано на оператор, которому предшествует указанная метка, следующие за ней инструкции могут проверить тип возникшей ошибки, уточнить причину и выполнить действия по ее устранению).
«Включенным» обработчиком ошибок называют подпрограмму, которая указана в инструкции On Error; «активным» обработчиком ошибок является включенный обработчик ошибок, который обрабатывает текущую ошибку. Если ошибка возникает в самом обработчике ошибок (в промежутке между возникновением ошибки и выполнением инструкции Resume, Exit Sub, Exit Function или Exit Property), то обработчик ошибок, определенный в текущей процедуре, не может обработать ошибку. Управление в этом случае возвращается в вызывающую процедуру; если в вызывающей процедуре включен обработчик ошибок, то обработка ошибки передается ему. Если этот обработчик ошибок является в данный момент активным, т.е. уже обрабатывает ошибку, то управление снова передается назад в вызывающую процедуру и т.д. до тех пор, пока не будет найден включенный, но не активный обработчик ошибок. Если включенный, но неактивный обработчик ошибок найден не будет, ошибка становится фатальной в том месте программы, в котором она впервые возникла. При каждой передаче управления обработчиком ошибок в вызывающую процедуру эта процедура становится текущей. После завершения обработки ошибки обработчиком в любой процедуре возобновляется выполнение текущей процедуры с той ее части, которая указана в инструкции Resume.
Для определения причины ошибки в подпрограммах обработки ошибок используют значение свойства Number объекта Err. Необходимо обеспечить в подпрограммах обработки ошибок проверку или сохранение существенных значений свойств объекта Err перед тем, как может возникнуть новая ошибка или перед вызовом процедуры, в которой может возникнуть новая ошибка. Значения свойств объекта Err описывают последнюю ошибку. Текст сообщения об ошибке, соответствующего коду ошибки Err.Number содержится в свойстве Err.Description.
Для отключения общей обработки следует использовать оператор On Error GoTo 0. Конструкция On Error GoTo 0 отключает обработку ошибок в текущей процедуре. Эта конструкция не задает переход на строку 0 для обработки ошибок, даже если в процедуре имеется строка с номером 0. Если инструкция On Error GoTo 0 не выполнялась, то обработчик автоматически отключается при выходе из процедуры.
Инструкция
On Error Resume Next
указывает, что возникновение ошибки выполнения приводит к передаче управления на инструкцию, непосредственно следующую за инструкцией, при выполнении которой возникла ошибка, или на инструкцию, непосредственно следующую за вызывающей инструкцией в процедуре, содержащей конструкцию On Error Resume Next, т.е. эта инструкция приводит к игнорированию ошибки. Это позволяет продолжить исполнение программы несмотря на ошибку выполнения. Это позволяет также встроить подпрограмму обработки ошибок в процедуру, а не передавать управление в другую часть процедуры. Конструкция On Error Resume Next становится неактивной при вызове новой процедуры, поэтому для внутренней обработки ошибок необходимо выполнять инструкцию On Error Resume Next в каждой вызываемой процедуре. Этой формой оператора следует пользоваться с осторожностью, так как ошибка фактически не обрабатывается. Рекомендуется при доступе к объектам использовать эту форму инструкции, а не On Error GoTo.
При обработке ошибок, возникающих при доступе к другим объектам, рекомендуется использовать конструкцию On Error Resume Next. Проверка объекта Err после каждого взаимодействия с другим объектом позволяет устранить неопределенность в том, при доступе к какому объекту возникла ошибка. Это позволяет всегда точно знать, какой объект поместил значение кода ошибки в свойство Err.Number, а также в каком объекте возникла ошибка (эта информация содержится в свойстве Err.Source).
Для того чтобы предотвратить выполнение программы обработки ошибок в тех случаях, когда ошибка не возникла, следует помещать соответствующую инструкцию Exit Sub, Exit Function или Exit Property перед подпрограммой обработки ошибки, как в следующем примере: