Testarea mai multor condiții folosind operatori logici

Sunt cazuri când trebuie testate două sau mai multe condiții înainte de a face o acțiune:

Dacă afirmația X este adevărată și afirmația Y este adevărată, atunci se face o acțiune; dacă afirmația X este adevărată sau afirmația Y este adevărată, atunci se face o altă acțiune; dacă afirmația X este adevărată și afirmația Y nu este adevărată, atunci se face altceva și asa mai departe.

De exemplu, dacă plouă și este rece, se ia echipamentul de ploaie care ține și cald.

Pentru a testa mai multe condiții, se folosesc operatorii logici VBA pentru a conecta condițiile. Tabelul următor prezintă operatorii logici pe care îi suportă VBA, cu exemple și comentarii scurte.

Dintre acești șase operatori logici, cel mai mult se folosesc operatorii de conjuncție (And), disjuncție (Or) și negare (Not), iar ceilalți trei se folosesc în ocazii speciale (rare).

VBA nu folosește evaluarea în scurt-circuit

De reținut la evaluarea condițiilor multiple: VBA nu folosește evaluarea în scurt-circuit în expresiile logice (spre deosebire de alte limbaje de programare, cum ar fi C și C++).

Evaluarea în scurt-circuit este un termen folosit pentru o tehnică simplă de logică folosită de majoritatea oamenilor atunci când iau decizii în fiecare zi: dacă prima sau mai multe condiții dependente sunt false, nu se mai pierde timp pentru evaluarea altor condiții suplimentare.

De exemplu, presupunem că se dă o masă gratuită dacă se livrează la timp un produs și se primește și o promoție. Dacă produsul nu este livrat la timp, șansele de a primi promoția sunt zero. A doua condiție nu se mai evaluează, deoarece rezultatul necesită îndeplinirea ambelor condiții și prima condiție nu a fost îndeplinită. Deci, se scurtcircuitează (se sare) orice testare suplimentară a stării.

VBA nu gândește astfel. Evaluează și a doua condiție (și alte condiții ulterioare), chiar dacă nu e nevoie. Evaluarea tuturor condițiilor ia mai mult timp (acum nu mai constituie o problemă), dar poate introduce complicații neașteptate în cod (lucru care poate fi o problemă).

De exemplu, codul următor produce o eroare atunci când selecția conține doar un caracter. Eroarea apare deoarece codul se termină la executarea funcției Mid cu un șir de lungime zero (selecția de un caracter minus un caracter) - chiar dacă această condiție nu ar trebui să fie evaluată atunci când prima condiție nu este îndeplinită (deoarece lungimea selecției nu este mai mare de 1):

Dim strLitera As String
strLitera = Selection.Text
If Len(strLitera) > 1 And _
  Mid(strLitera, Len(strLitera) - 1, 1) = "T" Then
  MsgBox "A doua litera este T.", vbInformation, "A doua litera"
End If

Pentru a evita acest tip de probleme, se folosesc blocuri If imbricate (nested). În următorul exemplu de cod, prima condiție nu este îndeplinită (din nou, pentru selecția unui singur caracter), așa că a doua condiție nu mai este evaluată. Se poate vedea cum un bloc If este imbricat în (conținut de) celălalt bloc If:

Dim strLitera As String
strLitera = Selection.Text
If Len(strLitera) > 1 Then
  If Mid(strLitera, Len(strLitera) - 1, 1) = "T" Then
    MsgBox "A doua litera este T.", vbInformation, "Penultima litera"
  End If
End If

Folosirea NOT pentru a modifica proprietățile booleene

Iată un truc util. Comanda Not este o modalitate la îndemână pentru a comuta între True și False. Folosind Not cu o variabilă sau proprietate booleană, se poate comuta starea variabilei sau a proprietății fără a mai verifica care este starea curentă. De exemplu, în Excel, se poate crea o structură If pentru a comuta proprietatea Boolean pentru variabila Saved (care controlează dacă Excel consideră că documentul activ conține modificări nesalvate) folosind cod, astfel:

If ActiveWorkbook.Saved = True Then 
 ActiveWorkbook.Saved = False Else
 ActiveWorkbook.Saved = True 
End If

Dar se poate obține același efect mult mai simplu, folosind Not, ca în codul următor:

ActiveWorkbook.Saved = Not ActiveWorkbook.Saved

Blocuri If

Ca în majoritatea limbajelor de programare, blocurile If din VBA sunt printre comenzile cele mai utile și versatile folosite la luarea unei decizii.

În secțiunea următoare, sunt prezentate trei moduri de folosire a instrucțiunii If:

  • If...Then
  • If...Then...Else
  • If...Then...ElseIf...Else

If...Then

If...Then îi transmite VBA să ia decizii simple. Când condiția este îndeplinită, se execută comanda (sau comenzile). Când condiția nu este îndeplinită, VBA sare peste linia cu comenzi din blocul condiţional.

O comandă If începe cu If și se încheie cu End If. (Comanda prescurtată If...Then poate fi scrisă pe o singură linie, iar în acest caz, comanda End If este omisă.)

SINTAXĂ

Comenzile simple If...Then pot fi scrise pe o singură linie. Comanda If...Then pe o singură linie arată astfel:

If conditie Then 'Codul care va fi executat se scrie aici

Atunci când condiția este îndeplinită, VBA execută comanda sau comenzile care urmează pe aceeași linie. Atunci când condiția nu este îndeplinită, VBA nu execută comanda sau comenzile de pe acea linie.

