Самоучитель VBA

         

Инструкция Option Explicit


Простейшим средством предотвращения случайных ошибок является использование инструкции Option Explicit. Эта инструкция предписывает явно описывать все переменные, встречающиеся в программе. Использование инструкции option Explicit позволяет избежать следующей трудно отслеживаемой ошибки. Предположим, что в программе используется переменная с именем ссуда, а при наборе имени этой переменной где-то в программе вместо русской буквы с по ошибке набрана латинская буква с. Визуально, эти имена ничем не отличаются друг от друга, но воспринимаются программой как имена разных переменных. Если бы использовалась инструкция option Explicit, а значит имело место явное описание переменной Ссуда, то компилятор указал бы на переменную ссуда с латинской буквой с, как на неописанную, и эта, трудно отслеживаемая ошибка, была бы быстро найдена.



Логические ошибки


Логические ошибки труднее всего обнаружить и устранить. Эти ошибки не приводят к прерыванию выполнения программы, т. е. визуально все идет гладко и выглядит так, как будто программа работает безупречно. Но это только кажущаяся идиллия, т. к. программа выдает неверные результаты. Локализация логических ошибок связана с тщательным анализом алгоритма программы с привлечением средств отладки VBA (рис. 12.8).

Рис. 12.8. Редактор кода в режиме прерывания



Ошибки компиляции


Ошибки компиляции возникают, если VBA не может интерпретировать введенный код. Например, при некорректном вводе числа скобок, неправильном имени, неполном вводе инструкции и т. д. Некоторые из этих ошибок обнаруживаются VBA при завершении набора строки с инструкцией в редакторе кода и после нажатия клавиши <Enter>. Строка, в которой содержится ошибка, выделяется красным цветом, и на экране отображается диалоговое окно с сообщением о возможной причине, вызвавшей ошибку (рис. 12.5).

Рис. 12.5. Сообщение об ошибке компиляции, обнаруженной при вводе инструкции

Рис. 12.6. Сообщение об ошибке компиляции в диалоговом окне Microsoft Visual Basic

Другие ошибки компиляции обнаруживаются перед выполнением программы. Отметим, что VBA каждый раз автоматически компилирует программу при ее запуске на выполнение. В VBA предусмотрена также возможность компилировать программу без запуска на выполнение посредством команды Отладка, Компилировать (Debug, Compile). В этом случае предполагаемое местоположение ошибки выделяется синим цветом и на экране отображается диалоговое окно Microsoft Visual Basic с сообщением о возможной причине, вызвавшей ошибку (рис. 12.6).





Ошибки выполнения


Ошибки выполнения возникают после успешной компиляции программы при ее выполнении. Причинами таких ошибок могут быть, например:

Некорректная информация при считывании файла с диска.

Некорректные данные, введенные пользователем, например требуется число, а пользователь вводит строковую информацию.

Некорректность вычислений, например деление на ноль.

В этих и подобных случаях на экране отображается диалоговое окно Microsoft Visual Basic с сообщением о номере ошибки и возможной причине, ее вызвавшей (рис. 12.7).

Рис. 12.7. Сообщение об ошибке выполнения в диалоговом окне Microsoft Visual Basic

Если в диалоговом окне Microsoft Visual Basic нажать кнопку Отладка (Debug), то в строке модуля желтым цветом будет выделена строка, вызвавшая ошибку и по причине которой выполнение программы было прервано. Кроме того, эта строка будет помечена стрелочкой. При прерывании выполнения программы VBA переходит в режим прерывания. Одной из наиболее удобных возможностей режима прерывания являются возможность узнать текущее значение переменных и свойств. Для этого достаточно расположить указатель мыши на имени свойства или переменной. Это вызовет появление всплывающей подсказки с текущим значением переменной или свойства. Из текста кода, изображенного на рисунке, видно, что значение переменной у равно 0, что и вызвало ошибку прерывания. Для задания режима вывода всплывающей подсказки с текущими значениями данных должен быть установлен флажок Подсказки значений данных (Auto Data Tips) диалогового окна Параметры (Options), вызываемого с помощью команды Сервис, Параметры (Tools, Options).



Отладка программ



При написании программ пользователь независимо от его опыта допускает те или иные ошибки. Кто-то из мудрых совершенно верно подметил, что только тот, кто ничего не делает, не совершает ошибок. Позвольте перефразировать эту жизненную мудрость для изучаемого в данной книге предмета следующим образом: в программах не делал ошибок только тот, кто никогда не писал их. Итак, ошибки — это объективная неизбежность или реальное воплощение этой неизбежности. Какие же бывают ошибки и как с ними бороться? Условно ошибки можно поделить на три типа: ошибки компиляции, выполнения и логические ошибки.



