Исключительная ситуация это ошибка при исполнении кода макроса

На чтение 25 мин. Просмотров 17.7k.

VBA Error Handling

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

Если вы ищете конкретную тему по обработке ошибок VBA, ознакомьтесь с приведенным ниже содержанием.

Если вы новичок в VBA, то вы можете прочитать пост от начала до конца, так как он выложен в логическом порядке.

Содержание

  1. Краткое руководство по обработке ошибок
  2. Введение
  3. Ошибки VBA
  4. Заявление об ошибке
  5. Err объект
  6. Логирование
  7. Другие элементы, связанные с ошибками
  8. Простая стратегия обработки ошибок
  9. Полная стратегия обработки ошибок
  10. Обработка ошибок в двух словах

Краткое руководство по обработке ошибок

Пункт Описание
On Error Goto 0 При возникновении ошибки код останавливается и отображает
ошибку.
On Error Resume Next Игнорирует ошибку и
продолжает.
On Error Goto [Label] Переход к определенной метке при возникновении ошибки.
Это позволяет нам справиться
с ошибкой.
Err Object При возникновении ошибки
информация об ошибке
сохраняется здесь.
Err.Number Номер ошибки.
(Полезно, только если вам
нужно проверить, произошла ли конкретная ошибка.)
Err.Description Содержит текст ошибки.
Err.Source Вы можете заполнить это, когда используете Err.Raise.
Err.Raise Функция, которая позволяет
генерировать вашу собственную ошибку.
Error Function Возвращает текст ошибки из
номера ошибки.
Вышло из употребления.
Error Statement Имитирует ошибку. Вместо этого используйте Err.Raise.

Введение

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

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

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

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

VBA Error Handling

Ошибки VBA

В VBA есть три типа ошибок

  1. Синтаксис
  2. Компиляция
  3. Время выполнения

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

Синтаксические ошибки

Если вы использовали VBA в течение какого-то времени, вы
увидите синтаксическую ошибку. Когда вы набираете строку и нажимаете return,
VBA оценивает синтаксис и, если он неверен, выдает сообщение об ошибке.

Например, если вы введете If и забудете ключевое слово Then,
VBA отобразит следующее сообщение об ошибке.

VBA Error Handling

Некоторые примеры синтаксических ошибок

' then отсутствует
If a > b

' не хватает = после i
For i 2 To 7

