[an error occurred while processing this directive]

В начало

Введение

1-й час. Знакомство с Visual Basic for Applications

2-й час. Работа с макросами

3-й час. Работа с элементами управления

4-й час. Переменные и константы

5-й час. Ввод данных

6-й час. Логика условных операторов

7-й час. Циклические вычисления

8-й час. Введение в объекты

9-й час. Основные объекты Excel

10-й час. Объект Range

11-й час. Редактор Visual Basic

12-й час. Отладка программ

13-й час. Обработка ошибок

14-й час. Экранные формы

15-й час. Автоматизация экранных форм

16-й час. Панели инструментов

17-й час. Работа с меню

18-й час. Диаграммы

19-й час. Сводные таблицы

20-й час. Получение внешних данных

21-й час. Доступ к данным с помощью ADO

22-й час. Еще об ADO

23-й час. Автоматизация

24-й час. Выполнение процедур

Приложение. Ответы

12-й час. Отладка программ

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

В этом часе будут рассмотрены следующие вопросы.

  • Тестирование и отладка программ.
  • Остановка выполнения приложений.
  • Использование окна Immediate.
  • Пошаговое выполнение процедур.
  • Отслеживание значений переменных и свойств.

Тестирование и отладка как этап разработки приложений

Предположим, что уже написан код вашей процедуры. Следующий этап в создании любой процедуры - тестирование написанного кода. Тестирование - это процесс выполнения процедуры и исследование всех аспектов ее работы. Например, в процессе тестирования вы должны ввести различные типы данных (конечно, если это предусмотрено в процедуре), щелкнуть на всех командных кнопках, сделать выделение с последующим манипулированием различных диапазонов ячеек и т.п. Цель тестирования - проверить правильность результатов выполнения процедуры и ее реакцию на разнообразные действия пользователя. Если во время работы процедуры получены неверные результаты вычислений, непредвиденная реакция на те или иные действия пользователя, либо вообще произошла остановка выполнения, то это говорит о том, что код процедуры имеет ошибки (bugs).

Теперь надо подумать, что вы, как программист, можете сделать для минимизации возможных неполадок в своей процедуре. Я, конечно, понимаю ваше стремление при создании нового проекта сразу приступить к написанию кода. Но если вы прислушались к моим рекомендациям по разработке приложений (см. начало 3-го часа "Работа с элементами управления"), то у вас есть сформулированные и документированные цели и требования к разрабатываемому приложению. В результате вы получаете четкую картину того, что и как должно выполнять приложение. Это, в свою очередь, помогает резко ограничить круг проблем, которые могут возникнуть при выполнении приложения. Также важно с практической точки зрения разграничивать приложения, разрабатываемые "для личного потребления", и приложения, с которым будут работать сторонние пользователи. Требования к приложениям, с которыми будут работать другие пользователи, естественно, значительно выше и на их тестирование и отладку потребуется больше времени. В любом случае, то время, которое вы потратите на анализ и документирование на первом этапе разработки приложения, с лихвой окупится на последующих этапах, в частности на этапе тестирования приложения.

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

Соглашения об именах элементов управления приведены в 3-м часе "Работа с элементами управления", а соглашения об именах переменных и констант - в 4-м часе "Переменные и константы".

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

Выполняя упражнения из этой книги, вы, вероятно, не раз допускали какие-либо ошибки при вводе кода. В этом случае после нажатия клавиши <Enter> вы видели окно с сообщением о синтаксической ошибке (рис. 12.1). По умолчанию редактор Visual Basic отслеживает синтаксические ошибки в коде процедур после нажатия клавиши <Enter>. Это полезное средство, но при желании вы его можете отключить (или восстановить), удалив (или установив) флажок опции Auto Syntax Check (Автоматическая проверка синтаксиса) на вкладке Editor (Редактор) диалогового окна Options (Параметры).

Другой тип ошибок называется ошибками выполнения (runtime error). Это такие ошибки, которые приводят к остановке выполнения приложения. Иногда вина за такие ошибки ложится на программиста. Например, вы ввели имя объекта с ошибкой. VBA может обнаружить такую ошибку только во время выполнения программы. Ошибки выполнения также могут быть реакцией на действия пользователя, которые не предусмотрены в программе, например на ввод некорректного значения аргумента функции, которую вы создали.

Наконец, существует еще один тип ошибок, который называется логическими ошибками (logic error). VBA не может отследить такой тип ошибок, так как в этом случае обычно нет грамматических и синтаксических ошибок в написании операторов. В этом случае говорят, что нарушена логика выполнения операторов. Далее вы узнаете, что большинство средств отладки направлено именно на поиск и исправление логических ошибок.

Рис. 12.1. Редактор Visual Basic немедленно реагирует на синтаксические ошибки

Отладка

Процесс локализации и исправления ошибок называется отладкой (debugging). VBA предлагает богатый набор средств отладки. К ним относятся:

  • окно быстрого выполнения Immediate,
  • наблюдение за значениями переменных,
  • точки останова,
  • пошаговое выполнение кода.

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

  1. Закройте все открытые книги.
  2. Откройте новую рабочую книгу.
  3. Нажмите комбинацию клавиш <Alt+F11> для открытия редактора Visual Basic.
  4. Вставьте модуль в текущую рабочую книгу.
  5. Создайте новую процедуру и назовите ее Ошибка.
  6. Введите код этой процедуры

Dim response

response = Application.InputBox("Введите ваше имя")

If response = "" Then

 MsgBox "Процедура завершена"

 Exit Sub

Else

 MsgBox "Ваше имя - " & response

End If

  1. Выполните процедуру. В окне ввода введите ваше имя и нажмите клавишу <Enter>. Появится окно сообщения, содержащее ваше имя. Итак, пока процедура работает как надо.
  2. Щелкните на кнопке ОК для закрытия окна сообщения.
  3. Нажмите <F5> для повторного выполнения процедуры.
  4. В окне ввода щелкните на кнопке Отмена. Что получилось? Получили окно сообщение, что ваше имя False! Но должны были получить окно сообщения, что процедура завершена!
  5. Щелкните на кнопке ОК для удаления окна сообщения.

Итак, процедура работает неправильно. Она определенно содержит ошибку, но как найти эту ошибку? На примере этой процедуры мы рассмотрим различные методы отладки.

Режим останова

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

  • Редактировать код процедуры.
  • Просматривать значения переменных, свойств и выражений.
  • Изменять значения переменных и свойств.
  • Выполнять операторы Visual Basic в окне быстрого выполнения Immediate.

В нашей процедуре, как вы догадываетесь, ошибка как-то связана с оператором InputBox. Строка, содержащая этот оператор, хороший кандидат для того, чтобы после ее выполнения остановить процедуру. Место в коде программы, где остановится выполнение процедуры, называется точкой останова (breakpoint). Есть несколько способов пометить строку кода точкой останова.

  • Выберите строку кода и выполните команду Debug > Toggle Breakpoint (Отладка > Установка точки останова).
  • Выберите строку кода и нажмите клавишу <F9>.
  • Выберите строку кода и щелкните напротив этой строки на серой правой границе окна кода. (Эта серая граница называется индикаторной панелью окна кода.)
  • Если на экране отображается панель инструментов Edit (Редактирование) или панель Debug (Отладка), то выберите строку кода и щелкните на кнопке Toggle Breakpoint (Переключатель точки останова) одной или другой панели инструментов.

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

Рис. 12.2. В окне кода точку останова найти нетрудно

Удалить точки останова можно точно теми же описанными выше способами, что и установить. Если в коде установлены несколько точек останова, чтобы удалить их все за один раз, выполните команду Debug > Clear All Breakpoint (Отладка > Удалить все точки останова) или нажмите комбинацию клавиш <Ctrl+Shift+F9>.

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

  1. Поместите текстовый курсор где-нибудь в строке, расположенной ниже строки, содержащей оператор InputBox.
  2. Нажмите клавишу <F9>. Вы увидите, что строка изменила цвет и рядом на индикаторной панели появилась точка.

Конечно, можно установить больше одной точки останова - столько, сколько считаете нужным. Теперь выполним процедуру Ошибка и посмотрим, какой эффект произведет точка останова.

  1. Выполните процедуру Ошибка.
  2. В окно ввода введите свое имя и нажмите клавишу <Enter>. Появится окно редактора Visual Basic, где будет выделена строка, на которой установлена точка останова (рис. 12.3).

