Instrumentele de depanare din VBA

VBA oferă o gamă solidă de instrumente de depanare pentru a vă ajuta să eliminați erorile din proceduri. În principal, la depanare se folosesc ferestrele Immediate, Locals și Watch. Aceste instrumente pot fi accesate în diferite moduri, una dintre ele fiind bara de instrumente Debug. Patru dintre butoane - Design Mode, Run Sub/ UserForm, Break și Reset - se află pe bara de instrumente Standard.

Heisenbug, Bugul lui BOHR și alte buguri care sunt greu de descoperit

Cu cât este mai complex și mai lung codul, cu atât este mai probabil să creați bug-uri care sunt dificil de descoperit. De obicei, cu determinare și ingeniozitate, puteți urmări chiar și cele mai dure buguri localizate într-o singură procedură. Dar bug-urile care depind de mai multe circumstanțe neprevăzute și improbabile care apar simultan pot fi greu de izolat.

De exemplu, o eroare care apare într-o procedură când utilizatorul face o anumită alegere într-o casetă de dialog este relativ ușor de descoperit. Dar dacă eroarea apare numai atunci când utilizatorul a făcut două alegeri particulare în caseta de dialog, este mult mai greu de localizat. Și dacă eroarea depinde de o combinație particulară de trei alegeri pe care utilizatorul le-a făcut în caseta de dialog, sau dacă depinde de un element din fișierul special din care procedura își obține datele, probabil că va dura mai mult timp să o identificați.

Programatorii definesc diverse tipuri de bug-uri rare, atribuindu-le nume derivate din discipline precum filozofia și fizica cuantică. De exemplu, un heisenbug este definit ca „un bug care dispare sau își modifică comportamentul atunci când se încearcă sondarea sau izolarea acestuia”. Heisenbug-urile frustrează, la fel ca bug-urile Bohr și mandelbugs (căutați detalii online dacă sunteți curioși). Dar cel mai rău tip de eroare este schroedinbug, care este un bug de proiectare sau de implementare care rămâne static până când cineva citește codul și observă că acesta nu ar trebui să funcționeze, după care încetează să funcționeze până când codul devine logic consecvent.

Aceste bug-uri sunt, desigur, ridicole - până când descoperi putregaiul din cod și trebuie să explici problema superiorilor tăi.

Modul Break

Modul Break este un instrument vital pentru depanarea procedurilor, deoarece vă permite să urmăriți codul executându-l pas cu pas - linie cu linie - în fereastra Cod (prin apăsarea repetată a tastei F8). Această tehnică se numește single-stepping (câte un singur pas).

De exemplu, dacă o instrucțiune If ... Then ... ElseIf ... Else pare să se execute incorect, o puteți parcurge în modul Break și să urmăriți exact ce instrucțiuni se execută și care sunt omise, pentru a ajunge la rezultatul incorect.

Acestea sunt cele mai simple modalități de a comuta la modul Break:

  • Clic pentru a plasa cursorul în procedura pe care doriți să o executați în fereastra Code și apăsați tasta F8 (sau faceți clic pe butonul Step Into din bara de instrumente Debug, sau alegeți Debug> Step Into) pentru a începe să o parcurgeți. Apăsați în mod repetat F8 pentru a parcurge codul.
  • Setați în procedură unul sau mai multe puncte de întrerupere (breakpoints) pentru a determina VBA să oprească execuția și să intre în modul Break atunci când ajunge la una dintre liniile marcate. Un punct de întrerupere vă permite să opriți execuția într-un anumit punct din cod. Cel mai simplu mod de a seta un punct de întrerupere este să faceți clic pe linia în care doriți să vă opriți. Faceți clic în bara din stânga ferestrei Code. (Puteți, de asemenea, să faceți clic dreapta pe linia de cod și alegeți Toggle > Breakpoint din meniul contextual.) Puteți seta orice număr de puncte de întrerupere. Sunt deosebit de utile atunci când trebuie să depistați o eroare pe care suspectați că este localizată într-o anumită procedură, deoarece un punct de întrerupere vă permite să rulați părțile unei proceduri care nu au probleme la viteză maximă și apoi să opriți procedura acolo unde credeți că s-ar putea să fie probleme. De pe acea linie puteți parcurge pas cu pas declarațiile suspecte pentru a urmări îndeaproape cum se execută.

Puteți intra în modul Break și în alte două moduri:

Întrerupeți codul apăsând Ctrl + Break și apoi faceți clic pe butonul Debug din caseta de dialog rezultat. În mod normal, singurul motiv pentru a intra în modul Break în acest fel este dacă codul se blochează într-o buclă nesfârșită (ceea ce veți recunoaște în mod obișnuit atunci când codul pare să nu facă nimic de mult timp sau se repetă când credeți că nu ar trebui să o facă). VBA evidențiază declarația care se execută atunci când apăsați Ctrl + Break, dar (în funcție de timp), este puțin probabil să fie declarația care provoacă problema în cod - va fi doar una dintre declarațiile din bucla cu probleme. Va trebui apoi să parcurgeți bucla pentru a identifica declarația incorectă.

  • La clic pe butonul Debug dintr-o casetă de dialog cu eroare de execuție, VBA evidențiază comanda care a provocat eroarea. (Puteți de asemenea să faceți clic pe butonul Ajutor din caseta de dialog runtime-error pentru a obține o explicație a erorii înainte de a face clic pe butonul Debug.)

METODA PAS CU PAS din ACCESS

Pe lângă găzduirea unei versiuni complete de VBA, Access include un instrument unic, de design macro, denumit Macro Builder. Pentru a experimenta Macro Builder, faceți clic pe Access, faceți clic pe fila Create de pe Panglică (Ribbon), apoi faceți clic pe pictograma Macro din extrema dreaptă. O comandă interesantă (adăugată la Builder în Access 2007) este metoda SingleStep a obiectului DoCmd. Aceasta funcționează oarecum ca și breakpoint, comutând în modul Break în timpul executării și afișând caseta de dialog specializată Macro Single Step din Access. Puteți insera DoCmd.SingleStep și într-o macrocomandă VBA. VBA recunoaște comanda ca pe o linie legitimă de cod. Cu toate acestea, VBA ignoră această afirmație în timpul perioadei de execuție. Doar macrocomenzile create în Access Builder vor răspunde metodei SingleStep.

Comenzile Step Over și Step Out

În secțiunea „Editarea macrocomenzilor înregistrate”, ați învățat cum să parcurgeți o procedură apăsând în mod repetat tasta F8 pentru a emite comanda Step Into, pentru a parcurge liniile pe rând. (De asemenea, puteți realiza această comandă făcând clic pe butonul Step Into din bara de instrumente Debug sau alegând Debug> Step Into, dar apăsarea tastei F8 este mai eficientă.)

Comanda Step Into (pas cu pas) vă permite să vedeți exact ce face fiecare comandă din cod, dar vor fi situații când trebuie să treceți peste secțiuni de cod care sunteți sigur că funcționează bine și să ajungeți mai rapid la o secțiune care pare suspectă. Această situație este valabilă și pentru structurile de buclă, care repetă anumite comenzi – se pierde timp dacă știți că eroarea pe care o urmăriți nu este în buclă.

Pentru a accelera verificarea codului, modul Break oferă trei comenzi: Step Over, Step Out și Run To Cursor.

Comenzile Step Over și Step Out nu sunt disponibile până nu comutați la modul Break (de exemplu, folosind comanda Step Into).

Comanda Step Over (care se poate porni apăsând Shift+F8, clic pe butonul Step Over de pe bara cu instrumente Debug, sau alegând Debug > Step Over) execută întreaga procedură Sub sau funcția apelată din procedura curentă în loc să parcurgă pas cu pas comenzile din procedură, ca în cazul comenzii Step Into. (Comanda "sare peste" acea procedură sau funcție.) Comanda Step Over se folosește atunci când se depenează o procedură care apelează o altă procedură sau funcție care nu are erori și care nu trebuie testată pas cu pas.

Comanda Step Out (care poate fi declanșată cu Ctrl+Shift+F8, cu clic pe butonul Step Out button de pe bara cu instrumente Debug, sau alegând Debug > Step Out) rulează ce a mai rămas din procedura curentă la viteză normală. Comanda Step Out se folosește pentru a executa rapid restul procedurii după ce ați parcurs partea care trebuia verificată pas cu pas.

