Проверка кода vba excel

Хитрости »

21 Март 2015              94833 просмотров


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

  Пример таблицы и кода (35,5 KiB, 2 854 скачиваний)


Что будет рассмотрено:

  • Способы отладки кода в момент появления ошибки
  • Использование окон Locals и Watches для отладки
  • Пошаговая отладка кода — что это такое, как и когда применять
  • Ошибок нет, но код все равно не выполняется

Помимо этого в конце статьи можно скачать файл с кодами ошибок VBA и их расшифровками.

Исходные данные
Допустим, имеется простая таблица
Таблица данных
И код, который должен пройтись по каждой строке таблицы, перемножить цену (столбец Цена) на количество (столбец Продажи шт), просуммировать перемноженные данные и вывести результирующую сумму в ячейку В17:

Option Explicit
Sub PrimitiveCode()
    Dim lr As Long, dblSumm As Double, dblIncr As Double
    'цикл от первой строки таблицы до последней
    For lr = 1 To 14
        'перемножение Цены на Количество (C*E)
        dblIncr = Cells(l, 3).Value * Cells(lr, 5).Value
        'прибавление результата к переменной общей суммы
        dblSumm = dblSumm + dblIncr
    Next
    'выводим результат в ячейку B17
    Cells(17, 2).Value = dblSumm
End Sub
Отладка кода в момент появления ошибки

Если посмотреть на код выше, то опытный программист VBA сразу поймет, что в таком виде код работать не будет – не выполнится и одна строка. Сразу появится ошибка:
Variable not defined

Ошибка означает, что внутри кода есть переменная, которая ранее не была объявлена.
Сама переменная, которую VBA считает не объявленной будет выделена:
Не объявленная переменная
Подробнее об этой ошибке и её причинах можно почитать в статье: Variable not defined или что такое Option Explicit и зачем оно нужно?
Если строки Option Explicit нет, то ошибка появится в момент выполнения строки с этой переменной, т.к. значение этой переменной будет 0, что нельзя использовать в качестве номер строки на листе. Как определить причину ошибки в конкретной строке описано ниже.

Если кратко, то переменной l нет среди объявленных переменных(Dim l As) и мы не можем её использовать, если объявлена директива Option Explicit(настоятельно рекомендую Option Explicit использовать всегда во избежание опечаток). В данном случае это опечатка и там должна быть lr, а не l. Исправляем переменную и код будет выглядеть так:

Sub PrimitiveCode()
    Dim lr As Long, dblSumm As Double, dblIncr As Double
    'цикл от первой строки таблицы до последней
    For lr = 1 To 14
        'перемножение Цены на Количество (C*E)
        dblIncr = Cells(lr, 3).Value * Cells(lr, 5).Value
        'прибавление результата к переменной общей суммы
        dblSumm = dblSumm + dblIncr
    Next
    'выводим результат в ячейку B17
    Cells(17, 2).Value = dblSumm
End Sub

С виду код теперь выполнен правильно и ошибок вызывать не должен. Однако, если его попытаться выполнить опять получим ошибку – на этот раз ошибку типов данных — Type Mismatch:
Type Mismatch
В момент появления главное нажать Debug, а не End (если будет желание прочитать про тип ошибки подробнее – можно еще нажать Help, текст будет на английском). VBA подсветит желтым строку, вычисления или операции в которой вызывают ошибку:
Строка ошибки
Теперь самый важный этап – необходимо определить причину ошибки. С виду все хорошо – одна ячейка перемножается на другую. Без опыта сложно сходу понять, что это ошибка типов данных, хоть VBA прямо об этом говорит(Type Mismatch – в переводе «Несовпадение типов»). Поэтому самое надежное в этом случае – это определить значение каждой составляющей той строки, в которой возникла ошибка. В случае с кодом выше можно воспользоваться двумя методами:

  1. Навести курсор мыши на любую переменную(dblSum, lr) и посмотреть всплывающую подсказку, которая показывает имя переменной и её текущее значение:
    Значение переменной
    Значение нашей переменной lr = 1. Запоминаем и переходим на лист с таблицей и смотрим, какое значение в ячейке первой строки третьего столбца(Cells(1,3)). Там значение Закуп цена, что явно не является числом. Следовательно перемножить его нельзя, т.к. это текст. Отсюда и ошибка типов – с текстом нельзя производить математические операции. Для вычислений предполагается в данном случае числовой тип данных(Integer,Long,Double).
  2. Узнать сразу значение ячейки Cells(lr, 3).Value и ячейки Cells(lr, 5).Value. Наведение курсора мыши в данном случае не даст результата. Как правило наведение курсора мыши не имеет эффекта если это не объявленные как переменные объекты (как в этом случае — Cells). Такие объекты не всегда могут быть вычислены в памяти в момент отладки. Поэтому чтобы просмотреть значение ячейки сначала необходимо отобразить окно Immediate(отобразить можно сочетанием клавиш Ctrl+G или через меню ViewImmediate Window). Выделить и скопировать полностью нужную переменную Cells(i, 3).Value и в окне Immediate написать:
    ?
    и после вопр.знака вставить скопированное. Должно получиться:
    ?Cells(i, 3).Value
    И нажать Enter. Строкой ниже в этом окне будет выведено значение для объекта или переменной (если оно может быть получено):
    Значение в окне Immediate
    По сути результат будет как и в первом примере – мы увидим, что в ячейке текст. Чем второй метод лучше первого? Тем, что таким образом можно сразу получить значение, не переходя на лист и не выискивая нужный номер строки. Ведь это в примере он равен 1, в реальности же строка может быть и 24451.

Окна Locals и Watches

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

Locals

и окно

Watches

.

Окно Locals

Окно Locals отображает все локальные переменные, задействованные в выполняемой в настоящий момент процедуре:
Locals Window
Как видно в этом окне отображается имя переменной, её тип и значение. Все хорошо, но в этом окне отображаются исключительно локальные переменные, объявленные на уровне модуля. Переменных других модулей, объявленные как Public и используемые в текущей процедуре там не отображаются. Подробнее про видимость переменных можно узнать в статье: Что такое переменная и как правильно её объявить?

Окно Watches
Окно Watches представляет большую ценность – в это окно можно просто «перетащить» нужную переменную или объект и в этом окне будут отражены все данные об имени переменной, её типе и текущем значении:
Watches Window
Теперь рассмотрим чуть подробнее как перетаскивать в это окно данные. На примере кода выше:

  • Выделяем Cells(i, 3).Value
  • Не снимая выделения наводим курсор мыши на это выделение
  • Зажимаем левую кнопку мыши и не отпуская её переносим курсор в любое место окна Watches

Теперь данные по переменной загружены и доступны для просмотра. По сути все умеют это делать — процесс очень схож с обычным перемещением файлов и папок по рабочему столу. Выделили и с зажатой левой кнопкой мыши перенесли в нужное место.
В чем еще один плюс этого окна – в этом окне можно оставлять эти значения и просматривать в моменты пошаговой отладки только занесенные в это окно переменные(про пошаговую отладку будет рассказано ниже). Если вдруг какая-то переменная/объект стали не нужны для постоянного отслеживания их данных – можно удалить их из окна Watches, чтобы не мешалась. Для этого выделяем переменную-правая кнопка мыши – Delete Watch. Так же можно поиграть с иными пунктами, наибольший интерес из которых на мой взгляд, представляет пункт Edit Watch. После его нажатия появится окно
Edit Watch
Самые основные пункты в этом окне, важные для отладки:

  • Break Then value Changes. Если его установить, VBA будет отслеживать значение этой переменной и останавливать код при любом изменении значения переменной. Это может пригодится для отслеживания значений в циклах
  • Break Then value Is True – пункт пригодится для переменных с типом Boolean или для логических выражений. Как только переменная или результат выражения примет значение True – код будет остановлен на этой строке.
    Например, необходимо остановить код, если номер строки будет равен 10(т.е. переменная lr примет значение 10). Тогда выражение будет иметь вид:

    If lr = 10 Then
    'код
    End if

    Тогда надо будет выделить в строке If lr = 10 Then само условное выражение lr = 10, перенести её в окно Watches, выделить строку в окне Watches с этим выражением, нажать правую кнопку мыши и выбрать Edit Watch. Выбрать в окне Break Then value Is True. Теперь как только переменная lr достигнет значения 10(т.е. обрабатываться будет 10-я строка таблицы) – код остановится и строка с выражением будет выделена желтым. Можно будет проанализировать другие переменные или продолжить выполнение кода в пошаговом режиме(см.далее).


Пошаговая отладка кода

После знакомства с отладкой кода при возникновении ошибки работать с пошаговой отладкой будет проще.

Что такое вообще пошаговая отладка?

Это просмотр этапов выполнения кода строка за строкой.

Для чего это может быть нужно?

  • Чтобы проанализировать чужой код и понять более точно, что он делает изнутри, а не только увидеть результат его выполнения
  • Если вы начинающий программист и часто используете макрорекордер(записываете макросы) — то пошаговая отладка поможет понять какое действия выполняет каждая строка. Это поможет быстрее научиться понимать код и убирать из него лишнее, а так же совмещать различные коды
  • Если внутри кода есть ошибка логики выполнения. Это, пожалуй, самая сложная ошибка, т.к. в этом случае VBA не останавливает работу и не говорит об ошибке. Код выполняется без ошибок, но результат не такой, как ожидалось. Это означает, что либо какой-то переменной назначается не то значение, либо какое-то условие неверно или выполняется не в тот момент, в который должно. В общем по сути это ошибка разработчика, не приводящая к ошибкам синтаксиса или типов, которые VBA может отследить.