Рис. 12.3. Когда при выполнении процедура достигает точки останова, открывается окно редактора Visual Basic

Рис. 12.4. Быстрый просмотр значений переменных

Теперь процедура находится в режиме останова, и есть возможность узнать значение, которое в данный момент приняла переменная response. Самый простой путь сделать это - поместить указатель мыши на имя переменной. Появится маленькое окошко, показывающее текущее значение переменной (рис. 12.4). Таким же образом можно просмотреть значения других переменных и свойств, которые вас интересуют. Просмотр значений переменных - это самое наименьшее, что вы можете сделать для поиска и устранения ошибок.

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

Использование окна Immediate

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

  • Задать значения переменных и свойств.
  • Изменить значения переменных и свойств.
  • Увидеть результат отладочных действий.
  • Вызвать на исполнение любую процедуру.
  • Ввести новые операторы и сразу их выполнить. Это позволяет экспериментировать с различными вариантами кода процедуры.
  • Копировать и вставлять фрагменты кода процедуры в окно Immediate и сразу их выполнять.

Рис. 12.5. Окно Immediate обычно располагается под окном кода

Просмотр значений в окне Immediate

Как было показано ранее, можно просмотреть текущие значения переменных в режиме останова, поместив указатель мыши на имя переменной. Другой путь просмотра значений переменных и свойств - окно Immediate. Для этого также предусмотрено несколько способов. Во-первых, в окне Immediate можно ввести слово Print (Печать) или знак вопроса (?), а затем - имя переменной или свойства. Во-вторых, можно ввести непосредственно в процедуру оператор Debug.Print, который будет показывать в окне Immediate значения заданных переменных. Ниже мы рассмотрим оба эти способа.

Сначала испробуем способ со словом Print (или, что то же самое, со знаком вопроса).

  1. Если процедура Ошибка все еще находится в режиме останова, приведите ее в исходное состояние, выполнив команду Run > Reset (Выполнить > Восстановить) или щелкнув на кнопке Reset стандартной панели инструментов.
  2. Начните выполнение процедуры, нажав клавишу <F5>. В окне ввода щелкните на кнопке Отмена. Поскольку при выполнении процедуры достигнута точка останова, то откроется редактор Visual Basic.
  3. Если в окне редактора вы не видите окно Immediate, нажмите комбинацию клавиш <Ctrl+G>. Откроется окно Immediate. Его также можно открыть с помощью команды View > Immediate Window (Вид > Окно Immediate).
  4. Чтобы узнать значение переменной response, щелкните в окне Immediate и введите ? response.
  5. Нажмите клавишу <Enter>. В следующей строке окна Immediate появится значение переменной response. В данном случае эта переменная имеет значение False (рис. 12.6).

Для вывода значения переменной или свойства можно ввести слово Print или знак вопроса - результат будет одинаков.

Если вы хотите выполнить оператор, который был ранее введен в окно Immediate (например, оператор Print для просмотра значений), установите курсор в строку с этим оператором и нажмите <Enter>.

  1. Выше мы упоминали, что в окне Immediate можно не только просмотреть значения переменных, но и задавать эти значения. Это позволяет проверить логику выполнения программы. В нашей процедуре оператор If должен вывести соответствующее окно сообщения, если переменная response имеет значение пустой строки. Но как это проверить? Для этого достаточно в окне Immediate ввести следующую строчку:

response = ""

  1. Нажмите клавишу <Enter>. Теперь переменная response имеет значение пустой строки.
  2. Нажмите клавишу <F5>, чтобы продолжить выполнение процедуры. Вы должны увидеть долгожданное окно с сообщением о том, что процедура завершена.
  3. Щелкните на кнопке ОК в окне сообщения для завершения процедуры.

Рис. 12.6. Просмотр значения переменной в окне Immediate