Comanda Run To Cursor (care poate fi declanșată apăsând Ctrl+F8 sau cu Debug > Run To Cursor) rulează codul la viteză normală până ajunge la comanda în care clipește cursorul din fereastra Code, după care comută la modul Break. Înainte de a porni această comandă, se face clic pe linia cu comanda corespunzătoare.

Fereastra Locals

Fereastra Locals afișează valorile și tipurile variabilelor sau expresiilor din procedura activă. Afișează o vedere de tip arborescent.

O expresie este o combinație de cuvinte cheie, operatori, variabile, și/sau constante. Variabilele sunt un tip de expresii; dar expresiile mai complexe sunt formate din mai mult de o variabilă: x > y, de exemplu, este o expresie care declară că x este mai mare decât y. Această expresie poate fi adevărată (True) sau falsă (False), în funcție de ceea ce se petrece în timpul rulării codului.

Coloana Expression afișează numele fiecărei expresii, afișat sub numele procedurii în care apare. Coloana Value afișează valoarea curentă a expresiei (inclusiv Empty dacă expresia este goală, sau Null ori Nothing, după cum este cazul). Coloana Type afișează tipul de dată al expresiei, cu tipul Variant afișat ca "Variant" cu tipul de dată atribuit (de exemplu, "Variant/String" pentru tipul Variant atribuit unui tip de date String).

Pentru a afișa fereastra Locals, clic pe butonul Locals Window de pe bara cu instrumente Debug sau se alege View > Locals Window. Pentru a ascunde fereastra Locals, clic pe butonul Close al ferestrei.

În fereastra Locals, puteți face clic pe butonul marcat cu trei puncte (...) pentru a afișa caseta de dialog Call Stack, descrisă mai jos. Acest buton este valabil doar în modul Break.

Cum se poate modifica poziția ferestrelor

De reținut că se poate modifica poziția ferestrelor, prin tragere sau cu dublu clic pe bara de titlu. Pentru a le readuce la locația de andocare implicită, se face încă o dată dublu clic pe bara de titlu.

Fereastra Watch este o fereastră separată care se folosește pentru a urmări valorile variabilelor și ale expresiilor pe măsură ce codul este executat. Pentru a afișa fereastra Watch, clic pe butonul Watch Window de pe bara cu instrumente Debug sau se alege View > Watch Window din VBA Editor. Pentru a ascunde fereastra Watch, clic pe butonul Close al ferestrei.

Fereastra Watch afișează expresiile watch – expresiile din cod care au fost specificate anterior de programator, pentru a vedea valorile acestor variabile sau expresii.

Informațiile afișate pot ajuta la detectarea valorilor neașteptate ale unei variabile sau expresii, care apar la rularea codului. Fereastra Watch afișează numele expresiilor sau ale variabilelor urmărite în coloana Expression, valorile lor în coloana Value, tipul lor (Integer, Byte, String, Long etc.) în coloana Type și contextul lor (modulul sau procedura în care operează) în coloana Context. Pentru a urmări în orice moment valoarea unei variabile, se poate folosi fereastra Watch, care funcționează doar în modul Break.

Dacă o variabilă sau o expresie afișată în fereastra Watch nu a fost inițializată, fereastra Watch afișează în coloana Value mesajul "< Out of Context >" și "Empty" (pentru o variabilă care nu este de tip Variant) sau, în coloana Type, mesajul "Variant/Empty" (pentru un Variant).

VBA Editor actualizează toate expresiile urmărite în fereastra Watch de fiecare dată când intrați în modul Break și ori de câte ori executați o declarație în fereastra Immediate. Deci, dacă parcurgeți o procedură în fereastra Code, apăsând tasta F8 (în modul Break), puteți urmări valoarea unei variabile sau expresii, pe măsură ce se execută fiecare instrucțiune. Aceasta este o modalitate excelentă de a identifica unde apare o eroare sau o valoare neașteptată - și este mult mai simplă decât mutarea mouse-ului peste fiecare variabilă sau expresie în cauză pentru a verifica valoarea acesteia folosind caracteristica Auto Data Tips.