Как делать пошаговую отладку? Все просто: устанавливаете курсор в любом месте внутри кода и нажимаете клавишу F8 (либо выбрать в меню DegubStep Into). Теперь при каждом нажатии клавиши F8 код будет выполнять одну строку кода за другой в той очередности, в которой они расположены в процедуре. Если внутри процедуры будет вызов второй процедуры или функции – код пошагово выполнит и её и затем вернется в основную процедуру.
Так же хочу привести еще пару сочетаний клавиш, которые удобно применять при пошаговой отладке:

  • Shift+F8(DegubStep Over) — выполнение вложенной функции/процедуры без захода в неё. Если внутри основной процедуры или функции выполняется другая процедура или функция и Вы уверены, что она работает правильно — просматривать пошагово весь код вложенной процедуры/функции не имеет смысла. Чтобы вложенная процедура/функция выполнилась без пошагового просмотра надо просто нажать указанное сочетание клавиш тогда, когда строка вызова вложенной процедуры/функции будет подсвечена желтым
  • Ctrl+Shift+F8(DegubStep Out) — завершение вложенной функции/процедуры и выход в основную с остановкой. Если все же перестарались и перешли в пошаговый проход вложенной функции(или сделали это специально, но посмотрели все, что надо) — то нажимаете это сочетание и код быстро выполнить вложенную функцию, перейдет в основную и остановится для дальнейшей пошаговой отладки
  • Ctrl+F8(DegubRun to Cursor) — выполнение процедуры до строки, в которой на данный момент установлен курсор

Точки останова
Но куда чаще бывает нужно не просто весь код пройти пошагово, а начать пошаговое выполнение только начиная с какой-либо одной строки, чтобы не мотать строк 40 кода(да еще с циклами) ради достижения одной какой-то строки. Еще точки останова очень полезны при отладке событийных процедур(вроде Worksheet_Change, Worksheet_BeforeDoubleClick, событий элементов форм и т.п.), т.к. они в большинстве своем содержат аргументы и выполнить по F8 их просто невозможно и выполняются они только при наступлении самого события, которые они призваны обработать. Тоже самое справедливо для функций пользователя(UDF) именно для проверки их работы из листа, т.к. эти функции нельзя начать выполнять по F5 — они начинают выполняться только после их пересчета и зачастую ошибки можно выявить исключительно при вызове именно с листа.
Чтобы дать понять VBA на какой строке необходимо будет остановится необходимо установить курсор мыши в любое место нужной строки и нажать F9 или DebugToggle Breakpoint. Строка будет выделена темно-красным цветом.
Это еще называется установкой точки останова. Убрать точку останова можно так же, как она была установлена – F9 или DebugToggle Breakpoint. Так же точку основа можно установить с помощью мыши: для этого необходимо в области левее окна с кодом напротив нужной строки один раз щелкнуть левой кнопкой мыши:
Точка останова

Теперь можно запустить код любым удобным способом (в отладке это как правило делается клавишей F5 или с панели: RunRun Sub/UserForm). Как только код дойдет до указанной точки останова он остановится и строка будет подсвечена желтым. Дальше можно либо продолжить выполнение в пошаговом режиме (нажимая F8), либо (проверив значения нужных переменных и объектов) нажать опять F5 и код продолжит выполняться автоматически, пока не выполнится или не достигнет другой точки останова. Самих же точек останова может быть сколько угодно и расположены они могут быть в любой процедуре или функции.
Следует помнить, что после закрытия файла с кодом точки останова не сохраняются и при следующем открытии книги их необходимо будет установить заново, если это необходимо.


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

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

  1. Логика кода построена неверно и ошибок VBA действительно не возникает. Но т.к. логика неверна — код выполняет не то, что от него ожидается. Решение одно — пошагово выполнить весь код и детально просмотреть всё, чтобы обнаружить в какой строке или строках нарушена логика
  2. Один из очень распространенных вариантов: в начале кода стоит обработчик ошибок On Error Resume Next и дальше обработчик не отменяется. Данный обработчик указывает VBA, что при возникновении ошибки её следует игнорировать и переходит к выполнению следующего оператора/строки. Таким образом ошибка хоть и возникает, но она пропускается и не показывается, а выполнение кода продолжается как ни в чем не бывало. Однако как правило одна ошибка влечет другую и третью и т.д. и может получиться так, что все строки после первой ошибочной станут так же ошибочными и как следствие не выполнятся. Данный оператор будет применяться либо до конца процедуры, либо до тех пор, пока в коде не будет поставлен иной обработчик ошибок:
    On Error GoTo Метка — переход выполнения кода к указанной метке(Метка).
    On Error GoTo 0 — по сути отменяет условный переход при возникновении ошибок. Метка 0 считается обнулением переходов

Один из примеров того, для чего может применяться обработчик ошибок можно найти в статье: Как из Excel обратиться к другому приложению. Там данный обработчик необходим, чтобы проверить открыто ли уже приложение Word. Если открыто — то ошибка не возникнет. Если же закрыто — то будет ошибка. И этот момент как правило и отслеживается. Я расставил подробные комментарии в коде, чтобы было более понятно что к чему:

Sub Check_OpenWord()
    Dim objWrdApp As Object
    On Error Resume Next 'необходимо, чтобы на первой же строке код не выдал ошибку при закрытом Word
    'пытаемся подключится к объекту Word
    Set objWrdApp = GetObject(, "Word.Application")
    'если Word закрыт - обязательно возникнет ошибка 429, 
    'указывающая на то, что невозможно подключиться к объекту Word
    'при этом переменная objWrdApp будет равняться Nothing, т.к. значение не удалось присвоить
    If objWrdApp Is Nothing Then
    'так же можно использовать и такую строку:
    'If Err.Number = 429 Then 'если ошибка 429 - значит Word не запущен - надо создавать новый
        'создаем новый экземпляр
        Set objWrdApp = CreateObject("Word.Application")
        'делаем приложение видимым. По умолчанию открывается в скрытом режиме
        objWrdApp.Visible = True
    Else
        'приложение открыто - выдаем сообщение
        MsgBox "Приложение Word уже открыто", vbInformation, "Check_OpenWord"
    End If