Перехват и обработка ошибок


Из диалогового окна Microsoft Visual Basic видно, что каждая ошибка имеет свой код. В табл. 12.1 приведены коды наиболее часто встречаемых ошибок.

Таблица 12.1. Коды наиболее часто встречаемых ошибок

Код

Сообщение

5

Приложение не запущено

6

Переполнение

7

Не хватает памяти

9

Индекс выходит за пределы допустимого диапазона

11

Деление на нуль

13

Несоответствие типа

18

Произошло прерывание, вызванное пользователем

52

Неправильное имя файла или идентификатор

53

Файл не найден

54

Неверный режим работы с файлом

55

Файл уже открыт

56

Ошибка ввода-вывода

61

Переполнение диска

68

Устройство недоступно

71

Диск не готов

72

Повреждена поверхность диска

335

Невозможен доступ к системным ресурсам

368

Истек срок действия данного файла. Программе требуется файл более новой версии

482

Ошибка принтера

В идеале разрабатываемое приложение не должно никогда аварийно прерываться. В приложении следует создать средства перехвата любой возможной ошибки, обработать ее, выдать сообщение пользователю и обеспечить безаварийное продолжение работы приложения. Обычно конструкция перехвата ошибок имеет следующую структуру.

Инструкция

On Error

Производит перехват ошибки. Устанавливает, что про грамма должна делать в случае появления ошибки.

Подпрограмма обработки ошибки

В этой подпрограмме определяется тип возникшей ошибки и устанавливается, что программа должна де-лать в зависимости от типа ошибки. Допустимы следующие синтаксисы.

Синтаксис 1:

On Error GoTo строка

Активизирует подпрограмму обработки ошибок, начало которой определяется обязательным аргументом строка, значением которого может быть либо метка строки, либо номер строки.

Синтаксис 2:

On Error Resume Next

Указывает, что при возникновении ошибки происходит передача управления на инструкцию, непосредственно следующую за инструкцией, где возникла ошибка.

Синтаксис 3:

On Error GoTo 0

Отключает любой активизированный обработчик ошибок в текущей процедуре.

Инструкция

Resume

Обеспечивает процедуре возможность продолжить работу после обработки ошибки. Допустимы следующие синтаксисы.

Синтаксис 1:

Resume

После обработки ошибки управление передается той инструкции, в которой произошла ошибка.

Синтаксис 2:

Resume строка

После обработки ошибки управление передается инструкции, определенной аргументом строка. Значением этого аргумента может быть любая метка строки или номер строки.

Синтаксис 3:

Resume Next

После обработки ошибки управление передается инструкции, следующей за инструкцией, в которой произошла ошибка.

Инструкция

Exit

Останавливает выполнение процедуры.

Допустимые синтаксисы:

Exit Sub

Exit Function

Exit Property

<
Подпрограмма обработки ошибки обычно включает объект Err, который содержит информацию об ошибках выполнения. Приведем свойства и методы объекта Err.

Свойства объекта Err



Number



Возвращает код ошибки



Source



Имя текущего проекта VBA



Description



Возвращает строковое выражение, содержащее текст сообщения об ошибке



HelpFile



Полное имя (включая диск и путь) файла справки VBA



HelpContext



Контекстный идентификатор файла справки VBA, соответствующий ошибке с кодом, указанным в свойстве

Number



LastDLLError



Содержит системный код ошибки для последнего вызова библиотеки динамической компоновки (DLL)

Методы объекта Err



Clear



Очищает все значения свойств объекта Err. Метод clear используется для явной очистки значений свойств объекта Err после завершения обработки ошибки. Это необходимо, например, при отложенной обработке ошибки, которая задается инструкцией on

Error Resume Next



Raise



Создает ошибку выполнения. Используется при моделировании ситуаций ошибки.

Синтаксис:

Raise number, source, description, helpfile, helpcontext

Аргументы:

number — номер ошибки, т. е. целое число от 0 до 65535

source — строковое выражение, определяющее имя объекта или приложения, в котором возникла ошибка

description — строковое выражение, содержащее описание ошибки

Helpfile — полное имя (включая диск и путь) файла справки Microsoft Windows, содержащего описание данной ошибки

helpcontext — контекстный идентификатор, определяющий соответствующий обрабатываемой ошибке раздел в файле, указанном в аргументе helpfile