Iată un scenariu tipic de depanare. Să presupunem că codul produce un rezultat neobișnuit, cum ar fi că salariul anual este de 2.200.000 USD. Ca de obicei, se încearcă să se afle unde este calculat acest câștig brusc și masiv. Observați fereastra Watch în timp ce parcurgeți codul pas cu pas, pentru a vedea pe ce linie de cod variabila MySalary sare de la 50.000 la 2.200.000. Acum sunteți chiar acolo aproape de locul unde se află eroarea și puteți examina cu atenție liniile precedente de cod pentru a vedea ce afectează variabila MySalary.

Deoarece expresiile de urmărire încetinesc execuția codului, Editorul VBA nu le salvează odată cu codul - trebuie să le refaceți pentru fiecare sesiune de editare. Cu toate acestea, Editorul stochează expresiile de vizionare în timpul sesiunii de editare curente, astfel încât puteți trece de la procedură la procedură fără a pierde expresiile de urmărire.

Setarea expresiilor Watch

Uneori, denumite și conditional breakpoints (puncte de întrerupere condiționale), expresiile de urmărire vă oferă o flexibilitate considerabilă în momentul depanării. Puteți cere editorului VBA să oprească execuția pentru majoritatea oricăror situații pe care le puteți gândi, cum ar fi întreruperea oricărei linii care determină o variabilă să depășească o anumită valoare, să coboare sub zero, să se schimbe la o lungime de șir mai scurtă, etc. Cu alte cuvinte, specificați o condiție, o expresie, cum ar fi MySalary> 50000, iar editorul VBA oprește automat execuția și afișează linia în care valoarea salariului crește peste 50.000. Astfel, punctul de întrerupere condiționat este unul dintre cele mai bune instrumente pe care le are un depanator.

Pentru a seta o expresie de urmărire, adăugați-o în lista din fereastra Watch urmând acești pași:

1. Selectați variabila sau expresia din cod, clic dreapta pe ea, apoi alegeți Add Watch din meniul contextual pentru a afișa caseta de dialog Add Watch. Variabila sau expresia la care s-a făcut clic dreapta apare în caseta text Expression. De asemenea, se poate selecta variabla sau expresia dorită din Debug > Add Watch pentru a afișa caseta de dialog Add Watch. Dacă se alege Debug > Add Watch fără a selecta variabila sau expresia, în caseta text Expression trebuie tastată expresia, lucru care este pierdere de timp.

2. Dacă este necesar, se ajustează setările din grupul Context. Lista ascunsă Procedure este setată la procedura curentă, iar lista Module este configurată la modulul curent.

3. În grupul Watch Type, dacă este cazul, se configurează butoanele radio:

  • Setarea implicită - Watch Expression – adaugă variabila sau expresia din caseta text Expression la lista din fereastra Watch. Cu toate acestea, punctele de pauză condiționale sunt mai utile atunci când faceți mai mult decât să observați pur și simplu starea variabilelor sau expresiilor. Următoarele două elemente din listă descriu adevăratul beneficiu al acestor puncte de întrerupere.
  • Break When Value Is True face ca VBA să comute la modul Break atunci când valoarea variabilei sau expresiei se modifică la True.
  • Break When Value Changes face ca VBA să comute la modul Break atunci când se modifică valoarea pentru expresia urmărită. Utilizați această setare atunci când aveți de-a face cu o expresie urmărită care are o valoare care nu se schimbă, dar care pare să se schimbe (cum ar fi MySalary în exemplul precedent) sau când doriți să fiți alertat de fiecare dată când o expresie se modifică.

4. Clic pe butonul OK pentru a adăuga expresia de urmărit la fereastra Watch.

Utilizați aceste două tehnici importante de întrerupere condițională

Butonul radio Break When Value Is True vă permite să rulați codul fără să parcurgeți fiecare declarație care nu schimbă valoarea expresiei de urmărite la True. Acest lucru vă permite să specificați că modul Break trebuie introdus, de exemplu, atunci când variabila depășește o anumită valoare (cum ar fi X> 10000) sau este egală cu o altă variabilă (cum ar fi x = y). Utilizarea acestui tip de pauză condițională poate fi extrem de utilă pentru urmărirea erorilor evazive.

Butonul radio Break When Value Change vă permite să rulați codul și să vă opriți în fiecare locație în care valoarea din cod se schimbă.

