Опубликован: 25.03.2009 | Уровень: для всех | Доступ: свободно
Лекция 8:

Отладка приложений, обработка ошибок

< Лекция 7 || Лекция 8: 1234 || Лекция 9 >

8.9. Работа с ошибками времени выполнения

08-03-Ошибки времени выполнения.docm - пример к п. 8.9.

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

В этой ситуации нам поможет перехват и обработка ошибок времени выполнения.

Давайте рассмотрим ситуацию, которая гарантированно вызовет ошибку - деление на 0. Добавим в документ Microsoft Word кнопку с именем cmd_SimpleInput, подпишем ее как Отсутствие перехвата ошибок.

Напишем простую программу (поместив ее в обработчик события Click кнопки cmd_SimpleInput ), которая запрашивает у пользователя два числа, делит одно на другое и выводит результат деления. Следующий код (листинг 8.7.) реализует эту функциональность:

Dim num_A
    Dim num_B
    Dim num_C
    num_A = InputBox("Введите число A")
    num_B = InputBox("Введите число B")
    num_C = num_A / num_B
    MsgBox ("А, деленое на В равняется: " + Str(num_C))
Листинг 8.7. Деление без обработки ошибок

Чтобы организовать обработку ошибок в программе нужно расположить перед потенциально опасным участком (в нашем случае - перед строкой, где происходит деление) оператор такого вида:

On Error GoTo Идентификатор_обработчика

Идентификатор обработчика ошибок - это номер или (что предпочтительнее) метка строки в коде текущей процедуры, куда должно быть передано управление при возникновении ошибки. Обработчик ошибок должен находиться в текущей процедуре. Использовать в качестве идентификатора обработчика имя процедуры или функции нельзя

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

После того, как опасный участок программы пройден, обработку ошибок желательно отключить - это можно сделать такой командой:

On Error GoTo 0

Так же при обработке ошибок можно пользоваться командой

On Error Resume Next

Эта команда подавляет вывод сообщения об ошибке, просто передавая управление в следующую, после ошибочной, строку.

Для работы с ошибками, возникающими при выполнении программы, существует специальный объект - Err. Он содержит информацию об ошибках времени выполнения. У этого объекта есть несколько важнейших методов и свойств

Метод Clear очищает информацию об ошибках в объекте Err.

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

Номера ошибок находятся в диапазоне 0 - 65535. В частности, номера 0 - 512 зарезервированы за системными ошибками, 513 - 65535 - за ошибками, коды которых пользователь может назначать самостоятельно.

Например, для вызова ошибки несоответствия типов переменных (она возникает при попытке записать в числовую переменную строковое значение и в других случаях), которая имеет код 13, достаточно выполнить такую команду:

Err.Raise (13)

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

Свойство Description содержит текстовое описание ошибки

Научим нашу программу обрабатывать ошибки, которые могут возникать при вводе "неправильных" чисел. В нашем простом примере возможно возникновение как минимум трех различных ошибок

  • если число B (делитель) будет равно 0 - это ошибка №11 - "Деление на 0"
  • если одно из введенных чисел (или оба) на самом деле - не числа. Например, пользователь случайно нажал OK, не введя число в поле ввода. Это - ошибка №13 - "Несоответствие типов"
  • если оба числа равны нулю - такая ситуация вызовет ошибку №6 - "Переполнение"

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

В результате этих рассуждений у нас получился такой код (листинг 8.8.), который мы разместим в обработчике события Click кнопки cmd_ErrHandler, подписанной как Обработка ошибок и размещенной в том же документе, что и вышеописанная кнопка

Dim num_A
    Dim num_B
    Dim num_C
    num_A = InputBox("Введите число A")
    num_B = InputBox("Введите число B")
    On Error GoTo ErrHandler
    'С этого момента начинаем наблюдение
    'за ошибками
    num_C = num_A / num_B
    On Error GoTo 0
    'Прекращаем наблюдение за ошибками
    MsgBox ("А, деленое на В равняется: " + _
    Str(num_C))
    Exit Sub
ErrHandler: 'Начало обработчика ошибок
    MsgBox ("Вызвана ошибка №" + _
    Str(Err.Number) + " " + _
    Err.Description)
    Select Case Err.Number
    Case 6:
    'Overflow - переполнение
    'обе переменные равны 0
        MsgBox ("Вы ввели A и B = 0")
        num_A = InputBox("Введите число A")
        num_B = InputBox("Введите число B")
    Case 11:
    'Деление числа на 0
        MsgBox ("Вы ввели B = 0")
        num_B = InputBox("Введите число B")
    Case 13:
    'Type mismatch - несоответствие типов
    'одно из чисел или оба - не числа
        MsgBox ("Одно из чисел или оба - не числа")
        num_A = InputBox("Введите число A")
        num_B = InputBox("Введите число B")
    Case Else:
    'на случай возникновения
    'непредусмотренной ошибки
        num_A = InputBox("Введите число A")
        num_B = InputBox("Введите число B")
    End Select
    Resume
End Sub
Листинг 8.8. Обработка ошибок

Обратите внимание на то, что перед меткой строки, с которой начинается обработчик мы поставили команду Exit Sub. Это сделано для того, чтобы программа, дойдя до последней строки своей основной части, не начала бы выполнять обработчик ошибок.

Перед опасной операцией деления мы поставили команду On Error GoTo ErrHandler - если при делении произойдет ошибка, будет вызван обработчик. Необязательно устанавливать эту команду строго перед опасной процедурой - мы можем поставить ее в любом месте программы до нее. После того, как опасный участок пройден - следует команда On Error GoTo 0 - она отключает слежение за ошибками.

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

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

8.10. Выводы

В этой лекции мы рассмотрели вопросы отладки программ и работы с ошибками. Теперь вы владеете основными приемами VBA, общими для программирования в любых приложениях Office. В следующих лекциях мы займемся программированием для MS Word и MS Excel.

< Лекция 7 || Лекция 8: 1234 || Лекция 9 >
Евгений Ушаков
Евгений Ушаков
О стоимости курса
Александр Новиков
Александр Новиков
Справочник по объектам VBA
Анатолий Федоров
Анатолий Федоров
Россия, Москва, Московский государственный университет им. М. В. Ломоносова, 1989
Михаил Алексеев
Михаил Алексеев
Россия, Уфа, УГАТУ, 2002