Dar blocul de instrucțiuni If...Then se poate scrie și pe mai multe linii. O comandă If...Then pe mai multe linii (liniile de cod dintre If și End If sunt numite și bloc) arată astfel:

If conditie Then
  'Codul care va fi executat este scris aici
End If

Atunci când condiția este îndeplinită, VBA execută toate comenzile din bloc (comenzile care se află între If și End If). Când condiția nu este îndeplinită, VBA sare peste comenzile din bloc și preia comenzile de după instrucțiunea End If.

Comanda If pe o singură linie nu folosește End If

De reținut că la comanda If...Then pe o singură linie, nu se pune la final End If, iar blocul If cere la final End If. VBA înțelege că o condiție If pe o singură linie se încheie pe aceeași linie.

Dar la blocul If trebuie specificat finalul condiției, pentru ca VBA să înțeleagă care este codul pe care trebuie să îl ignore în cazul în care condiția este evaluată la False. Blocurile If sunt mai ușor de citit.

EXEMPLE

Comenzi If pe o singură linie

Dim bytVarsta As Integer
bytVarsta = InputBox("Introduceti varsta.", "Varsta")
If bytVarsta < 18 Then MsgBox "Nu aveti voie sa cumparati alcool.",, "Fara alcool"

Prima linie declară variabila bytVarsta de tip Integer. A doua linie cere utilizatorului să introducă vârsta într-o casetă de dialog și o stochează în variabilă. A trei linie verifică valoarea din bytVarsta și afișează mesajul Fara alcool dacă valoarea din bytVarsta este mai mică decât 18.

Se pot include mai multe instrucțiuni pe o singură linie, dacă sunt separate de două puncte. O comandă If pe o singură linie poate avea mai multe comenzi. Pe acea linie se specifică acțiunea sau acțiunile care vor fi executate dacă expresia din comanda If...Then este evaluată la True.

De exemplu, pentru a opri macrocomanda după afișarea mesajului Fara alcool, se poate include comanda End după două puncte pe aceeași linie, astfel:

If bytVarsta < 18 Then MsgBox "Nu aveti voie sa cumparati alcool.",, "Minor": End

Modul în care VBA execută codul este:

  1. Mai întâi evaluează condiția.
  2. Atunci când condiția este îndeplinită, execută prima comandă de după Then - în acest caz, afișează mesajul Fara alcool. Apoi trece la executarea celorlalte comenzi de pe acea linie. De reținut că toate comenzile If de pe o singură linie depind doar de acea comandă If. Ele sunt executate (sau nu) în funcție de condiția pusă – dacă este adevărată sau falsă.
  3. După ce utilizatorul închide mesajul Fara alcool (cu click pe butonul OK – singurul buton), VBA execută comanda de după cele două puncte: End.

Se pot adăuga și alte comenzi pe aceeași linie „logică”, separate între ele de două puncte. Dacă se introduce și comanda End, ea ar trebui să fie ultima, deoarece încheie procedura. (Pentru VBA, o linie logică înseamnă că este o linie unică de cod care trebuie executată, indiferent de liniile fizice reale, pe care codul le afișează pe monitor.)

Se poate adăuga și o altă declarație If:

If bytVarsta < 21 Then If bytVarsta > 18 Then MsgBox _
"Poti vota, dar nu ai voie sa bei alcool.",, "Fara alcool": End

Însă, folosind această abordare, la această linie din editorul Visual Basic, există câteva probleme:

  • În primul rând, liniile lungi de cod trebuie întrerupte folosind caracterul de continuare a liniei – în caz contrar, acestea se duc în marginea ferestrei Codului în Editor, forțând derularea pe orizontală pentru a citi capătul liniei. Se pot ascunde toate ferestrele, cu excepția ferestrei Code, sau se poate utiliza o dimensiune de font mai mică pentru cod sau se poate folosi un monitor mai mare, dar probabil lucrul cu linii lungi de cod e destul de dificil. Deci, în practică, se evită folosirea de instrucțiuni pe o singură linie de cod. Declarația End este probabil cea mai lungă care poate fi adăugată.
  • În al doilea rând, liniile lungi de cod (întrerupte sau neîntrerupte) care implică o serie de declarații tind să devină confuze vizual. Chiar dacă totul este evident la introducerea codului, este posibil ca el să devină greu de citit atunci când este modificat câteva luni mai târziu. De obicei, se recomandă folosirea de blocuri If în locul instrucțiunilor complexe If pe o singură linie.

Blocurile If

Construcțiile de blocuri If funcționează la fel ca și cele pe o singură linie, însă blocurile conțin mai multe linii - de obicei câte o comandă pentru fiecare linie - și au la final comanda End If. De exemplu, instrucțiunea If cu o linie din secțiunea precedentă ar putea fi scrisă și ca un bloc If astfel:

If bytVarsta < 18 Then
  MsgBox "Nu ai voie sa cumperi alcool.",, "Fara alcool"
  End
End If

Dacă condiția din prima linie (linia cu comanda If) returnează True, VBA execută instrucțiunile din blocul If. VBA afișează caseta de mesaje și apoi execută instrucțiunea End.

În acest exemplu, blocurile If sunt mai ușor de citit (și, prin urmare, mai ușor de depanat) decât instrucțiunile If de pe o singură linie. Acest lucru este valabil mai ales atunci când sunt imbricate mai multe comenzi If.

Pentru a facilita citirea blocurilor, convenția este să se apese tasta Tab pentru a muta la dreapta liniile din bloc (VBA ignoră indentarea în timpul execuției). Indentarea se poate vedea și în exemplul de cod anterior.

La blocurile scurte If, ca și cel de mai sus, indentarea nu face o diferență mare. Dar, în declarațiile If complexe, indentarea face diferența între un cod clar și unul de neînțeles, ca în secțiunea de mai jos, la „Imbricarea blocurilor If”.

Comenzi If...Then...Else

Comenzile If...Then sunt utile pentru a urma o singură cale în funcție de o condiție, dar uneori este nevoie să se aleagă între două căi de urmat. Pentru aceasta, se folosește comanda If...Then...Else.

Folosind o comandă If...Then...Else, se poate face o anumită acțiune atunci când condiția este True și o altă acțiune dacă este False. Este la fel ca în limbajul zilnic, de exemplu Daca ploua, iau umbrela, altfel iau protectia solara.

Comenzile If...Then... Else pot fi folosite și la casetele cu mesaje care au două butoane. Dacă utilizatorul face clic pe butonul OK, codul va face o anumită acțiune. La clic pe butonul Cancel, va face altceva.

Comanda IF...THEN...ELSE se folosește pentru situațiile TRUE/FALSE

Comanda If...Then...Else este folosită la situații în care sunt întâlnite condițiile adevărat/fals. (Ca și la întrerupătorul electric – deschis sau închis.) Pentru situații mai complexe, în care apar trei sau mai multe condiții, se folosește o comandă logică mai complexă, cum ar fi If…Then...ElseIf…Else sau Select Case. Ele vor fi descrise ulterior.

Sintaxa

Sintaxa pentru comanda If...Then...Else este următoarea:

If conditie Then
   Comenzi1
Else
   Comenzi2 
End If

Dacă conditie este True, VBA execută Comenzi1, primul grup de comenzi. Dacă conditie este False, VBA mută executarea la linia Else și execută Comenzi2, al doilea grup de comenzi.

Și aici există opțiunea de a construi o comandă pe o singură linie If...Then...Else sau blocuri de comenzi If...Then...Else. Se recomandă crearea de blocuri If...Then...Else pentru că sunt mai ușor de citit și depanat și pentru că o structură If...Then...Else este mai lungă decât structura If...Then și va rezulta o linie mult mai lungă.

Exemplu

Un exemplu simplu pentru comanda If...Then...Else este prezentat mai jos.

1. Sub Criticul_de_Carte_Electronica()
2. 
3.   Dim intPaginiCarte As Integer
4. 
5.   intPaginiCarte = InputBox _
     ("Introduceti numarul de pagini din ultima carte citita.", "Criticul de Carte Electronica")
6.  If intPaginiCarte > 1000 Then
7.    MsgBox "Cartea are multe pagini.", vbOKOnly _
         + vbExclamation, "Criticul de Carte Electronica"
8.  Else
9.    MsgBox "Cartea nu are prea multe pagini.", vbOKOnly _ 
         + vbInformation, "Criticul de Carte Electronica"
10. End If
11.    
12. End Sub

Iată ce se petrece în procedura de mai sus:

  • Linia 1 începe procedura, iar linia 12 o încheie. Liniile 2, 4 și 11 sunt goale.
  • Linia 3 declară variabila intPaginiCarte de tip Integer. Linia 5 atribuie variabilei intPaginiCarte rezultatul din caseta de dialog care cere utilizatorului să introducă numărul de pagini al ultimei cărți citite.
  • Linia 6 verifică dacă intPaginiCarte este mai mare decât 1000. Dacă este, se execută comanda de pe linia 7, care afișează un mesaj.
  • Dacă intBookPages nu este mai mare decât 1000, VBA comută la comanda Else de pe linia 8 și execută instrucțiunea următoare, care afișează un alt mesaj pentru utilizator.
  • Linia 10 încheie condiția If.

Comenzile If...Then...ElseIf...Else

Ultima variantă a comenzii If este blocul If...Then...ElseIf...Else, care se folosește pentru a decide între trei sau mai multe variante de acțiune. Se poate folosi orice număr de linii ElseIf, în funcție de cât de complexă este condiția care va fi verificată.

Din nou, comanda If...Then...ElseIf...Else poate să fie scrisă pe o singură linie sau în blocuri de comenzi. În majoritatea cazurilor, se folosesc blocurile If...Then...ElseIf...Else, care sunt mai ușor de construit, citit și depanat. Ca și la alte comenzi If, comanda If...Then...ElseIf... Else nu are nevoie de instrucțiunea End If, iar blocul If...Then...ElseIf...Else are nevoie de End If.

Sintaxa

Sintaxa pentru If...Then...ElseIf...Else este următoarea:

If conditie1 Then comenzi1
ElseIf conditie2 Then comenzi2
[ElseIf conditie3 Then comenzi3]
[Else
comenzi4]
End If

Dacă condiția exprimată în conditie1 este True, VBA execută comenzi1, primul bloc de instrucțiuni, apoi reia execuția la linia de după clauza End If. Dacă condiția este falsă, VBA comută la prima clauză Elself și evaluează starea exprimată în conditie2. Dacă returnează adevărat, VBA execută comenzi2 și apoi sare la linia de după linia End If; dacă este Fals, VBA trece la următoarea condiție Elself (dacă există una) și evaluează starea (aici, conditie3).

Dacă toate condițiile din declarațiile Elself se dovedesc false, VBA se ramifică la declarația Else (dacă există) și execută declarațiile de după aceasta (aici, comenzi4). Instrucțiunea End If încheie instrucțiunea condițională, iar execuția continuă cu linia de după End If.

Clauza Else este opțională, deși în multe cazuri este o idee bună să fie inclusă pentru a permite VBA să facă o altă acțiune dacă niciuna dintre condițiile specificate în clauzele If și ElseIf nu se dovedesc a fi adevărate. Programatorul nu poate prezice întotdeauna toate condițiile în care se execută programul, astfel încât comanda Else ajută la o finalizare a listei de If-uri. Așa se poate face față la o situație care nu se află în listă.

Pot fi scrise orice număr de clauze ElseIf într-un bloc If, fiecare cu propria condiție. Dar dacă într-o instrucțiune If sunt prea multe condiții ElseIf (de exemplu, mai mult de 5 sau 10), se recomandă folosirea comenzii Select Case, descrisă mai jos.

EXEMPLE

Mai jos sunt prezentate două exemple de comenzi If...Then...ElseIf...Else:

  • O comandă simplă If...Then...ElseIf...Else care execută instrucțiuni în funcție de butonul apăsat pe o casetă de dialog cu trei butoane
  • O comandă If...Then...ElseIf fără condiția Else

Comanda simplă If...Then...ElseIf...Else

Comanda simplă If...Then...ElseIf...Else de mai jos, este perfectă pentru o casetă de dialog cu trei butoane.

1.  Sub Crearea_unui_Document()
2.   
3.  Dim lngButon As Long
4.  Dim strMesaj As String
5.   
6.  strMesaj = "Creati un document nou bazat pe " & _
      "VP Report project?" & vbCr & vbCr & _
      "Clic Yes pentru a folosi sablonul VP Report." & vbCr & _
      "Clic No pentru a deschide un document gol." & vbCr & _ 
      "Clic Cancel pentru a renunta la crearea unui document nou."
7.   
8.  lngButon = MsgBox _
      (strMesaj, vbYesNoCancel + vbQuestion, "Creare document nou")
9.   
10.   If lngButon = vbYes Then
11.      Documents.Add Template:= "z:\public\template\vpreport.dotm"
12.   Elself lngButon = vbNo Then
13.      Documents.Add
14.   Else 'lngButon is vbCancel
15.      End
16.   End If
17.    
18.   End Sub

Procedura Crearea_unui_Document de mai sus afișează o casetă de dialog Yes/No/Cancel care propune utilizatorului să creeze un document nou bazat pe proiectul VP Report. Utilizatorul poate alege cu butonul Yes să creeze un astfel de document, cu butonul No să creeze un document gol, sau cu butonul Cancel să închidă procedura fără crearea unui document.

Iată și descrierea comenzilor din cod:

  • Linia 1 începe procedura, iar linia 18 o încheie.
  • Linia 2 este goală, pe linia 3 se declară variabila lngButon de tip Long și pe linia 4 se declară variabila strMesaj de tip String. Linia 5 este goală.
  • Linia 6 atribuie variabile strMesaj de tip String textul pentru caseta de dialog. Linia 7 este goală.
  • Linia 8 afișează caseta de dialog, folosind strMesaj ca prompt, specificând și constanta vbYesNoCancel pentru a afișa o caseta de dialog de tip Yes/No/Cancel și titlul (Creare document nou). Rezultatul acțiunii asupra casetei de dialog este atribuit variabilei lngButon de tip Long. Linia 9 este goală.
  • Linia 10 începe cu comanda If...Then...ElseIf...Else și compară valoarea lngButon cu vbYes.

Dacă linia 10 returnează True, linia 11 folosește metoda Add a obiectului Documents pentru a adăuga un document nou bazat pe șablonul vpreport.dotm. Dacă nu, este evaluată condiția Elself de pe linia 12, care compară valoarea din lngButon cu vbNo. Dacă utilizatorul a dat clic pe butonul Yes de pe caseta de dialog, VBA caută șablonul numit vpreport.dotm în folderul z:\public\template\ pentru a putea rula comanda de pe linia 11. Dacă șablonul nu există, este afișat un mesaj de eroare. Aici se poate modifica calea și numele fișierului din cod, pentru a accesa un fișier șablon.

  • Dacă a doua comparație returnează True, linia 13 folosește metoda Add a obiectului Documents pentru a crea un document nou. Dacă nu, este activată comanda Else de pe linia 14 pentru că utilizatorul trebuie să fi ales butonul Cancel din caseta de dialog. Comanda End de pe linia 15 încheie executarea procedurii.
  • Linia 16 încheie comanda If. Linia 17 este goală.

Acest exemplu este puțin neobișnuit deoarece comanda Else este limitată la trei opțiuni, pentru că acesta este numărul maxim de răspunsuri posibile pentru o casetă de dialog—Yes, No și Cancel.

Deoarece comanda If verifică răspunsul vbYes și comanda Elself verifică răspunsul vbNo, doar răspunsul vbCancel va fi ales pentru comanda Else.

În alte circumstanțe, comanda Else este folosită pentru orice nu este prins de declarațiile If și Elself de deasupra lui Else, deci mai întâi se verifică dacă instrucțiunile If și Elself acoperă toate situațiile care trebuie evaluate înainte de a ajunge la instrucțiunea Else. Așadar, instrucțiunea Else se află în partea de jos a blocului.

De exemplu, dacă utilizatorul este întrebat care sunt culorile steagului României, trebuie furnizate instrucțiuni If și Elself pentru roșu, galben și albastru. Dacă se omite, de exemplu, alb (una dintre posibilități) și culoarea albă pentru utilizator, codul va trece la instrucțiunea Else, care ar putea afișa un mesaj incorect, cum ar fi „Culoarea aleasă nu este pe steag."