De asemenea, puteți trage o variabilă sau o expresie din fereastra Cod în fereastra Watch; astfel, se stabilește o expresie de urmărire implicită în contextul curent. Pentru a seta Break When Value Is True sau Break When Value Changes, editați expresia de urmărire după ce o trageți în fereastra Watch.

Editarea expresiilor de urmărire

Pentru a edita o expresie de urmărire, faceți clic dreapta pe ea în fereastra Watch și alegeți Edit Watch din meniul contextual sau selectați-o în fereastra Watch și alegeți Debug> Edit Watch. Oricare dintre acțiuni va afișa caseta de dialog Edit Watch cu expresia de urmărire selectată în caseta Expression. Modificați contextul sau tipul de urmărire pentru expresia urmărită utilizând setările din caseta grup Context și caseta grup Watch Type, apoi faceți clic pe butonul OK pentru a aplica modificările.

Ștergerea expresiilor de urmărit

Pentru a șterge o expresie de urmărit, faceți clic dreapta pe ea în fereastra Watch și alegeți Delete Watch din meniul contextual. De asemenea, puteți șterge expresia curentă de urmărit făcând clic pe butonul Delete din caseta de dialog Edit Watch.

Folosirea caracteristicii Quick Watch

Pentru situațiile în care nu este necesară crearea unei expresii de urmărit pentru o expresie sau o variabilă, atunci când doriți doar să observați valoarea, puteți utiliza funcția Quick Watch, care afișează caseta de dialog Quick Watch care conține contextul și valoarea expresiei selectate.

Pentru a utiliza Quick Watch, în modul Break, selectați expresia sau variabila în fereastra Code și apoi faceți clic pe butonul Quick Watch din bara de instrumente Debug, alegeți Debug> Quick Watch sau apăsați Shift + F9. (Dacă lucrați deja în caseta de dialog Quick Watch, puteți face clic pe butonul Adăugare pentru a adăuga expresia în fereastra Watch.)

Fereastra Immediate

Utilizarea fereastrei Immediate este ca un carnet pentru notițe virtual. În fereastra Immediate introduceți linii de cod pe care doriți să le testați rapid, fără a fi necesar să le introduceți într-o procedură și apoi să testați întreaga procedură. O a doua utilizare majoră a ferestrei Immediate este de a afișa informații pentru a vă ajuta să verificați valorile variabilelor în timpul executării unei proceduri.

În primul caz, tastați codul în fereastra Immediate, apoi apăsați Enter pentru a vedea imediat rezultatele. În cel de-al doilea caz, inserați în cod instrucțiuni Debug.Print care afișează informații în fereastra Immediate, unde le puteți vizualiza cu ușurință. Vom explora ambele aceste tehnici în secțiunile următoare.

Pentru a afișa fereastra Immediate, faceți clic pe butonul Immediate Window din bara de instrumente Debug, alegeți View > Immediate Window sau apăsați Ctrl + G. Pentru a ascunde fereastra Immediate, faceți clic pe butonul Close al ferestrei.

Puteți executa cod în fereastra Immediate în modurile Break și Design.

Ce NU PUTEȚI fac în fereastra IMMEDIATE

Există câteva restricții pentru codul folosit în fereastra Immediate:

  • Nu puteți folosi comenzi declarative (cum ar fi Dim, Private, Public, Option Explicit, Static sau Type) sau comenzi de control-flow (cum ar fi GoTo, Sub sau Function). Aceste comenzi în VBA duc la afișarea erorii "Invalid in Immediate Pane".
  • Nu puteți folosi comenzi pe mai multe linii (cum ar fi blocurile de comenzi If sau For...Next) deoarece nu este nicio conexiune logică între comenzile de pe liniile diferite din fereastra Immediate: fiecare linie este tratată singular.
  • Nu puteți adăuga puncte de întrerupere - breakpoints în fereastra Immediate.

Introducerea de cod în fereastra IMMEDIATE

Fereastra Immediate acceptă o serie de scurtături standard pentru editare și combinații de taste, cum ar fi Ctrl + X (Cut), Ctrl + C (Copiere), Ctrl + V (Lipire), Ctrl + Home (mută punctul de inserare la începutul ferestrei), Ctrl + End (mută punctul de inserare la sfârșitul ferestrei), Delete (șterge selecția curentă) și Shift + F10 (afișează meniul contextual).