End Sub

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


Конечно, статья не описывает способы устранения ошибок — это просто невозможно. Только известных типов ошибок в VBA более 3 тысяч. Все их упоминать бессмысленно. Целью статьи было помочь начинающим найти строку с ошибкой и рассказать как производить отладку кода при необходимости. А все остальное придет с опытом. Однако на всякий случай я решил выложить файл Excel с описанием большей части ошибок, которые могут возникнуть. В файле указан номер ошибки, описание на английском и описание на русском. Причин ошибки может быть множество, поэтому нет однозначных рекомендаций по устранению каждой из них. Все зависит от данных и от самого кода.

  Ошибки VBA с описанием (152,0 KiB, 5 562 скачиваний)

Удачи в программировании!


Статья помогла? Поделись ссылкой с друзьями!

  Плейлист   Видеоуроки


Поиск по меткам



Access
apple watch
Multex
Power Query и Power BI
VBA управление кодами
Бесплатные надстройки
Дата и время
Записки
ИП
Надстройки
Печать
Политика Конфиденциальности
Почта
Программы
Работа с приложениями
Разработка приложений
Росстат
Тренинги и вебинары
Финансовые
Форматирование
Функции Excel
акции MulTEx
ссылки
статистика

Окно Immediate используется в VBA Excel при написании и отладке процедур для тестирования отдельных строк кода, проверки текущих значений переменных и в качестве калькулятора.

Отображается на экране окно Immediate сочетанием клавиш Ctrl+G или через меню редактора VBA: View → Immediate Window.

Чтобы протестировать выполнение отдельных строк кода VBA Excel в окне Immediate необходимо:

  • ввести строку кода в окне Immediate,
  • нажать клавишу Enter.

Код в окне Immediate можно вводить с использованием контекстных подсказок и выбором из них объектов, свойств и методов, точно так же, как и непосредственно в модуле VBA. Можно строку кода скопировать из процедуры и вставить в окно Immediate из буфера обмена. При нажатии клавиши Enter курсор может находиться в любом месте проверяемой строки.

Пример 1
Откройте окно Immediate, вставьте в него строку

Range(«A1:A5») = «Тестируем окно Immediate»

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

Проверка значений переменных

Для отображения в окне Immediate значений переменных используется метод Print класса Debug (Debug.Print). Рассмотрим работу этого метода сразу на примере.

Пример 2

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

Sub Primer2()

Dim a As Byte, b As Byte, c As Byte

a = 15

b = (a + 35) / 5

c = a * b 50

‘Каждая переменная в отдельной строке:

Debug.Print a

Debug.Print b

Debug.Print c

‘Все переменные в одной строке

‘с разделителем «точка с запятой»:

Debug.Print «a = « & a; «b = « & b; _

«c = « & c

‘с разделителем «запятая»:

Debug.Print «a = « & a, «b = « & b, _

«c = « & c

End Sub

Помечаем маркерами строки с методом Debug.Print, кликнув по левому полю напротив нужных строк, чтобы в этих местах остановить исполнение кода. Строка с маркером, на котором остановилась программа, будет выполнена после очередного нажатия кнопки Run Macro или клавиши F5.

Результаты выполнения кода смотрите на изображении:

Проверка значений переменных

Проверка значений переменных

Если при размещении нескольких элементов после метода Debug.Print не указать разделитель, редактор VBA при запуске кода на выполнение автоматически вставит между элементами разделитель «точка с запятой». Сравните с результатом использования в качестве разделителя символа «запятая».

При работе с переменными можно изменять их значение непосредственно в окне Immediate. Введите строку с присвоением переменной нового значения и нажмите клавишу Enter. Значение переменной будет перезаписано.

Пример 3
Пример изменения значения переменной в окне Immediate во время исполнения кода VBA Excel:

Sub Primer3()

Dim a As Variant

a = WorksheetFunction.Pi

Debug.Print a

‘Вводим в окне Immediate строку

‘a = «Сейчас число Пи округлим»

‘нажимаем Enter и далее F5

Debug.Print a

‘Вводим в окне Immediate строку

‘a = 3.14

‘нажимаем Enter и далее F5

Debug.Print a

End Sub

В этом примере переменной a присваивается значение числа Пи. Далее мы непосредственно в окне Immediate дважды меняем значение этой переменной. Маркер остановки исполнения кода ставим на второй и третьей строке Debug.Print a. Результаты смотрите на изображении:

Изменение значения переменной в окне Immediate

Изменение значения переменной в окне Immediate

Окно Immediate как калькулятор

Чтобы воспользоваться окном Immediate как калькулятором введите в нем ключевое слово «Print» или символ «?», затем вычисляемое выражение и нажмите клавишу Enter. При таких вычислениях пробелы в выражениях игнорируются.

Вычисления в окне  Immediate

Вычисления в окне Immediate

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

Количество строк в окне Immediate

Согласно проведенным опытам, максимальное количество строк в окне Immediate составляет 201 позицию: двести строк с данными и одна — пустая. При заполнении пустой строки, под ней добавляется новая пустая строка, а первая (верхняя) строка с данными исчезает.

Таким образом, максимальная вместимость окна Immediate ограничена 200 строками с данными. Это замечание актуально при выведении больших объемов информации с помощью метода Debug.Print. Допустимое количество знаков в одной строке — 950. Тестирование проводилось в VBA Excel 2016.


Syntax Errors

Syntax  errors occur as you are writing your code. If you have a syntax error the offending code will be displayed in red and a Compile error warning will be displayed.

5 FREE EXCEL TEMPLATES
Plus Get 30% off any Purchase in the Simple Sheets Catalogue!

Syntax errors occur when you make a grammatical error in your code like leaving out speech marks when referring to a range…

… or leaving out brackets where they are needed.

For both of the above syntax errors you get the same Compile error message. For the second error it’s pretty useful for the first, not so useful.

You may want to turn Syntax error warnings off in Tools | Options | [Editor Tab].  Untick the option Auto Syntax Check. Syntax errors will still be displayed in red when you untick this option – so you will still be able to spot them!

Compile Errors

5 FREE EXCEL TEMPLATES
Plus Get 30% off any Purchase in the Simple Sheets Catalogue!

Compile errors only become apparent when you compile your code.  Code will always compile before it runs but you can compile without running it by clicking  Debug |Compile VBA Project.

Compile errors are not shown in red, but you do get an error message when you compile the procedure. In the example below, the Worksheets object name is spelt incorrectly.

When you attempt to run the procedure you get this error message…

… and the code enters break mode.  You can see below that the first line of code is highlighted in yellow with a yellow arrow in the margin – this is the breakpoint (meaning the code couldn’t execute beyond this point) and the offending keyword is highlighted in blue.

Now you can fix the spelling error, Reset the procedure with VBE’s Reset button as shown below and attempt to run the code again.

If you just compile the procedure rather than compile and run, the code will not enter break mode.

Using Option Explicit

Always use Option Explicit so any errors you make referring to variable names or other misspellings are picked up when you compile your code. For example the misspelling or vbRed in the code below is only picked up as a compile error if Option Explicit is used.

5 FREE EXCEL TEMPLATES
Plus Get 30% off any Purchase in the Simple Sheets Catalogue!

Run-time Errors

Run-time errors do not appear in red like a syntax error, nor do they occur when you compile a procedure (compile without running), but they do occur when you attempt to run a procedure.

The code below attempts to select a sheet that is not available and therefore produces a run-time error.  Run-time errors put your procedure into break mode: break mode temporarily stops the code running until you fix the problem and resume execution.

The yellow arrow and yellow highlighting indicate the position at which the code stopped – the break point.  Lines of code above the break point have been successfully executed.

This is the run-time error displayed for this code.

To fix the error, you need to click on the Debug button on the run-time error dialog box. This will allow you to fix your code and then resume code execution from the break point.  Use the VBE’s Continue button to resume running the code or use the F5 keyboard shortcut.

Error Handling

Some run-time errors occur not because of errors in your code necessarily but because the procedure encounters unexpected things in your data like missing workbooks, worksheets or values, or unexpected data types.  For this reason you will need to build error handling code into your procedures in expectation of any of these problems.

Run-time error are covered in more depth in the tutorial on Error Trapping and Handling.

Stepping Through Code

5 FREE EXCEL TEMPLATES
Plus Get 30% off any Purchase in the Simple Sheets Catalogue!

When you step through code you are executing one line of code at a time.  This might be useful if your procedure produces unexpected results or an error.  By stepping through code you are much more likely to identify and resolve any problems.

To step through code you need to put your procedure into break mode: Click Debug | Step Into or use the F8 shortcut key.

The first line of code will be highlighted in yellow and when you press F8 again, that line of code will be executed. Press F8 again and the next line of code will be executed and so on and so on.

To see what your code is actually doing, split your screen so that the VBE and Excel are both visible.

Breakpoints

You can set a breakpoint in your code so that all code above it is executed normally but from your breakpoint onwards you can step through the code. This is useful in long procedures where it would be tedious to step through every line of code before you get to the part that you are trying to debug.

You can click into the grey margin to set a breakpoint or click into a line of code and then select Debug | Toggle Breakpoint or use the F9 shortcut key.

To remove the breakpoint click the breakpoint circle.

Immediate Window

The Immediate Window can be used to display the current value assigned to a variable or property: useful information when debugging code! To show the Immediate Window click View | Immediate Window or use the keyboard shortcut CTRL G.

Take this simple example.  Our code is going to loop through the numbers on our worksheet and multiply each number by 10. When it gets to Goat the code will produce a run-time error.

The code for the procedure is as follows…

Sub UsingImmediateWindow()
Dim rg As Range, MyData As Range
Set MyData = Range("A1:A12")
For Each rg In MyData
    Debug.Print rg
    rg = rg * 10
Next rg
End Sub

Using Debug.Print

Notice the line of code that reads

5 FREE EXCEL TEMPLATES
Plus Get 30% off any Purchase in the Simple Sheets Catalogue!

Debug.Print rg

The Debug.Print code will display the value of the variable rg in the Immediate Window as shown below. The run- time error means that only 5 values are shown in the Immediate Window.

From a debugging point of view this is a great bit of information as we can see exactly why the data has caused an error.

If I wanted to find out the cell address for the word Goat, I can type ? rg.Address into the Immediate Window, press ENTER and the answer is displayed on the line below.

I could even change the value of rg in the Immediate Window by typing rg = 5 which fixes the problem and I am now able to execute the remainder of the code.

Using ? In the Immediate Window

You do not have to use Debug.Print in your code to show variable or property values in the Immediate Window.

As you are stepping through code or at the point you have a debug error, just type a question mark to the left of the variable or property you want to examine. Press ENTER and the answer will appear on the line below.

Watch Window

The Watch Window allows you to place a watch on the value of a variable or property.  As with the Immediate Window this is a useful tool when you are trying to debug code.

To show the Immediate Window click View | Watch Window.

The easiest way to add a watch is to right-click on the variable or property and select Add Watch…

The Watch Window will only show values when you are in break mode.

In this example we want to format cell background colours based on the value in the cell.  The cell’s value will be used to set the colour index number of the cell’ s interior property.  There are 56 colours available in the colour index palette.  You will notice two values that could be problematic: 200 in cell A20 and TRUE is A28.  200 will cause a run-time error but TRUE won’t.

Here is the code for our procedure

Sub UsingWatchWindow()
Dim rg As Range, MyData As Range
Dim FontColour As Byte
Set MyData = Worksheets("Using Watch Window").Range("A1:A56")
MyData.ClearFormats
For Each rg In MyData
    FontColour = WorksheetFunction.RandBetween(1, 56)
    rg.Interior.ColorIndex = rg
    rg.Font.ColorIndex = FontColour
Next rg
End Sub

We are going to add a watch for rg and rg.address before we run the code.

Right-click on the rg variable any place it appears in the code and click Add Watch…

Click on OK to confirm and the watch is added to the Watch Window.

To add a watch for rg.address do the same thing again but edit the expression to include .address

Click on OK to confirm and the watch is added to the Watch Window.

Lastly we are going to add a watch that puts the code into break mode if rg is a logical value.  Repeat as before to add a watch and edit the expression so it reads as…

WorksheetFunction.IsLogical(rg)

Change the Watch Type to Break When Value is True

Click on OK to confirm and the watch is added to the Watch Window.

Our three watches…

When we run the code a run-time error occurs as we expected.  Hit  Debug  and the Watch Window shows us the offending value and cell address.

I can now quickly find and change the value on my worksheet.  Once done I click Continue in the VBE to take my procedure out of break mode.  The procedure goes into break mode again, not because of run-time error but because of my third watch which stops the code if rg is a logical value.  Without this watch the code would have continued and I would have a missed a potential problem in my data.

5 FREE EXCEL TEMPLATES
Plus Get 30% off any Purchase in the Simple Sheets Catalogue!

Locals Window

5 FREE EXCEL TEMPLATES
Plus Get 30% off any Purchase in the Simple Sheets Catalogue!

The Locals Window shows a complete list of all your procedure’s variable when in break mode.  To show the Locals Window, click View | Locals Window.

In this example we are going to encounter a run-time overflow error when x * y exceeds the Byte storage limit of 255.

Sub UsingLocalsWindow()
    Dim x As Byte
    Dim y As Byte
        For x = 1 To 100
            For y = 1 To 100
                Cells(x, y) = x * y
            Next y
        Next x
End Sub

If we weren’t quite sure how to debug our run-time error we could look at the Locals Windows to see the values assigned to x and y.

So we could work out that 3 x 86 = 258 and together with the run-time error message work out that we need to declare x and y with a data type of Integer.

I am trying to debug a long code I wrote and I need to step line by line.

The thing is I am on a mac and don’t know how to use an F8 in that case. Could anyone tell me how can I do that otherwise and how do I know which line is causing problems with execution?

Martijn Pieters's user avatar

asked May 6, 2013 at 11:56

seigna's user avatar

1

To check which line is giving you the error, you can use the ERL property. See this sample code below.

Sub sample()
Dim i As Long

On Error GoTo Whoa

10    Debug.Print "A"
20    Debug.Print "B"
30    i = "Sid"
40    Debug.Print "A"

50    Exit Sub
Whoa:
    MsgBox "Error on Line : " & Erl
End Sub

For this to work, you will have to number the code lines as I have done above. Run the above code and see what happens.

answered May 6, 2013 at 13:24

Siddharth Rout's user avatar

Siddharth RoutSiddharth Rout

146k17 gold badges206 silver badges250 bronze badges

Sub Main()

    Dim lNum As Long

    On Error GoTo ErrHandler

    lNum = 1 / 0

ErrExit:
    Exit Sub

ErrHandler:
    Debug.Print Err.Description
    Stop
    Resume

End Sub

When you get to Stop, then Step Into twice. If you don’t have F8, you should have a menu item for stepping into a line. Resume will take you back to the line that caused the error.

answered May 6, 2013 at 21:32