O comandă If...Then...ElseIf fără condiția Else

Se poate utiliza o instrucțiune If ... Then ... ElseIf fără condiția Else atunci când nu este necesară o altă opțiune dacă niciuna dintre condițiile din instrucțiunea If nu returnează True. În exemplul precedent, situația a avut trei rezultate clar definite: Utilizatorul poate alege butonul Yes, butonul No sau butonul Cancel din caseta de mesaje. Așadar, s-a putut folosi o condiție If pentru a testa dacă utilizatorul a ales butonul Da, o condiție ElseIf pentru a testa dacă utilizatorul a ales butonul No și o condiție Else pentru a testa dacă nu a fost ales niciunul (ceea ce înseamnă că a fost ales butonul Cancel). (Clic pe butonul Close [X] din bara de titlu a unei căsuțe de mesaje este echivalentul alegerii butonului Cancel din caseta de mesaje.)

Ca exemplu de situație în care nu trebuie acționat în niciun fel dacă nici o condiție nu este adevărată, se ia în considerare instrucțiunea If din procedura Verificare_Parola de mai jos. Această procedură verifică dacă parola introdusă de un utilizator pentru a proteja un articol are lungimea adecvată.

Nu se acționează în niciun fel dacă nicio condiție nu este adevărată

1. Sub Verificare_Parola()
2. 
3.  Dim strParola As String
4. 
5.  ParolaGresita:
6.  
7.  strParola = InputBox _
      ("Introduceti parola pentru a proteja acest element la modificari:", "Parola")
8.        
9.   If Len(strParola) = 0 Then
10.    End
11.  ElseIf Len(strParola) < 6 Then
12.   MsgBox "Parola aleasa este prea scurta." & vbCr _
      & vbCr & "Alegeti o parola cu lungimea " & _
      "intre 6 si 15 caractere.", _ vbOKOnly + vbCritical, "Parola scurta"
13.   GoTo ParolaGresita
14.   Elself Len(strParola) > 15 Then
15.   MsgBox "Parola aleasa este prea lunga." & vbCr & vbCr & "Alegeti o parola cu lungimea " & _
      "intre 6 si 15 caractere.", vbOKOnly + vbCritical, "Parola lunga"
16.   GoTo ParolaGresita
17.   End If
18.    
19.   End Sub

Această procedură forțează utilizatorul să introducă o parolă lungă de 6-15 caractere. Iată ce se petrece:

  • Linia 1 începe procedura, iar linia 19 o încheie.
  • Linia 2 este goală, iar linia 3 declară variabila strParola de tip String.
  • Linia 4 este goală. Linia 5 conține o etichetă (label), ParolaGresita, la care VBA va sări în buclă dacă parola introdusă de utilizator este necorespunzătoare. Linia 6 este goală.
  • Linia 7 afișează o casetă pentru introducere date care cere utilizatorului să introducă parola, pe care VBA o stochează în variabila strParola. Linia 8 este goală.
  • Linia 9 verifică variabila strParola pentru a vedea dacă lungimea parolei este zero, adică un șir gol. Acest lucru se întâmplă dacă utilizatorul a făcut clic pe butonul Cancel sau pe butonul OK fără a introduce text în câmpul respectiv. Una din cele două acțiuni determină VBA să comute la linia 10, unde execută comanda End care încheie executarea procedurii.
  • Dacă lungimea variabilei strParola nu este zero (adică utilizatorul a introdus text și a dat clic pe butonul OK), clauza If de pe linia 9 returnează False iar VBA sare pe linia 11, unde verifică dacă lungimea variabilei strParola este mai mică decât șase caractere.
  • Dacă lungimea variabilei strParola are mai puțin de 6 caractere, VBA execută codul de pe liniile 12 și 13. Linia 12 afișează un mesaj care îi spune utilizatorului că parola este prea scurtă și specifică care trebuie să fie lungimea parolei. Această casetă de informare conține doar butonul OK, deci când utilizatorul face clic pentru a continua, VBA continuă pe linia 13, apoi executarea sare la eticheta ParolaGresita de pe linia 5. De aici, procedura se repetă, afișând din nou caseta de introducere a parolei, pentru a încerca din nou.
  • Dacă variabila strParola are 6 sau mai multe caractere, executarea trece de pe linia 11 la a doua clauză ElseIf de pe linia 14, unde VBA verifică dacă lungimea strParola depășește 15 caractere.
  • Dacă lungimea strParola este mai mare decât 15 caractere, VBA execută codul de pe liniile 15 și 16: Linia 15 afișează un mesaj (din nou doar cu butonul OK) care informează utilizatorul că parola este prea lungă, iar de pe linia 16 se sare execuția procedurii la eticheta ParolaGresita, afișând din nou caseta de introducere a parolei.

În acest caz, nu mai este nevoie de încă o comandă Else pentru că utilizatorul a furnizat o parolă care nu îndeplinește condițiile clauzelor If sau ElseIf, iar execuția trece de blocul If și continuă pe linia de după comanda End If.

Crearea de bucle cu If și GoTo

Se pot construi bucle cu comenzile If și GoTo, ca în exemplul anterior.