' отсутствует правая скобка
b = left("АБВГ",1

Синтаксические ошибки относятся только к одной строке. Они
возникают, когда синтаксис одной строки неверен.

Примечание. Диалоговое окно «Ошибка синтаксиса» можно отключить, выбрав «Сервис» -> «Параметры» и отметив «Автосинтаксическая проверка». Строка по-прежнему будет отображаться красным цветом в случае ошибки, но диалоговое окно не появится.

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

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

Примеры ошибок компиляции:

  • Оператор If без соответствующего оператора End If
  • For без Next
  •  Select без End Select
  • Вызов Sub или Function, которые не существуют
  • Вызов Sub или Function с неверными параметрами
  • Присвоение Sub или Function того же имени, что и для модуля
  • Переменные не объявлены (Option Explicit должен присутствовать в верхней части модуля)

На следующем снимке экрана показана ошибка компиляции,
которая возникает, когда цикл For не имеет соответствующего оператора Next.

VBA Error Handling

Использование Debug-> Compile

Чтобы найти ошибки компиляции, мы используем Debug->
Compile VBA Project из меню Visual Basic.

Когда вы выбираете Debug-> Compile, VBA отображает первую
обнаруженную ошибку.

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

Debug-> Compile также будет включать синтаксические
ошибки в поиск, что очень полезно.

Если ошибок не осталось и вы запускаете Debug-> Compile,
может показаться, что ничего не произошло. Однако «Компиляция» будет недоступна
в меню «Отладка». Это означает, что ваше приложение не имеет ошибок компиляции
в текущий момент.

Debug->Compile Error Summary

Debug-> Compile находит ошибки компиляции (проекта).

Он также найдет синтаксические ошибки.

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

Если нет ошибок компиляции, оставленная опция Компиляция
будет отображаться серым цветом в меню.

Debug-> Compile Usage

Вы должны всегда использовать Debug-> Compile, прежде чем
запускать свой код. Это гарантирует, что ваш код не будет иметь ошибок
компиляции при запуске.

Если вы не запускаете Debug-> Compile, то VBA может
обнаружить ошибки компиляции при запуске. Их не следует путать с ошибками
времени выполнения.

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

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

VBA Error Handling

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

Другие примеры ошибок времени выполнения

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

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

Ожидаемые и неожиданные ошибки

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

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

Sub OtkritFail()
    
    Dim sFile As String
    sFile = "C:\Документы\Отчет.xlsx"
    
    ' Используйте Dir, чтобы проверить, существует ли файл
    If Dir(sFile) = "" Then
        ' если файл не существует, отобразить сообщение
        MsgBox "Файл не найден" & sFile
        Exit Sub
    End If
    
    ' Код достигнет только если файл существует
    Workbooks.Open sFile
    
End Sub

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

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

Ошибки времени выполнения, которые не являются ошибками VBA

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

Позвольте мне объяснить это на примере. Представьте, что у
вас есть приложение, которое требует, чтобы вы добавили значения в переменные a
и b

Допустим, вы по ошибке используете звездочку вместо знака
плюс

Это не ошибка VBA. Ваш синтаксис кода является совершенно
законным. Однако, с вашей точки зрения, это ошибка.

Эти ошибки не могут быть обработаны с помощью обработки ошибок, поскольку они, очевидно, не будут генерировать никаких ошибок. Вы можете справиться с этими ошибками, используя Unit Testing and Assertions.

Заявление об ошибке

Как мы видели, есть два способа обработки ошибок во время
выполнения

  1. Ожидаемые ошибки — напишите конкретный код для
    их обработки.
  2. Неожиданные ошибки — используйте операторы
    обработки ошибок VBA для их обработки.

Оператор VBA On Error используется для обработки ошибок.
Этот оператор выполняет некоторые действия при возникновении ошибки во время
выполнения.

Есть четыре различных способа использовать это утверждение

  1. On Error Goto 0 — код останавливается на строке с ошибкой и отображает сообщение.
  2. On Error Resume Next — код перемещается на следующую строку. Сообщение об ошибке не отображается.
  3. On Error Goto [label] — код перемещается на определенную строку или метку. Сообщение об ошибке не отображается. Это тот, который мы используем для обработки ошибок.
  4. On Error Goto -1 — очищает текущую ошибку.

Давайте посмотрим на каждое из этих утверждений по очереди.

On Error Goto 0

Это поведение по умолчанию VBA. Другими словами, если вы не
используете On Error, это поведение вы увидите.

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

Давайте посмотрим на пример. В следующем коде мы не
использовали строку On Error, поэтому VBA будет использовать поведение On Error
Goto 0 по умолчанию.

Sub IspDefault()

    Dim x As Long, y As Long
    
    x = 6
    y = 6 / 0
    x = 7

End Sub

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

VBA Error Handling

Когда появляется ошибка, вы можете выбрать End или Debug

Если вы выберете Конец, то приложение просто остановится.

Если вы выберете Отладить, приложение остановится на строке
ошибки, как показано на скриншоте ниже.

VBA Error Handling

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

Это поведение не подходит для приложения, которое вы
передаете пользователю. Эти ошибки выглядят непрофессионально и делают
приложение нестабильным.

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

Используя On Error Goto [label], мы можем дать пользователю
более контролируемое сообщение об ошибке. Это также предотвращает остановку
приложения. Мы можем заставить приложение работать предопределенным образом.

On Error Resume Next

Использование On Error Resume Next указывает VBA
игнорировать ошибку и продолжать работу.

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

Если мы добавим Resume Next к нашему примеру Sub, то VBA
проигнорирует ошибку деления на ноль

Sub UsingResumeNext()

    On Error Resume Next
    
    Dim x As Long, y As Long
    
    x = 6
    y = 6 / 0
    x = 7

End Sub

Это не очень хорошая идея, чтобы сделать это. Если вы
игнорируете ошибку, то поведение может быть непредсказуемым. Ошибка может
повлиять на приложение несколькими способами. Вы можете получить неверные
данные. Проблема в том, что вы не знаете, что что-то пошло не так, потому что
вы подавили ошибку.

Приведенный ниже код является примером использования Resume
Next.

Sub OtprSoobsch()

   On Error Resume Next
   
    ' Требуется ссылка:
    ' Библиотека объектов Microsoft Outlook 15.0
    Dim Outlook As Outlook.Application
    Set Outlook = New Outlook.Application

    If Outlook Is Nothing Then
        MsgBox " Не удается создать сеанс Microsoft Outlook." _
                   & " Письмо не будет отправлено."
        Exit Sub
    End If
    
End Sub

В этом коде мы проверяем, доступен ли Microsoft Outlook на компьютере. Все,
что мы хотим знать — это доступно или нет. Нас не интересует конкретная ошибка.

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

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

On Error Goto [label]

Вот как мы используем обработку ошибок в VBA. Это эквивалент функциональности Try and Catch, которую вы видите на
таких языках, как C # и
Java.

При возникновении ошибки вы отправляете ошибку на
определенный ярлык. Обычно это внизу саба.

Давайте применим это к подводной лодке, которую мы
использовали

Sub IspGotoLine()

    On Error Goto eh
    
    Dim x As Long, y As Long
    
    x = 6
    y = 6 / 0
    x = 7
    
Done:
    Exit Sub
eh:
    MsgBox "Произошла следующая ошибка: " & Err.Description
End Sub

Снимок экрана ниже показывает, что происходит при возникновении ошибки.

VBA Error Handling

VBA переходит на метку eh, потому что мы указали это в
строке «Перейти к ошибке».

Примечание 1: Метка, которую мы используем в операторе On… Goto, должна быть в текущей Sub / Function. Если нет, вы получите ошибку компиляции.

Примечание 2: Когда возникает ошибка при использовании On Error Goto [label], обработка ошибок возвращается к поведению по умолчанию, т.е. код остановится на строке с ошибкой и отобразит сообщение об ошибке. См. Следующий раздел для получения дополнительной информации об этом.

On Error Goto -1

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

При возникновении ошибки с помощью функции On Error Goto [label] поведение обработки ошибки возвращается к поведению по умолчанию, т.е. On Error Goto 0 . Это означает, что если произойдет другая ошибка, код остановится на текущей строке.

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

Посмотрите на код ниже. Первая ошибка приведет к переходу
кода на метку eh. Вторая ошибка остановится на строке с ошибкой 1034.

Sub DveOshibki()

    On Error Goto eh
        
    ' генерировать ошибку «Несоответствие типов»
    Error (13)

Done:
    Exit Sub
eh:
    ' генерировать «определенную приложением» ошибку
    Error (1034)
End Sub

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

В коде ниже мы добавили строку

после того как мы поймаем первую ошибку.

Это не имеет никакого эффекта, так как ошибка не была
очищена. Другими словами, код остановится на строке с ошибкой и отобразит
сообщение.

Sub DveOshibki()

    On Error Goto eh
        
    ' генерировать ошибку «Несоответствие типов»
    Error (13)

Done:
    Exit Sub
eh:
    On Error Goto eh_other
    ' генерировать «определенную приложением» ошибку
    Error (1034)
Exit Sub
eh_other:
    Debug.Print "ehother " & Err.Description
End Sub

Для устранения ошибки мы используем On Error Goto -1.
Думайте об этом как об установке ловушки для мыши. Когда ловушка сработает, вам
нужно установить ее снова.

В приведенном ниже коде мы добавляем эту строку, и вторая
ошибка теперь приведет к переходу кода на метку eh_other.

Sub DveOshibki()

    On Error Goto eh
        
    ' генерировать ошибку «Несоответствие типов»
    Error (13)

Done:
    Exit Sub
eh:
    ' явная ошибка
    On Error Goto -1
    
    On Error Goto eh_other
    ' генерировать «определенную приложением» ошибку
    Error (1034)
Exit Sub
eh_other:
    Debug.Print "ehother " & Err.Description
End Sub

Примечание 1. Вероятно, в редких случаях полезно использовать On Error Goto -1. Мне лично никогда не приходилось пользоваться этой линией. Помните, что как только вы выйдете из Sub, ошибка все равно будет очищена.

Примечание 2. у объекта Err есть член Clear. Использование Clear очищает текст и цифры в объекте Err, но НЕ сбрасывает ошибку.

Использование On Error

Как мы уже видели, VBA будет делать одну из трех вещей при возникновении ошибки:

  • Остановитесь и отобразите ошибку.
  • Игнорируйте ошибку и продолжайте.
  • Перейти к определенной строке.

VBA всегда будет настроен на одно из этих действий. Когда вы
используете On Error, VBA изменит ваше поведение и забудет о любом предыдущем.

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

Sub ErrorSostoyaniya()

    Dim x As Long
    
    ' Перейти на этикетке, если ошибка
    On Error Goto eh
    
    ' это проигнорирует ошибку в следующей строке
    On Error Resume Next
    x = 1 / 0
    
    ' это отобразит сообщение об ошибке в следующей строке
    On Error Goto 0
    x = 1 / 0
  
Done:  
   Exit Sub
eh:
    Debug.Print Err.Description
End Sub

Err объект

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

При возникновении ошибки времени выполнения VBA
автоматически заполняет объект Err деталями.

Приведенный ниже код выведет «Error Number: 13 Type
Mismatch», которое возникает, когда мы пытаемся поместить строковое значение в
длинное целое число.

Sub IspErr()

    On Error Goto eh
    
    Dim total As Long
    total = "aa"

Done:
    Exit Sub
eh:
    Debug.Print "Номер ошибки: " & Err.Number _
            & " " & Err.Description
End Sub

Err.Description предоставляет подробную информацию об ошибке, которая происходит. Это текст, который вы обычно видите, когда возникает ошибка, например, «Несоответствие типов»

Err.Number — это идентификационный номер ошибки, например, номер ошибки для «Несоответствие типов» — 13. Единственное время, когда вам действительно нужно это, если вы проверяете, что произошла конкретная ошибка, и это необходимо только в редких случаях.

Свойство Err.Source кажется отличной идеей, но оно не работает при ошибке VBA. Источник вернет имя проекта, которое вряд ли сузит место возникновения ошибки. Однако, если вы создаете ошибку с помощью Err.Raise, вы можете установить источник самостоятельно, и это может быть очень полезно.

Получение номера строки

Функция Erl используется для возврата номера строки, где
произошла ошибка.

Это часто вызывает путаницу. В следующем коде Erl вернет ноль.

Sub IspErr()

    On Error Goto eh
    
    Dim val As Long
    val = "aa"

Done:
    Exit Sub
eh:
    Debug.Print Erl
End Sub

Это потому, что нет номеров строк. Большинство людей не
понимают этого, но VBA позволяет вам иметь номера строк.

Если мы изменим подпрограмму, указав номер строки, она теперь выведет 20.

Sub IspErr()

10        On Error Goto eh
          
          Dim val As Long
20        val = "aa"

Done:
30        Exit Sub
eh:
40        Debug.Print Erl
End Sub

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

Когда вы закончите работу над проектом и передадите его
пользователю, в этот момент может быть полезно добавить номера строк. Если вы
используете стратегию обработки ошибок в последнем разделе этого поста, то VBA
сообщит строку, где произошла ошибка.

Использование Err.Raise

Err.Raise позволяет нам создавать ошибки. Мы можем
использовать его для создания пользовательских ошибок для нашего приложения,
что очень полезно. Это эквивалент оператора Throw в Java \ C #.

Формат следующий

Err.Raise [error number], [error source], [error description]

Давайте посмотрим на простой пример. Представьте, что мы
хотим убедиться, что в ячейке есть запись длиной 5 символов. Мы могли бы иметь конкретное сообщение для
этого

Public Const ERROR_INVALID_DATA As Long = vbObjectError + 513

Sub ReadWorksheet()

    On Error Goto eh
    
    If Len(Sheet1.Range("A1")) <> 5 Then
        Err.Raise ERROR_INVALID_DATA, "ReadWorksheet" _
            , "Значение в ячейке A1 должно иметь ровно 5 символов."
    End If
    
    ' продолжить, если ячейка имеет действительные данные
    Dim id As String
    id = Sheet1.Range("A1")
    

Done:
    Exit Sub
eh:
    ' Err.Raise отправит код сюда
    MsgBox " Обнаружена ошибка: " & Err.Description
End Sub

Когда мы создаем ошибку, используя Err.Raise, нам нужно присвоить ей номер. Мы можем использовать любое
число от 513 до 65535 для нашей ошибки. Мы должны использовать vbObjectError с номером,
например

Err.Raise vbObjectError + 513

Использование Err.Clear

Err.Clear используется для очистки текста и чисел из объекта
Err.Object. Другими словами, он очищает описание и номер.

Редко вам понадобится его использовать, но давайте
рассмотрим пример, где вы могли бы.

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

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

Sub IspErrClear()

    Dim count As Long, i As Long

    ' Продолжите, если ошибка, так как мы проверим номер ошибки
    On Error Resume Next
    
    For i = 0 To 9
        ' генерировать ошибку для каждого второго
        If i Mod 2 = 0 Then Error (13)
        
        ' Проверьте на ошибку
        If Err.Number <> 0 Then
            count = count + 1
            Err.Clear    ' Очистить Err, как только он считается
        End If
    Next

    Debug.Print " Количество ошибок было: " & count
End Sub

Примечание: Err.Clear сбрасывает текст и цифры в объекте ошибки, но не очищает ошибку — см. On Error Goto -1 для получения дополнительной информации об очистке фактической ошибки.

Логирование

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

Код ниже показывает очень простую процедуру регистрации

Sub Logger(sType As String, sSource As String, sDetails As String)
    
    Dim sFilename As String
    sFilename = "C:\temp\logging.txt"
    
    ' Архивный файл определенного размера
    If FileLen(sFilename) > 20000 Then
        FileCopy sFilename _
            , Replace(sFilename, ".txt", Format(Now, "ddmmyyyy hhmmss.txt"))
        Kill sFilename
    End If
    
    ' Откройте файл для записи
    Dim filenumber As Variant
    filenumber = FreeFile 
    Open sFilename For Append As #filenumber
    
    Print #filenumber, CStr(Now) & "," & sType & "," & sSource _
                                & "," & sDetails & "," & Application.UserName
    
    Close #filenumber
    
End Sub

Вы можете использовать это так:

' Создать уникальный номер ошибки
Public Const ERROR_DATA_MISSING As Long = vbObjectError + 514

Sub CreateReport()

    On Error Goto eh
    
    If Sheet1.Range("A1") = "" Then
       Err.Raise ERROR_DATA_MISSING, "CreateReport", "Данные отсутствуют в ячейке A1"
    End If

    ' другой код здесь
Done:
    Exit Sub
eh:
    Logger "Error", Err.Source, Err.Description
End Sub

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

Ниже приведен пример регистрации. То, как вы реализуете
журналирование, зависит от характера приложения и его полезности.

Sub ReadingData()
    
    Logger "Information", "ReadingData()", "Starting to read data."
       
    Dim coll As New Collection
    ' Read data
    Set coll = ReadData
    
    If coll.Count < 10 Then
        Logger "Warning", "ReadingData()", "Number of data items is low."
    End If
    Logger "Information", "ReadingData()", "Number of data items is " & coll.Count
    
    Logger "Information", "ReadingData()", "Finished reading data."

End Sub

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

Другие элементы, связанные с ошибками

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

Функция ошибки

Функция Error используется для печати описания ошибки с
заданным номером ошибки. Он включен в VBA для обеспечения обратной
совместимости и не нужен, поскольку вместо него можно использовать описание
Err.Description.

Ниже приведены некоторые примеры

' Распечатать текст «Деление на ноль»
Debug.Print Error(11)
' Распечатать текст "Несоответствие типов"
Debug.Print Error(13)
' Распечатать текст "Файл не найден"
Debug.Print Error(53)

Заявление об ошибке

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

В следующем коде мы моделируем ошибку «Разделить на ноль».

Sub ZayavlObOshibke()

    On Error Goto eh
        
    ' Это создаст деление на ноль ошибок
    Error 11
    
    Exit Sub
eh:
    Debug.Print Err.Number, Err.Description
End Sub

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

Простая стратегия обработки ошибок

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

Основная реализация

Это простой обзор нашей стратегии

  1. Поместите строку On Error Goto Label  в начале нашего верхнего Sub.
  2. Поместите Label у обработки ошибок в конце нашего верхнего
    Sub.
  3. Если происходит ожидаемая ошибка, обработайте ее и продолжайте.
  4. Если приложение не может продолжить работу, используйте Err.Raise для перехода к метке обработки ошибок.
  5. В случае непредвиденной ошибки код автоматически перейдет к метке обработки ошибок.

На следующем рисунке показан обзор того, как это выглядит

error-handling

Следующий код показывает простую реализацию этой стратегии

Public Const ERROR_NO_ACCOUNTS As Long = vbObjectError + 514

Sub BuildReport()

    On Error Goto eh
    
    ' Если ошибка в ReadAccounts, то перейти к ошибке
    ReadAccounts
    
    ' Сделай что-нибудь с кодом
    
Done:
    Exit Sub
eh:
    ' Все ошибки будут прыгать сюда
    MsgBox Err.Source & ": Произошла следующая ошибка  " & Err.Description
End Sub

Sub ReadAccounts()
    
    ' ОЖИДАЕМАЯ ОШИБКА - Может обрабатываться кодом
    ' Приложение может обрабатывать A1 равным нулю
    If Sheet1.Range("A1") = 0 Then
        Sheet1.Range("A1") = 1
    End If
    
    ' ОЖИДАЕМАЯ ОШИБКА - не может быть обработана кодом
    ' Приложение не может быть продолжено, если нет учетной записи
    If Dir("C:\Документы\Отчет.xlsx") = "" Then
        Err.Raise ERROR_NO_ACCOUNTS, "UsingErr" _
                , "There are no accounts present for this month."
    End If

    ' НЕОЖИДАННАЯ ОШИБКА - не может быть обработана кодом
    ' Если ячейка B3 содержит текст, мы получим ошибку несоответствия типов
    Dim total As Long
    total = Sheet1.Range("B3")
    
    
    ' продолжить и читать счета
    
End Sub

Это хороший способ реализации обработки ошибок, потому что

  • Нам не нужно добавлять код обработки ошибок в
    каждую подпрограмму.
  • Если возникает ошибка, то VBA корректно
    завершает работу приложения.

Полная стратегия обработки ошибок

Стратегия выше имеет один недостаток. Он не сообщает вам,
где произошла ошибка. VBA не наполняет Err.Source чем-либо полезным, поэтому мы
должны сделать это сами.

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

Целью этой стратегии является предоставление вам стека * и
номера строки в случае возникновения ошибки.

* Стек — это список вспомогательных функций, которые
использовались в данный момент при возникновении ошибки.

Это наша стратегия

  1. Разместите обработку ошибок во всех
    подпрограммах.
  2. Когда происходит ошибка, обработчик ошибок
    добавляет подробности к ошибке и вызывает ее снова.
  3. Когда ошибка достигает самой верхней
    подпрограммы, она отображается.

Мы просто «всплываем» из-за ошибки. Следующая диаграмма
показывает простое визуальное представление о том, что происходит, когда в Sub3
возникает ошибка

Error Handling – bubbling

Единственная грязная часть этого — правильное форматирование
строк. Я написал две подводные лодки, которые справляются с этим, поэтому он
позаботится о вас.

Это две вспомогательные подводные лодки

Option Explicit

Public Const MARKER As String = "NOT_TOPMOST"

' Вызывает ошибку и добавляет номер строки и имя текущей процедуры
Sub RaiseError(ByVal errorno As Long, ByVal src As String _
                , ByVal proc As String, ByVal desc As String, ByVal lineno As Long)
    
    Dim sLineNo As Long, sSource As String
    
    ' Если маркера нет, тогда RaiseError вызывается впервые.
    If Left(src, Len(MARKER)) <> MARKER Then

        ' Добавить номер строки ошибки, если она есть
        If lineno <> 0 Then
            sSource = vbCrLf & "Line no: " & lineno & " "
        End If
   
        ' Добавить маркер и процедуру к источнику
        sSource = MARKER & sSource & vbCrLf & proc
        
    Else
        ' Если ошибка уже возникла, просто добавьте имя процедуры
        sSource = src & vbCrLf & proc
    End If
    
    ' Если код останавливается здесь, убедитесь, что DisplayError находится в верхней части Sub
    Err.Raise errorno, sSource, desc
    
End Sub

' Отображает ошибку, когда она достигает самого верхнего sub
' Примечание: вы можете добавить вызов для входа из этого подпункта
Sub DisplayError(ByVal src As String, ByVal desc As String _
                    , ByVal sProcname As String)

    ' Удалить маркер
    src = Replace(src, MARKER, "")
    
    Dim sMsg As String
    sMsg = " Произошла следующая ошибка: " & vbCrLf & Err.Description _
                    & vbCrLf & vbCrLf & " Расположение ошибки: "
    
    sMsg = sMsg + src & vbCrLf & sProcname
    
    ' Показать сообщение
    MsgBox sMsg, Title:="Ошибка "
    
End Sub

Пример использования этой стратегии

Вот простое кодирование, которое использует эти Sub. В этой стратегии мы не размещаем какой-либо код в верхнем подпрограмме. Мы только вызываем подводные лодки.

Sub Topmost()

    On Error Goto EH
    
    Level1

Done:
    Exit Sub
EH:
    DisplayError Err.source, Err.Description, "Module1.Topmost"
End Sub

Sub Level1()

    On Error Goto EH
    
    Level2

Done:
    Exit Sub
EH:
   RaiseError Err.Number, Err.source, "Module1.Level1", Err.Description, Erl
End Sub

Sub Level2()

    On Error Goto EH
    
    ' Ошибка здесь
    Dim a As Long
    a = "7 / 0"

Done:
    Exit Sub
EH:
    RaiseError Err.Number, Err.source, "Module1.Level2", Err.Description, Erl
End Sub

Результат выглядит так

error handling output

Если в вашем проекте есть номера строк, результат будет содержать номер строки ошибки.

error handling output line

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

“Programmatic Access to Visual Basic Project is not trusted”

Чтобы решить эту проблему, выполните следующие действия.

  1. Перейдите в раздел «Разработчик» на ленте и
    нажмите «Macro Security», которая находится под кодом.
  2. Нажмите «Настройка макроса» в левом списке.
  3. Поставьте флажок в поле «Доверительный доступ к
    объектной модели проекта VBA».
  4. Нажмите Ok.

Обработка ошибок в двух словах

  • Обработка ошибок используется для обработки ошибок, возникающих во время работы приложения.
  • Вы пишете определенный код для обработки ожидаемых ошибок. Вы используете оператор обработки ошибок VBA
    On Error Goto [label] для отправки VBA на метку при возникновении непредвиденной ошибки.
  • Вы можете получить подробную информацию об ошибке из Err.Description.
  • Вы можете создать свою собственную ошибку, используя Err.Raise.
  • Использование одного оператора On Error в самой верхней подпрограмме перехватит все ошибки в подпрограммах, которые вызываются отсюда.
  • Если вы хотите записать имя Sub с ошибкой, вы можете обновить ошибку и сбросить ее.
  • Вы можете использовать журнал для записи информации о приложении, когда оно запущено.

В языке программирования VBA (Visual Basic for Applications) для работы с макросами Excel часто возникают ситуации, когда в коде необходимо обрабатывать потенциальные ошибки. Ошибки могут возникать в результате некорректных входных данных, неправильного ввода пользователя или других непредвиденных ситуаций.

Одним из способов обработки ошибок в VBA является использование инструкции Exit Sub. Эта инструкция позволяет покинуть текущую процедуру (Sub) или функцию (Function) и вернуться обратно к вызывающей их процедуре или функции. Если в коде возникает ошибка, то оператор Exit Sub прерывает выполнение текущей процедуры и передает управление обратно вызывающей процедуре.

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

Инструкция Exit Sub является мощным инструментом для обработки ошибок в VBA Excel. Она позволяет контролировать выполнение кода и поведение программы в случае возникновения ошибок. Правильное использование инструкции Exit Sub позволяет создавать более надежные и безопасные макросы, а также улучшить пользовательский опыт при работе с Excel.

Содержание

  1. VBA Excel: учимся исключать ошибки в выражениях с помощью Exit Sub
  2. Что такое VBA Excel?
  3. Зачем исключать ошибки в выражениях?
  4. Виды ошибок в выражениях
  5. Как использовать Exit Sub для исключения ошибок?
  6. Практические примеры использования Exit Sub

VBA Excel: учимся исключать ошибки в выражениях с помощью Exit Sub

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

Оператор Exit Sub используется в сочетании с конструкцией On Error и позволяет управлять переходом к нужному участку кода при возникновении ошибки. Рассмотрим пример:

Sub DivisionByZero()
On Error GoTo ErrorHandler
Dim a As Integer
Dim b As Integer
Dim result As Integer
a = 10
b = 0
result = a / b
Exit Sub
ErrorHandler:
MsgBox "Ошибка деления на ноль!"
End Sub

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

Оператор Exit Sub сразу после ошибочной операции прерывает выполнение кода и переводит выполнение программы на метку ErrorHandler. В результате выводится сообщение с информацией о возникшей ошибке.

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

Что такое VBA Excel?

С помощью VBA Excel можно создавать пользовательские формы, добавлять новые функции и процедуры, а также создавать и редактировать рабочие книги и листы Excel. Язык VBA Excel основан на языке программирования Visual Basic и предоставляет широкие возможности для автоматизации рутинных задач.

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

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

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

Зачем исключать ошибки в выражениях?

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

1. Обработка ошибок:

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

2. Улучшение читаемости кода:

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

3. Сокрытие ошибок от конечных пользователей:

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

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

Виды ошибок в выражениях

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

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

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

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

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

5. Ошибка нулевой ссылки: Эта ошибка возникает, когда вы пытаетесь обратиться к объекту или переменной, которая имеет значение Null или не инициализирована.

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

Как использовать Exit Sub для исключения ошибок?

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

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

Вот пример, который показывает, как использовать оператор Exit Sub:


Sub Пример()
Dim number As Integer
number = InputBox("Введите число:")
If number < 0 Then
MsgBox "Ошибка: Число не может быть отрицательным."
Exit Sub
End If
' Продолжение кода в случае отсутствия ошибок
MsgBox "Число " & number & " прошло проверку."
End Sub

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

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

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

Практические примеры использования Exit Sub

Example 1:


Sub MySub()
Dim x As Integer
On Error GoTo ErrorHandler
x = 10 / 0
'... some additional code
Exit Sub
ErrorHandler:
MsgBox "Ошибка: деление на ноль!"
Exit Sub
End Sub

В этом примере используется конструкция Exit Sub для прекращения выполнения подпрограммы, если возникает ошибка деления на ноль. После обработки ошибки с помощью ErrorHandler: код ниже этой метки не будет выполнен.

Example 2:


Sub MySub()
Dim x As Integer
On Error Resume Next
x = 10 / 0
If Err.Number <> 0 Then
MsgBox "Ошибка: деление на ноль!"
Exit Sub
End If
'... some additional code
Exit Sub
End Sub

В данном примере используется конструкция Exit Sub для прекращения выполнения подпрограммы в случае возникновения ошибки деления на ноль. После деления переменной x будет присвоено значение 0, и в случае ошибки код ниже условия If Err.Number <> 0 не будет выполнен.

Example 3:


Sub MySub()
Dim x As Integer
Dim y As Integer
On Error GoTo ErrorHandler1
x = 10 / 0
'... some additional code
On Error GoTo ErrorHandler2
y = 20 / 0
'... some additional code
Exit Sub
ErrorHandler1:
MsgBox "Ошибка 1: деление на ноль!"
Exit Sub
ErrorHandler2:
MsgBox "Ошибка 2: деление на ноль!"
Exit Sub
End Sub

В этом примере используется две конструкции Exit Sub и две метки ошибок для обработки разных ошибок деления на ноль. Если возникнет первая ошибка, выполнение кода перейдет к метке ErrorHandler1: и дальнейшая часть кода не будет выполнена. Точно так же, в случае второй ошибки, выполнение перейдет к метке ErrorHandler2:.

Поискав по рунету материал на тему обработки ошибок в VBA, не увидал на первых двух страницах результатов поиска чего-то, что мне понравилось. Может плохо смотрел, но решил написать на эту тему свою статью.

Простите, но — немного словоблудия :)

Ошибки в программе

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

  1. Вы обращаетесь к объекту по имени, а объекта с таким именем в коллекции нет

  2. Вы хотите выделить ячеку на одном листе, а этот лист в данный момент не является активным (типичнейшая ошибка новичков в Excel VBA)

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

  4. Вы ссылаетесь на элемент массива, который находится за пределами его границ.

  5. Вы пытаетесь присвоить переменной значение, которое оно не может хранить. Например, переменной типа Long нельзя присвоить строковую константу или переменной типа Integer присвоить знанчение превышающее число 32767.

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

  • Continue (продолжить) — этот пункт во время возникновения ошибки всегда не активен. Он активен, когда по ходу выполнения программы вы использовали оператор Stop. Кстати это очень полезный оператор для отладки программы.

  • End (завершить) — завершение исполнения программы

  • Debug (отладка) — переход в режим отладки, в котором можно посмотреть, на каком операторе возникла ошибка, что содержат переменные, можно даже перетащить жёлтую полоску, подсвечивающую текущий оператор, назад, и модифицировать знанчение переменных через окно Immediate window (впрочем это экзотика). В общем случае кнопка Debug позволяет посмотреть, где случилась ошибка и попытаться понять почему так случилось.

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

Почему вообще в коде возникают ошибки?

  1. Много ошибок во время написания кода возникает по невнимательности или не совсем адекватного понимания того, что делаешь. Таких ошибок, как правило, очень много, особенно у начинающих программистов, но эти ошибки довольно легко отловить и исправить, так как, пока вы их не исправите, ничего не работает. Ну, например, вы должны извлечь данные из 5-го столбца, а вы извлекаете из 6-го, а их там банально нет. Ясно, что вы это очень быстро заметите.

  2. Вторая группа ошибок — это ошибки оптимиста. Когда программа написана в целом правильно, но алгоритм не готов к ударам судьбы в виде неожиданных действий со стороны пользователя, ошибок ввода-вывода (вы рассчитывали считать данные из файла, а файла с таким именем не оказалось, либо он заблокирован другим приложением), особенностей конфигурации компьютера (разные версии ОС или офиса, которые в некоторых мелочах отличаются).

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

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

Задачи механизмов обработки ошибок

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

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

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

Файл примера

Скачать

Код без обработки ошибок

Вот простой пример с потолка. Если вызвать Example_00, то она прекрасно отработает без ошибок и вернёт это:

В функцию GetCalories передаётся строка с блюдом, а она должна вернуть его калорийность, сверившись с таблицей в A1:B7.

Давайте поищем слабые места в этом коде. Первое, что должно прийти в голову — если мы ищем, то, что произойдёт, если мы не найдём? А произойдёт, конечно же, ошибка. Её инициирует метод Match.


Ещё одно слабое место этой подпрограммы: функция возвращает вещественный тип Double, и даже, если поиск оказался удачным, то в Cells(intRow, 2) может случайно находиться текстовая строка, а потому, когда вы числовому типу попытаетесь присвоить строковый тип, также произойдёт ошибка. И, если вы второй ошибки сможете избежать за счёт дополнительного оператора if с проверкой через IsNumber(), то избежать первой ошибки таким способом нельзя. Что же делать? А вот тут на сцену выходят операторы обработки ошибок.

Есть 2 подхода к обработке ошибок: автономный подход и выносной. Эти термины я придумал только что, чтобы проще было их обсуждать.

Автономный подход

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

Итак, что тут сделано:

  1. Сразу после объявления функции GetCalories_v1 идёт оператор on error resume next, который в случае возникновения в каком-либо месте ошибки, предписывает VBA просто передавать управление на следующий оператор, идущий после ошибочного.

  2. Мы объявили переменные. Необъявленные переменные получают тип Variant и значение по умолчанию Empty. Объявленные переменные числовых типов инициируются нулём, строковые — пустой строкой, то есть я наперёд знаю, что они содержат, а это хорошо для обработки ошибок.

  3. На вызове метода WorksheetFunction.Match у нас возникает ошибка, так как искомого значения в таблице нет. А это, между прочим, был оператор присваивания ( = ). Прежде, чем левой части оператора присваивания (intRow) что-то будет присвоено, необходимо вычислить правую часть оператора присваивания (WorksheetFunction.Match…), а поскольку в процессе этого вычисления возникает ошибка, то переменная intRow остаётся такой, какой была! А, как я уже сказал, VBA автоматически её инициализирует нулём до начала исполнения подпрограммы. Получается, что, если в этом операторе возникнет ошибка, то в intRow будет ноль. Если ошибки во время поиска не возникнет, то ноля там не будет ни при каких раскладах, так как строки на листе нумеруются с единицы.

  4. И вот этот ноль мы и контролируем, добавляя оператор If. Если intRow больше нуля, то WorksheetFunction.Match отработала штатно, а если нет — то работу подпрограммы надо прерывать, но об этом чуть позже.

  5. Далее мы помним, что Cells(intRow, 2) может теоретически вернуть строковое значение, которое вызовет ошибку Type missmatch при присвоении переменной типа Double (GetCalories_v1), поэтому мы вставляем дополнительную проверку промежуточной переменной varTemp тому, что она числовая. И если это так, то присваиваем GetCalories_v1 значение из varTemp.

  6. В случае возникновения любой ошибки внутри GetCalories_v1 она просто вернёт ноль. Почему ноль? Потому что переменная GetCalories_v1 тоже инициализируется нулём и об этом не надо заботиться, а в случае ошибки она останется в неприкосновенности.

  7. Соответственно родительский код (в нашем случае его роль играет процедура Example_01) должен проверить, а не вернёт ли GetCalories_v1 ноль, и быть готовым к этой ситуации.

  8. А вот теперь тонкий момент, который не все понимают. Почему я использовал промежуточные переменные intRow и varTemp? Вроде бы есть очевидный ответ — чтобы не вычислять значение выражений с Match и Cells 2 раза. Отчасти это, конечно, так. Но это, в данном случае, не главная причина. Главная причина в том, что такой код

    вызовет неправильное поведение программы. Если у нас Match вызовет исключение, то VBA передаст управление на СЛЕДУЮЩИЙ оператор, а следующий оператор в данном случае это то, что идёт после Then — присваивание переменной varTemp значения. Таким образом наша проверка на наличие ошибки сработает с точностью до наоборот, передав управление в ту часть кода, которая должна быть защищена от ситуации, когда Match не нашла строку в таблице. Вот почему важно в операторе If не иметь ничего такого, что могло бы вызвать ошибку.

  9. Как видите, в этом подходе мне зачастую даже нет необходимости проверять объект Err, чтобы понять, что произошла ошибка, так как я ориентируюсь на то, что промежуточные переменные остаются неинициализированными, что является показателем наличия ошибки.