В предыдущем примере для получения доступа к окну Immediate мы установили точку останова, которая переводила процедуру в режим останова. Затем получали в полное распоряжение окно Immediate. Но если по каким-либо причинам вы не хотите останавливать выполнение процедуры, но хотите знать значения переменных или свойств во время выполнения, то необходимо использовать оператор Debug.Print. Этот оператор вставляется непосредственно в код процедуры и выводит соответствующий текст в окно Immediate во время ее выполнения. Чтобы воспользоваться этим оператором в процедуре Ошибка, сделайте следующее.

  1. Выполните команду Debug > Clear All Breakpoints для удаления всех точек останова из процедуры.
  2. Удалите текст из окна Immediate.
  3. Измените код процедуры следующим образом (изменения выделены полужирным шрифтом):

Public Sub Ошибка()

 Dim response

 response = Application.InputBox("Введите свое имя")

 Debug.Print "Значение response: " & response

 If response = " " Then

  MsgBox "Процедура завершена"

  Exit Sub

 Else

  MsgBox "Ваше имя - " & response.

 End If

End Sub

  1. Нажав клавишу <F5>, начните выполнение процедуры.
  2. Введите свое имя в окне ввода и нажмите клавишу <Enter>.
  3. Щелкните на кнопке OK для закрытия окна сообщения.
  4. Снова выполните процедуру.
  5. В окне ввода щелкните на кнопке Отмена, а затем на кнопке OK, чтобы закрыть последующее окно сообщения.
  6. Вернитесь в редактор Visual Basic.

В окне Immediate вы увидите две строки текста (рис. 12.7). Первая строка появилась во время первого выполнения процедуры, вторая – при повторном выполнении.

Рис. 12.7. Оператор Debug.Print пишет историю изменения значения переменной

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

В большинстве случаев при отладке проверяется логика выполнения процедуры, поэтому необходимо отслеживать порядок исполнения строк кода. Это особенно необходимо при проверке работы операторов If и Select. Для этого применяется особый режим выполнения программ - пошаговое выполнение, когда программа останавливается после исполнения каждой строки кода.

Существует два режима пошагового выполнения: Step Into (Тотальное пошаговое выполнение) и Step Over (Пошаговое выполнение с перешагиванием через процедуры). Оба режима позволяют пошагово выполнять весь код процедуры и отслеживать значения переменных и свойств.

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

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

  1. Удалите оператор Debug.Print из процедуры.
  2. Установите точку останова в строке после оператора InputBox. Нажмите <F5>, чтобы начать выполнение процедуры.
  3. Щелкните на кнопке Отмена в окне ввода. Вы вернетесь в окно редактора Visual Basic, так как процедура достигла точки останова. Следующий выполняемый оператор - оператор If. Надо проследить, как выполняется этот оператор. По логике, сейчас условное выражение в операторе If имеет значение True (Истина), и должен выполняться оператор вывода окна сообщения (о том, что процедура завершена).
  4. Нажмите клавишу <F8>, чтобы перейти в пошаговый режим и выполнить следующий оператор. Заметьте, что после проверки условия оператора If процедура не стала выполнять оператор вывода окна сообщения, а перешла к пункту Else (рис. 12.8). Вот и найден оператор, который работает не так, как мы рассчитывали!

Рис. 12.8. В пошаговом режиме на выполняемый оператор указывает стрелка на индикаторной панели

  1. Нажмите клавишу <F5>, чтобы продолжить выполнение процедуры в обычном режиме.

Наблюдение за переменными

Visual Basic предлагает еще один способ отслеживания значений переменных и свойств, который называется наблюдением за выражениями. Наблюдаемые выражения (watch expressions) - это любые определенные пользователем выражения Visual Basic, позволяющие просматривать значения многих переменных или выражений. Конечно, наблюдаемые выражения должны быть корректными с точки зрения языка VBA.

Существует три режима наблюдения за выражениями, которые задаются выбором соответствующих переключателей в диалоговом окне Add Watch (Добавление наблюдаемых выражений) (рис. 12.9).

  • Режим Watch Expression (Наблюдаемое выражение) - отслеживаются значения заданных выражений без всякого влияния на ход выполнения приложения.
  • Режим Break When Value Is True (Останов, если значение истинно) - выполнение процедуры приостанавливается, если наблюдаемое выражение принимает значение True.
  • Режим Break When Value Changes (Останов, если значение изменилось) - выполнение процедуры приостанавливается, если наблюдаемое выражение изменило свое значение.

