Вилов помилок та налагодження коду vba, excel для всіх
Дуже часто початківці працювати в VBA стикаються з різними помилками, які видає код в момент виконання. Якщо не знати як поступити в даному випадку - то дуже складно буде виправити код швидко, а то і взагалі неможливо буде визначити причину помилки без допомоги більш "просунутих" користувачів. Новачки часто роблять правки навмання, що може породжувати інші помилки, а це в свою чергу не тільки ускладнює пошук початкової помилки, але і може привести до неможливості виправити код взагалі. Тому в цій статті я вирішив описати як виробляти налагодження коду та визначати помилки.
Щоб описане в статті можна було відразу випробувати в практиці раджу скачати файл приклад:
Що буде розглянуто:
Крім цього в кінці статті можна скачати файл з кодами помилок VBA і їх розшифровками.
Початкові дані
Припустимо, є проста таблиця
І код, який повинен пройтися по кожному рядку таблиці, перемножити ціну (стовпець Ціна) на кількість (стовпець Продажі шт), підсумувати перемножені дані і вивести результуючу суму в клітинку В17:
На вигляд код тепер виконаний правильно і помилок викликати не повинен. Однак, якщо його спробувати виконати знову отримаємо помилку - на цей раз помилку типів даних (Type Mismatch):
У момент появи головне натиснути Debug. а не End (якщо буде бажання прочитати про тип помилки докладніше - можна ще натиснути Help, текст буде англійською). VBA підсвітить жовтим рядок, обчислення або операції в якій викликають помилку:
Тепер найважливіший етап - необхідно визначити причину помилки. На вигляд все добре - одна осередок перемножується на іншу. Без досвіду складно відразу зрозуміти, що це помилка типів даних, хоч VBA прямо про це говорить (Type Mismatch - в перекладі "Розбіжність типів"). Тому найнадійніше в цьому випадку - це визначити значення кожної складової тієї рядки, в якій виникла помилка. У випадку з кодом вище можна скористатися двома методами:
Вікна Locals і Watches
Так само для відстеження значень змінних дуже зручно використовувати вікно Locals і вікно Watches.
вікно Locals
Вікно Locals відображає всі локальні змінні, задіяні в виконуваної в даний момент процедурі:
Як видно в цьому вікні відображається ім'я змінної, її тип і значення. Все добре, але в цьому вікні відображаються виключно локальні змінні, оголошені на рівні модуля. Змінних інших модулів, оголошені як Public і використовуються в поточній процедурі там не відображаються. Детальніше про видимість змінних можна дізнатися в статті: Що таке змінна і як правильно її оголосити?
вікно Watches
Вікно Watches представляє велику цінність - в це вікно можна просто "перетягнути" потрібну змінну або об'єкт і в цьому вікні будуть відображені всі дані про ім'я змінної, її тип і поточному значенні:
Тепер розглянемо трохи докладніше як перетягувати в це вікно дані. На прикладі коду вище:
- Виділяємо Cells (i, 3) .Value
- Не знімаючи виділення наводимо курсор миші на це виділення
- Затискаємо ліву кнопку миші і не відпускаючи її переносимо курсор миші в потрібне місце Watches
- Breack Then value Changes. Якщо його встановити, VBA буде відстежувати значення цієї змінної і зупиняти код при будь-якій зміні значення змінної. Це може стане в нагоді для відстеження значень в циклах
- Breack Then value Is True - пункт стане в нагоді для змінних з типом Boolean або для логічних виразів. Як тільки змінна або результат вираження прийме значення True - код буде зупинений на цьому рядку.
Наприклад, необхідно зупинити код, якщо номер рядка дорівнюватиме 10 (тобто. Змінна lr прийме значення 10). Тоді вираз матиме вигляд:
Тоді треба буде виділити в рядку If lr = 10 Then саме умовний вираз lr = 10. перенести її у вікно Watches. виділити рядок у вікні Watches з цим виразом, натиснути праву кнопку миші і вибрати Edit Watch. Вибрати у вікні Breack Then value Is True. Тепер як тільки змінна lr досягне значення 10 (тобто. Оброблятися буде 10-й рядок таблиці) - код зупиниться і рядок з виразом буде виділена жовтим. Можна буде проаналізувати інші змінні або продовжити виконання коду в покроковому режимі (см.далее).
Для чого це може бути потрібно?
- Щоб проаналізувати чужий код і зрозуміти більш точно, що він робить зсередини, а не тільки побачити результат його виконання
- Якщо ви програміст і часто використовуєте макрорекордер (записуєте макроси) - то покрокова налагодження допоможе зрозуміти яке дії виконує кожен рядок. Це допоможе швидше навчитися розуміти код і прибирати з нього зайве, а так само поєднувати різні коди
- Якщо всередині коду є помилка логіки виконання. Це, мабуть, найскладніша помилка, тому що в цьому випадку VBA не зупиняє роботу і не говорить про помилку. Код виконується без помилок, але результат не такий, як очікувалося. Це означає, що або якийсь змінної призначається не те значення, або якась умова невірно або виконується не в той момент, в який повинно. Загалом по суті це помилка розробника, що не призводить до помилок синтаксису або типів, які VBA може відстежити.
Як робити покрокову налагодження? Все просто: встановлюєте курсор в будь-якому місці всередині коду та натиснути клавішу F8 (або вибрати в меню Degub -Step Into). Тепер при кожному натисканні клавіші F8 код буде виконувати один рядок коду за одною в тій черговості, в якій вони розташовані в процедурі. Якщо всередині процедури буде виклик на іншу процедури або функції - код покроково виконає і її, після чого повертається в основну процедуру.
Так само хочу навести ще пару поєднань клавіш, які зручно застосовувати при покрокової налагодженні:
точки зупинки
Але куди частіше буває потрібно не просто весь код пройти покроково, а почати послідовне виконання тільки починаючи з якої-небудь однієї рядки, щоб не мотати строк 40 коду (та ще з циклами) заради досягнення однієї якоїсь рядки. Ще точки зупину дуже корисні при налагодженні подієвих процедур (на кшталт Worksheet_Change, Worksheet_BeforeDoubleClick, подій елементів форм і т.п.), тому що вони в більшості своїй містять аргументи і виконати по F8 їх просто неможливо і виконуються вони лише при настанні самої події, які вони покликані обробити.
Щоб дати зрозуміти VBA на якому рядку необхідно буде зупиниться необхідно встановити курсор миші в будь-яке місце потрібного рядка і натиснути F9 або Debug -Toggle Breackpoint. Рядок буде виділена темно-червоним кольором.
Це ще називається установкою точки зупину. Прибрати точку зупину можна так само, як вона була встановлена - F9 або Debug -Toggle Breackpoint. Так само точку основа можна встановити за допомогою миші: для цього необхідно в області лівіше вікна з кодом навпроти потрібної рядки один раз клацнути лівою кнопкою миші:
Тепер можна запустити код будь-яким зручним способом (у налагодженні це як правило робиться клавішею F5 або з панелі: Run -Run Sub / UserForm). Як тільки код дійде до зазначеної точки зупину він зупиниться і рядок буде підсвічена жовтим. Далі можна або продовжити виконання в покроковому режимі (натискаючи F8). або (перевіривши значення потрібних змінних і об'єктів) натиснути знову F5 і код продовжить виконуватися автоматично, поки не виконається або не досягне іншої точки зупину. Самих же точок зупину може бути скільки завгодно і розташовані вони можуть бути в будь-якій процедурі чи функції.
Слід пам'ятати, що після закриття файлу з кодом точки зупину не зберігаються і при наступному відкритті книги їх необхідно буде встановити заново, якщо це необхідно.
Помилок немає, але код все одно не виконується
Ще хочу додати, що помилки можуть з'являтися не завжди, навіть якщо вони є. Буває і так, що код виконується без помилок, але проте або виконується не так, або взагалі нічого не робить. Як правило причин дві: