Хитрости »
21 Март 2015 94771 просмотров
Очень часто начинающие работать в VBA сталкиваются с различными ошибками, которые выдает код в момент выполнения. Если не знать как поступить в данном случае – то очень сложно будет исправить код быстро, а то и вообще невозможно будет определить причину ошибки без помощи более «продвинутых» пользователей. Новички зачастую делают правки наугад, что может порождать иные ошибки, а это в свою очередь не только затрудняет поиск первоначальной ошибки, но и может привести к невозможности исправить код вообще. Поэтому в этой статье я решил описать как производить отладку кода и определять ошибки.
Чтобы описанное в статье можно было сразу опробовать в практике советую скачать файл пример:
Пример таблицы и кода (35,5 KiB, 2 851 скачиваний)
Что будет рассмотрено:
- Способы отладки кода в момент появления ошибки
- Использование окон 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 сразу поймет, что в таком виде код работать не будет – не выполнится и одна строка. Сразу появится ошибка:
Ошибка означает, что внутри кода есть переменная, которая ранее не была объявлена.
Сама переменная, которую 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:
В момент появления главное нажать Debug, а не End (если будет желание прочитать про тип ошибки подробнее – можно еще нажать Help, текст будет на английском). VBA подсветит желтым строку, вычисления или операции в которой вызывают ошибку:
Теперь самый важный этап – необходимо определить причину ошибки. С виду все хорошо – одна ячейка перемножается на другую. Без опыта сложно сходу понять, что это ошибка типов данных, хоть VBA прямо об этом говорит(Type Mismatch – в переводе «Несовпадение типов»). Поэтому самое надежное в этом случае – это определить значение каждой составляющей той строки, в которой возникла ошибка. В случае с кодом выше можно воспользоваться двумя методами:
- Навести курсор мыши на любую переменную(dblSum, lr) и посмотреть всплывающую подсказку, которая показывает имя переменной и её текущее значение:
Значение нашей переменной lr = 1. Запоминаем и переходим на лист с таблицей и смотрим, какое значение в ячейке первой строки третьего столбца(Cells(1,3)). Там значение Закуп цена, что явно не является числом. Следовательно перемножить его нельзя, т.к. это текст. Отсюда и ошибка типов – с текстом нельзя производить математические операции. Для вычислений предполагается в данном случае числовой тип данных(Integer,Long,Double). - Узнать сразу значение ячейки Cells(lr, 3).Value и ячейки Cells(lr, 5).Value. Наведение курсора мыши в данном случае не даст результата. Как правило наведение курсора мыши не имеет эффекта если это не объявленные как переменные объекты (как в этом случае — Cells). Такие объекты не всегда могут быть вычислены в памяти в момент отладки. Поэтому чтобы просмотреть значение ячейки сначала необходимо отобразить окно Immediate(отобразить можно сочетанием клавиш Ctrl+G или через меню View —Immediate Window). Выделить и скопировать полностью нужную переменную Cells(i, 3).Value и в окне Immediate написать:
?
и после вопр.знака вставить скопированное. Должно получиться:
?Cells(i, 3).Value
И нажать Enter. Строкой ниже в этом окне будет выведено значение для объекта или переменной (если оно может быть получено):
По сути результат будет как и в первом примере – мы увидим, что в ячейке текст. Чем второй метод лучше первого? Тем, что таким образом можно сразу получить значение, не переходя на лист и не выискивая нужный номер строки. Ведь это в примере он равен 1, в реальности же строка может быть и 24451.
Окна Locals и Watches
Так же для отслеживания значений переменных очень удобно использовать окно
Locals
и окно
Watches
.
Окно Locals
Окно Locals отображает все локальные переменные, задействованные в выполняемой в настоящий момент процедуре:
Как видно в этом окне отображается имя переменной, её тип и значение. Все хорошо, но в этом окне отображаются исключительно локальные переменные, объявленные на уровне модуля. Переменных других модулей, объявленные как Public и используемые в текущей процедуре там не отображаются. Подробнее про видимость переменных можно узнать в статье: Что такое переменная и как правильно её объявить?
Окно Watches
Окно Watches представляет большую ценность – в это окно можно просто «перетащить» нужную переменную или объект и в этом окне будут отражены все данные об имени переменной, её типе и текущем значении:
Теперь рассмотрим чуть подробнее как перетаскивать в это окно данные. На примере кода выше:
- Выделяем Cells(i, 3).Value
- Не снимая выделения наводим курсор мыши на это выделение
- Зажимаем левую кнопку мыши и не отпуская её переносим курсор в любое место окна Watches
Теперь данные по переменной загружены и доступны для просмотра. По сути все умеют это делать — процесс очень схож с обычным перемещением файлов и папок по рабочему столу. Выделили и с зажатой левой кнопкой мыши перенесли в нужное место.
В чем еще один плюс этого окна – в этом окне можно оставлять эти значения и просматривать в моменты пошаговой отладки только занесенные в это окно переменные(про пошаговую отладку будет рассказано ниже). Если вдруг какая-то переменная/объект стали не нужны для постоянного отслеживания их данных – можно удалить их из окна Watches, чтобы не мешалась. Для этого выделяем переменную-правая кнопка мыши – Delete 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 (либо выбрать в меню Degub —Step Into). Теперь при каждом нажатии клавиши F8 код будет выполнять одну строку кода за другой в той очередности, в которой они расположены в процедуре. Если внутри процедуры будет вызов второй процедуры или функции – код пошагово выполнит и её и затем вернется в основную процедуру.
Так же хочу привести еще пару сочетаний клавиш, которые удобно применять при пошаговой отладке:
- Shift+F8(Degub —Step Over) — выполнение вложенной функции/процедуры без захода в неё. Если внутри основной процедуры или функции выполняется другая процедура или функция и Вы уверены, что она работает правильно — просматривать пошагово весь код вложенной процедуры/функции не имеет смысла. Чтобы вложенная процедура/функция выполнилась без пошагового просмотра надо просто нажать указанное сочетание клавиш тогда, когда строка вызова вложенной процедуры/функции будет подсвечена желтым
- Ctrl+Shift+F8(Degub —Step Out) — завершение вложенной функции/процедуры и выход в основную с остановкой. Если все же перестарались и перешли в пошаговый проход вложенной функции(или сделали это специально, но посмотрели все, что надо) — то нажимаете это сочетание и код быстро выполнить вложенную функцию, перейдет в основную и остановится для дальнейшей пошаговой отладки
- Ctrl+F8(Degub —Run to Cursor) — выполнение процедуры до строки, в которой на данный момент установлен курсор
Точки останова
Но куда чаще бывает нужно не просто весь код пройти пошагово, а начать пошаговое выполнение только начиная с какой-либо одной строки, чтобы не мотать строк 40 кода(да еще с циклами) ради достижения одной какой-то строки. Еще точки останова очень полезны при отладке событийных процедур(вроде Worksheet_Change, Worksheet_BeforeDoubleClick, событий элементов форм и т.п.), т.к. они в большинстве своем содержат аргументы и выполнить по F8 их просто невозможно и выполняются они только при наступлении самого события, которые они призваны обработать. Тоже самое справедливо для функций пользователя(UDF) именно для проверки их работы из листа, т.к. эти функции нельзя начать выполнять по F5 — они начинают выполняться только после их пересчета и зачастую ошибки можно выявить исключительно при вызове именно с листа.
Чтобы дать понять VBA на какой строке необходимо будет остановится необходимо установить курсор мыши в любое место нужной строки и нажать F9 или Debug —Toggle Breakpoint. Строка будет выделена темно-красным цветом.
Это еще называется установкой точки останова. Убрать точку останова можно так же, как она была установлена – F9 или Debug —Toggle Breakpoint. Так же точку основа можно установить с помощью мыши: для этого необходимо в области левее окна с кодом напротив нужной строки один раз щелкнуть левой кнопкой мыши:
Теперь можно запустить код любым удобным способом (в отладке это как правило делается клавишей F5 или с панели: Run —Run Sub/UserForm). Как только код дойдет до указанной точки останова он остановится и строка будет подсвечена желтым. Дальше можно либо продолжить выполнение в пошаговом режиме (нажимая F8), либо (проверив значения нужных переменных и объектов) нажать опять F5 и код продолжит выполняться автоматически, пока не выполнится или не достигнет другой точки останова. Самих же точек останова может быть сколько угодно и расположены они могут быть в любой процедуре или функции.
Следует помнить, что после закрытия файла с кодом точки останова не сохраняются и при следующем открытии книги их необходимо будет установить заново, если это необходимо.
Еще хочу добавить, что ошибки могут появляться не всегда, даже если они есть. Бывает и так, что код выполняется без ошибок, но однако либо выполняется не так, либо вообще ничего не делает. Как правило причин две:
- Логика кода построена неверно и ошибок VBA действительно не возникает. Но т.к. логика неверна — код выполняет не то, что от него ожидается. Решение одно — пошагово выполнить весь код и детально просмотреть всё, чтобы обнаружить в какой строке или строках нарушена логика
- Один из очень распространенных вариантов: в начале кода стоит обработчик ошибок 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
ссылки
статистика
Отладка кода программы (процедуры) в редакторе VBA Excel. Горячие клавиши для команд меню Debug, окна Immediate и Locals, пункт Compile VBAProject.
Команды меню Debug редактора VBA Excel предназначены для отладки кода программ (процедур). Вызвать их можно как через меню, так и сочетанием клавиш.
Горячие клавиши для вызова команд меню Debug:
Команда | Горячие клавиши | Описание |
---|---|---|
Step Into (один шаг) | F8 | Запускает режим отладки и выполняет операторы кода по одному, в том числе в вызванных процедурах |
Step Over (шаг с обходом) | Shift+F8 | Выполняет вызванную процедуру не пошагово, а как единое целое, и переход к следующему оператору отлаживаемой программы |
Step Out (шаг с выходом) | Ctrl+Shift+F8 | При нахождении в вызванной процедуре выполняет оставшиеся ее операторы и переход к следующему оператору отлаживаемой программы |
Ran To Cursor (до курсора) | Ctrl+F8 | Выполняет операторы отлаживаемой процедуры до курсора |
Toggle Breakpoint (точка останова) | F9 | Устанавливает точку останова |
Compile VBAProject (компиляция) | — | Выполняет компиляцию проекта VBA |
Окна Immediate и Locals
Окна Immediate Window и Locals Window открываются через одноименные пункты меню View главной панели инструментов редактора VBA. Окно Immediate можно вызвать сочетанием клавиш «Ctrl+G».
В окне Immediate при отладке программы отображаются строки, возвращенные методом Debug.Print.
Окно Locals показывает переменные и их содержимое во время приостановок выполнения кода. Значения переменных можно не только наблюдать, но и изменять их непосредственно в окне Locals. Далее процедура будет выполняться с новыми значениями переменных.
Пункт Toggle Breakpoint
Команда Toggle Breakpoint устанавливает точку останова программы в том месте, где стоит курсор. Но установить точку останова можно проще: кликните на сером поле слева от строки кода, на которой надо остановиться, и точка останова будет вставлена.
Когда вы нажимаете клавишу F5 (Run Macro), программа выполняется до точки останова, строка с точкой останова не выполняется. На этом этапе можно просмотреть переменные в окне Locals и отладочную информацию, выведенную в окно Immediate с помощью метода Debug.Print.
Пункт Compile VBAProject
Если вам необходимо проверить все процедуры проекта на соответствие правилам синтаксиса VBA, проведите попытку компиляции проекта, нажав пункт Compile VBAProject в меню Debug.
Если ошибок нет, то ничего не произойдет, только пункт Compile VBAProject станет недоступным для нажатия.
При обнаружении ошибки компилятор откроет процедуру с ошибкой и выделит ее. После исправления ошибки, проведите следующую попытку компиляции проекта, и так до исправления всех ошибок.
Пример отладки кода
Скопируйте следующую процедуру и вставьте ее в любой программный модуль:
Sub Primer() Dim x, y, z x = 525 y = x * 2 Debug.Print «y = « & y z = x & y Debug.Print «z = « & z End Sub |
Откройте через меню View окна Immediate Window и Locals Window. Установите курсор внутри вставленной процедуры.
Нажимайте последовательно клавишу F8 и наблюдайте за происходящим. В конце отладки сформируется следующая картина:
После завершения отладки окно Locals очищается, записи в окне Immediate сохраняются.
Пример проверки синтаксиса кода VBA Excel с помощью компилятора.
Добавьте к любой строке кода отлаживаемой процедуры точку и нажмите в меню Debug на пункт Compile VBAProject. Компилятор укажет на ошибку.
When we use VBA to write code in excel or when we any programming language to write code we may encounter errors that need to be analyzed, checked, and fixed. To overcome this problem most IDEs and programming languages support debugging. Debugging is the process of executing your programming codes step by step and checking which the steps currently compiler is executing, what are their values, and what is their output, we will use debugging. Alternatively, we can also execute each programming statement one by one and check the output, it is almost similar to debugging but it is not convenient and took a lot of time. To learn more in detail about debugging please refer to Software Engineering | Debugging.
Debugging VBA Code
In this example, we will use the following sub-procedure to understand the VBA debugging process.
‘define a sub procedure
Sub fun()‘declare 3 variables
Dim a, b, i As Integer
a = 0
b = 0‘iterating
For i = 1 To 5a = a + 1
b = b + 1Next
End Sub
Now, we will run our VBA macro. For this Click On Run Button In Toolbar.
Once, we run our VBA code, the entire program gets executed at once.
Getting Started with Debugging
To start with debugging process, we need to observe the values of each and every statement before and after execution. We can observe it in Locale Window. To insert the Locals Window in our VBA editor we will go to View > Locals Window.
Once, we click on the Locals Window option, it will add locals window at bottom of our VBA Editor.
This Locals Window will show the currently debugging Expression, its current Value, and the Type of the expression currently getting executed.
Step into Function (F8)
The Step Into function is used to execute the code step by step, it highlights the currently executing step in yellow color. In order to debug the sub-procedure, we need to Place The Cursor Inside VBA Editor > Toolbar > Debug > Step Into (F8).
Note: We can also use a shortcut F8 for calling Step Into function.
Once, we click on Step Into, it will start debugging and we can get the currently executing expression, its value, and type from the local’s window.
Furthermore, we can use the shortcut for Step Into – F8 and the values of the variables in the local’s window get updated. In case we need to execute the entire program in one go, we need to click on the Run button from the toolbar window.
Step over Function (Shift + F8)
The Step Over function is used for escaping the sub-procedure. For example, if we have a sub-procedure inside another sub-procedure and we want to escape it while debugging as soon as the cursor reaches that procedure we will call Step Over function, and it will escape that particular procedure.
Note: We can also use a shortcut as Shift + F8 for calling the Step Over function.
Here, we will add one more sub-procedure to our existing procedure. For this, we need to first add a module and define a sub-procedure. To add a module go to VBA Project > Right-Click > Insert > Module.
This will insert a module.
Now, we will insert a sub-procedure in our inserted module.
‘define a sub-procedure
Sub addition()‘declare 3 variables
Dim a, b, res As Integer
a = 1
b = 2
res = a + bEnd Sub
We will call our addition() sub-procedure in our main procedure.
Now, if we debug our sub-procedure, as soon as the debugger reaches to Call addition step, it will move to our addition procedure.
If we want to avoid our debugger to move to the addition() procedure, we need to call the Step Over(Shift + F8) function when the debugger reaches to Call addition step.
Step out Function (Ctrl + Shift + F8)
The Step Out function is used to move out of the sub-procedure. Let’s understand it with the above example. If we want to escape the call of addition sub-procedure but, by mistake, we have called it by pressing too many Step Into(F8) functions. Then to move out of the sub-procedure we can call Step Out(Ctrl + Shift + F8), it will move out our debugger from the currently executing procedure.
Breakpoints (F9)
When we execute our code, the breakpoint is a line where the debugger will pause and wait. For example, if there are thousands of lines of code and we want to keep track of a particular line of code, we can use breakpoint there. To place a breakpoint we need to place our cursor where we want the breakpoint and then press F9 or we can simply click inside the margin area beside the editor line.
Watch Window
As above, we have seen using the Locals Window we can keep track of all the variables. But, If we want to keep track of only one variable we can use Watch Window to keep watch on a single variable. In order to insert the watch window, we need to go to View > Watch Window.
Once, we click on the Watch Window option, it will get inserted at the bottom of the VBA editor.
We will be using the following sub-procedure to use the watch window.
‘define a sub procedure
Sub fun()‘declare 3 variables
Dim a, b, i As Integer
a = 0
b = 0‘iterating
For i = 1 To 5a = a + 1
b = b + 1Next
End Sub
In order to add a variable to the Watch Window, we need to Select Variable > Right-Click > Add Watch.
Once, we click Add Watch option a popup will come we need to click on the OK button.
This will inset the variable to the Watch Window.
Now, if we will debug our VBA code, we can watch over the variable in the Watch Window.
When you write VBA, or any programming language, you are going to encounter errors in it, or should we call them unintended features? Basically you can’t write any substantial amount of code without needing to fix errors and make sure that it works as it’s supposed to.This post is going to look at the tools I use the most in the VBA editor to help debugging VBA code.
These debugging tools not only let you fix problems, they allow you to gain a better understanding of code, so can be used to familiarise yourself with code written by someone else.
Getting Started
The first thing you need to do is open the VBA editor, press ALT + F11 in Excel.
Of course you need a bit of code to debug, so here’s a trivial example. This code is available to download.
Enter your email address below to download the sample workbook.
By submitting your email address you agree that we can email you our Excel newsletter.
Sub ListNumbers() Dim counter As Integer Dim myRange As Range Set myRange = Range("B11") For counter = 0 To 10 myRange.Offset(counter).Value = counter - 1 Next counter ChangeFont End Sub Sub ChangeFont() ActiveCell.Font.Bold = True End Sub
The Debugging Tools
When I say ‘tools’ what I am referring to are ways the VBA editor allows us to interact and run the code.
If you look at the Debug menu in the VBA editor this is what you will see
Almost all the tools (or commands) have a shortcut key and you should learn these as it’s a much quicker way to debug, rather than going to the menu all the time.
Running Code : F5
Whilst this isn’t listed in the Debug menu, you will use it when debugging.
When you place the cursor into a sub, either with a mouse or using the keyboard, press F5 to run that sub.
Also, if you are stepping through code (F8 — see below) and get to a point where you are happy with what you have checked, you can press F5 to execute the rest of the code.
You can’t use F5 or F8 to run a sub that requires parameters, or to execute a function.
Stepping Through Code : F8
With the cursor in the sub, press F8 to execute one line of code at a time.
The next line to be executed will be highlighted in yellow, with a yellow arrow pointing to it.
Each time you press F8, the line highlighted in yellow is executed, and the next line to be run is highlighted.
Notice that the DIM statements declaring variables are not included in this and are stepped over.
You can press F8 to execute every line of code, one at a time, until the sub ends.
Stepping Over Code : SHIFT + F8
If your code calls another sub, you may not want to step through each line of code in that 2nd sub. In this case you can ‘step over’ the 2nd sub and immediately continue executing the code in your 1st sub.
My sub ListNumbers calls another sub ChangeFont. When code execution gets to the call for ChangeFont, I can press SHIFT + F8, the ChangeFont sub is executed, but I don’t have to wait for this, and the code pauses again at the next line which is the End Sub statement.
Stepping Out of Code : CTRL + SHIFT + F8
If I find myself in a called sub, either intentionally or accidentally because I pressed F8 too many times, I can Step Out of that sub by pressing CTRL + SHIFT + F8.
What this means is that the code in the sub will be executed, but code execution will pause at the next statement after the call to the sub.
So in my code, if I am in ChangeFont, stepping out of this sub will pause the code at the End Sub statement of ListNumbers.
Breakpoints : F9
A breakpoint is a line in your code where you tell VBA to pause and wait.
To create a breakpoint you can either position the cursor on the desired line and press F9, or just click in the margin beside that line. A dark red/brown dot will appear beside the line in question to indicate a breakpoint has been set, and that line of code is highlighted in the same color.
Clicking on the dot again will remove the breakpoint, as will pressing F9
You can set as many breakpoints as you want so removing them all can take some time if you have a lot of code. To make this easier, pressing CTRL + SHIFT + F9 removes all breakpoints.
You can use breakpoints to interrupt the code in a function and check that it is working.
Run to Cursor : CTRL+ F8
This works in a similar way to breakpoints, but are not not set. With a breakpoint, that breakpoint exists until you remove it. With run to cursor, it only works once.
To do this, position your cursor on the line where you want code execution to pause and press CTRL + F8
Changing the Next Line to Execute
As you are stepping through code, you’ll notice that the next line to execute is highlighted in yellow, and has a yellow arrow pointing to it in the margin.
You can use your mouse to drag this arrow to whatever line you want in the same sub (provided it’s an executable line), and execution will then continue from there.
This is extremely useful if you want to alter the value of something or fix a bug and then re-execute the code to see if your changes have the desired effect.
So if I have started my For loop where the variable counter takes the values from 0 to 10, and then decide I want counter to actually go up to 20, I just drag the yellow arrow back up to the start of the For loop, change 0 to 20, then start stepping through the loop again.
That’s great I hear you say, but I’m not sure what value counter has. So how do we check that?
Checking the Value of Variables
There are a number of ways to do this, the easiest is to just hover your mouse over the variable while your are debugging:
Debug.Print
Or you can use the Debug.Print statement, I use this a lot. This will print the vale of a variable to the Immediate Window. CTRL + G to show the Immediate Window.
Insert the Debug.Print statement directly into your code like so:
This will only work with ‘simple’ data types (integer, string, long etc) but won’t work with things like ranges.
You can also type the statement directly into the Immediate window (and hit enter) and get the variable’s value
Debug.Print will print any string so you can make it more descriptive if you like e.g.
Debug.Print "At this precise moment in time, counter has the value " & counter & ", thanks for asking."
Watches
You can Watch a variable and its value is shown in the Watch window. If your Watch window isn’t showing, turn it on from the View menu in the VBA editor.
To watch a variable, place the cursor in the variable, right click and then click on Add Watch.
You now have 3 choices. Don’t worry about the Context as you shouldn’t need to change this. What you need to decide is do you want to simply watch the variable. In which case you’ll see its value change as the code executes. Or do you want to break (like breakpoints) when the variables value is True (for Boolean variables) or break when the value changes.
If we are just interested in seeing the value as it changes then choose Watch Expression, otherwise choose the appropriate Break option.
You’ll now be able to see the value of your variable change in real time.
Locals Window
The Locals window is like the Watch window, you can see variable values in real time. Use the View menu to turn it on.
Altering Code While Debugging
As I’ve demonstrated, you can alter your code on the fly while you are debugging. This is a great way to iron out issues. Just change the offending code, then use your mouse to drag the yellow arrow to change the next line to be executed.
Interacting With the Workbook While Debugging
Similar to changing code whilst debugging, you can interact with your workbook(s) while debugging.
With the code paused, you can change the data in the worksheet, select different sheets or workbooks etc.
Be aware of doing this as it may cause unintended results for any code that refers to the ActiveCell or ActiveWorkbook as my ChangeFont sub does.
Skip to content
Как правильно создавать пользовательские функции и где нужно размещать их код, мы подробно рассмотрели ранее в этой статье. Чтобы решить проблемы при создании пользовательской функции, вам скорее всего придется выполнить ее отладку. Тогда вы будете уверены, что функция работает правильно.
Мы рассмотрим несколько способов, как это сделать:
- Что такое отладка функции?
- Способ 1. Использование MsgBox
- Способ 2. Пошаговое выполнение.
- Способ 3. Применение оператора Debug.Print
- Способ 4. Вызов функции из процедуры.
Вы можете выбрать для себя наиболее подходящий метод.
Что такое отладка функции?
Когда вы создаете пользовательскую функцию, всегда существует возможность, что вы допустите ошибку и она не сразу будет работать так, как вам нужно.
Пользовательские функции обычно достаточно сложные. И не всегда они сразу начинают работать правильно. Формула может возвратить неверный результат или ошибку #ЗНАЧ!. В отличие от стандартных функций Excel, никаких других сообщений вы не увидите.
Есть ли способ отследить работу пользовательской функции по шагам, чтобы проверить, как работает каждый оператор, входящий в нее? Да, есть. Для этого и используется отладка.
Я предложу вам несколько способов проверки работы пользовательской функции, чтобы вы могли выбрать наиболее подходящий для себя.
В качестве примера используем пользовательскую функцию GetMaxBetween из нашей предыдущей статьи, которая вычисляет максимальное число в указанном диапазоне значений:
Аргументы функции — это диапазон ячеек, в которых записаны числа, а также верхний и нижний предел значений.
Способ 1. Поместите в важных местах функцию MsgBox.
Для того, чтобы следить за выполнением расчетов, можно в нужных местах выводить на экран значения самых важных переменных. Это можно сделать при помощи всплывающих диалоговых окон.
MsgBox — это диалоговое окно, которое вы можете использовать, чтобы показывать пользователю какое-то сообщение.
MsgBox является функцией и имеет синтаксис, аналогичный другим функциям VBA:
MsgBox( prompt [, buttons ] [, title ] [, helpfile, context ] )
prompt — это обязательный аргумент. Он содержит сообщение, которое вы видите в диалоговом окне. Его также можно использовать для отображения значений отдельных переменных.
Все остальные аргументы являются не обязательными.
[buttons] — определяет, какие кнопки и значки отображаются в MsgBox. Например, если я использую vbOkOnly, то будет отображаться только кнопка OK. Даже если вы пропустили этот аргумент, эта кнопка используется по умолчанию.
[title] — здесь вы можете указать заголовок окна сообщения.
Приступим к отладке. Чтобы показать сообщение, добавим в код пользовательской функции GetMaxBetween перед оператором Case Else следующую строку:
MsgBox vMax, , «Count — » & i
Получим следующий код:
Function GetMaxBetween(rngCells As Range, MinNum, MaxNum)
Dim NumRange As Range
Dim vMax
Dim arrNums()
Dim i As Integer
ReDim arrNums(rngCells.Count)
For Each NumRange In rngCells
vMax = NumRange
Select Case vMax
Case MinNum + 0.01 To MaxNum - 0.01
arrNums(i) = vMax
i = i + 1
MsgBox vMax,, "Count -" & i
Case Else
GetMaxBetween = 0
End Select
Next NumRange
GetMaxBetween = WorksheetFunction.Max(arrNums)
End Function
С помощью переменной vMax в диалоговом окне мы увидим, какие числа соответствуют условиям для отбора, чтобы из них затем выбрать наибольшее. При помощи выражения «Count — » & i в заголовке окна мы указываем, сколько чисел мы уже выбрали, чтобы определить максимальное значение. С каждым новым значением счетчик будет увеличиваться.
В ячейку С1 нашего рабочего листа запишем формулу
=GetMaxBetween(A1:A6;10;50)
После того, как будет нажата клавиша Enter, вы увидите сообщение, как на скриншоте ниже:
Это первое число из диапазона A1:A6, которое соответствует условиям: больше 10, но меньше 50.
После того, как вы нажмете ОК, появится второе сообщение с числом 14. Остальные числа не соответствуют условиям отбора. Поэтому функция завершает работу и возвращает наибольшее из двух значений — 17.
Таким образом, мы шаг за шагом отследили всю работу нашей функции и выяснили, что она работает верно.
Функцию MsgBox можно использовать в самых важных местах кода пользовательской функции, чтобы контролировать изменение значений отдельных переменных. Окна с сообщениями могут оказаться очень полезными, когда у вас большая функция и много вычислений. В этом случае вам будет легко определить, в какой части кода происходит ошибка.
Способ 2. Определите точки остановки и выполните функцию пошагово.
Вы можете добавить в код вашей функции точки останова (Breakpoint), на которых будет останавливаться выполнение вычислений. Так можно пошагово проследить процесс расчёта. При этом вы можете посмотреть, как изменяются значения переменных.
Чтобы добавить точку остановки, поместите курсор в строку с оператором, в котором вы решили приостановить выполнение. Потом нажмите правую кнопку мыши и выберите команду Debug –> Toggle Breakpoint или просто нажмите клавишу F9
. Также можно кликнуть в нужном месте на вертикальной серой области слева от кода функции.
Появится красный кружок, как вы видите на скриншоте ниже. Строка кода, где будет остановлен расчет, выделяется красным цветом.
Теперь при работе функции будет открываться окно редактора VBA. Курсор будет установлен в точке остановки.
Если вы наведете курсор мыши на любую из переменных в коде функции, вы сможете увидеть их текущее значение. Для контроля выполнения вычислений это очень полезно. Вы видите это действие на скриншоте ниже.
Чтобы продолжить вычисления, просто нажмите клавишу F5
.
Примечание. После точки останова вы можете приступить к пошаговому отслеживанию хода вычислений. Если вы нажмете кнопку F8, будет выполнена только одна следующая строка кода VBA. Желтая линия со стрелкой также переместится в позицию последнего выполненного кода.
Поскольку выполнение функции снова приостанавливается, вы можете просматривать текущие значения всех переменных функции с помощью курсора мыши.
Следующее нажатие F8
продвинет нас на шаг вперед. Таким образом, вы можете нажимать F8
до конца расчета. Или нажмите F5
, чтобы продолжить вычисление до следующей точки останова.
В случае возникновения ошибки курсор будет остановлен в той точке кода, где произошла ошибка. И вы также увидите всплывающее сообщение об ошибке. Это позволяет легко определить причину проблемы.
Указанные вами точки останова действуют, пока вы не закрыли файл. При повторном его открытии вам нужно снова их указывать. Согласитесь, что это не всегда удобно.
Эту проблему можно решить. Вставьте в код функции в нужных точках оператор Stop, и вы сможете прервать выполнение программы так же, как при использовании точек останова.
Когда VBA встретит оператор Stop, он остановит расчёты и будет ожидать ваших действий. Проверьте значения переменных, затем нажмите F5
для продолжения.
Оператор Stop является частью программы и поэтому не удаляется при закрытии книги, как это происходит с точкой останова. Когда вы закончите отладку, удалите его сами. Либо превратите в комментарий, поставив перед ним одинарную кавычку (‘).
Способ 3. Отладка при помощи оператора Debug.Print
В коде функции вы можете разместить оператор Debug.Print. Это полезно, чтобы проконтролировать значения переменных, которые циклически изменяются.
Пример такого кода вы видите на скриншоте ниже.
Оператор Debug.Print i, vMax выводит числа, которые были обработаны функцией, и их порядковые номера (начиная с 1).
В окне Immediate вы видите два числа (17 и 14) из выбранного диапазона, которые соответствуют установленным ограничениям и среди которых и будет определено максимальное. Цифры 1 и 2 означают, что функция выполнила 2 цикла, в которых были выбраны числа. Мы видим значения самых важных переменных, как ранее делали при помощи MsgBox. Но при этом не останавливали работу функции.
Способ 4. Вызвать функцию из процедуры
Можно вызвать пользовательскую функцию не из ячейки рабочего листа, а из процедуры. В этом случае все ошибки будут показаны в окне Visual Basic Editor.
Вот как можно вызвать из процедуры пользовательскую функцию GetMaxBerween:
Sub Test()
Dim x
x = GetMaxBetween(Range("A1:A6"), 10, 50)
MsgBox (x)
End Sub
Установите курсор в любое место кода и нажмите F5. Если ошибки в функции нет, вы увидите всплывающее окно с результатом расчетов.
В случае ошибки вы увидите соответствующее сообщение в редакторе VBA. Расчет будет приостановлен, и строка кода, в которой произошла ошибка, будет выделена жёлтым цветом. Вы легко определите, где и почему возникла проблема.
Это все. Теперь вы создали свою надстройку, добавили ее в Excel и можете использовать в ней пользовательскую функцию. Если вы хотите использовать больше функций, просто напишите их код в модуле надстройки в редакторе VBA и сохраните его.
На сегодня все. Мы рассмотрели различные способы отладки пользовательских функций и узнали, как использовать их в своей рабочей книге. Мы очень надеемся, что эти рекомендации будут вам полезны. Если возникнут вопросы, пишите в комментариях к этой статье.