Fereastra Immediate acceptă, de asemenea, următoarele taste de editare VBA și combinații de taste:

  • F5 continuă rularea procedurii.
  • Alt+F5 rulează cod pentru manipularea erorilor din procedura curentă.
  • F8 pentru executarea codului pas cu pas (executarea unei singure comenzi la un moment dat).
  • Shift+F8 executarea doar a unei proceduri (executarea unei singure proceduri la un moment dat).
  • Alt+F8 rulează cod pentru manipularea erorilor pentru procedura curentă.
  • F2 afișează fereastra Object Browser.

La final, fereastra Immediate are două comenzi proprii:

  • Apăsarea tastei Enter rulează linia curentă din cod.
  • Apăsarea combinației de taste Ctrl+Enter inserează o linie nouă - carriage return.

Afișarea informației în fereastra Immediate

Pe lângă introducerea declarațiilor în fereastra Immediate pentru testare rapidă, puteți utiliza această fereastră pentru o altă tehnică de depanare. Pentru a include în procedurile dvs. declarații care tipăresc informații în fereastra Immediate, folosiți metoda Print a obiectului Debug. Astfel puteți crea un jurnal în timpul executării, un jurnal pe care mai târziu îl puteți examina pentru erori sau comportament ciudat. Nu mai este nevoie să afișați valori pas cu pas sau casete de mesaje care conțin valoarea unei variabile. Puteți afișa datele pentru studii ulterioare.

Sintaxa pentru metoda Print este următoarea:

    Debug.Print [outputlist]

outputlist este un argument opțional care specifică expresia sau expresiile care vor fi afișate. Se poate include outputlist—sau metoda Print care afișează o linie goală, care nu prea este de ajutor. Construiți outputlist folosind următoarea sintaxă:

   [Spc(n) | Tab(n)] expression

Aici, Spc(n) inserează caractere spațiu iar Tab(n) inserează caractere Tab, unde n este numărul de spații sau Tab-uri care vor fi introduse. Ambele argumente sunt opționale, care se folosesc rareori.

expression este un argument opțional care specifică expresia numerică sau expresia String care va fi afișată:

  • Pentru a specifica mai multe expresii, ele se separă cu spații sau cu punct-virgulă.
  • O valoare Boolean afișează True sau False (după caz).
  • Dacă outputlist este Empty, Print nu afișează nimic. Dacă outputlist este Null, Print afișează Null.
  • Dacă outputlist este eroare, Print afișează Error errorcode, unde errorcode este codul care specifică eroarea respectivă.

Ca exemplu, puteți înregistra conținutul variabilelor (expresiilor) NumeClient, Adresa1, Adresa2, Oras, Stat și CodPostal, de tip String, în fereastra Immediate într-un format de adresă utilizând următoarele declarații:

Debug.Print NumeClient
Debug.Print Adresa1 & "," & Adresa2
Debug.Print City & "," & State & " " & CodPostal

În următorul exemplu, procedura următoare afișează numele și căile tuturor fișierelor Excel deschise în fereastra Immediate:

Sub See_All_Workbook_Names()
  Dim oBook As Workbook
    For Each oBook In Workbooks 
    Debug.Print oBook.FullName
    Next 
End Sub

În practică, Debug.print este folosit de programatori ca o alternativă rapidă și eficientă de depanare cu ferestrele Watch, casetele mesaj sau breakpoints. Trebuie să vedeți dacă ceva nu merge bine cu o variabilă (valoarea sa este greșită, dar unde merge greșit?). Așadar, inserați câteva instrucțiuni Debug.Print pentru a afișa valoarea variabilei în timpul executării unei proceduri. Apoi puteți vedea dacă valoarea este greșită în acea locație sau în altă parte a codului.

Dacă programul conține mai multe proceduri, puteți folosi Debug.Print pentru numele procedurii. Acest exemplu identifică atât procedura, cât și numele variabilei din instrucțiunea Debug.Print:

Debug.Print "In procedura Sub Add_Tax, variabila intLocal este: " & intLocal 

Această comandă afișează ca rezultat în fereastra Immediate:

In procedura Sub Add_Tax, variabila intLocal este: 7