На конкретном примере покажем, как применяется объект Err при создании обработчика ошибок. В предыдущем разделе в процессе создания диалотового окна деление и связанной с ним программы, на первый взгляд были предусмотрены все возможные ошибки. Но это только на первый взгляд. Введем, например, в поле Знаменатель значение 1е-40. Это число ничем не лучше или не хуже любого другого числа типа single.


Тем не менее, вместо вывода результата произойдет аварийное прерывание выполнения программы с отображением сообщения об ошибке переполнения. Усовершенствуем программу с учетом возможности обработки подобной ошибки. В обработчике ошибок предусмотрим два отклика:

Пользователь информируется программой в случае появления ошибки переполнения, знаменателю и числителю присваиваются 1 и с этими данными проводятся вычисления.

При появлении ошибки, отличной от ошибки переполнения, выполнение программы прерывается с информированием пользователя об ошибке (рис. 12.4).



Рис. 12.4. Диалоговое окно с указанием типа ошибки

Private Sub CommandButtonl_Click()

Dim Числитель, Знаменатель, Результат As Single

'

' Передача управления на обработчик ошибок,

' помеченный меткой Обработка

'

On Error GoTo Обработка

'

' Проверка, является ли числитель числом

'

If IsNumeric(TextBoxl.Text) = False Then MsgBox "Ошибка в числителе",

vblnformation, "Деление" TextBoxl.SetFocus

Exit Sub

End If

' Проверка, является ли знаменатель числом

'

If IsNumeric(TextBox2.Text) = False Then

MsgBox "Ошибка в знаменателе",

vblnformation, "Деление"

TextBox2.SetFocus

Exit Sub

End If

'

' Проверка, не является ли знаменатель нулем

'

If CDbl(TextBox2.Text) = 0 Then

MsgBox "Знаменатель не может быть нулем", vblnformation, "Деление"

TextBox2.SetFocus

Exit Sub

End If

'

Числитель = CDbl(TextBoxl.Text)

Знаменатель = CDbl(TextBox2.Text)

Результат = Числитель / Знаменатель

TextBox3 . Text = CStr (.Результат)

'

' Выход из процедуры в случае успешного нахождения результата

'

Exit Sub

'

' Обработчик ошибок

'

Обработка: Select Case Err.Number

'

' Обработка ошибки переполнения

'

Case Is = 6

MsgBox " Произошла ошибка переполнения",

vblnformation, "Деление"

TextBoxl.Text = 1

TextBox2.Text = 1

Знаменатель = 1

Числитель = 1 Resume

' Обработка любой другой ошибки

'

Case Else

MsgBox "Произошла ошибка: " & Err.Description &

vblnformation, "Деление"

Exit Sub

End Select

End Sub

В заключение отметим, что в случае, если разрабатываемое приложение состоит из нескольких процедур, причем в некоторых из них необходимо создать по обработчику ошибок, бывает более удобно для сокращения программы и для большей ясности структуры кода написать отдельную процедуру с обработчиком всех ошибок.




Пошаговое выполнение программ


Редактор VBA позволяет выполнять пошаговую отладку программы. Ее можно выполнить либо при помощи панели инструментов Отладка (Debug), либо меню Отладка (Debug), которое включает команды и соответствующие комбинации клавиш (рис. 12.9). Если панель инструментов Отладка (Debug) не отображена на экране, то ее можно отобразить, выполнив команду Вид, Панели инструментов, Отладка (View, Toolbars, Debug).

Рис. 12.9. Панель инструментов Отладка и раскрывающееся меню Отладка

Для выполнения программы в пошаговом режиме используются четыре команды:

Команда Отладка, Шаг с заходом (Debug, Step Into), либо кнопка Шаг с заходом (Step Into) панели инструментов Отладка (Debug) осуществляет последовательную шаг за шагом отладку всей программы, включая процедуры, вызываемые в программе.

Команда Отладка, Шаг с обходом (Debug, Step Over), либо кнопка Шаг с обходом (Step Over) панели инструментов Отладка (Debug) осуществляет последовательную шаг за шагом отладку всей программы, исключая процедуры, т. е. если встречается процедура, то она выполняется целиком, а не пошагово, как это делается в команде Отладка, Шаг с заходом (Debug, Step Into).

Команда Отладка, Шаг с выходом (Debug, Step Out), либо кнопка Шаг с выходом (Step Out) панели инструментов Отладка (Debug) завершает выполнение текущей процедуры и останавливает процесс пошаговой отладки на следующей после вызвавшей ее инструкции программы.

Команда Отладка, Выполнить до текущей позиции (Debug, Run to Cursor) выполняет программу до инструкции, на которой установлен курсор.



ПРОЦЕДУРЫ ОБРАБОТКИ ОШИБОК И ОТЛАДКА ПРОГРАММ


ГЛАВА 12. ПРОЦЕДУРЫ ОБРАБОТКИ ОШИБОК И ОТЛАДКА ПРОГРАММ

РАЗРАБОТКА ПРОЦЕДУР, ПРЕДОТВРАЩАЮЩИХ ПОЯВЛЕНИЕ ОШИБОК

Перехват и обработка ошибок

ОТЛАДКА ПРОГРАММ

Ошибки компиляции

Ошибки выполнения

Логические ошибки

Инструкция Option Explicit

Пошаговое выполнение программ

Точка останова

Вывод значений свойств и переменных

Глава 12.

Процедуры обработки ошибок и отладка программ



Разработка процедур, предотвращающих появление ошибок



При составлении приложений важно предусмотреть, чтобы программа анализировала возможные ошибки, возникающие при ее выполнении по вине пользователя, и информировала его об этом, подсказывая, что конкретно он сделал неправильно. При этом возможно два подхода:

Предотвращение ошибок: программно анализировать вводимые или вычисляемые данные и в случае, если они могут приводить к ошибке, обеспечить, чтобы программа информировала пользователя о необходимости корректного задания данных.

Обработка ошибок: в случае появления ошибки, перехватить ее, обработать и программно откликнуться на возникшую ошибку.

При создании приложений надо сочетать оба подхода, применяя в каждом конкретном случае и для каждой возможной ошибки тот, который кажется разработчику наиболее эффективным.

В данном разделе рассмотрим процесс создания приложения, в котором предотвращается появление ошибок, на простейшем примере:

В диалоговом окне два поля (числитель и знаменатель) предусмотрены для ввода данных. Пользователь вводит в них по числу (рис. 12.1).

По нажатию кнопки Счет, программа делит число, введенное в поле Числитель, на число, введенное в поле знаменатель, и выводит полученный результат в поле ответ.

Следующая программа производит деление числителя на знаменатель по нажатию кнопки Счет без контроля появления возможных ошибок:

Private Sub CommandButtonl_Click()

Dim Числитель, Знаменатель, Результат As Double

Числитель = CDbl(TextBoxl.Text)

Знаменатель = CDbl(TextBox2.Text)

Результат = Числитель / Делитель

TextBoxS.Text = CStr(Результат)

End Sub

Рис. 12.1. Диалоговое окно Деление

Несмотря на то что рассматриваемая ситуация очень простая, она уже таит в себе множество подводных камней. Например, если пользователь по невнимательности забудет ввести в поле числитель или в поле Знаменатель число при нажатии кнопки счет происходит аварийное прерывание программы с малопонятным сообщением о несоответствии типов отображаемом в диалоговом окне Microsoft Visual Basic (рис. 12.2)





Рис. 12.2. Диалоговое окно Microsoft Visual Basic с сообщением об ошибке

Данное сообщение об ошибке связано с одной из следующих двух инструкций в программе:

Числитель = CDbl(TextBoxl.Text)

Знаменатель = CDbl(TextBox2.Text)

где аргументом функции соы должна быть строка, преобразуемая в число. Если в какое-то из полей, числитель или Знаменатель, ничего не введено, по умолчанию из этого поля будет считываться пустая строка. Но пустая строка не может быть преобразована в число, и поэтому из-за функции CDbl происходит ошибка. Ошибка о несоответствии типов возникнет также, если в одно из полей пользователь по неосторожности введет число с десятичной запятой, а установками системы предусматривается десятичная точка и наоборот.

Такие ошибки ввода легко избежать, если производить в программе предварительную проверку: преобразуются ли вводимые данные в числа? Эту предварительную проверку можно, например, сделать, как показано в следующей процедуре, в которой предусмотрены:

Проверка того, будет ли вводимая информация в поля ввода преобразовываться в числа.



Рис. 12.3. Пример сообщения о некорректном вводе данных

Если вводимая информация не преобразуется в числа, то выдается сообщение о поле, в которое некорректно введены данные, и на него перемещается фокус. Например, в ситуации, показанной на рис. 12.3, в поле

Знаменатель было введено число с десятичной запятой, в то время как установки системы предусматривают десятичную точку. Поэтому процедура вызвала отображение диалогового окна деление с сообщением об ошибке в знаменателе и установила фокус на поле знаменатель.

Private Sub CoramandButtonl_Click()

Dim Числитель, Знаменатель, Результат As Single

'

If IsNumeric(TextBoxl.Text) = False Then MsgBox "Ошибка в числителе",

vblnformation, "Деление" TextBoxl.SetFocus

Exit Sub

End If

'