Dar mulți profesori și programatori nu recomandă buclele cu If și GoTo. Este o practică proastă, deoarece buclele If...GoTo pot crea „codul spaghetti” (căi de execuție care se realizează într-un mod aleatoriu și sunt greu de prevăzut). Astfel de căi pot fi nu doar nepotrivite, ci și un coșmar pentru depanare.

Cu toate acestea, versiunile simple ale buclelor If și GoTo pot funcționa perfect. Folosirea sau nu a comenzii GoTo în cod poate fi o preferință personală sau depinde de politica companiei sau convingerile profesorului.

Mai jos este descris modul în care poate fi utilizat GoTo.

SINTAXĂ

Declarația GoTo este simplă și poate fi utilă. Sintaxa este următoarea:

GoTo line

Aici, argumentul line poate fi o etichetă (sau, mai rar, numărul unei linii) din procedura curentă.

Numărul unei linii este numărul care se află la începutul liniei, pentru a o identifica. De exemplu, iată o demonstrație a comenzii GoTo:

Sub Demo_of_GoTo()
1
If MsgBox("Go to line 1?", vbYesNo) = vbYes Then GoTo 1 
End If 
End Sub

A doua linie conține aici doar numărul liniei, 1, care identifică linia. A treia linie afișează un mesaj care oferă o alegere de a trece înapoi pe linia 1; dacă utilizatorul face clic pe butonul Yes, VBA execută comanda GoTo 1 și revine la linia etichetată cu 1, după care afișează din nou mesajul. (Dacă utilizatorul alege butonul No, VBA iese din blocul If.)

Cu toate acestea, se recomandă folosirea unei etichete în locul unui număr pentru o linie. Eticheta de linie este un nume pentru o anumită linie. O etichetă începe cu o literă și se termină cu două puncte. Între literă și cele două puncte, eticheta poate consta din orice combinație de caractere. De exemplu, mai sus a fost folosită eticheta ParolaGresita:, pentru a face bucla înapoi la o etapă anterioară într-o procedură atunci când au fost îndeplinite anumite condiții. Poate că exemplul chintesențial al unei etichete este Bye: eticheta plasată în mod tradițional la sfârșitul unei proceduri de utilizare cu această declarație GoTo:

GoTo Bye

Când această etichetă este plasată chiar deasupra comenzii EndSub, pur și simplu iese din macrocomandă.

GoTo este de obicei utilizat cu o condiție. Dacă se folosește fără o condiție pentru a reveni în cod la o linie anterioară comenzii GoTo, se poate creea o buclă infinită. Și dacă se folosește declarația GoTo Bye fără o condiție, procedura se oprește - nu va fi executată nicio declarație care se află după această linie. Se sare direct la sfârșitul macrocomenzii.

EXEMPLU

Ca exemplu al comenzii GoTo cu o condiție, se poate folosi comanda GoTo Bye împreună cu o casetă mesaj care să întrebe dacă utilizatorul dorește ca să se execute o anumită procedură:

Response = MsgBox("Doriti crearea unui raport zilnic" & _
  "din documentul curent?", _ 
  vbYesNo + vbQuestion, "Creare Raport Zilnic")
If Response = vbNo Then GoTo Bye

Dacă utilizatorul face clic pe butonul No din caseta mesaj, VBA execută comanda GoTo Bye, comutând la eticheta Bye: care se află la sfârșitul subrutinei.

Un alt motiv bun pentru a evita utilizarea numerelor de linie ca țintă este că, ulterior, se pot insera anumite coduri înainte de linia țintă, lucru care ar putea duce la o eroare (deoarece numărul corect al liniei țintă se schimbă din cauza adăugării de linii noi).

Blocuri If imbricate

Blocurile If pot fi imbricate (nested) sau puse unul în altul pentru a gestiona eventualele modificări necesare din cod. Fiecare bloc If imbricat trebuie să fie complet în sine. (Aceasta înseamnă că fiecare bloc imbricat trebuie să înceapă cu un If și să se încheie cu propriul său End If.)

De exemplu, dacă se introduce un bloc If în interiorul altui bloc If (dar fără pune End If-ul care încheie If-ul imbricat), VBA presupune că linia End If pentru If-ul exterior încheie If-ul imbricat.

Pentru a face blocurile mai ușor de citit, se recomandă aranjarea lor pe diferite niveluri. Acest lucru este deosebit de important atunci când sunt mai multe blocuri imbricate. Indentarea oferă indicii vizuale, făcând clară linia If asociată cu linia End If. Cu alte cuvinte, indentarea face ca diferitele blocuri If să iasă în evidență.

Exemplul de mai jos arată cum se face pot imbrica mai multe comenzi If:

1. If conditie1 Then 'incepe primul If
2.      If conditie2 Then 'incepe al doilea If
3.            If conditie3 Then 'incepe al treilea If
4.               instructiuni1
5.            ElseIf conditie4 Then 'ElseIf pentru al treilea If
6.               instructiuni2
7.            Else 'Else pentru al treilea If
8.               instructiuni3
9.            End If 'End If pentru al treilea If
10.      Else 'Else pentru al doilea If
11.          If conditie5 Then 'incepe al patrulea If
12.             instructiuni4
13.          End If 'End If pentru al patrulea If
14.      End If 'End If pentru al doilea If
15. Else 'Else pentru primul If
16.     instructiuni5
17. End If 'End If pentru primul If

Astfel, se poate urmări cu ușurință fluxul de execuție. De exemplu, dacă condiția1 din linia 1 este False, VBA se ramifică la instrucțiunea Else din linia 15 și continuă execuția de acolo. Dacă condiția1 de pe linia 1 este adevărată, VBA evaluează condiția2 de pe linia 2 și așa mai departe.

Indentarea este doar pentru claritatea vizuală. Înlesnește înțelegerea codului pentru oameni - VBA nu-i acordă atenție. Comenzile anterioare imbricate If sunt, de asemenea, adnotate cu comentarii, astfel încât să se poată vedea care linie Else, ElseIf și End If corespunde liniei If. Însă, după indentare, comentarea nu este necesară.

Prin contrast, se poate vedea și versiunea fără indentări pentru blocurile imbricate. Această versiune este dificil de urmărit pentru oameni - mai ales atunci când sunt adăugate și alte linii de cod:

1.   If conditie1 Then
2.   If conditie2 Then
3.   If conditie3 Then
4.   instructiuni1
5.   ElseIf conditie4 Then
6.   instructiuni2
7.   Else
8.   instructiuni3
9.   End If
10.  Else
11.  If conditie5 Then
12.  instructiuni4
13.  End If
14.  End If
15.  Else                           '
16.  instructiuni5
17.  End If

Rareori este nevoie urgentă să fie imbricate mai multe blocuri If. Adesea, trebuie imbricată doar o instrucțiune If ... Then într-o instrucțiune If ... Then ... Else sau în cadrul unei instrucțiuni If...Then...ElseIf... Else. Iată arată un exemplu din Word.

Imbricarea unui bloc If...Then

1. Selection.HomeKey Unit:=wdStory
2. Selection.Find.ClearFormatting
3. Selection.Find.Style = ActiveDocument.Styles("Heading 5")
4. Selection.Find.Text = " "
5. Selection.Find.Execute
6. If Selection.Find.Found Then
7. lngResponse = MsgBox("Transform in stilul nota speciala?", vbOKCancel, "Transformare Special Note")
8.       If IngResponse = vbOK Then
9.           Selection.Style = "Special Note"
10.      End If
11. End If

Codul de mai sus caută în documentul activ text scris cu stilul Heading 5 și când îl găsește, afișează un mesaj care se oferă să modifice stilul în Special Note aplicând stilul Special Note. Iată etapele care au loc:

  • Linia 1 mută punctul de inserție la începutul documentului.
  • Linia 2 șterge formatarea din comanda Find (pentru a se asigura că nu se caută o anumită formatare).
  • Linia 3 setează Heading 5 ca stil pentru comanda de căutare Find, iar linia 4 setează șirul de căutare ca șir gol (" ").
  • Linia 5 execută operațiunea Find.
  • Liniile de la 6 până la 11 conțin bucla If...Then. Linia 6 verifică dacă operațiunea Find de pe linia 5 a găsit un paragraf în stil Heading 5. Dacă a găsit, VBA execută codul de pe liniile de la 7 până la 10.
  • Linia 7 afișează un mesaj care întreabă utilizatorul dacă vrea să modifice paragraful într-o notă specială.
  • Linia 8 începe comanda imbricată If...Then și verifică răspunsul utilizatorului din caseta mesaj.
  • Dacă răspunsul utilizatorului este vbOK—adică utilizatorul a ales butonul OK, VBA execută comanda de pe linia 9, care înlocuiește stilul Heading 5 cu stilul Special Note (care se presupune că este inclus în stilurile valabile în documentul curent sau în șablon).
  • Linia 10 conține comanda End If pentru comanda If...Then imbricată, iar linia 11 conține comanda End If pentru blocul exterior If...Then.

În cazul în care un document conține mai mult de o instanță a stilului Heading 5, se poate folosi o buclă Do While...Loop pentru a căuta fiecare instanță.

Blocurile Select Case

Blocul Select Case oferă o alternativă la blocurile multiple If...Then sau la comenzile ElseIf. Select Case combină posibilitatea de luare a deciziei a construcțiilor If cu un cod mai simplu.

Comanda Select Case se folosește atunci când decizia care trebuie luată este complicată, deoarece implică mai mult de două sau trei valori diferite care sunt evaluate.

Blocurile Select Case sunt mai ușor de citit decât blocurile If...Then complexe, mai ales pentru că există mai puțin cod. Astfel, blocurile Select Case sunt mai ușor de modificat: atunci când trebuie ajustate una sau mai multe valori, este mai puțin cod de eliminat.

Sintaxă

Sintaxa pentru Select Case este următoarea:

Select Case ExpresieDeTestat 
    Case Expresie1 
      Instructiuni1
    [Case Expresie2 
      Instructiuni2]
    [Case Else 
      InstructiuniPentruElse]
End Select

Iată cum funcționează sintaxa:

  • Select Case începe blocul, iar End Select o încheie.
  • ExpresieDeTestat este expresia care determină care dintre instrucțiunile Case este executată.
  • Expresie1, Expresie2 etc sunt expresiile pe care VBA le verifică în ExpresieDeTestat.

De exemplu, se poate testa pentru a vedea butoanele care au fost alese dintr-un formular al utilizatorului. ExpresieDeTestat este legată de un anumit buton; dacă este ales primul buton, VBA alege Expresie1 și execută declarațiile din rândurile următoare Case Expresie1; dacă este ales al doilea buton, VBA alege Expresie2 și execută declarațiile din rândurile care urmează în cazul Expresie2; și așa mai departe pentru restul blocurilor Case.

Cazul Else este similar cu clauza Else din blocul If. Case Else este o clauză opțională care (dacă este inclusă) este executată dacă niciuna dintre expresiile de mai sus nu se potrivește.

Exemplu