Выносной подход

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

Обратите внимание, что:

  1. Оператор on error теперь в случае ошибки предписывает передавать управление на метку ErrorHandler, которая объявлена в конце кода процедуры GetCalories_v2

  2. В коде мы никак не заботимся о каких-либо проверках. Возникла ошибка? Иди на метку — там разберутся.

  3. Если ошибки не случилось, то, чтобы программа не стала исполнять строчки, предназначенные для обработки ошибок, перед меткой ErrorHandler обычно ставят оператор Exit Sub или Exit Function (в зависимости от типа подпрограммы).

  4. Принципиальный момент — наличие оператора On Error Resume Next сразу после метки ErrorHandler. Дело в том, что после того, как вы перешли на метку ErrorHandler, очень опасно иметь действующим оператор On Error GoTo ErrorHandler, так как, если у вас в обработчике ошибки случится любая ошибка, то управление будет передано опять на метку и, как нетрудно понять, образуется бесконечный цикл. Поэтому сразу после метки мы возможность возникновения цикла ликвидируем оператором On Error Resume Next.

Что лучше?

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

Автономный подход

Преимущества Недостатки
Есть возможность точно идентифицировать каждую конкретную проблему (если вы её предусмотрели), возникающую во время исполнения, что позволит вам дать самые точные инстркции пользователю для предотвращения появления исключения в будущем. Достаточно трудоёмок, так как подразумевает наличие большого количества проверок в коде. Каждое потенциально опасное действие должно быть снабжено соответствующим оператором If, в котором контролируется значение переменной или код ошибки.
Надо хорошо представлять себе ситуации, где могут возникнуть ошибки, в противном случае ряд ошибок вы просто не заметите на этапе отладки.
Необходимо больше кода, а также требуется опыт и фантазия.
Необходимо больше промежуточных переменных