If IsNumeric(TextBox2.Text) = False Then

MsgBox "Ошибка в знаменателе",

vblnformation, "Деление"

TextBox2.SetFocus



Exit Sub

End If

'

Числитель = CDbl(TextBoxl.Text)

Знаменатель = CDbl(TextBox2.Text)

Результат = Числитель / Делитель

TextBox3.Text = CStr(Результат)

End Sub

Но это еще не все подводные камни, которые подстерегают неосторожного пользователя при вводе данных даже в этом простом примере. Если пользователь в поле Знаменатель введет 0, то также произойдет аварийная остановка выполнения программы с отображением в диалоговом окне Microsoft Visual Basic сообщения: Деление на 0. Для избежания подобной ошибки будем проверять не только, являются ли введенные в поле данные числом, но и что это не ноль. Например, добавим перед расчетным блоком в процедуре следующую дополнительную проверку:

If CDbl(TextBox2.Text) = 0 Then

MsgBox "Знаменатель не может быть нулем", vblnformation, "Деление"

TextBox2.SetFocus

Exit Sub

End If




Точка останова


Точка останова устанавливается или снимается с помощью команды Отладка, Точка останова (Debug, Toggle Breakpoint), либо посредством кнопки Точка останова (Toggle Breakpoint) панели инструментов Отладка (Debug). На листе модуля точки останова выделяются полосой кирпичного цвета и кругом того же цвета (рис. 12.10).

В одном проекте может быть несколько точек останова. Точки останова предназначены для приостановки выполнения программы. Все инструкции, расположенные выше, между и ниже точек останова, выполняются в обычном режиме.

Одновременно снять все точки останова можно, выполнив команду Отладка, Снять все точки останова (Debug, Clear All Breakpoint).



Вывод значений свойств и переменных


Одним из наиболее удобных средств режима отладки является возможность узнать текущее значение переменных и свойств. Для этого достаточно расположить указатель мыши на имени свойства или переменной. Это вызовет появление всплывающей подсказки с текущим значением переменной или свойства. Для установки режима вывода всплывающей подсказки с текущими значениями данных должен быть установлен флажок Подсказки значений данных (Auto Data Tips) диалогового окна Параметры (Options), вызываемого командой Сервис, Параметры (Tools, Options).

Рис. 12.10. Точки останова

Другим способом отслеживания текущих значений данных является использование диалогового окна Контрольные значения (Quick Watch), отображаемого на экране с помощью команды Вид, Окно контрольного значения (View, Quick Watch), либо команды Отладка, Контрольное значение (Debug, Quick Watch) (рис. 12.11). Диалоговое окно Контрольные значения (Quick Watch) применяется для одновременного отображения текущих значений нескольких данных. Команда Отладка, Добавить контрольное значение (Debug, Add Watch) позволяет добавить новые контрольные значения в диалоговом окне Контрольные значения (Quick Watch).

Удаление контрольного значения из диалогового окна производится посредством его выделения и нажатия клавиши <Delete>.

Существует также программный способ вывода значений свойств и переменных в диалоговом окне Контрольные значения (Quick Watch) при помощи метода Print объекта Debug. Ниже приведен пример программного способа вывода значения переменной:

ПроверяемаяПеременная = "Вывод текста в окно отладки." Debug.Print ПроверяемаяПеременная

Окно Локальные переменные (Locals Window), отображаемое на экране командой Вид, Окно локальных переменных (View, Locals Window), выводит значения всех переменных текущей процедуры, а не только специально выбранных, как это происходит в окне Контрольные значения (Quick Watch).

Внешний же вид и структура обоих окон, Локальные переменные (Locals Window) и Контрольные значения (Quick Watch), одни и те же.




Рис. 12.11. Диалоговое окно Контрольные значения

Окно Проверка (Immediate Window), отображаемое на экране командой Вид, Окно отладки (View, Immediate Window), предоставляет пользователю возможность:

Набирать и вычислять отдельные инструкции VBA. Для этого достаточно в окне Проверка (Immediate Window) ввести соответствующую инструкцию и нажать клавишу <Enter>. Единственным ограничением на использование, инструкции является то, что она должна быть набрана в одну строку. Например,

s=0: For i=1 to 5: s=s+i^2: Next i: MsgBox s

Определять текущие значения переменных и свойств. Для этого в окне Проверка (Immediate Window) надо набрать вопросительный знак, имя переменной или свойства и нажать клавишу <Enter>. Например,



Устанавливать новые текущие значения переменных. Для этого в окне Проверка (Immediate Window) надо набрать имя переменной, знак равенства и новое значение переменной:

х = 15