Dick Kusleika's user avatar

Dick KusleikaDick Kusleika

32.5k4 gold badges51 silver badges73 bronze badges

1

  1. Right click the toolbar.
  2. Choose «Customize…»
  3. Select «Debug»
  4. Drag «Step Into» into your toolbar.

Cees Timmerman's user avatar

answered May 6, 2013 at 12:17

saru_'s user avatar

saru_saru_

1211 silver badge1 bronze badge

A bug is a mistake or error in a program that causes it not to work correctly. Debugging is the process of removing and fixing bugs to get a program to function properly. There are different types of bugs that have different causes and solutions. Bugs can be errors, mistakes, oversights, or poorly implemented logic. Some bugs are easy to detect and fix while others are difficult to recognize and rectify. A bug will ultimately cause a compile error, a runtime error, or an incorrect result.

Compile Errors

Compile Errors occur at compile-time when a language rule has been broken. A program will not run if it has an error in compilation. To detect compile errors use Debug → Compile VBAProject on the toolbar in the Visual Basic Editor. Using Debug → Compile will compile the code in all modules and raise an error message if there is a compile error anywhere, whereas running a procedure in one module may not show the compile error in another procedure or module.

Compile Error Procedures
Debug Compile
Compile Error Procedures Debug Compile

Syntax Errors are compile errors that occur because a syntax rule has been broken. Syntax is the structure of a language and determines what is considered a valid statement. By default, Auto Syntax Check is enabled and the Visual Basic Editor will alert syntax errors and certain other compile errors and highlight them red. If auto syntax check is disabled, pop-up messages will not appear but syntax errors will still appear in red. To enable or disable auto syntax check go to Tools → Options → Editor → Code Settings → Auto syntax check.

Disable Auto Syntax Check

Unhandled Runtime Errors

Runtime Errors occur while a program is running. Unhandled runtime errors will cause program execution to pause and a message will be displayed. The user can either press End to end execution of the program or press Debug to open the Visual Basic Editor and view the line of code that caused the runtime error. Runtime errors can be handled using the On Error statement which is discussed in the Error Handling section.

Runtime Error

Logical Errors

Bugs which cause incorrect output can be the trickiest to debug because the code can appear to work properly under the right conditions but then work incorrectly under other conditions. These silent logical errors are usually caused by poorly thought-out or poorly implemented logic or overlooking aspects of a problem or solution. This type of bug can often be caught through testing and reviewing the output of the code.

Public Function RandomLong(MinValue As Long, MaxValue As Long) As Long

    'BAD CODE - If MinValue > MaxValue erroneous results occur

    Randomize
    RandomLong = Int((MaxValue - MinValue + 1) * Rnd + MinValue)

End Function

Public Function RandomLong(MinValue As Long, MaxValue As Long) As Long

    'FIXED - Unacceptable state causes a runtime error instead of returning wrong answers

    If MinValue > MaxValue Then
        Err.Raise 5
    End If

    Randomize
    RandomLong = Int((MaxValue - MinValue + 1) * Rnd + MinValue)

End Function

A runtime error could exist within a silent error if it only occurs under specific conditions. Code may run normally under normal conditions but then break when an edge case is encountered, causing an unhandled runtime error which can leave a program or associated data in an intermediate state.

Debug Object

The Debug object contains two methods which assist in debugging VBA code, Print and Assert. The Debug object has a default global instance and cannot be instantiated. The Debug object can be accessed at any time in VBA just by typing Debug.

Debug.Print

Debug.Print is used to print text to the Immediate Window.

Public Sub Example()

    Debug.Print "Hello, World!"

End Sub

Debug Print

Debug.Assert

Debug.Assert will pause execution if a boolean expression does not evaluate to True. If the expression evaluates to False or Null execution will be paused.

Public Sub Example()

    Debug.Assert 1 > 0
    Debug.Assert True
    Debug.Assert 1

    Debug.Assert 1 < 0  'Pauses Execution
    Debug.Assert False  'Pauses Execution
    Debug.Assert 0      'Pauses Execution
    Debug.Assert Null   'Pauses Execution

End Sub

Debug Assert

Pause Program Execution

There are a number of ways to cause a program to pause execution and allow the user to inspect the state of a program in break mode.

Breakpoints

Breakpoints can be used in the Visual Basic Editor to pause program execution when a particular line of code is reached. Execution will pause before the line of code is executed. Breakpoints can be toggled by clicking in the margin next to the line of code, right-clicking the line of code and selecting Toggle → Breakpoint, or by using the Edit or Debug toolbars.

Breakpoint

Breakpoint Paused

Stop Statement

The Stop statement will pause execution when the keyword is encountered in the code.

Stop Statement

Watches

Watches can be used to pause execution when an expression evaluates to True or when the value of an expression changes.

Watch Break When Value Is True
Watch Break When Value Is True Paused

Runtime Errors

By default, when an unhandled runtime error is encountered a message will appear describing the error, giving the option to End program execution or to Debug. Selecting Debug will jump to the line of code that caused the error and leave program execution paused.

Unhandled Runtime Error

Different error trapping options can be selected to pause execution on all errors or to pause on errors inside class modules.

Error Trapping Option Description
Break on All Errors Will enter break mode when any error is encountered regardless of error handling code.
Break in Class Module Will enter break mode and show error inside class modules.
Break on Unhandled Errors This is the default setting. Will enter break mode when an unhandled runtime error occurs.

Error Trapping Options

Debug.Assert

Debug.Assert will cause execution to pause if a boolean expression does not evaluate to True. If the expression evaluates to False or Null execution will pause.

Public Sub Example()

    Debug.Assert 1 = 0
    Debug.Assert False
    Debug.Assert 0
    Debug.Assert Null

End Sub

Stepping Through Code

There are tools in the Visual Basic Editor for stepping through code which allow developers to take a close look at the way a program executes each line of code. There is: Step Into, Step Over, Step Out, and Run To Cursor. These tools can be accessed from the Debug Toolbar or by using keyboard shortcuts.

Tool Shortcut Description
Step Into F8 Executes a line of code and enters into procedures.
Step Over Shift + F8 Executes a line of code but will not enter procedures.
Step Out Ctrl + Shift + F8 Executes all lines of code within a procedure.
Run to Cursor Ctrl + F8 Executes all lines of code up to where the cursor is currently located.

Navigating Code

Navigating code is an important skill for programming as well as debugging. When a project grows it becomes more complicated to navigate the code. The Visual Basic Editor provides tools that facilitate navigating code.

Definition Shortcut

The Definition shortcut allows the developer to jump directly to a where a variable or procedure is defined. To jump to the definition of a variable or procedure right-click on the identifier and select Definition from the right-click menu or use the keyboard shortcut Shift + F2.

Definition

LastPosition Shortcut

The LastPosition shortcut allows the developer to jump to the position in code they last edited. To jump to the last position right-click in the Visual Basic Editor and select LastPosition or use the keyboard shortcut Ctrl + Shift + F2.

Last Position

Bookmarks

Bookmarks can be used to explicitly set positions in the code that can be cycled through. To set a Bookmark right-click on the line of code and select Toggle → Bookmark. To cycle through Bookmarks, use the Edit Toolbar.

Toggle Bookmark

Object Box and Procedure Box

The object box and procedure box drop-downs allow a developer to view all the objects and procedures in a module and jump directly to specific procedures as well as insert event procedures if applicable. The object box and procedure box are located at the top of the coding window. The object box is on the left and the procedure box is on the right.

Procedure Box

Split Code Window

The code window can be split so different parts of the same code window can be viewed simultaneously. To split the code window drag the handle at the top right corner of the code window.

Split Handle

Split code windows view the same code and changes in either window are reflected in both windows.

Split

Module And Procedure View

Code windows can be toggled between module view and procedure view. Module view makes the entire module visible in the code window. Procedure view makes only the current procedure visible in the code window. To toggle between module view and procedure view use the toggle buttons at the bottom left corner of the code window.

Module Procedure View

Useful Shortcuts

Action Shortcut Description
Intellisense Ctrl + j Shows options for completing code
Auto-Completion Ctrl + space Completes code or shows options for completing code
Definition Shift + F2 Jumps to where a variable or procedure is defined
Last Position Ctrl + Shift + F2 Jumps to the last active position in a code module

Important Windows

The Immediate Window, Locals Window, and Watch Window are all powerful debugging tools. These windows can be accessed from the View menu in the Visual Basic Editor.

VBE View Menu

Immediate Window

The Immediate Window can be used to view output, run code, and evaluate expressions. The Immediate Window can be accessed by pressing Ctrl + g in the Visual Basic Editor or from View → Immediate Window.

Immediate Window Examples

Debug.Print

Debug.Print outputs text to the immediate window. For example, Debug.Print «Hello, World!» will output «Hello, World!» to the immediate window.

Call Procedures

Procedures can be called from the immediate window by typing the name of the procedure followed by any parameters and pressing enter.

Evaluate Expressions Using «?»

To evaluate an expression in the immediate window type a «?» followed by the expression and press enter.

Execute Code Statements

Code can be typed directly in the immediate window and executed. Because only one line can be used in the immediate window to type code, write multiple statement using the «:» statement separator.

Locals Window

The Locals windows is used to track the values and types of variables during program execution. Pausing execution, stepping through code, and looking at the locals window is an effective way to observe changes in the state of a program. The Locals Window can be accessed from View → Locals Window.

Locals Window

Watches

The Watch Window is used to view how expressions evaluate during a program’s execution and to pause execution when certain conditions are reached. To Add a watch, highlight an expression, right-click the expression, and select Add Watch. Alternatively, right-click the Watch Window, select Add Watch, and type the expression. To access the Watch Window navigate to View → Watch Window.

Right-Click Add Watch
Add Watch
Watch Break on Value Change

Call Stack Window

The call stack window shows a list of active procedures. To see the call stack dialog either navigate to View → Call Stack, click the call stack icon on the Debug toolbar, or use the shortcut Ctrl + L.

Call Stack Window

Понравилась статья? Поделить с друзьями:
  • Проверка качества данных в excel
  • Проверка возраста в excel
  • Проверка значения в ячейке excel на несколько ячеек
  • Проверка вводимых значений источник excel
  • Проверка значений в ячейках excel на совпадения