Ca și exemplu pentru blocul Select Case, se consideră codul de mai jos, care cere utilizatorului să introducă viteza de tastare, apoi afișează un răspuns corespunzător.

1. Sub Verificare_Viteza_De_Tastare()
2.       
3.   Dim varVitezaTastare As Variant
4.   Dim strMsg As String
5.       
6.   varVitezaTastare = InputBox _
        ("Cate cuvinte puteti tasta pe minut?", "Viteza de tastare")
7.      Select Case varVitezaTastare
8.      Case " "
9.        End
10.    Case Is < 0, 0, 1 To 50
11.      strMsg = "va recomandam sa invatati sa tastati mai rapid " & _ 
                     "inainte de a aplica la un job."
12.    Case 50 To 60
13.       strMsg = "Se poate si mai rapid. "
14.    Case 60 To 75
15.    strMsg = "Viteza de tastare este multumitoare."
16.    Case 75 To 99
17.    strMsg = "Viteza de tastare e mai mult decat adecvata. "
18.    Case 100 To 200
19.    strMsg = "Viteza este foarte buna."
20.    Case Is > 200
21.    strMsg = "Nu cred ca se poate tasta asa de rapid."
22.    End Select
23.     
24.    MsgBox strMsg, vbOKOnly, "Viteza de tastare "
25.     
26.    End Sub

Iată ce se petrece în procedura Verificare_Viteza_De_Tastare de mai sus:

  • Linia 1 începe procedura, iar linia 26 o încheie.
  • Linia 2 este goală. Linia 3 declară variabila varVitezaTastare de tip Variant, iar linia 4 declară variabila strMsg de tip String. Linia 5 este goală.
  • Linia 6 afișează o casetă de dialog care cere utilizatorului să introducă viteza de tastare. Stochează valoarea în variabila varVitezaTastare.
  • Linia 7 începe blocul Select Case, care preia variabila varVitezaTastare.
  • Apoi, VBA evaluează fiecare clauză Case în parte, până găsește una care returnează True.

Prima clauză Case, de pe linia 8, compară varVitezaTastare cu șirul gol (" ") pentru a vedea dacă utilizatorul alege butonul Cancel sau butonul OK fără a introduce o valoare în caseta text. Atunci când Case " " este True, VBA execută comanda End de pe linia 9, încheind procedura.

  • Dacă Case " " este False, VBA trece la următoarea clauză Case - linia 10 din acest exemplu - unde compară varVitezaTastare cu trei elemente: mai mic decât 0 (Is < 0), apoi 0 și de la 1 la 50 de cuvinte pe minut. Aici se pot observa trei lucruri:
      1. Se pot include mai multe elemente de comparare în aceeași comandă Case care se separă unele de altele prin virgule.
      2. Folosirea cuvântului cheie Is cu operatorul de comparare (aici, operatorul mai mic - less than) verifică relația dintre două numere.
      3. Cuvântul cheie To denotă intervalul de valori.
  • Dacă varVitezaTastare se potrivește cu unul dintre elementele de comparare de pe linia 10, VBA atribuie variabilei strMsg de tip String textul de pe linia 11 apoi continuă execuția pe linia de după comanda End Select.
  • Dacă varVitezaTastare nu se află în interval, VBA trece la următoarea clauză Case și o evaluează. Atunci când VBA găsește o clauză Case care returnează True, execută comanda de după acea clauză (în acest caz, atribuie un șir text variabilei strMsg) apoi continuă cu executarea liniei de după comanda End Select.
  • Pentru orice situație cu excepția celei de pe linia 8 (care încheie procedura), linia 24 afișează un mesaj care conține textul stocat în strMsg.

Un bloc Select Case poate fi o modalitate bună de a specifica o anumită acțiune, în funcție de alegerea pe care o face utilizatorul într-un control de tip ListBox sau ComboBox.

De obicei, controalele ListBox sau ComboBox afișează o listă cu multe opțiuni diferite, de exemplu județele dintr-o țară. După ce utilizatorul face clic pentru a selecta un element dintr-un control ListBox sau ComboBox, elementul ales apare în proprietatea Value a controlului. Apoi, macrocomanda poate să verifice această proprietate Value ca pe o expresie de testare în blocul Select case și să acționeze în consecință.

Atunci când contează ordinea elementelor

Încă ceva despre structurile complexe de testare. Se verifică dacă în comenzile Select Case și If...Then...Else (sau alte structuri multiple If) condițiile de testare sunt evaluate în ordinea corespunzătoare. Aceasta înseamnă că fiecare condiție care trebuie evaluată trebuie să excludă toate condițiile care o urmează.

De exemplu, se întreabă utilizatorul ce vârstă are și cazurile de testare sunt configurate astfel:

1. Varsta = InputBox ("Ce varsta ai?")
2. 
3. Select Case Varsta
4. 
5. Case < 50
6.   strMsg = "Esti aproape de pensie."
7. 
8. Case < 12
9. strMsg = "Salut, tinere."

Aici, codul este greșit. Linia 8 nu va fi executată niciodată pentru că un număr mai mic decât 50, include și numărul 12, deci va fi executată doar comanda de pe linia 5. (Expresia "mai mic decât 50" include "mai mic decât 12.")

Pentru ca să fie corect, codul trebuie scris invers, astfel:

Case < 12
   strMsg = "Salut, tinere."
Case < 50
   strMsg = " Esti aproape de pensie."

Această problemă se poate evita prin testarea egalității sau a intervalului, ca mai sus:

Case 50 To 60