Выносной подход

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

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

Операторы

On Error { GoTo label | Resume Next | GoTo 0 }

Оператор on error управляет тем, на какой участок вашего кода будет передано управление в случае возникновения ошибки. Данный оператор можно вставить в любое место вашей программы или подпрограммы. Есть 3 варианта:

  1. On error goto label — после того, как этот оператор выполнен, ошибка, возникшая на других операторах программы приведёт к переходу на метку label.

  2. On error resume next — после такого оператора, VBA будет игнорировать возникшую ошибку и передавать управление на следующий оператор, стоящий за тем, в котором возникла ошибка.

  3. On error goto 0 — это режим по-умолчанию. В случае возникновения ошибки данный режим приведёт к появлению на экране стандартного обработчик ошибок VBA с кнопками End и Debug.

Resume { label | Next | [0] }

Данный оператор возобновляет выполнение программы. Применяется в выносном методе обработки ошибок.

  1. resume label— возобновление с метки label

  2. resume next — возобновление со следующего оператора

  3. resume или resume 0 — возобновление с оператора, вызвавшего ошибку. Это имеет смысл, если вы устранили ошибку в своём обработчике. На мой взгляд, на практике такое применяется крайне редко.

Goto label

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

Exit { Do | For | Function | Sub }

Досрочный выход из циклов (Do или For) и досрочный выход из подпрограмм (функции или процедуры). Могут пригодиться при обработке ошибок, но вообще это операторы и без того чрезвычайно полезны.

Объект Err

  1. Err — глобальный объект (его не надо объявлять, а можно сразу пользоваться), который содержит информацию о последней ошибке, случившейся в вашей программе. Проверяя Err сразу после возникновения исключения или после ситуации, которая могла привести к исключению, вы можете понять, что имело место на самом деле.

  2. Свойство Err.Number — содержит числовой код ошибки, по которому их различают в программе. Поскольку Number — свойство по умолчанию, то вы можете его опускать, то есть Err и Err.Number — это эквиваленты. Значение ноль говорит о том, что ошибки не произошло.

  3. Err.Description — содержит англоязычное краткое описание ошибки

  4. Err.Source — возвращает имя модуля, в котором возникла ошибка

  5. Err.Clear — сбрасывает последнюю ошибку. Err сбрасывается также при выполнении оператором Resume, Exit (любого типа кроме Do и For) и On Error.

  6. Err.Raise — искусственно вызывает исключение указанного в переданном параметре типа. Можно использовать для тестирования вашей подсистемы обработки ошибок.

P.S.

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

Читайте также:

  • Работа с объектом Range

  • Работа с объектом Range (часть 2)

  • Sheet happens

  • Поиск границ текущей области

  • Массивы в VBA

  • Структуры данных и их эффективность

  • Автоматическое скрытие/показ столбцов и строк

In this Article

  • VBA Errors Cheat Sheet
    • Errors
  • VBA Error Handling
  • VBA On Error Statement
    • On Error GoTo 0
    • On Error Resume Next
    • Err.Number, Err.Clear, and Catching Errors
    • On Error GoTo Line
  • VBA IsError
  • If Error VBA
  • VBA Error Types
    • Runtime Errors
    • Syntax Errors
    • Compile Errors
    • Debug > Compile
    • OverFlow Error
  • Other VBA Error Terms
    • VBA Catch Error
    • VBA Ignore Error
    • VBA Throw Error / Err.Raise
    • VBA Error Trapping
    • VBA Error Message
    • VBA Error Handling in a Loop
  • VBA Error Handling in Access

VBA Errors Cheat Sheet

Errors

On Error – Stop code and display error

On Error Goto 0

On Error – Skip error and continue running

On Error Resume Next

On Error – Go to a line of code [Label]

On Error Goto [Label]

Clears (Resets) Error

On Error GoTo1

Show Error number

MsgBox Err.Number

Show Description of error

MsgBox Err.Description

Function to generate own error

Err.Raise

See more VBA “Cheat Sheets” and free PDF Downloads

VBA Error Handling

VBA Error Handling refers to the process of anticipating, detecting, and resolving VBA Runtime Errors. The VBA Error Handling process occurs when writing code, before any errors actually occur.

VBA Runtime Errors are errors that occur during code execution. Examples of runtime errors include:

  • Referencing a non-existent workbook, worksheet, or other object (Run-time Error 1004)
  • Invalid data ex. referencing an Excel cell containing an error (Type Mismatch – Run-time Error 13)
  • Attempting to divide by zero

VBA On Error Statement

Most VBA error handling is done with the On Error Statement. The On Error statement tells VBA what to do if it encounters an error. There are three On Error Statements:

  • On Error GoTo 0
  • On Error Resume Next
  • On Error GoTo Line

On Error GoTo 0

On Error GoTo 0 is VBA’s default setting. You can restore this default setting by adding the following line of code:

On Error GoTo 0

When an error occurs with On Error GoTo 0, VBA will stop executing code and display its standard error message box.

vba runtime error 13

Often you will add an On Error GoTo 0 after adding On Error Resume Next error handling (next section):

Sub ErrorGoTo0()

On Error Resume Next
    ActiveSheet.Shapes("Start_Button").Delete
On Error GoTo 0

'Run More Code