Используем в качестве наблюдаемого выражения переменную response.

  1. Удалите из процедуры все точки останова.
  2. Выделите имя переменной response в процедуре Ошибка.
  3. Выполните команду Debug > Add Watch (Отладка > Добавить наблюдаемое выражение), чтобы открыть диалоговое окно Add Watch (рис. 12.9).

Рис. 12.9. В этом диалоговом окне задаются режимы наблюдения за выражениями

  1. Поскольку в процедуре выделено слово response, то оно автоматически появится в поле Expression (Выражение) диалогового окна Add Watch. He изменяйте установки в секции Context (Состояние), где задано, из какой процедуры какого модуля наблюдается переменная (другими словами, здесь задается область видимости наблюдаемого выражения).
  2. Установите переключатель Break When Value Changes.
  3. Щелкните на кнопке ОК.

Если хотите быстро создать наблюдаемое выражение, выделите нужное выражение (например, имя переменной) в окне кода и выполните команду Debug > Quick Watch (Отладка > Быстрое наблюдение) либо нажмите комбинацию клавиш <Shift+F9>. Наблюдение в этом случае будет проводиться в режиме Watch Expression, т.е. без вмешательства в ход выполнения процедуры.

  1. Нажмите <F5> для начала выполнения процедуры.
  2. Щелкните на кнопке Отмена в окне ввода. Процедура перейдет в режим останова, так как переменная response изменила свое значение. В редакторе Visual Basic появится окно Watches (Наблюдение), показывающее значение переменной response (рис. 12.10).
  3. Нажмите <F5> для продолжения выполнения процедуры.

Рис. 12.10. Окно Watches показывает значения всех наблюдаемых выражений

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

  1. Выполните команду Debug > Edit Watch (Отладка > Редактирование наблюдаемых выражений). Откроется диалоговое окно Edit Watch (рис. 12.11).
  2. Так как у нас только одна наблюдаемая переменная, то в поле Expression будет выделено слово response. Щелкните на кнопке Delete (Удалить), и наблюдение за переменной будет отменено.

Рис. 12.11. Это окно используется для редактирования и удаления наблюдаемых выражений

Исправление ошибок

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

Листинг 12.1. Исправленная процедура Ошибка

1: Public Sub Ошибка()

2:  Dim response

3:

4:  response = Application.InputBox("Введите ваше имя")

5:  If response = False Then

6:   MsgBox "Процедура завершена"

7:   Exit Sub

8:  Else

9:   MsgBox "Ваше имя -" & response

10:  End If

11: End Sub

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

Резюме

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

Вопросы и ответы

Вопрос. Как можно выполнить только часть процедуры?

Ответ. Установите точки останова в те строки кода, начиная с которых вы хотите остановить или приостановить выполнение процедуры.

Вопрос. Почему лучше использовать наблюдаемые выражения вместо оператора Print в окне Immediate?

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

Практикум

С помощью тестов и упражнений вы проверите, насколько хорошо усвоили изложенный материал. Ответы на вопросы смотрите в Приложении.

Тесты

  1. Как называется режим, в который переходит процедура, достигнув точки останова?
  2. Как проследить за последовательностью выполняемых операторов?
  3. Как просмотреть значения переменных и свойств в окне Immediate?
  4. Какой еще, кроме установки точек останова, есть способ приостановить выполнение процедуры?
  5. Истинно или ложно следующее утверждение: в режиме останова вы не можете просмотреть значения переменных?
  6. Назовите два режима пошагового выполнения программ.
  7. Истинно или ложно следующее утверждение: наблюдаемые выражения никогда не воздействуют на ход выполнения процедуры?

Упражнение

Создайте следующую процедуру:

Sub ПримерЧас12()

 Dim sWhichState As String

 sWhichState = InputBox("Введите название штата, _

  куда доставляется груз")

 Select Case sWhichState

  Case "FL"

   MsgBox "Стоимость доставки 3.50"

  Case "NY"

   MsgBox "Стоимость доставки 5.00"

  Case "OH"

   MsgBox "Стоимость доставки 2.00"

  Case "CA"

   MsgBox "Стоимость доставки 6.00"

  Case Else

   MsgBox "В этот штат доставка не предусмотрена"

 End Select

End Sub

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

[an error occurred while processing this directive]