End Sub

On Error Resume Next

On Error Resume Next tells VBA to skip any lines of code containing errors and proceed to the next line.

On Error Resume Next

Note: On Error Resume Next does not fix an error, or otherwise resolve it. It simply tells VBA to proceed as if the line of code containing the error did not exist. Improper use of On Error Resume Next can result in unintended consequences.

A great time to use On Error Resume Next is when working with objects that may or may not exist. For example, you want to write some code that will delete a shape, but if you run the code when the shape is already deleted, VBA will throw an error. Instead you can use On Error Resume Next to tell VBA to delete the shape if it exists.

On Error Resume Next
    ActiveSheet.Shapes("Start_Button").Delete
On Error GoTo 0

Notice we added On Error GoTo 0 after the line of code containing the potential error. This resets the error handling.

In the next section we’ll show you how to test if an error occurred using Err.Number, giving you more advanced error handling options.

VBA Coding Made Easy

Stop searching for VBA code online. Learn more about AutoMacro — A VBA Code Builder that allows beginners to code procedures from scratch with minimal coding knowledge and with many time-saving features for all users!

automacro

Learn More

Err.Number, Err.Clear, and Catching Errors

Instead of simply skipping over a line containing an error, we can catch the error by using On Error Resume Next and Err.Number.

Err.Number returns an error number corresponding with the type of error detected. If there is no error, Err.Number = 0.

For example, this procedure will return “11” because the error that occurs is Run-time error ’11’.

Sub ErrorNumber_ex()

On Error Resume Next
ActiveCell.Value = 2 / 0
MsgBox Err.Number

End Sub

vba run-time error 11 err.number

Error Handling with Err.Number

The true power of Err.Number lies in the ability to detect if an error occurred (Err.Number <> 0).  In the example below, we’ve created a function that will test if a sheet exists by using Err.Number.

Sub TestWS()
    MsgBox DoesWSExist("test")
End Sub

Function DoesWSExist(wsName As String) As Boolean
    Dim ws As Worksheet
    
    On Error Resume Next
    Set ws = Sheets(wsName)
    
    'If Error WS Does not exist
    If Err.Number <> 0 Then
        DoesWSExist = False
    Else
        DoesWSExist = True
    End If

    On Error GoTo -1
End Function

Note: We’ve added a On Error GoTo -1 to the end which resets Err.Number to 0 (see two sections down).

With On Error Resume Next and Err.Number, you can replicate the “Try” & “Catch” functionality of other programming languages.

On Error GoTo Line

On Error GoTo Line tells VBA to “go to” a labeled line of code when an error is encountered.  You declare the Go To statement like this (where errHandler is the line label to go to):

On Error GoTo errHandler

and create a line label like this:

errHandler:

Note: This is the same label that you’d use with a regular VBA GoTo Statement.

Below we will demonstrate using On Error GoTo Line to Exit a procedure.

On Error Exit Sub

You can use On Error GoTo Line to exit a sub when an error occurs.

You can do this by placing the error handler line label at the end of your procedure:

Sub ErrGoToEnd()

On Error GoTo endProc

'Some Code
    
endProc:
End Sub

or by using the Exit Sub command:

Sub ErrGoToEnd()

On Error GoTo endProc

'Some Code
GoTo skipExit
    
endProc:
Exit Sub

skipExit:

'Some More Code

End Sub

Err.Clear, On Error GoTo -1,  and Resetting Err.Number

After an error is handled, you should generally clear the error to prevent future issues with error handling.

After an error occurs, both Err.Clear and On Error GoTo -1 can be used to reset Err.Number to 0. But there is one very important difference: Err.Clear does not reset the actual error itself, it only resets the Err.Number.

What does that mean?  Using Err.Clear, you will not be able to change the error handling setting. To see the difference, test out this code and replace On Error GoTo -1 with Err.Clear:

Sub ErrExamples()

    On Error GoTo errHandler:
        
    '"Application-defined" error
    Error (13)
    
Exit Sub
errHandler:
    ' Clear Error
    On Error GoTo -1
    
    On Error GoTo errHandler2:
    
    '"Type mismatch" error
    Error (1034)
    
Exit Sub
errHandler2:
    Debug.Print Err.Description
End Sub

Typically, I recommend always using On Error GoTo -1, unless you have a good reason to use Err.Clear instead.

VBA On Error MsgBox

You might also want to display a Message Box on error.  This example will display different message boxes depending on where the error occurs:

Sub ErrorMessageEx()
 
Dim errMsg As String
On Error GoTo errHandler

    'Stage 1
    errMsg = "An error occured during the Copy & Paste stage."
    'Err.Raise (11)
    
    'Stage 2
    errMsg = "An error occured during the Data Validation stage."
    'Err.Raise (11)
     
    'Stage 3
    errMsg = "An error occured during the P&L-Building and Copy-Over stage."
    Err.Raise (11)
     
    'Stage 4
    errMsg = "An error occured while attempting to log the Import on the Setup Page"
    'Err.Raise (11)

    GoTo endProc
    
errHandler:
    MsgBox errMsg
   
endProc:
End Sub

Here you would replace Err.Raise(11) with your actual code.

VBA IsError

Another way to handle errors is to test for them with the VBA ISERROR Function. The ISERROR Function tests an expression for errors, returning TRUE or FALSE if an error occurs.

Sub IsErrorEx()
    MsgBox IsError(Range("a7").Value)
End Sub

VBA Programming | Code Generator does work for you!

If Error VBA

You can also handle errors in VBA with the Excel IFERROR Function.  The IFERROR Function must be accessed by using the WorksheetFunction Class:

Sub IfErrorEx()

Dim n As Long
n = WorksheetFunction.IfError(Range("a10").Value, 0)

MsgBox n
End Sub

This will output the value of Range A10, if the value is an error, it will output 0 instead.

VBA Error Types

Runtime Errors

As stated above:

VBA Runtime Errors are errors that occur during code execution. Examples of runtime errors include:

  • Referencing a non-existent workbook, worksheet, or other object
  • Invalid data ex. referencing an Excel cell containing an error
  • Attempting to divide by zero

vba runtime error 13

You can “error handle” runtime errors using the methods discussed above.

Syntax Errors

VBA Syntax Errors are errors with code writing. Examples of syntax errors include:

  • Mispelling
  • Missing or incorrect punctuation

The VBA Editor identifies many syntax errors with red highlighting:

vba syntax error example

The VBA Editor also has an option to “Auto Syntax Check”:

vba syntax error option

When this is checked, the VBA Editor will generate a message box alerting you syntax errors after you enter a line of code:

vba syntax compile error

I personally find this extremely annoying and disable the feature.

Compile Errors

Before attempting to run a procedure, VBA will “compile” the procedure. Compiling transforms the program from source code (that you can see) into executable form (you can’t see).

VBA Compile Errors are errors that prevent the code from compiling.

A good example of a compile error is a missing variable declaration:

vba compile error variable

Other examples include:

  • For without Next
  • Select without End Select
  • If without End If
  • Calling a procedure that does not exist

Syntax Errors (previous section) are a subset of Compile Errors.

AutoMacro | Ultimate VBA Add-in | Click for Free Trial!

Debug > Compile

Compile errors will appear when you attempt to run a Procedure. But ideally, you would identify compile errors prior to attempting to run the procedure.

You can do this by compiling the project ahead of time. To do so, go to Debug > Compile VBA Project.

vba debug compile

The compiler will “go to” the first error. Once you fix that error, compile the project again. Repeat until all errors are fixed.

You can tell that all errors are fixed because Compile VBA Project will be grayed out:

vba compile vbaproject

OverFlow Error

The VBA OverFlow Error occurs when you attempt to put a value into a variable that is too large. For example, Integer Variables can only contain values between -32,768 to 32,768. If you enter a larger value, you’ll receive an Overflow error:

vba overflow error

Instead, you should use the Long Variable to store the larger number.

Other VBA Error Terms

VBA Catch Error

Unlike other programming languages, In VBA there is no Catch Statement. However, you can replicate a Catch Statement by using On Error Resume Next and If Err.Number <> 0 Then. This is covered above in Error Handling with Err.Number.

AutoMacro | Ultimate VBA Add-in | Click for Free Trial!

VBA Ignore Error

To ignore errors in VBA, simply use the On Error Resume Next statement:

On Error Resume Next

However, as mentioned above, you should be careful using this statement as it doesn’t fix an error, it just simply ignores the line of code containing the error.

VBA Throw Error / Err.Raise

To through an error in VBA, you use the Err.Raise method.

This line of code will raise Run-time error ’13’: Type mismatch:

Err.Raise (13)

vba runtime error 13

VBA Error Trapping

VBA Error Trapping is just another term for VBA Error Handling.

VBA Error Message

A VBA Error Message looks like this:

vba runtime error 13

When you click ‘Debug’, you’ll see the line of code that is throwing the error:

vba raise error

AutoMacro | Ultimate VBA Add-in | Click for Free Trial!

VBA Error Handling in a Loop

The best way to error handle within a Loop is by using On Error Resume Next along with Err.Number to detect if an error has occurred (Remember to use Err.Clear to clear the error after each occurrence).

The example below will divide two numbers (Column A by Column B) and output the result into Column C. If there’s an error, the result will be 0.

Sub test()
Dim cell As Range

On Error Resume Next
For Each cell In Range("a1:a10")

    'Set Cell Value
    cell.Offset(0, 2).Value = cell.Value / cell.Offset(0, 1).Value
    
    'If Cell.Value is Error then Default to 0
    If Err.Number <> 0 Then
         cell.Offset(0, 2).Value = 0
         Err.Clear
    End If
 Next
End Sub

VBA Error Handling in Access

All of the above examples work exactly the same in Access VBA as in Excel VBA.

Function DelRecord(frm As Form)
'this function is used to delete a record in a table from a form
   On Error GoTo ending
   With frm
      If .NewRecord Then
         .Undo
         Exit Function
      End If
   End With
   With frm.RecordsetClone
      .Bookmark = frm.Bookmark
      .Delete
      frm.Requery
   End With
   Exit Function
   ending:
   End
End Function

При выполнении макросов Excel могут возникнуть ошибки, которые в VBA делят на три категории:

  • Ошибки компиляции
  • Ошибки выполнения
  • Логические ошибки (баги)

Далее мы поговорим о каждом из трёх типов ошибок VBA подробно.

Содержание

  1. Ошибки компиляции
  2. Ошибки выполнения
  3. Перехват ошибок выполнения
  4. Логические ошибки

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

Компилятор VBA рассматривает ошибки компиляции как недопустимые и выделяет их в коде ещё до того, как дело дойдёт до запуска макроса.

Если при написании кода допущена синтаксическая ошибка, то редактор VBA сигнализирует об этом немедленно: либо при помощи окна с сообщением, либо выделяя ошибку красным цветом, в зависимости от статуса режима Auto Syntax Check.

Примечание: При включённом режиме Auto Syntax Check каждый раз, при появлении в редакторе Visual Basic во введённом коде синтаксической ошибки, будет показано соответствующее сообщение. Если же этот режим выключен, то редактор VBA продолжит сообщать о синтаксических ошибках, просто выделяя их красным цветом. Опцию Auto Syntax Check можно включить/выключить в меню Tools > Options редактора Visual Basic.

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

Ошибки в Excel VBA

Например, сообщение «Compile error: Variable not defined» при попытке запустить выполнение кода VBA говорит о том, что происходит попытка использовать или обратиться к переменной, которая не была объявлена для текущей области (такая ошибка может возникнуть только если используется Option Explicit).

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

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

Примером такой ошибки может служить попытка выполнить деление на ноль. В результате будет показано сообщение «Run-time error ’11’: Division by zero«.

Ошибки в Excel VBA

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

Ошибки в Excel VBA

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

В случае если код сложнее, чем в нашем примере, то, чтобы получить больше информации о причине возникновения ошибки VBA, можно проверить значения используемых переменных. В редакторе VBA для этого достаточно навести указатель мыши на имя переменной, или можно открыть окно отслеживания локальных переменных (в меню редактора View > Locals Window).

Коды различных ошибок выполнения расшифрованы на сайте Microsoft Support (на английском). Наиболее часто встречающиеся ошибки VBA перечислены в этой таблице:

5 Недопустимый вызов процедуры (Invalid procedure call)
7 Недостаточно памяти (Out of memory)
9 Индекс вне заданного диапазона (Subscript out of range)

Эта ошибка возникает при попытке обратиться к элементу массива за пределами заданного размера массива – например, если объявлен массив с индексами от 1 до 10, а мы пытаемся обратиться к элементу этого же массива с индексом 11.

11 Деление на ноль (Division by zero)
13 Несоответствие типа (Type mismatch)

Эта ошибка возникает при попытке присвоить переменной значение не соответствующего типа – например, объявлена переменная i типа Integer, и происходит попытка присвоить ей значение строкового типа.

53 Файл не найден (File not found)

Иногда возникает при попытке открыть не существующий файл.

Перехват ошибок выполнения

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

Для того, чтобы помочь справиться с возникающими ошибками, VBA предоставляет разработчику операторы On Error и Resume. Эти операторы отслеживают ошибки и направляют выполнение макроса в специальный раздел кода VBA, в котором происходит обработка ошибки. После выполнения кода обработки ошибки, работа программы может быть продолжена с того места, где возникла ошибка, или макрос может быть остановлен полностью. Далее это показано на примере.

'Процедура Sub присваивает переменным Val1 и Val2 значения,
'хранящиеся в ячейках A1 и B1 рабочей книги Data.xlsx расположенной в каталоге C:\Documents and Settings

Sub Set_Values(Val1 As Double, Val2 As Double)

   Dim DataWorkbook As Workbook

   On Error GoTo ErrorHandling

      'Открываем рабочую книгу с данными

      Set DataWorkbook = Workbooks.Open("C:\Documents and Settings\Data")

      'Присваиваем переменным Val1 и Val2 данные из рабочей книги DataWorkbook

      Val1 = Sheets("Лист1").Cells(1, 1)
      Val2 = Sheets("Лист1").Cells(1, 2)

      DataWorkbook.Close

   Exit Sub

ErrorHandling:

   'Если файл не найден, предлагаем пользователю разместить его в
   'нужном месте и продолжить работу

   MsgBox "Рабочая книга не найдена! " & _
      "Пожалуйста добавьте книгу Data.xlsx в каталог C:\Documents and Settings и нажмите OK."

   Resume

End Sub

В этом коде производится попытка открыть файл Excel с именем Data. Если файл не найден, то пользователю будет предложено поместить этот файл в нужную папку. После того, как пользователь сделает это и нажмёт ОК, выполнение кода продолжится, и попытка открыть этот файл повторится. При желании вместо попытки открыть нужный файл, выполнение процедуры Sub может быть прервано в этом месте при помощи команды Exit Sub.

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

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

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

Редактор Excel VBA предоставляет набор инструментов отладки, которые помогут найти и исправить логические ошибки в коде VBA. В данной статье мы не будем рассматривать подробно эти инструменты. Любознательный пользователь может найти обзор инструментов отладки VBA на сайте Microsoft Help & Support (на английском).

Оцените качество статьи. Нам важно ваше мнение:

Понравилась статья? Поделить с друзьями:
  • Инфинити fx35 ошибка p1051
  • Исключительная привилегия лексическая ошибка
  • Инфинити фх 35 ошибка датчика коленвала
  • Иск об устранении реестровой ошибки кто ответчик
  • Инфинити fx35 ошибка b1134