Şerban CRIŞCOTĂ
Programarea în VISUAL BASIC for Application
CUPRINS CAP.I ELEMENTELE DE BAZA ALE LIMBAJULUI DE PROGRAMARE VBA - VISUAL BASIC FOR APPLICATION I-5 I.1. Noiuni generale despre VBA.............................................................................................................. I-5
I.1.1. Utilizarea limbajului de programare VBA....................................................................................... I-5 I.1.2. Necesitatea utilizării codului VBA în aplicaii Access.................................................................... I-5 I.1.3. Modulele de cod VBA în Access..................................................................................................... I-6 I.1.4. Elementele generale ale limbajului VBA ........................................................................................ I-7 I.1.5. Structura rutinelor VBA .................................................................................................................. I-7 I.1.6. VBA – mediul de dezvoltare şi depanare ........................................................................................ I-7 I.2. Tipuri de date ..................................................................................................................................... I-12
I.2.1. Tipuri de date elementare .............................................................................................................. I-12 I.2.1.1.Date
numerice întregi ..............................................................................................................................I-12 numerice reale.................................................................................................................................I-12 I.2.1.3.Tipul de date BOOLEAN – logic..............................................................................................................I-12 I.2.1.4.Tipul de date STRING – şir de caractere.................................................................................................I-13 I.2.1.5.Tipul de date DATE – data calendaristică şi timpul ................................................................................I-14 I.2.1.2.Date
I.2.2. Tipuri de date structurate............................................................................................................... I-14 I.2.2.1.Tipul I.2.2.2.TYPE
de date ARRAY – tablou..................................................................................................................I-14 – Crearea tipurilor de date definite de utilizator...........................................................................I-14
I.2.3. Tipul de date VARIANT ............................................................................................................... I-15 I.3. Variabile.............................................................................................................................................. I-16
I.3.1. Declararea variabilelor................................................................................................................... I-16 I.3.2. Caractere folosite ca Type-declaration .......................................................................................... I-16 I.3.3. Option Explicit (declararea explicită a variabilelor)...................................................................... I-16 I.3.4. Variabile Locale şi Globale ........................................................................................................... I-17 I.3.5. Variabile Publice şi Private ........................................................................................................... I-18 I.3.6. Variabile Statice ............................................................................................................................ I-18 I.3.7. Variabile – domeniul şi durata de valabilitate ............................................................................... I-19 I.3.8. Declararea şi folosirea variabilelor ARRAY................................................................................. I-19 I.4. Constante ............................................................................................................................................ I-21 I.5. Limbajul VBA – Instruciuni executabile........................................................................................ I-22
I.5.1. Instruciunea de atribuire ............................................................................................................... I-22 I.5.2. Structurile de control ..................................................................................................................... I-24 I.5.2.1.Structura
secvenială ................................................................................................................................I-24 alternativă ................................................................................................................................I-24 I.5.2.2.a)Structura alternativă simplă ...............................................................................................................I-24 I.5.2.2.b)Structura alternativă multiplă ............................................................................................................I-25 I.5.2.3.Structura repetitivă ..................................................................................................................................I-27 I.5.2.3.a)Structura repetitivă cu test. Instruciunea Do…Loop........................................................................I-27 I.5.2.3.b)Structura repetitivă cu contor. Instruciunea For…Next ...................................................................I-28 I.5.2.2.Structura
I.6. Rutine – proceduri şi func ii ............................................................................................................. I-29
I.6.1. Ce este o rutină şi ce elemente o definesc?.................................................................................... I-29 I.6.2. Transmiterea datelor prin parametri .............................................................................................. I-30 I.6.3. Crearea (definirea) unei rutine....................................................................................................... I-31 I.6.3.1.Proceduri
(Subrutine) ..............................................................................................................................I-31
I.6.3.2.Funcii......................................................................................................................................................I-32
I.6.4. Apelarea unei rutine....................................................................................................................... I-32 I.6.4.1.Apelarea I.6.4.2.Apelarea
unei proceduri (subrutine)........................................................................................................I-32 unei funcii................................................................................................................................I-33
I.6.5. Domeniul de vizibilitate al rutinelor.............................................................................................. I-33 I.6.6. Durata de viaă a rutinelor ............................................................................................................. I-33 I.6.7. Rut in e def in it e de ut il iza tor . Int rod uce rea cod ulu i VBA ............................................ I-33 I.6.8. Procedurile evenimentelor............................................................................................................. I-34 I.6.9. Utilizarea combinată a procedurilor eveniment cu rutinele utilizator ........................................... I-35 I.6.10. Parametri opionali ...................................................................................................................... I-36 I-2
I.7. Biblioteci standard de proceduri şi func ii ...................................................................................... I-36
I.7.1. Funcii matematice ........................................................................................................................ I-37 I.7.1.1.Int(număr);
Fix(număr) ...........................................................................................................................I-37
I.7.1.2.Abs(num ăr)...............................................................................................................................................I-37 I.7.1.3.Sgn(număr)...............................................................................................................................................I-37 I.7.1.4.Sqr(număr)...............................................................................................................................................I-38 I.7.1.5.Exp(număr) ..............................................................................................................................................I-38 I.7.1.6.Log(număr) ..............................................................................................................................................I-38 I.7.1.7.Rnd
[(număr)] ..........................................................................................................................................I-38 ...............................................................................................................................................I-39 I.7.1.9.Cos(număr) ..............................................................................................................................................I-39 I.7.1.10.Tan(număr) ............................................................................................................................................I-39 I.7.1.11.Atn(număr).............................................................................................................................................I-39 I.7.1.12.Calculul funciilor matematice derivate.................................................................................................I-39 I.7.1.8.Sin(număr)
I.7.2. Funciile TEXT – pentru stringuri ................................................................................................. I-39 I.7.2.1.
Asc(string)................................................................................................................................................I-39 I.7.2.2.Chr(CodCaracter)....................................................................................................................................I-40 I.7.2.3.AscB(string);
AscW(string); ChrB(CodCh); ChrW(CodCh).................................................I-40 ...........................................................................................................................................I-40 I.7.2.5.UCase(string)...........................................................................................................................................I-41 I.7.2.6.LTrim(string); RTrim(string); Trim(string) .............................................................................................I-41 I.7.2.7.Len(String | NumeVariabila)....................................................................................................................I-41 I.7.2.8.Left(string, lungime).................................................................................................................................I-41 I.7.2.9.Right(string, lungime) ..............................................................................................................................I-42 I.7.2.10.Mid(string, start [,lungime])..................................................................................................................I-42 I.7.2.11.InStr([start,]string1,string2[,compare])................................................................................................I-43 I.7.2.12.String(număr,caracter) ..........................................................................................................................I-43 I.7.2.13.Space(număr).........................................................................................................................................I-43 I.7.2.14.Format(expresie[,format]).....................................................................................................................I-44 I.7.2.4.LCase(string)
I.7.3. Funcii pentru tablouri (array) - UBound şi LBound..................................................................... I-45 I.7.4. Funcii de conversie....................................................................................................................... I-45 I.7.4.1.Str(Număr) ...............................................................................................................................................I-45 I.7.4.2.Val(string) ................................................................................................................................................I-45
I.7.5. Funcii pentru mesaje..................................................................................................................... I-46 I.7.5.1.MsgBox(prompt[,buttons][,title]) ............................................................................................................I-46 I.7.5.2.InputBox(prompt[,title][,default][,X][,Y])...............................................................................................I-47
I.7.6. Funcii cu tipul: Date/ Time........................................................................................................... I-48 I.7.6.1.DatePart(interval,date)............................................................................................................................I-48 I.7.6.2.DateDiff(interval,date1,date2).................................................................................................................I-48 I.7.6.3.DateAdd(interval,number,date) ............................................................................................................... I-49 I.7.6.4.Day(date);
Month(date); Year(date)........................................................................................................I-49 Minute(date); Hour(date) .................................................................................................I-49 I.7.6.6.Now(); Date(); Time()..............................................................................................................................I-49 I.7.6.7.DateSerial(year, month, day)...................................................................................................................I-49 I.7.6.8.TimeSerial(hour, minute, second) ............................................................................................................I-49 I.7.6.5.Second(date);
I.7.7. Funcii: structuri de control ........................................................................................................... I-50 I.7.7.1.IIf(condiie,
TruePart, FalsePart)............................................................................................................I-50 caz-1[,caz-2,... [,caz-n]]) .................................................................................................I-50 I.7.7.3.Switc h(ex pr-1 ,val ue-1 [,e xpr-2 ,val ue-2 … [,ex pr-n ,val ue-n] ]..] )................................................I-50 I.7.7.2.Choose(index,
I.7.8. Funcii de inspecie........................................................................................................................ I-51 I.7.8.1.IsNull(expresie)........................................................................................................................................I-51 I.7.8.2.IsEmpty(NumeVariabila) .........................................................................................................................I-51 I.7.8.3.IsMissing(NumeParametru).....................................................................................................................I-51 I.7.8.4.VarType(NumeVariabilă).........................................................................................................................I-52
I.7.9. Funciile agregate SQL.................................................................................................................. I-52 I.7.10. Funciile agregate de domeniu..................................................................................................... I-53
I-3
I-4
Cap.I Elementele de bază ale limbajului de Basic for Application
programare VBA - Visual
I.1. Noiuni generale despre VBA I.1.1. Utilizarea limbajului de programare VBA Basic este unul din cele mai vechi limbaje de programare. El a fost creat în ideea de a se realiza un limbaj de programare necesar unui specialist dintr-un anumit domeniu, care nu are cunoştine aprofundate despre sistemele de calcul. Basic a fost implementat iniial, în sistemele de operare, ca un interpretor, adică ca un sistem care în momentul în care preia o instruciune sursă Basic, o transformă imediat în instruciuni obiect (cod maşină) şi le execută. Pentru a îl face cât mai accesibil, au existat variante de Basic care au implementat şi comenzi specifice unui sistem de operare, ajungându-se până la a se realiza calculatoare dedicate pentru lucrul sub Basic, fără sisteme de operare. Evident, fiind conceput pe aceste principii, aplicaiile realizate nu erau performante, ele neutilizând eficient facilităile unui sistem de calcul. Treptat, s-a trecut la realizarea unor implement ări, tehnic mai performante, prin realizarea de compilatoare pentru Basic sub diferite sisteme de operare, adică a unor module care transformă un fişier cu instruciuni sursă Basic într-un fişier care conine instruciuni direct executabile, în cod obiect. În felul acesta s-au separat cele două aciuni efectuate de un interpretor în acelaşi timp şi anume: compilarea programului sursă şi execuia programului obiect. Firma Microsoft a realizat o versiune de Basic, numită Visual Basic, care pe lângă principiile iniiale s-a dorit a rezolva următoarea problemă – un limbaj de programare universal, unic, care să poată fi folosit atât în aplicaiile de sistem (în locul limbajului C) cât şi în cele utilizator, performant atât din punct de vedere al limbajului (implementând conceptele de programare modulară , programare structurată şi programare la nivel de obiect) cât şi din punct de vedere al utilizării tuturor facilităilor sistemului de operare. Astfel s-au creat, pe baza aceluia şi nucleu de programareBasic, trei sisteme: Microsoft Visual Basic (VB), ca limbaj universal de programare; Visual Basic for Application (Visual Basic pentru aplicaii), prescurtat uzual VBA, ca un limbaj complex pentru dezvoltarea aplicaiilor în cadrul programelor din Microsoft Office. Aceasta înseamnă că nucleul limbajului, componentele sale şi mediul sunt aceleaşi în Access, Word sau Excel. VBA este aproape identic cu limbajul universal de programare Microsoft Visual Basic; Visual Basic Script (VB Script), utilizat în special pentru aplicaiile Internet.
I.1.2. Necesitatea utiliz
ă rii codului VBA în aplica
ţ ii Access
Aplicaiile mai simple din Access pot fi scrise fără a fi nevoie de vreo instruc iune, eventual folosind comenzile macro. Deşi comenzile macro sunt foarte bune pentru rezolvarea rapid ă a unor prelucrări necesare pentru dezvoltarea majorităii aplicaiilor de bază, realizarea unor aplicaii complexe, profesioniste în Access se face folosind limbajul VBA. Acest lucru se datorează faptului că, spre deosebire de comenzile macro, VBA oferă posibilităi de lucru specifice limbajelor de nivel înalt de programare orientată pe obiecte. Câteva dintre aceste posibilităi sunt: • tratarea erorilor prin proceduri speciale create de proiectant. În timpul execu iei unei aplicaii pot interveni diverse erori (de exemplu o împărire la zero sau ieşirea din domeniul de definiie al unei variabile etc.) pe care sistemul le tratează în general prin stoparea modulului unde apar sau chiar a întregii aplicaii. VBA oferă posibilitatea ca la apariia unei erori, controlul să fie dat unui modul de cod VBA, realizat de proiectant, care să rezolve în funcie de context situaia apărută, fără a mai fi necesară stoparea modulului respectiv sau a aplicaiei. • crearea unor structuri ciclice pentru parcurgerea seturilor de înregistr ări. Datele unei tabele sau cereri de selecie se pot manipula ca pe un fi şier specific, numit set de înregistrări; • execuia proceselor tranzacionale. Acestea reprezintă practic posibilitatea de a efectua actualizările într-un set de înregistrări, global, la un anumit moment. În cazul apari iei unei erori se pot anula toate actualizările din procesul respectiv, setul de înregistrări rămânând nemodificat; • apelarea funciilor Windows API, prin care se pot folosi module ale sistemului de operare; I-5
utilizarea variabilelor, constantelor şi a literalilor; crearea şi manipularea prin program a obiectelor necesare aplicaiei; • crearea de clase de obiecte; De asemenea VBA uşurează scrierea bibliotecilor de funcii reutilizabile, precum şi proiectarea şi depanarea proceselor complexe de către programatori. În concluzie, deşi comenzile macro pot da soluii rapide problemelor simple, limitările lor determină necesitatea folosirii limbajului VBA pentru dezvoltarea soluiilor mai complexe. • •
I.1.3. Modul ele de c od V BA î n Access
Codul VBA este scris în unităi numite rutine, care pot fi proceduri (subrutine) sau funcii. Aceste proceduri şi funcii sunt păstrate în obiecte numite module de cod, şi anume: Module specifice unui anumit formular sau raport. Modulele specifice unui formular sau raport sunt în general numite coduri din spatele formularelor (Code Behind Forms – CBF). Rutinele din acest loc pot fi vizibile (cunoscute, apelabile) doar din modulul respectiv de cod. Codul din spatele formularului sau raportului se poate accesa prin acionarea pictogramei specifice codului VBA (după selecia obiectului respectiv) sau prin apăsarea celor trei puncte (…) din dreptul unui eveniment al paginii respective a unui obiect aparinând formularului sau raportului respectiv. Dacă procedura eveniment nu este creată, atunci automat un Wizard va crea structura acesteia, adic ă instruciunile de declarare şi sfârşit precum şi completarea listei de parametri dacă este cazul. Dacă procedura eveniment a fost creată anterior, atunci se va afişa poriunea din pagina de cod a formularului sau raportului care conine respectiva procedură. Modulele globale (generale), se pot afişa prin acionarea paginii Module, din fereastra Database. Foarte important este faptul că rutinele scrise în această zonă pot fi vizibile (dacă sunt declarate Public) nu numai din toate modulele de cod ale aplica iei, dar chiar din obiecte ale aplica iei, din formulare, rapoarte, cereri sau tabele. Exemplu. Dacă în modulul global se găseşte o funcie declarată public, cu numele 'Prag', aceasta va putea fi folosită în expresii din orice: − modul general sau din spatele unui formular sau raport; − controale calculate din formulare sau rapoarte; − proprietăi ale controalelor sau ale tabelelor (de exemplu Validation Rule, Default Value); − criterii din cereri; − câmpuri calculate din cereri; − practic de oriunde este acceptată o expresie. Orice modul de cod este format din două pări: În prima parte se introduc declaraiile generale ale modulului, valabile în întreg modulul. Acestea sunt: : Option Explicit, care forează declararea tuturor − Opiunile modulului. De exemplu variabilelor folosite în modul. − Declararea tipurilor, variabilelor şi constantelor , vizibile în tot modulul de cod. În a doua parte se introduc rutinele (proceduri sau funcii) modulului de cod. O procedură (subrutină) este o rutină care execută o aciune: ia unui − la apari eveniment al unui aplica − apelarea (lansarea) ei dintr-o altobiect ă rutinăalVBA ; iei; O funcie este un tip special de rutină, datorită faptului că poate întoarce o valoare, chiar în numele
ei. Deci codul VBA poate fi găsit în rapoarte, formulare şi module de cod. În formulare şi rapoarte, codul VBA poate fi plasat în rutinele (func ii sau proceduri) definite de utilizator, ca şi în procedurile eveniment, pe când în modulele generale, codul VBA este plasat numai în rutinele definite de utilizator. De fapt, pentru a construi cu succes rutine în cod VBA, sunt foarte importante dou ă lucruri: • ce determină stabilirea domeniului de vizibilitate (valabilitate) al variabilelor şi rutinelor; • cum se transmit şi se întorc valorile din rutine; I-6
În concluzie, putem spune că programarea în VBA nu este procedurală, adică nu avem de-a face cu un program clasic, cu început şi sfârşit, care rezolvă paşii unui algoritm. Codul VBA este practic format din rutine, care sunt executate numai atunci când se produc anumite evenimente. Deci codul VBA implică realizarea unui programări discontinue. I.1.4. Elementele generale ale limbajului VBA
Definirea unui limbaj de programare (ca şi a VBA) se face în general prin configurarea următoarelor elemente de bază:
tipuri de date; variabile; • constante; • instruciuni: − instruciunea de atribuire; − structuri de control; • rutine (proceduri şi funcii); • biblioteci. Dacă limbajul de programare este orientat la nivel de obiect, aşa cum este Visual Basic sau VBA, atunci trebuie definite şi elemente referitoare la: • referirea obiectelor; • crearea modulelor de clase de obiecte; • crearea şi manipularea obiectelor (instane ale claselor de obiecte); • crearea şi manipularea coleciilor de obiecte. Limbajele de programare dezvoltate mai pun la dispoziie programatorilor: • proceduri specifice de tratare a erorilor; • modalităi de verificare şi depanare a erorilor de programare; • proceduri de import/ export de obiecte exterioare aplicaiei; • interaciunea cu sistemul de operare; • manipularea datelor organizate în fişiere sau baze de date. • •
I.1.5. Struc tura ruti nelor VBA
Scrierea rutinelor se face respectând urm ătoarele reguli: • prima instruciune defineşte tipul rutinei, procedură sau funcie; • ultima instruciune executabilă este End Sub | Function; • la început se pun de obicei (dar nu este obligatoriu) instruc iunile declarative (tipuri de date, variabile, constante); • toate instruciunile au o anumită sintaxă care ine seama de numărul de rânduri pe care sunt scrise; • semnul de continuare a unui rând este format din două caractere, spaiu şi liniuă cu shift ( _ ); • semnul pentru începutul unui comentariu este apostroful ('). Sfârşitul comentariului este la sfârşitul rândului. I.1.6. VBA – medi ul de dezvol tare
ş i depanare
Odată intrat într-un modul de cod, Access oferă proiectantului de aplicaii un sistem complex pentru realizarea sistem sunt:şi asistarea activităii de programare în VBA. Printre cele mai utilizate instrumente ale acestui
Editarea rutinelor
Sunt oferite facilităile curente de editare promovate de Microsoft în produsele sale. Există şi mai multe trucuri speciale destinate activităii de programare, printre care: − recunoaşterea cuvintelor cheie ale limbajului; − afişarea listelor cu proprietăile şi metodele obiectelor utilizate; − marcarea recunoaşterii unei denumiri date de utilizator (unei variabile, rutine etc.) prin refacerea formei introduse la declararea acesteia; În VBA sistemul nu face deosebire între literele mari şi mici. Dacă la declararea unui obiect, sunt folosite combinaii de litere mari şi mici, (după anumite convenii), atunci când se vor introduce I-7
denumirile respective cu acelaşi tip de literă, sistemul va reface forma ini ială a lor. În acest fel programatorul va sesiza imediat eventualele greşeli comise la introducerea denumirii obiectelor.
Compilarea rutinelor
Există 3 comenzi de compilare (vezi figura): − compilarea întregii aplicaii şi salvarea codului obiect rezultat; − compilarea întregii aplicaii dar fără modificarea codului obiect existent; − compilarea numai a modulelor de cod deschise (înc ărcate în memorie). Prezena erorilor de compilare este marcată punctual şi este însoită de informaiile necesare unei depanări rapide. De asemenea, sistemul încă din faza de editare semnalează imediat erorile de compilare depistabile în acel moment (de exemplu cele referitoare la corectitudinea sintaxei instruciunilor).
Execuia după o comandă manuală (deci nu ca urmare a producerii unui eveniment) a rutinelor O rutină fără parametri se poate executa direct din modulul de cod. Acest lucru se face:
• prin plasarea cursorului pe instruciunea de la care se doreşte începerea execuiei; în felul acesta rutina se poate executa pornind de la oricare dintre instruciunile sale executabile; • prin acionarea uneia dintre cele 4 comenzi de RUN(vezi figura)şi anume: − Run: execuia tuturor instruciunilor rutinei (eventual şi a rutinelor apelate) fără oprire; − Step Into: execuia tuturor instruciunilor rutinei (eventual şi a rutinelor apelate) cu oprire după fiecare instruciune executată; − Step Over: execuia tuturor instruciunilor rutinei (eventual şi a rutinelor apelate) cu oprire după fiecare instruciune executată în rutina apelantă, dar fără oprire în rutinele apelate; − Step Out: execuia tuturor instruciunilor până la sfârşitul rutinei principale (apelante), dar cu oprire numai în rutinele de rang superior celei din care s-a dat această comandă; se foloseşte când se doreşte reluarea execuiei dintr-o rutină apelată, dar fără oprire la instruciunile din aceasta. În rutine se pot introduce breakpoint-uri (puncte de oprire) printr-un click pe marginea formularului modulului de cod în dreptul instruciunii pe care se doreşte oprirea execuiei. Acest marcaj se vizualizează printr-un punct de culoare maro. Ştergerea breakpoint-urilor se face printr-un nou click sau prin comanda specifică din meniu (vezi figura). Se pot introduce în sursă breakpoint-uri prin instruciunea STOP.
Urmărirea traseului programului şi evoluiei încărcării cu date a variabilelor, în vederea depanării.
Pentru depanare, aşa cum am mai arătat, programul se poate executa şi cu oprire după fiecare instruciune sau la un breakpoint. Pentru a marca acest lucru (program în execuie şi oprit) sistemul va face galben fondul instruciunii pe care s-a oprit. După oprirea programului pe o instruciune, se poate vedea valoarea pe care o are în acel moment o variabilă, prin plasarea cursorului pe aceasta. Este posibil ca în ieşirea virtuală, Debug Windows, să se introducă toate expresiile provenite de la instruciunea: Debug.Print expresie. Vizualizarea obiectului Debug Windows se poate face la un moment dat prin Ctrl + G sau prin pictograma specifică (vezi figura).
I-8
Meniul de execu ie şi depanare al VBA este prezentat mai jos: Afişează fereastra Debug. În aceasta se vor regăsi toate afişările făcute cu instrDebug.Print
Bara Visual Basic
Resetează toate variabilele globale ale aplicaiei. Run
Stop
Execută instruciune cu instruciune dar cursorul galben de execuie se va opri numai pe:
Toate Nu va mai intra în instr. rutinele apelate
Nu se va mai opri în rutina în care este
Comenzi de compilare
Cursorul de marcare a instruciunii care se va executa. Punctul de întrerupere(Breakpoint) Va determina oprirea rulării programului acolo unde este întâlnit. Se recunoaşte prin culoarea maro a instruciunii şi a unui punct în fa a ei.
Lansarea unei aciuni de pe bara Debug se face printr-un click pe opiunea dorită, sau în unele cazuri, prin utilizarea grupurilor de comenzi rapide ce se găsesc în dreptul lor.
Urmărirea execuiei pas cu pas a unei rutine
• În Debug Windows | Locals se permite vizualizarea informaiilor de stare în momentul lans ării în execuie a unei rutine. Informaiile vizează: − numele variabilelor folosite în cadrul rutinei curente; − valorile acestora în momentul execuiei rutinei; − tipurile de date corespunzătoare variabilelor folosite. În momentul executării unei proceduri apelate, utilizatorul are posibilitatea vizualizării informaiilor de stare din cadrul procedurii apelante. Pentru o bună înelegere prezentăm un exemplu (suma a două numere):
Public Sub SumaNumere() Dim A As Byte Dim Dim B C As As Byte Integer A = 10 B = 16 C=A+B MsgBox "Suma este" & C End Sub
În continuare vom urm ări grafic modul în care procedura este executată. Pas 1. Lansarea în execuie a rutinei.
I-9
Se vor efectua următoarele două aciuni: − se plasează cursorul în cadrul procedurii în locul de unde va porni execu ia acesteia (pe primul rând pentru execuia de la început); − se execută instruciunea prin folosirea tastei Step Into ( sau F8). Apariia culorii galbene pe instruciunea Sub arată începutul execuiei rutinei (cursorul a fost plasat ial pe această instruciune). Dacă se va deschide fereastra Debug Windows | Locals (Ctrl + G) se va ini vedea starea elementelor procedurii (nume variabile, valoarea acestora, tipul de date corespunzător). Valoarea variabilelor A, B şi C este, în acest moment 0, deoarece, ele fiind de tip Byte şi respectiv Integer, se iniializează cu 0. Pas 2. Se accesează din nou Step Into (sau comanda rapidă F8).
Cursorul (culoarea galbenă) s-a mutat pe instruciunea A = 10. Execuia rutinei a sărit peste cele trei instruciuni de declarare a variabilelor, deoarece acestea determină alocarea pentru variabile a spaiului de memorie necesar înainte de execuia rutinei şi anume în faza de compilare. Faptul că în panoul Locals, valoarea variabilei A este tot 0, arată că în momentul în care culoarea galbenă se găseşte pe o instruciune, aceasta nu este încă executată. Pas 3. Se accesează din nou Step Into (sau comanda rapidă F8)
Culoarea galbenă s-a mutat pe instruciunea B = 16 iar în panoul Locals se observă că valoarea variabilei A este în acest moment 10 iar valoarea variabilei B este tot 0 (instruciunea nu este executată). Pas 4. Se accesează din nou Step Into (sau comanda rapidă F8).
Culoarea galbenă s-a mutat pe instruciunea C = A + B . Se observă că, de şi A are valoare 10 iar B are valoare 16, în acest moment, suma lor este tot 0, ceea ce confirmă încă o dată că în momentul în care culoarea galbenă se găseşte pe o instruciune, aceasta nu este executată, ci numai după ce culoarea galbenă a trecut de instruciunea respectivă ea se execută. Pentru vizualizarea valorii unei variabile în momentul execu iei rutinei se poate utiliza şi o altă metodă prezentată deja: se poziionează cursorul mouse-ului pe variabila căreia dorim să-i aflăm valoarea şi I-10
se aşteaptă un interval scurt de timp. Se va observa apariia unei casete imediat sub variabilă în care este specificată valoarea acesteia. Pas 5. Se accesează din nou Step Into (sau comanda rapidă F8)
ă se26pozi ioneaz ă cursorul Daceste pe variabila moment (suma valorilor celormouse-ului două variabile A şi B:C10se+ observ 16). ă cum valoarea acesteia în acest Pas 6. Se accesează din nou Step Into (sau comanda rapidă F8).
După executarea instruciunii <> va apărea un mesaj (o casetă) cu stringul "Suma=" la care este concatenată valoarea variabilei C (valoarea 26 – calculată anterior). De asemenea dacă poziionăm cursorul mouse-ului pe variabila C din cadrul instruciunii <>, se afişează valoarea 26. La o nouă accesare a butonului Step Into se observă dispariia culorii galbene, semn că execuia rutinei s-a încheiat. În continuare vom crea un punct de întrerupere cu ajutorul mouse-ului prin click în partea stângă pe bara verticală în dreptul instruciunii dorite.
Bara verticală Punctul de întrerupere Dacă se operează la lansarea în execuie a procedurii conform cu pasul nr. 1 se va observa apariia culorii galbene pe prima instruciune (semn că execuia rutinei a început). După lansarea în execuie a rutinei, dacă se va folosi opiunea RUN (comanda rapidă F5) se va observa că marcajul galben trece direct pe instruciunea care are punctul de întrerupere (sărind peste instruciunile A = 10, B = 16, C = A + B).
Analizând acum valorile variabilelor, observăm că s-au executat totuşi toate instruciunile până la punctul de întrerupere. La o nou ă accesare a opiunii RUN se va afişa mesajul specific (Suma = 26) după care execuia se va încheia. Pentru demarcarea punctului de întrerupere vom face click pe acesta. I-11
În concluzie, din cele prezentate putem afirma că mediul de depanare reprezintă un instrument foarte eficient în determinarea erorilor de execuie şi a optimizării aplicaiilor.
I.2. Tipuri de date Prin dată se înelege orice entitate asupra căreia poate opera calculatorul. În cod ma şină datele se reprezintă sub forma unei secvene de cifre binare. În cazul limbajelor de nivel înalt se face abstrac ie de detaliile de reprezentare a datelor, dezvoltând conceptul de tip de date. În memoria calculatorului orice dată apare ca o succesiune de bii. Modul în care pentru o astfel de succesiune se asociaz ă o valoare depinde de interpretarea ce i se d ă. La nivelul limbajelor de programare o astfel de interpretare este reprezentată de tipul datelor. Un tip de date este noiunea folosită pentru a defini mulimea valorilor pe care le pot avea datele ce aparin acestui tip, dimensiunea efectivă pe care o ocupă în memorie datele, precum şi operaiile ce se pot efectua asupra acestor date. VBA pune la dispoziia programatorului tipuri de date predefinite (standard), cum ar fi cele pentru numerele întregi, numerele reale, caractere sau booleene (logice), precum şi posibilitatea de declarare a unor tipuri de date proprii (definite de programator) cu ajutorul instruciunii Type. Tipurile de date pot fi: − elementare (simple)– o variabilă de acest tip va conine o singură valoare; − structurate– o variabilă de acest tip va con ine mai multe valori elementare. I.2.1. Tipur i de date elem entar e I.2.1.1.Date numerice întregi Numele tipului de date
Memoria ocupată
Domeniul de valori
Numărul de valori
Byte (octet)
1 octet
0 … 255
2^8
0
btValue
Integer (întreg)
2 octei
–32.768…+32.767
2^16
0
iCounter
2^32
0
lAmount
Long
– 2.147.283.648
4 octei
(întreg lung) Currency
Valoarea Ex. de nume iniială variabilă
+2.147.483.647 922.337.203. +/–
15 cifreşi 8 octei 0 cValuta (valută) 685.477,5808 4 zecimale Literalii numere întregi se scriu funcie de sistemul de numeraie folosit, astfel: − pentru sistemul zecimal: numărul respectiv; Ex.: 1000; –100; 33; − pentru sistemul hexazecimal: prefixul &H; Ex.: &HA1; &H9; − pentru sistemul octal: prefixul &O; Ex.: &O8; &O17.
Un literal reprezintă o valoare, de tip numeric, string, dată etc., care se introduce direct în codul sursă VBA (de exemplu într-o expresie) fiind evaluată exact aşa cum este scrisă.
I.2.1.2.Date numerice reale Numele Memoria tipului de date ocupată Single (precizie simplă) 4 octei Double 8 octei
Domeniu Domeniu Valoare Ex. de nume Mantisa(M) Exponent(E) iniială variabilă
aprox 7 cifre
E-45…E38 zecimale aprox 14 cifre E-324…E308
0
sngValue
0
dValue
zecimale Datele numerice reale se exprimă sub forma: +/–M * 10^+/–E (precizie dublă)
I.2.1.3.Tipul de date BOOLEAN – logic Numele tipului de date Boolean (logic)
Spaiul de memorare
Domeniu de valori
Valoarea iniială
True (–1) False (0) False (0) Tipul de date BOOLEAN este compatibil cu tipul de date INTEGER.
2 octei
I-12
Ex. de nume variabilă
bRaspuns
I.2.1.4.Tipul de date STRING –
ş ir de caractere
Există două tipuri de date de tip String şi anume: − string de lungime variabilă, care poate conine până la 2^31 caractere (aproximativ 2 miliarde); − string de lungime fixă, care poate conine până la 2^16 caractere (aproximativ 64 de mii). Codul folosit este codul ANSI şi are date în intervalul 0-255. Primele 128 caractere (0-127) corespund literelor şi simbolurilor de pe o tastatură US, adică codului ASCII. Dintre acestea primele 32 sunt caractere netipăribile, dar care pot avea efect în afişarea datelor. De exemplu: • caracterul cu codul 7, Bell – semnal sonor; • caracterul cu codul 8, Back Space – caracter înapoi; • caracterul cu codul 9, Tab – salt la următorul marcaj; • caracterul cu codul 10, LF – trecerea la rând nou (urm ător); • caracterul cu codul 13, CR – face retur de car (început de rând). Următoarele 128 caractere (128-255) corespund caracterelor speciale, diacriticelor, accente, simboluri valutare, litere în alfabete internaionale etc. Literalii string se scriu între ghilimele ("…."). La iniializare variabilele de tip string vor avea valoarea şir vid, adică "". Operatorul pentru concatenarea datelor este & (se poate folosi şi sem- nul +). La formarea numelor variabilelor de tip string, se foloseşte de obicei prefixul s. De exemplu sNume. Codul ASCII
În tabela de mai jos codurile ASCII sunt date în: • sistemul de numeraie zecimal – în celule, înaintea fiecărui caracter; • sistemul de numeraie hexazecimal – pe cele 2 margini, astfel: − prima cifră hexazecimală pe primul rând; − a doua cifră hexazecimală pe prima coloană. H 0 1 2 3 4 5 6 8 9 A B C
0 1 2 3 16 · 32 [space] 48 0 · 0 17 · 33 49 1 · ! 1 18 · 34 50 2 · " 2 19 · 35 51 3 · # 3 20 · 36 52 4 · $ 4 21 · 37 53 5 · % 5 22 · 38 54 6 · & 6 55 7 ' 7 Bell 23 · 39 56 8 ( 8 BS 24 · 40 57 9 ) 9 Tab 25 · 41 58 : * 10 LF 26 · 42 27 · 43 59 ; · + 11 28 · 44 60 < · , 12
D E F
13 14 15
7
CR · ·
29 · 45 30 · 46 31 · 47
. /
4 5 6 64 @ 80 P 96 ` 65 A 81 Q 97 a 66 B 82 R 98 b 67 C 83 S 99 c 68 D 84 T 100 d 69 E 85 U 101 e 70 F 86 V 102 f 71 G 87 W 103 g 72 H 88 X 104 h 73 I 89 Y 105 i 74 J 90 Z 106 j 75 K 91 [ 107 k 76 L 92 \ 108 l
61 = 77 M 93 62 > 78 N 94 63 ? 79 O 95
] ^ _
7 112 p 113 q 114 r 115 s 116 t 117 u 118 v 119 w 120 x 121 y 122 z 123 { 124 |
109 m 125 110 n 126 111 o 127
} ~ ·
Deşi ne-am aştepta ca un caracter să ocupe un octet (8 bits) de memorie –codul ANSI are 256 = 2^8 de simboluri (caractere) –, totuşi spaiul ocupat de un caracter în memorie este de 2 octe i. Aceasta se datorează faptului că memorarea caracterelor se face în codul UNICODE, cod care ocupă 2 octei şi care conine un număr de 2^16 simboluri. De exemplu în memorie caracterele ASCII, vor avea pe primul octet codul ASCII al caracterului iar în al doilea 0, iar caracterele ANSI cu cod mai mare de 127, vor avea în al doilea octet 1. Deci, în limbajul Visual Basic, caracterele se folosesc în codul ANSII (ASCII), deşi în memorie ele sunt în codul UNICODE.
I-13
I.2.1.5.Tipul de date DATE – data calendaristic
ă ş i timpul
Numele tipului de date
Spaiul de memorare
Domeniu de valori
Ex. de nume variabil ă
Date (data + timpul)
8 octei
Data: 1/1/100 la 12/31/9999 Timp: 0:00:00 la 23:59:59
dtStartDate
Literalii date se scriu între diezi (#…. #). De exemplu: #January 1, 1993# sau #1 Jan 93#. Afişarea datelor şi timpului se face conform formatului specificat în S.O. Windows prin comanda Regional Settings. De obicei se pune prefixul dt la numele unei variabilele de tip Date. Un număr poate fi convertit în tip Date, folosindu-se convenia: − data calendaristică – se află în partea stângă a punctului zecimal; − timpul – în partea din dreapta punctului zecimal.
Ora 24 este 0.0 iar ora 12 este 0.5; Numerele negative reprezintă date anterioare celei de 30/Decembrie/1899.
I.2.2. Tipur i d e date str uctur ate
Visual Basic include mecanismele necesare construirii unor tipuri noi, prin restrângeri sau combinări ale tipurilor deja definite. Aceste mecanisme poartă numele de constructori de tipuri şi joacă un rol esenial în programare. I.2.2.1.Tipul de date ARRAY – tablou
Un Tablou – Array defineşte o mulime de valori care sunt de acelaşi tip de dată. Un Array, deşi se materializează printr-o singură variabilă, poate stoca mai multe date de acelaşi tip în compartimentele (elementele) sale. Structura unui asemenea tip poate avea o dimensiune sau mai multe. Un Array se caracterizează prin 3 elemente dintre care primele două definesc structura: − numărul de dimensiuni; − numărul de elemente (celule) ale fiec ărei dimensiuni. Practic se foloseşte numărul de ordine al primului (implicit 0) şi al ultimului element al fiecărei dimensiuni; − tipul de date al elementelor tabloului. Poate fi orice tip de date, eventual chiar tot array. Utilizarea tablourilor se face numai prin referirea fiec ărui element în parte (folosind numele tabloului indexat la elementul respectiv). Deci în VBA nu se pot efectua operaii direct cu întreaga structură a tabloului; de exemplu o mutare de date dintr-un tablou în altul cu aceea şi structură se poate face numai prin mutarea separată a tuturor elementelor tabloului. Tablourile de octei constituie o excepie la ultima afirmaie. Exemplu. Pentru a stoca cheltuielile pe care le facem în fiecare zi a unui an vom declara o singur ă variabilă de tip Array, cu 365 elemente de tip numeric, decât 365 variabile individuale. Fiecare element din tablou va conine o singură valoare. Implicit un tablou se indexează de la 0. Declararea variabilei se va face: Dim cCheltuieli (364) As Currency
Cu procedura de mai jos introducem valoarea 22 în primele 100 de zile: Sub ExempluArray () Dim cCheltuieli (364) As Currency Dim intI As Integer For intI = 0 to 99 cCheltuieli (intI) = 22 Next End Sub
I.2.2.2.TYPE – Crearea tipurilor de date definite de
utilizator
Există posibilitatea să se creeze structuri noi de date, definite de proiectant (utilizator), formate din combinări din alte tipuri de date. Declararea unui nou tip de date se face cu instruciunea TYPE astfel: [Public | Private] Type NumeTip NumeElement1 As type I-14
NumeElement2 As type ... End Type
Referirea la variabilele de un tip definit de utilizator, se poate face: − pentru întreaga structură (folosind numele variabilei); − pentru fiecare element în parte (folosind numele elementului respectiv calificat – cu semnul punct – cu numele variabilei). Declararea unui tip de date nu se poate face decât la nivelul unui modul de cod. Deci nu se pot declara tipuri de date la nivelul unei rutine. Exemplu. Option Compare Database Option Explicit Public Type Person 'se declară tipul de date la nivelul modulului Nume As String Prenume As String Virsta As Integer End Type Sub TypeTest () Dim Primul As Person, Doilea As Person'se declară 2 var. de tip Person Primul.Nume = "Ionescu" 'se folosesc elementele tipului Person Primul.Prenume = "Ion" Primul.Virsta = 21 Doilea = Primul 'se transferă întregul tip de dată Person MsgBox Doilea.Nume & " " & Doilea.Prenume & ", _ varsta=" & Doilea.Virsta & " ani"' afişează şi valoriea unei expresie End Sub
Caracterul (') se foloseşte pentru marcarea comentariilor. Caracterele ( _ ) se folosesc pentru continuarea unei instruciuni pe următorul rând.
I.2.3. Tipul de date VARIANT
Acest tip de date, specific limbajului Visual Basic, este deosebit de puternic fiind compatibil cu: − toate tipurile numerice; − tipul Date; − tipul String; − tipul Object. Deşi uşurează munca de programare, totuşi folosirea variabilelor de tip variant diminueaz ă performanele programului, atât ca memorie ocupat ă cât şi ca timp de execu ie. Numele Spaiul de tipului de date memorare Variant 16 octei (numere) Variant 22 octei (string)
Domeniu
Valoarea iniială
Ex. de nume variabil ă
ca la numeric Empty (Gol)
vntValue
ca la stringuri Empty (Gol)
vntNume
Valorile EMPTY, NULL, STRING VID − EMPTY – reprezintă valoarea pe care o are o variabil ă variant care nu este iniializată. Aceasta înseamnă că variabila a fost declarată dar nu a fost încă introdusă o valoare în ea. La prima introducere a unei date într-o variabilă de tip variant, aceasta se va configura în conformitate cu tipul respectiv de date. − NULL – reprezintă o valoare pe care o ia o variabil ă variant în care datele nu sunt valide. − String de lungime 0 (vid, gol) – string care nu conine nici o valoare (nici un caracter), adică este "". Tipul de date OBJECT – va fi prezentat în următorul capitol.
I-15
I.3. Variabile Variabilele sunt nume de locaii de memorie care conin valori de un anumit tip, ce se modific ă în timpul execuiei programului. Variabilele se caracterizează prin: • Domeniul de vizibilitate (valabilitate): se referă la momentul când acestea apar şi dispar din 'codul sursă'. Variabilele apar atunci când sunt declarate prima dată, după care apar şi dispar în funcie de domeniul lor de vizibilitate. În momentul când variabilele apar (devin vizibile), li se pot atribui valori de un anumit tip şi pot fi folosite în cadrul instruciunilor. În rest, ele sunt invizibile şi nu se pot referi. • Durata de via ă (valabilitate): se referă la timpul cât variabila ocupă loc în memorie. Când se creează variabile trebuie avut în vedere mai multe lucruri. Modul şi locul în care se declară o variabilă determină domeniul de vizibilitate, durata de viaă şi alte caracteristici ale acesteia. Următoarele subiecte analizate vă vor face să înelegei mai bine declararea variabilelor în limbajul Visual Basic. I.3.1. Decla rare a varia bile lor
Declararea variabilelor se face de obicei cu instruc iunea declarativă DIM. Forma acestei instruciuni este: Dim NumeVariabilă As TipulDeDateAlVariabilei • Numele variabilei respectă regulile folosite la formarea numelor. În practica program ării, se obişnuieşte să se pună un prefix convenional la nume, care să indice tipul de date al variabilei. (Vezi exemplele de nume de variabile din modulul Tipuri de date). • O variabilă poate fi declarată specificându-se următoarele tipuri de date: Byte, Integer, Long, Currency, Single, Double, Date, String (pentru variabile de lungime variabil ă), String * length (pentru variabile de lungime fix ă), Object, sau Variant, sau a unui tip de date definit cu declaraia Type. Nespecificarea unui tip de date duce la crearea unor variabile de tip Variant. • Se pot declara mai multe variabile pe acela şi rând, separate prin virgul ă, dar este obligatorie folosirea explicită a tipului de dată pentru fiecare variabilă. Exemplu. Dim intX As Integer, intY As Integer, intZ As Integer şi linie, fără a se specifica tipul pentru O greşeală obişnuită este declararea mai multor variabile pe aceea fiecare variabilă declarată ca în exemplul de mai jos. Dim iCounter, iAge, iWeight As Integer În acest caz, numai ultima variabilă este declarată ca o variabilă de tip Integer (întreg). Celelalte variabile sunt declarate de tipul Variant (tipul implicit al unei variabile este variant). Această eroare este foarte periculoasă, deoarece unele limbaje de programare (PASCAL), folosesc o asemenea notare pentru a declara toate variabilele de pe aceeaşi linie de acelaşi tip.
I.3.2. Caractere folosite ca Type-declaration
Anumite variabile mai pot fi create automat de un anumit tip, folosindu-se în loc de specifica ia As, anumite caractere speciale, denumite caractere de tip, la sfârşitul numelui variabilei, în declaraia Dim. Astfel: Tipul de date
Integer Long Currency Single Double String Variant
Caracterele de tip
%
&
@
!
#
$
implicit
Acest tip de declaraii este importat din variantele mai vechi de Basic, dar nu este recomandabil. Exemplu. Următoarele declaraii sunt echivalente. Dim Nume As String Dim Virsta As Integer Dim Anul As Variant
I.3.3. Option Explicit (declararea explicit
~ Dim Nume$ ~ Dim Virsta% ~ Dim Anul ă a variabilelor)
Este o instruciune declarativă care poate fi inclusă în seciunea General Declarations a unui modul de cod (prima parte a acestuia). Când Option Explicit este plasat într-un modul de cod, toate variabilele din interiorul acestuia trebuie s ă fie declarate înainte de folosire, în caz contrar producându-se o eroare de compilare. I-16
Introducerea instruciunii declarative Option Explicit în fiecare modul, formular sau raport se poate face automat prin activarea opiunii Require Variable Declarations (cere declaraii de variabile) din meniul Tools | Options | Module. Este foarte important ca aceast ă instruciune (Option Explicit) să fie plasată în toate modulele de cod. Asigurai-vă că ai configurat opiunea la valoarea True! Dacă proprietatea specificată mai sus nu este setată (False), atunci practic variabilele pot s ă nu fie de loc declarate. Declararea acestora se face implicit, în func ie de datele cu care se încarcă la prima folosire variabila (ca în limbajul FORTRAN). De exemplu, instruciunea: x=10 ar genera şi declararea unei variabile de tip întreg. Folosirea acestei metode este foarte periculoasă, deoarece poate cauza multe probleme. În concluzie, cea mai eficientă şi mai sigură metodă de declarare a variabilelor este de a folosi în totalitate instruciunea declarativă Dim, pentru fiecare variabilă, ca în exemplul urm ător: Dim iCounter As Integer Dim sName As string ş se vede, acest tip decompilatorului declaraie consine atât numele variabilei, cât şi tipul datelor pe care le poate Aconacum ine. Acest lucru permite ă intercepteze erori de genul memor ării unui şir într-o variabilă de tip întreg. De asemenea, prin selectarea celui mai scurt tip de date pentru fiecare variabil ă, se reduc substanial resursele necesare executării programului.
I.3.4. Var iab ile Loc ale ş i Globale
În funcie de locul de declarare, variabilele pot fi: − locale – variabile declarate în interiorul rutinei, care sunt vizibile (domeniul de valabilitate) numai în aceasta; − globale (modale) – variabile declarate în secia de declaraii generale de la începutul unui modul de cod. În acest caz variabila va fi vizibilă în toate rutinele modulului respectiv de cod. Exemplu. Fie declararea variabilei: Dim sName As String
Dacă această declaraie se face: •
ă locală; va putea fi folosit ăale numai în aceasta, fiind o variabil în secrutin iuneaă –deeadeclara modulului de cod – ea este global • într-o ii generale ă şi va putea fi utilizată în toate rutinele modulului respectiv, dar nu şi în alte module de cod (aceast ă caracteristică o au numai variabilele declarate Public în modulul general de cod). Deci variabilele globale sunt vizibile din orice rutină aparinând modulului în care au fost declarate. Valoarea variabilei poate fi schimbată de orice subrutină sau funcie din modulul respectiv. În următorul exemplu variabila globală miCounter: − ia valoarea 20 în procedura Fac20; − ia valoarea 10 în procedura Fac10; − este afişată valoarea care se găseşte în ea în procedura Afisez. Option Explicit ' [General Declarations]
Dim miCounter As Integer Private Sub Fac20 () miCounter = 20 End Sub Private Sub Fac10 () miCounter = 10 End Sub Private Sub Afisez () MsgBox miCounter End Sub
Reinei câteva observaii: − convenia de numire a variabilei modale prin folosirea literei m ca prefix al numelui acesteia. Aceasta o face să fie uşor recunoscută de programator ca o variabilă de nivel modul (globală); − folosii declaraiile de nivel modul numai pentru variabilele care trebuie s ă fie văzute din mai multe rutine;
I-17
− încercai s ă evitai (atunci când este posibil) utilizarea variabilelor globale. Aceast ă metodă face codul mai modular şi mai uşor de depanat.
I.3.5. Variabile Publice
ş i Private
O variabilă publică poate fi accesată (este vizibilă, are domeniul de valabilitate) de oriunde din aplicaie. Variabilele publice se folosesc de obicei ca identificatori de acces, valori de configurare pentru mediul de lucru şi alte date care trebuie să fie vizibile pentru întreaga aplicaie. Declaraiile variabilelor publice trebuie să fie plasate în seciunea General Declarations a modulului general de cod. Pentru declararea variabilelorpublice se foloseşte cuvântul cheiePUBLIC, în loc deDIM. Exemplu. O declaraie de variabilă publică arată aşa: Option Explicit Public piCounter As Integer
De obicei, convenional se indică tipul public al unei variabile, folosind prefixul p la numele acesteia. Rutina următoare, ataşată evenimentului Click al butonului de comandă cmdPublic, după ce face 50 variabila publică piCounter, o afişează. Private Sub cmdPublic_Click () piCounter = 50 Msgbox piCounter End Sub Se poate folosi cuvântul cheie PRIVATE, în loc de DIM, pentru a declara variabile private în seciunea
de declaraii generale a modulului de cod inând , adică variabile care nu suntvizibile decât de rutinele apar modulului respectiv de cod. Exemplu. Private MyName As String Cuvântul cheieDIM este echivalent cuPRIVATE atunci când se folosesc la declararea variabilelor în modulele de cod. Este totuşi indicată folosirea expresieiprivate, pentru a face codul mai lizibil (maişuor de citit şi mai rapid de interpretat). I.3.6. Variabile Statice Variabile statice se pot declara numai în rutine, prin folosirea cuvântului cheieSTATIC, în loc de cuvântul cheie DIM. Variabilele statice au proprietatea de a-şi păstra valoarea între două apeluri ale rutinei în care au fost declarate. Exemplul următor ilustrează diferena dintre variabilele locale şi cele statice. Deoarece variabilele locale sunt iniializate la fiecare apel al codului, de fiecare dată când executai această procedură, se va afişa numărul 1. Private Sub cmdLocal_Click () Dim iCounter As Integer iCounter = iCounter + 1 MsgBox iCounter End Sub
De fiecare dată când acest cod este executat, instruciunea declarativă Dim defineşte variabila iCounter şi o iniializează cu 0. Ea este puin diferită faă de următoarea secvenă de cod, care ilustrează folosirea variabilelor statice: Private Sub cmdLocal_Click () Static iCounter As Integer iCounter = iCounter + 1 MsgBox iCounter End Sub
De fiecare dată când acest cod este executat, variabila cu numele iCounter este incrementată şi reinută. Deci la prima execuie se va afşa 1, la a doua se va afişa 2, la a treia se va afişa 3 etc. Practic o variabilă statică este definită numai la primul apel al rutinei în care a fost declarată. Deoarece, fiind statică, nu mai este distrusă la terminarea rutinei, la următoarea apelare nu va mai fi definită şi va avea deci valoarea anterioară apelului.
I-18
I.3.7. Variabile – domeniul
ş i durata de valabilitate
Aşa cum am arătat, domeniul de valabilitate sau vizibilitate a variabilelor este determinat de cuvântul utilizat în declararea variabilei: Dim, Private, Public şi de locul unde acesta e plasat, determinând ca variabila respectivă să fie locală , modală (globală) sau publică şi să poată fi folosită numai într-o rutină, la nivelul unui modul de cod sau în toate modulele de cod. Ar trebui să facei tot posibilul ca majoritatea variabilelor din codul dumneavoastră să fie locale, deoarece acestea sunt ferite de o eventuală modificare (accidentală) de către alte rutine. Durata de viaă sau valabilitate a variabilelor reprezintă, aşa cum am mai arătat, timpul cât variabila are alocat spaiu în memorie. Fără alte instruciuni speciale, o variabilă se creează în momentul în care modulul în care este declarată, este apelată şi dispare (se distruge, elibereaz ă spaiul de memorie ocupat) în momentul terminării modulului respectiv. Astfel: − o variabilă locală, declarată într-o procedură eveniment, va fi alocată numai în timpul execuiei procedurii respective (bineîneles dacă nu este statică); − o variabilă globală, declarată într-un modul de cod al unui formular, va fi alocată cât timp formularul respectiv va fi în execuie; − o variabilă publică, declarată într-un modul general de cod va fi alocată în tot timpul execuiei aplicaiei. I.3.8. Declararea
ş i folosirea variabilelor ARRAY
Variabilele Array (tablou) se declară la fel ca orice altă variabilă folosindu-se instruciunile declarative Dim, Static, Private, sau Public. Diferena faă de declararea unei variabile simple este aceea că la tablouri, între paranteze, trebuie să se specifice pentru fiecare dimensiune – în ordine şi separate prin virgulă dacă sunt mai multe dimensiuni – valoarea minimă (de obicei se omite fiind implicit ă) şi maximă a indicelui dimensiunii respective.
Declararea tablourilor cu dimensiuni fixe - statice Dim NumeTablou (N1 [, N2 [, N3…. ]) As TipDeDată
Aşa cum se observă, marginea de jos a indicelui a fost omis ă. Ea implicit se consideră a avea valoarea 0. Totuşi marginea de jos a indicelui se poate fixa la valoarea 1, dacă este introdusă în modulul respectiv de cod, în seciunea de declaraii generale, instruciunea declarativă Option Base 1. Exemplu. Declaraia Dim MyArray (9, 10) As Integer va crea un tabel cu 2 dimensiuni, cu 10 şi respectiv 11 elemente, cu primul indice cu valori între (0 - 9 ) şi al doilea indice cu valori între ( 0 10), în care toate cele 110 elemente (celule) sunt de tip Integer. Ca orice declaraie care nu specifică tipul, şi tablourile declarate fără tip sunt de tip Variant. În acest caz, fiind Variant, fiecare element va ocupa 16 bytes dacă este numeric sau 22 bytes dacă este string. Deci la tablouri mari se poate ajunge la un consum mare de memorie, ceea ce trebuie s ă determine o rezervă în folosirea tablourilor de Variant. Exemplu. În continuare se prezintă ce memorie vor ocupa tablourile. Dim MyVariantArray (10) As Variant ' Tablou Variant – cel puin _ 176 bytes (11 el. * 16 bytes). Dim MyIntegerArray (10) As Integer ' Tablou Integer foloseşte _ 22 bytes (11 elemenste * 2 bytes). Dim MyDoubleArray (10) As Double ' Tablou Double-precision_ 88 bytes (11 el. * 8 bytes). Dim MyVariantArray (10) ' Tablou Variant – cel puin _ 176 bytes (11 el. * 16 bytes). Dim MyIntegerArray (99, 99) As Integer ' Tablou Integer foloseşte _ 100 * 100 * 2 bytes (20.000 bytes). Dim MyDoubleArray (99, 99) As Double ' Tablou Double-precision.. _ 100 * 100 * 8 bytes (80.000 bytes). Dim MyVariantArray (99, 99) ' Tablou Variant – cel puin _ 160.000 bytes (100 * 100 * 16 bytes). Se pot declara tablouri specificându-se explicit şi marginea de jos a indicelui. Dim NumeTablou (J1 To N1 [, J2 To N2 …. ]) As TipDeDată Cu J s-a notat marginea de jos a indicelui, iarNcumarginea de sus a indicelui. I-19
Declararea tablourilor cu dimensiuni variabile – dinamice
În timp ce tablourile cu dimensiuni fixevor ocupa din etapa de compilare o anumit ă dimensiune de memorie care nu mai poate fi modificat ă în timpul execuiei, tablourile dinamice pot să-şi modifice dimensiunile în timpul execu iei. Un tablou dinamic se declară la fel, cu Static, Dim, Private sau Public, fără însă a se specifica nimic între paranteze. Dim NumeTablou () As TipDeDată Exemplu. Dim sngArray () As Single Cu instruciunea executabilă ReDim (cu o structură asemănătoare cu cea a lui Dim), care se poate plasa oriunde în cod după declararea unui tablou dinamic, se va redimensiona în momentul execuiei acesteia tabloul cu noile dimensiuni, eventual putându-se schimba şi tipul de date. Exemplu. ReDim sngArray(11) redimensionează tabloul, dar nu modifică tipul de date al elementelor şi provoacă pierderea datelor din tablou. Instruciunea ReDim provoacă pierderea
datelor din tabloul pe care îl redimension ăm. Pentru a se evita acest lucru se poate folosi clauza Preserve. Folosirea acestei clauze nu permite îns ă modificarea numărului de dimensiuni sau a marginii de jos ai indecşilor. Exemplu. ReDim Preserve sngArray(UBound(sngArray)+10) − va redimensiona tabloul, mărind cu 10 numărul lui de elemente şi va păstra datele ce erau în tablou înainte de executarea instruciunii; − funcia Ubound întoarce indicele superior maxim al unui tablou;
Utilizarea tablourilor
Un tablou poate fi utilizat ca orice variabilă simplă de tipul respectiv. Referirea unui element al tabloului se face prin numele tabloului, urmat între paranteze de indicele (indicii) elementului respectiv. Exemplu. Sub FillArrayMulti () Dim intI As Integer, intJ As Integer Dim sngMulti (1 To 5, 1 To 10) As Single For intI = 1 To 5 For intJ = 1 To 10 sngMulti (intI, intJ) = intI * intJ 'indroduce în fiecare element _
produsul indicilor elementului. ' afişează indicii elementului şi valoarea din acesta. MegBox " Tablou ( " & intI & ", " & intJ & " ) = " & sngMulti (intI, intJ) Next intJ Next intI End Sub
Tablouri de octei
Un tablou de octei este un tablou dinamic de tipul BYTE. El poate fi utilizat ca orice tablou dinamic, dar mai are o proprietate care îl face util în lucrul cu stringuri, şi anume: − un tablou de octei se poate referi şi direct, numai prin numele lui, f ără indici. În felul acesta el devine compatibil cu tipul de date string, permiând transferurile directe de date între tablourile de octei şi stringuri . Trebuie remarcat că în această operaie fiecare caracter al strigului va ocupa 2 elemente din tabloul de octei, deoarece, aşa cum am mai arătat, caracterele sunt memorate în UNICODE (deci pe 2 octei). Exemplu. Pentru înelegerea acestei secvene trebuie studiate mai întâi, în capitolul despre func iile text, precizările făcute pentru codul UNICODE. Public Sub TestMatOcteti () Dim Caracter As String, Sir As String * 3 Dim X() As Byte
' Tablou de octei, va avea 6 elemente deoarece pentru un caracter din _ string sunt necesare 2 elemente de 1 octet ReDim X(5) I-20
Dim k As Integer, j As Integer, i As Integer Sir = "1AŞ" X = Sir For i = 0 To 2 j = i + 1 ' în "J" se va calcula numărul caracterului în string.. 1, 2, 3 _ necesar pt. func ia MID Caracter = Mid (Sir, j, 1) ' în "Caracter" se vor introduce caracterele k = 2 * (i)'În K–poziia în tablou a primului octet al caracterului:0,2,4 Debug.Print "Caracterul = " & Caracter & "; CodUnicode= " & AscW(Caracter) & "; CodAnsii= " & Asc(Caracter) & "; Octetul 1= " & X(k) & "; Octetul 2= " & X(k+1) ' Ceea ce se afişează cu Debug.Print se poate vizualiza prin comanda _ View | Debug Window MsgBox "Caracterul = " & Caracter & "; CodUnicode= " & AscW(Caracter) & "; CodAnsii= " & Asc(Caracter) & "; Octetul 1= " & X(k) & "; Octetul 2= " & X(k+1) Next i For i = 0 To 5 Debug.Print "Octetul " & i & " = " & X(i) MsgBox "Octetul " & i & " = " & X(i) Next i End Sub
După execuie se va găsi afişat în Debug. Print: Caracterul = 1; CodUnicode= 49; CodAnsii= 49; Octetul 1= 49; Octetul 2= 0 Caracterul = A; CodUnicode= 65; CodAnsii= 65; Octetul 1= 65; Octetul 2= 0 Caracterul = Ş; CodUnicode= 350; CodAnsii= 170; Octetul 1= 94; Octetul 2= 1 Octetul 0 = 49 Octetul 1 = 0 Octetul 2 = 65 Octetul 3 = 0 Octetul 4 = 94 Octetul 5 = 1
În memoria internă, dacă o variabilă nestructurată ocupă mai muli octei (de exemplu o variabil ă integer ocupă 2 octei), atunci cel mai semnificativ dintre aceştia se găseşte la dreapta. Deci dacă într-o variabilă integer se găseşte valoarea: 266 (zecimal) = 0000.0001.0000.1010 (binar) = 01.0A (hexazecimal) Atunci aceasta se va găsi în memorie sub forma: (0000.1010) (0000.0001) – deci cu octetul cel mai semnificativ (0000.0001) aşezat la dreapta. Din tabelul de mai jos, se observă cum se găseşte în memoria internă, într-o variabilă de tip tablou de octei, datele dintr-un string. Caracterele din string
‘1’
‘A’
‘Ş ’
Cod ANSI 49 65 170 1octet/caracter - zecimal Cod UNICODE 49 65 350 2 octei/caracter-zecimal Memorie -Tabloul X 0011.0001 0000.0000 0100.0001 0000.0000 0101.1110 0000.0001 6 octei - binar Memorie -Tabloul X 6 octei - hexa Memorie -Tabloul X 6 octei - zecimal
31 49
00 0
41 65
00 0
5E 94
01 1
I.4. Constante Prin declararea unei constante, se poate atribui unui nume, o valoare. Aceasta se face prin instruciunea declarativă Const. După declarare, o constantă nu îşi mai poate modifica valoarea. Forma instruciunii declarative CONST este: [Public | Private] Const NumeConstantă [As TipData] = Valoare O constantă se comportă practic ca o variabilă, iniializată cu o anumită valoare, care nu se mai poate schimba în timpul execuiei aplicaiei. I-21
Regulile aplicate variabilelor privind domeniul şi durata de valabilitate sunt efective şi în cazul constantelor. Deci vom avea: − constante locale sau globale, în funcie de locul de declarare (în rutin ă sau seciunea de declaraii generale a modulului de cod); − constante publice sau private, dacă folosim sau nu în fa a cuvântului cheie Const cuvintele cheie Private, Public. Exemplu. Public Const conAge As Integer = 34 ' conAge este o constantă _ Publică , Integer, cu valoarea 34. Constantele se pot declara în două moduri şi anume: − cu tip explicit, şi anume: Boolean, Byte, Integer, Long, Currency, Single, Double, Date, String, sau Variant, ca în exemplul de mai sus; − cu tip implicit, în care clauza As lipseşte iar tipul va fi determinat de tipul datei cu care se încarc ă constanta. De exemplu dacă avem declaraiile: Const Ziua = "Miercuri" Const Virsta = 44
atunci prima constantă va fi de tip string, iar a doua integer. Ca şi la variabile, se pot declara mai multe constante pe acela şi rând, cu specificarea (dacă este explicită) a tipului pentru fiecare constantă în parte. Const conAge As Integer = 34, conWage As Currency = 35000, _ conNume="Soare"
În exemplul de mai sus primele dou ă constante sunt declarate explicit, Integer respectiv Currency, iar a treia, implicit, string.
I.5. Limbajul VBA – Instruciuni executabile Limbajele de programare au un set de instruciuni care constituie lista completă a posibilităilor de care dispune programatorul pentru a determina rezolvarea unei probleme (aplica ie) pe un sistem de calcul. Instruciunile unui limbaj de programare sunt de două feluri: − Instruciuni declarative, care practic nu determină executarea unei aciuni de către sistemul de şte indicaii care se dau compilatorului. De exemplu instruc iunile de declarare ale calcul, tipurilorcidenumai date, nivariabilelor sau constantelor (Dim, Const, Type etc.), opiunile de compilare (Option Explicit, Option Base, Option Compare Database, etc. ) − Instruciuni executabile, care reprezintă descrierea unei aciuni pe care o va efectua sistemul de calcul, în special privind datele aplicaiei (If, For, Do etc.). Execuia unei instruciuni reprezintă efectuarea operaiei specificate de codul instruciunii, interpretate la un moment dat de unitatea centrală a unui sistem de calcul sau de un procesor. De obicei, execuia instruciunii presupune obinerea operanzilor din memoria internă sau din registrele unităii centrale, formarea rezultatului şi depunerea acestuia într-un registru al unit ăii centrale sau în memoria internă. Ca exemplu de operaii pe care le face unitatea central ă a sistemului de calcul sunt operaiile de adunare, scădere, citire, scriere, comparaie, etc. Limbajele moderne de programare au un set redus de instruciuni complexe: − declararea structurilor de date; − instruciunea de atribuire – prin care se calculează expresii; − structurile de control – prin care se determină "traseul" printre instruciuni, adică ordinea în care se execută instruciunile; − declararea şi apelarea rutinelor; − crearea modulelor de clase de obiecte; − crearea şi manipularea obiectelor. Practic, instruciunile executabile ale limbajelor moderne de programare sunt instruciunea de atribuire şi instruciunile prin care se realizează structurile de control. Alte operaii necesare unei aplicaii (ca de exemplu executarea operaiilor de Input/ Output), sunt realizate prin rutine din bibliotecile de obiecte, funcii şi proceduri disponibile limbajului respectiv de programare.
I.5.1. Inst ru c ţ iunea de atribuire
Forma acestei instruciuni este: NumeVariabilă = Expresie I-22
Aciunea acestei instruciuni constă în calcularea expresiei (din dreapta semnului =) şi depunerea rezultatului în variabilă (din stânga semnului =). Pentru a se executa cu succes instruciunea, este necesar ca rezultatul expresiei să aparină unui tip de date compatibil cu cel al variabilei. În caz contrar se va produce o eroare de execuie (pe care le vom trata în alt capitol). Totuşi compilatorul încearcă trecerea peste anumite incompatibilităi, a căror rezolvare este evidentă, efectuând automat conversiile între tipuri diferite de date, dacă este posibil. Exemplu. Private Sub TestExpresie () Dim Vstr As String Dim Vnr As Integer Vstr = "251" Vnr = 251 + 40 ' prelucrări normale Vstr = 251 + 40 ' nu produce eroare de execuie;
' efectuează adunarea după care transformă constanta numerică 291 _ în stringul "291" Vnr = Vstr ' nu produce o eroare de execuie; ' transformă stringul "291" în constanta numerică 291 Vstr = Vnr + "ABC" ' va produce eroare de execu ie – _ TYPE-MISMATCH; nu se poate efectua adunarea. Vstr = Vnr & "ABC" ' nu produce eroare. Vnr = "ABC" ' va produce eroare de execuie – TYPE MISMATCH End Sub Formarea expresiilor în Visual Basic
O expresie este formată din termeni asupra cărora se efectuează anumite operaii. O expresie a cărei evaluare este o valoare logică (True sau False) se mai numeşte condiie. • Termenii pot fi: variabile, constante, literali (valori date direct) sau funcii (proprii sau din biblioteci). • Operatorii sunt de trei tipuri şi anume: − aritmetici , care acionând asupra unor termeni scalari (numere, stringuri, date calendaristice, etc.) vor determina tot un rezultat de aceeaşi natură (scalar): ^ * / \ Ridicare la Împărire Împărire Înmulire putere reală întreagă 5^2=25
5*2=10
5/2=2,5
10\3=3
Mod Restul împăririi 0 Mod 3=1
+
-
Adunare Sc ădere 5+2=7
5-2=3
& Concatenare şiruri "Ab" & 2="Ab2"
− relaionali , care acionând asupra unor termeni scalari (numere, stringuri, date calendaristice, etc. ) vor determina un rezultat logic (boolean):
< mai mic (1<1) =False
<= mai mic sau egal (5<=5) =True
Is
>
>= = <> mai mare mai mare egal ne egal sau egal (5>4) =True (5>=5) =True (5=5) =True (5<>5) = False Like
apartenena la o mulime
La fel ca = pt. stringuri/evaluează caracterele generice din al doilea string
(5 Is [1, 2, 3]) = False
("ARAD" Like "AR*") = True
Caracterele generice generează o mulime de caractere astfel:
? * # [Listă char] ex. [A-R]
Un singur caracter. Zero sau mai multe caractere. Un singur număr (0-9).
("a2B3a" Like "a?a") = False ("a2B3a" Like "a*a") = True ("a2a" Like "a#a") = True
Un singur caracter din listă.
("F" Like "[A-Z]") = True
[!Listă caractere] Un singur char care nu este în listă. ( ("F" Like "[!A-Z]") = False
− logici , având valori logice (True, False) ca operanzi, vor determina un rezultat tot logic: I-23
Op NOT True False
False True
Op 1 Op 2 AND
Op 1 Op 2 OR
Op 1 Op 2 XOR
True True False False
True True False False
True True False False
True False True False
True False False False
True False True False
True True True False
True False True False
False True True False
Mai există două funcii logice, mai puin folosite, şi anume: • EQV – utilizată pentru verificarea echivalenei logice a două expresii; • IMP – utilizată pentru verificarea implicării logice între două expresii. Operatorii sunt aşezai de la stânga la dreapta în ordinea priorităii lor în execuie, care este în general cea obişnuită din matematică. Parantezele rotunde sunt folosite pentru stabilirea unei ordini explicite a priorităii în execuie a operaiilor. Aşa cum am mai arătat, dacă un termen al unei expresii este NULL, atunci şi rezultatul expresiei este tot NULL. Spunem că NULL-ul se propagă în expresii. Totuşi există o excepie, şi anume la operatorul de concatenare a şirurilor, &: dacă un termen este NULL, iar celălalt nu este NULL, atunci rezultatul va fi chiar termenul diferit de NULL. Valoarea EMPTY în expresii este considerată, în funcie de tipul de date pe care îl reprezint ă, chiar valoarea cu care se iniializează variabilele de tipul respectiv (astfel, în expresii, dacă un termen numeric este EMPTY, atunci se va considera = 0; dacă este logic = False; dacă este string = şir vid; etc.). I.5.2. Struc turi le de contr ol
Aşa cum am mai arătat, structurile de control stabilesc ordinea în care se execut ă instruciunile. Există trei structuri de control, şi anume: structura secvenială, structura alternativă (decizională) şi structura repetitivă (în buclă, în ciclu). I.5.2.1.Structura secven
ială
Reprezintă execuia secvenială a instruciunilor, în ordinea în care au fost scrise. Nu necesit ă folosirea unei instruciuni. I.5.2.2.Structura alternativ
ă
Reprezintă execuia din mai multe grupuri de instruc iuni introduse numai a unui singur grup, în funcie de evaluarea unor condiii. I.5.2.2.a)Structura alternativ
ă simpl ă
Instruciunea: If... Then... Else If condiie Then
Grup 1 de instruciuni [Else
Grup 2 de instruciuni] End IF
Structura If... Then... Else evaluează dacă condiia este adevărată sau falsă. Dacă: • condiia este adevărată, vor fi executate toate instruciunile dintre If şi Else (Grup 1 de instruciuni); • condiia este falsă, vor fi executate toate instruciunile dintre Else şi End If (Grup 2 de instruciuni). Folosirea clauzei Else este opională. O condiie cu rezultatul NULL este tratată ca şi cum ar fi FALSE. Exemplu. Private Sub cmdIf_Click () ' evenimentul click al unui buton de comandă If IsNull(Me!txtValue) Then ' Condiia testează dacă în controlul txtValue, este introdusă o
valoare. Acest lucru se face cu funcia IsNULL, studiată în alt modul MsgBox "Trebuie sa introduceti o valoare" Else MsgBox "Ati introdus:" & Me!txtValue I-24
End If End Sub
Un control în care nu este introdus nimic va avea valoarea NULL.
I.5.2.2.b)Structura alternativ
ă multipl ă
În locul folosirii a mai multor instruciuni If... Then... Else, atunci când decizia se ia prin evaluarea mai multor condiii (Structura alternativă multiplă), este mult mai simplă, fără îndoială, utilizarea instruciunii Select Case sau a instruciunii If... Then... ElseIF…Else
Instruciunea Select Case Select Case NumeVariabilă Case Valoare1
Grup 1 de instruciuni [Case Valoare2
Grup 2 de instruciuni]
[Case ValoareX
Grup X de instruciuni] ……………………… [Case Else
Grup else de instruciuni] End Select
Această instruciune evaluează mai multe condiii formate prin verificarea egalităilor între valoarea variabilei ataşate instruciunii (NumeVariabilă), şi valorile din dreptul cuvintelor cheie CASE (ValoareI). Deci: Condiia I va fi: NumeVariabilă=ValoareI Condiiile sunt evaluate pe rând, în ordinea plas ării lor în instruciune, până când se găseşte una adevărată. După găsirea unei condiii advărate atunci se va executa grupul corespunzător de instruciuni, după care instruciunea Select Case se termină, programul continuând cu prima instruciune plasată după aceasta. Dacă toate condiiile sunt false atunci se vor executa – dacă există – instruciunile dintre Else …. End Select (Grup else de instruciuni). Dacă mai multe condiii sunt adevărate, atunci se va executa numai un singur grup de instruciuni şi anume cel aflat după prima condiie găsită adevărată. În ValoareI se pot introduce: − reuniuni de mulimi – operatorul virgulă (ex: 1, 2, 5); − intervale – operatorul TO (ex: 1 To 7); − submulimi – operatorul IS (ex: Is > 7). Folosirea clauzei Case Else este opională. O condiie cu rezultatul NULL este tratată ca şi cum ar fi FALSE. Exemplu. Sub TestCase() Dim NumeV As Integer NumeV = 5 Select Case NumeV Case 7 'condiia: NumeV=7 - False MsgBox "Grup 1 de instruciuni" Case 5, 9 'condiia: (NumeV=5) OR (NumeV=9) - True MsgBox "Grup 2 de instruciuni"
'execuia instruciunii(lor) la care condiia=True 'după execuie, instruciunea Case se termină Case 1 To 9 'condiia: (NumeV>=1) AND (NumeV<=9) - True 'deşi şi această condiie=true, acest grup nu va fi executat MsgBox "Grup 3 de instruciuni" I-25
Case Else MsgBox "Grup else de instruciuni" End Select End Sub Exemplu. Procedura următoare este ataşată evenimentului Click a unui buton de comandă cu numele
cmdCase, care se află într-un formular, în care se mai află şi un control textbox cu numele txtValue. Această secvenă se va executa numai atunci când se va face click pe butonul de comandă cu numele cmdCase. Private Sub cmdCase_Click () Dim IResponse As Integer
' Me!NumeControl este o expresie prin care se accesează datele aflate _ într-un control plasat în formularul respectiv. ' Un control se comportă ca o variabilă de tip variant. ă controlul este NULL atunci nu este introdusă nici o valoare. 'IfDac IsNull(Me!txtValue) Then iResponse = 0 Else IResponse = Val(Me!txtValue) 'VAL transformă în număr un string. End If Select Case iResponse Case 0 MsgBox "Trebuie sa introduceti un numar" Case 1 To 5 MsgBox "Ati introdus o valoare intre 1 si 5" Case 7, 11, 21 MsgBox "Ati introdus 7, 11 sau 21" Case Else MsgBox "Ati introdus un numar incorect" End Select End Sub
Această procedură utilizează în prima parte o instruciune If pentru a evalua dacă txtValue este Null, caz în care se memorează un zero într-o variabilă numită iResponse. În caz contrar, valoarea coninută în controlul txtValue este memorată în iResponse. Instruciunea Case evaluează coninutul variabilei iResponse. Dacă valoarea este 0, este afişată o casetă de text cu mesajul "Trebuie să introducei un număr". Dacă valoarea este între 1 şi 5 inclusiv, este afişată o casetă de text coninând mesajul "Ai introdus o valoare între 1 şi 5". Dacă utilizatorul introduce 7, 11 sau 21, este afişat un mesaj corespunzător. În celelalte cazuri, utilizatorul primeşte un mesaj care indică introducerea unui număr incorect.
Instruciunea If... Then... ElseIF…Else If condiie-1 Then [grup 1 de instruciuni] ElseIf condiie-n Then [grup n de instruciuni] ……………. ….. Else [grup else de instruciuni] End If
Instruciunea funcionează similar instruciunii Select Case, numai că: − condiiile introduse sunt independente, ne mai fiind obligatorie prezen a unei variabile ca un termen al condiiei. Deci instruciunea va evalua pe rând, în ordine, condiia 1, 2 etc. • Prima condiie găsită adevărată va determina execuia grupului respectiv de instruciuni şi terminarea instruciunii. • Dacă toate condiiile sunt false, vor fi executate toate instruc iunile dintre Else şi End If (Grup else de instruciuni). Folosirea clauzei Else este opională. I-26
O condiie cu rezultatul NULL este tratată ca şi cum ar fi FALSE.
Exemplu. Sub TestElseIf() Dim V1 As String Dim V2 As String V1 = InputBox("V1=") V2 = InputBox("V2=") If V1 = "" Then 'nu se introduce valoare în V1- şir gol MsgBox "In V1 nu este nici o valoare" ElseIf V2 = "" Then MsgBox "In V1 este ceva, dar nu si in V2" Else MsgBox "Valorile introduse:V1=" & V1 & "; V2=" & V2 End If End Sub
I.5.2.3.Structura repetitiv
ă
Reprezintă execuia repetată a unui anumit grup de instruciuni, numit ciclu sau buclă, până când o condiie ia o anumită valoare. I.5.2.3.a)Structura repetitiv
ă cu test. Instruc
iunea Do…Loop
Execută în mod repetat un ciclu şi anume: • cât timp (While) o condiie este TRUE sau • pân ă când (Until) o condiie devine TRUE Există două forme ale instruciunii Do, în funcie de locul unde se g ăseşte plasată condiia şi anume la început sau sfârşit: Do [{While | Until} condiie] Do [grup instruciuni] [grup instruciuni] sau [Exit Do] [Exit Do] [grup instruciuni] [grup instruciuni] Loop [{While | Until} condiie] Loop Instruciunea Exit Do provoacă ieşirea forată din ciclu. De obicei se execută în funcie de evaluarea unei condiii într-o instruciune IF. Este permisă folosirea instruciunii Do şi fără nici o condiie. În acest caz este obligatorie inserarea în ciclul Do a unei instruciuni Exit Do sau Exit Sub | Function, pentru a nu se genera un ciclu f ără sfârşit. Condiia este evaluată în funcie de locul unde este plasată în instruciune şi anume: − la prima formă a instruciunii (cea din stânga) –înainteaexecutării ciclului; − la a doua formă a instruciunii (cea din dreapta) –după executarea ciclului. Ciclul se execută minim de la: − prima formă a instruciunii (cea din stânga) – se poate ca ciclul s ă nu se execute de loc; − a doua formă a instruciunii (cea din dreapta) – ciclul se va executa minim o dat ă. O condiie cu rezultatul NULL este tratată ca şi cum ar fi FALSE. Exemplu. Private Sub cmdLoop1_Click () Dim iCounter As Integer iCounter = 1 Do While iCounter < 5 MsgBox iCounter ICounter = iCounter + 1 Loop End Sub
Procedura va afişa patru mesaje, cu numere de la 1 la 4. Această structură nu asigură întotdeauna executarea secvenei de cod din interiorul buclei. Dacă în iCounter este introdusă o valoare mai mare sau egală cu 5, codul din interiorul buclei nu va fi executat niciodată. I-27
Dacă secvena de cod trebuie să fie executată necondiionat cel puin o dată, se va folosi urm ătoarea structură: Exemplu. Private Sub cmdLoop2_Click () Dim iCounter As Integer iCounter = 5 Do MsgBox iCounter ICounter = iCounter + 1 Loop While iCounter < 5 End Sub
Procedura va afişa un mesaj cu num ărul 5. Acest cod va fi executat cel pu in o dată, indiferent de valoarea din iCounter, deoarece evaluarea condiiei se face după executatea ciclului. Structura Do While|Until... Loop face evaluarea condiiei înainte de executarea ciclului şi de aceea nu asigură execuia acestuia. Structura Do... Loop While|Until face evaluarea condiiei după executarea ciclului şi de aceea execuia acestuia este asigurată cel puin o dată. I.5.2.3.b)Structura repetitiv
ă cu contor. Instruc
iunea For…Next
Repetă un ciclu de un anumit num ăr de ori. Mai există o structură: FOR EACH... NEXT, care se aplică coleciilor de obiecte sau tablourilor şi care va fi prezentat ă în următorul capitol. Această instruciune permite parcurgerea automată a tuturor elementelor unei colecii sau tablou. Forma instruciunii FOR este: For contor = start To end [Step pas] [grup instruciuni]
[Exit For] [grup instruciuni] Next [contor] în care: − contor – variabilă numerică folosită pentru stabilirea numărului de execuii ale ciclului; − start – valoarea iniială a contorului; − end – valoarea finală a contorului; ă; poate fi pozitivă sau negativă (implicit este 1); − pas – valoarea cu care contorul se incrementeaz incrementarea se efectuează după execuia fiecărui ciclu. Funcionarea instruciunii FOR se face prin parcurgerea urm ătoarelor etape: a) se determină în funcie de valoarea (pozitivă sau negativă) pe care o are pasul (step), condiia de terminare a ciclului şi anume: − Dacă PAS >=0, condiia va fi: contor > end; − Dacă PAS < 0, condiia va fi: contor < end; b) se evaluează condiia de terminare a ciclului; c) în continuare, dac ă condiia este: − FALSE – se execută ciclul şi se continuă instruciunea FOR cu etapad); − TRUE – nu se execută ciclul şi se termină instruciunea FOR. Programul continuă cu instruciunile de după NEXT; d) după executarea ciclului se adună pasul la contor. După această operaie instruciunea FOR continuă cu repetarea evaluării condiiei, adică cu etapa b).
Deci, practic, la fiecare ciclu, contorul va parcurge toate valorile de la start la end. Dacă pasul este: • pozitiv, atunci: − dinamica contorului va fi cresc ătoare, prin adăugarea valorii pasului la fiecare ciclu; − pentru ca s ă se execute cel puin un ciclu, trebuie ca la început start<=end ; − numărul de cicluri efectuate va fi: end-start+1. • negativ, atunci: I-28
− dinamica contorului va fi descrescătoare, prin scăderea valorii absolute a pasului la fiecare
ciclu; − pentru ca s ă se execute cel puin un ciclu, trebuie ca la început start>=end ; − numărul de cicluri efectuate va fi: start-end+1. Instruciunea Exit For provoacă ieşirea forată din ciclu şi continuarea programului cu instruciunile de după NEXT. De obicei se execută în funcie de evaluarea unei condiii într-o instruciune IF. Sunt admise imbricări ale structurilor For, dacă sunt folosite variabile contor diferite ca în exemplul următor:
For I = 1 To 10 For J = 1 To 10 For K = 1 To 10 ... Next K Next J Next I Într-un For trebuie evitată schimbarea valorii contorului.
Structura For... Next este folosită atunci când sunt un număr exact de iteraii de executat.
Exemplu. Private Sub cmdForNext_Click () Dim iCounter As Integer For iCounter = 1 To 5 MsgBox iCounter Next iCounter End Sub
Procedura va afişa cinci mesaje, cu numere de la 1 la 5. Observai că: − iCounter se auto-incrementează; − se pot folosi variabile atât pentru valoarea de start, cât şi pentru cea de sfârşit; − dacă valoarea de incrementare a contorului este diferită de 1, se dă după cuvântul cheie STEP, printr-un literal sau o variabilă (pas).
Exemplu. Private Sub cmdForNext_Click () Dim iCounter As Integer For iCounter = 5 To 1 Step -1 MsgBox iCounter Next iCounter End Sub
Procedura va afişa cinci mesaje, cu numere de la 5 la 1.
I.6. Rutine – proceduri şi funcii I.6.1. Ce est e o r uti n ă ş i ce elemente o definesc?
Rutina este o structură de sine stătătoare, asemănătoare unui program, prin care se efectueaz ă o anumită aciune. Ea este executată numai atunci când este lansată (apelată), de către un obiect al aplicaiei care poate fi: − programul – numai în cazul limbajului Visual Basic, dar nu şi în cel al VBA; − o altă rutină; − un eveniment al unui obiect al aplicaiei; − un macro. Rutina poate fi apelată de un număr nelimitat de ori din diferite locuri. După execuia unei rutine, controlul revine obiectului care a provocat apelarea rutinei. Toate declaraiile (variabile, constante) făcute în interiorul rutinei sunt locale, fiind deci vizibile numai din interiorul acesteia. De asemenea, durata de viaă a datelor locale este numai în intervalul de timp cât rutina se află în execuie. La terminarea rutinei, are loc automat eliberarea din memorie a tuturor variabilelor şi constantelor locale ale acesteia. I-29
În Visual Basic nu sunt permise imbricări de rutine. Deci într-o rutină nu se poate declara o altă rutină. Diferit faă de programe, rutina interacionează cu obiectul care a provocat lansarea (apelarea) ei, prin transferarea de date din şi înspre acesta. Acest lucru se realizează în două moduri şi anume: Prin lista de parametri. Aceasta reprezintă practic nişte variabile, prin intermediul cărora se face: − un transfer de date de la modulul care apelează la rutină – parametri de intrare – produs în momentul apelării rutinei; − un transfer de date de la rutină înspre modulul apelant – parametri de ieşire – produs în momentul terminării rutinei şi preluării controlului de către modulul apelant; Prin variabile globale sau publice. Aceste variabile fiind vizibile şi din modulul apelant şi din rutină, evident că prin ele se pot face transferuri de date în ambele sensuri între cele dou ă obiecte. • Definirea unei rutine se face prin atribuirea unui nume (obligatoriu) acesteia şi prin stabilirea listei de parametri (opional). Parametrii definii în rutină se numesc parametri formali. • Declararea parametrilor formali se face după regulile aplicate la declararea variabilelor. • Apelarea unei rutine se face prin numele ei. • La apelarea unei rutine, corespunzător fiecărui parametru formal, trebuie să existe o dată de acelaşi tip în modulul apelant, care poate fi o variabilă, o constantă, o expresie sau un literal. Aceste date formează lista parametrilor actuali şi este declarată o dată cu apelarea rutinei. Evident parametrii actuali şi formali trebuie să fie de acelaşi tip şi să ocupe acelaşi loc în cele două liste. • Parametrii de intrare ai rutinei pot fi în lista parametrilor actuali: variabile, constante, literali sau expresii. • Parametrii de ieşire ai rutinei pot fi în lista parametrilor actuali numai variabile, deoarece aceştia prin definiie îşi pot schimba valoarea în timpul execuiei rutinei. Din punct de vedere al terminologiei se mai obişnuieşte să se folosească în loc de parametru termenul argument.
I.6.2. Transmiterea datelor prin parametri
Există două modalităi de transmitere a datelor prin parametri şi anume, prin valoare sau prin adresă (referină).
Apelarea rutinelor şi transmitera parametrilor prin valoare
Din figura următoare se obsevă că avem perechi de parametri, actuali şi formali, care reprezintă practic două variabile care se sincronizează de două ori: prima dată la apelarea rutinei şi a doua dată la terminarea rutinei. Astfel la apelarea rutinei se face practic pentru fiecare pereche de parametri operaia de transfer: ParametruFormal=ParametruActual (de ex: A1=X1 sau A2=X2 etc.) iar la terminarea rutinei transferul invers: ParametruActual=ParametruFormal (de ex: T=B1 sau Y=B1 etc.) Modul apelant ………. Instr N….. X1=…. Instr N+1.. X2=…. Apelare rutină - Rtest
X1,X2
Y
Rutina Nume: Rtest Parametrii formali: Intrare: A1, A2
A1,A2
Ieşire:
Instr1
B1
Parametri actuali:X1, X2, Y
………... ..= A1 + A2 ' folosirea
Instr. ….= …Y
……….. Instr J…… M1=…. Instr J+1… M2=…. Apelare rutină - Rtest
'parametrilor de intrare M1,M2
……….. B1= …… ' folosirea
A1,A2
'parametrilor de ieşire
Parametri actuali:M1, M2, T
Instr. ….= …T
B1
T
……….. Sfârşit rutină
B1
……..
I-30
Deci în acest caz se transferă anumite valori, în ambele sensuri, şi actuali. Spunem că transmisia parametrilor se face prin valoare.
între perechile de parametri formal
Apelarea rutinelor şi transmitera parametrilor prin adresă Modul apelant ………. Instr N….. X1=…. Instr N+1.. X2=…. Apelare rutină - Rtest Parametri actuali:X1,X2,Y Instr. ….= …Y ……….. Instr J…… M1=…. Instr J+1… M2=…. Apelare rutină - Rtest Parametri actuali:M1,M2,T
Instr. ….= …T ………..
Rutina Nume: Rtest Parametri actuali X1
X2
Y
a d r e s e
Parametrii formali: Intrare:A1,A2 Ieşire:B1
Instr1
A1 A2 B1 Parametri formali
……….. ..= A1+A2 'folosirea 'parametrilor de intrare ………..
Parametri actuali X1 X2 Y
B1 = ….. 'folosirea 'parametrilor de ieşire ……….. Sfârşit rutină
a d r e s e A1 A2 B1 Parametri formali
În acest caz lucrurile se petrec altfel. Transferul se face numai la apelarea rutinei, dar nu se vor transfera valori, ci rutina va primi adresele parametrilor actuali. În acest fel în rutină parametrii formali se vor genera în memorie peste parametrii actuali. Deci rutina va lucra practic cu parametrii actuali, de şi va folosi numele parametrilor formali în expresii. În Visual Basic, dacă nu se fac precizări suplimentare, transmiterea parametrilor se face prin adresă (referină). I.6.3. Crear ea ( defi nire a) u nei r uti ne
sunt de două feluri: proceduri (sau subrutine) şi funcii. Diferena dintre ele constă în faptulRutinele că: şire care este chiar numele func iei. • Funciile au un parametru implicit de ie • Procedurile sunt apelate prin instruciuni, iar funciile sunt apelate prin introducerea numelui acesteia într-o expresie (ca şi cum ar fi o variabilă sau constantă). Funciile pot fi folosite direct oriunde este cerută o expresie, cu condiia vizibilităii ei din locul de apelare. Astfel putem folosi func ii ca: parametri de intrare pentru rutine, la definirea propriet ăilor din controale, la cereri etc. I.6.3.1.Proceduri (Subrutine) [Private|Public][Static] Sub NumeProcedura [(ListaParametriFormali)] [declaraii locale de: variabile, constante, etc. ] [instruciuni] [Exit Sub] [instruciuni] End Sub
• Instruciunea Exit Sub provoacă, dacă este întâlnită, terminarea procedurii şi redarea controlului modulului apelant, la instruciunea care se găseşte imediat după cea de apelare. În mod normal procedurile se termină la instruciunea End Sub. • Opiunile Private sau Public au acelaşi rol ca cel prezentat la variabile. Astfel, procedura declarată Public în modulul general de cod va fi vizibilă din toate modulele de cod ale aplicaiei, iar cea declarată Private va fi vizibilă numai din modulul în care este declarată. Dacă nu se foloseşte nici una din cele două opiuni, procedura va fi considerată Public. • Opiunea Static determină ca toate variabilele locale declarate în procedură să funcoineze ca variabilele statice. • Toate instruciunile sunt permise în proceduri,folosind date care pot fi: − parametrii formali;
I-31
− variabilele şi constantele globale; − variabilele şi constantele locale;
Este indicat ca să se evite, pe cât posibil, în crearea rutinelor, folosirea variabilelor globale. Pentru schimburile de date dintre rutină şi modulul apelant este recomandată utilizarea numai a parametrilor formali. Acest lucru se datorează faptului că o rutină care foloseşte multe variabile globale este de multe ori foarte puin lizibilă, greu de depanat sau de întreinut. • Lista Parametrilor Formali – reprezintă o listă de variabile, declarate după regulile prezentate la variabile şi separate prin virgulă. Un parametru se declară conform structurii de mai jos: [ByVal | ByRef] NumeParametru As TipDate Opiunile ByVal sau ByRef precizează modalitatea de transmitere a parametrului respectiv şi anume: − ByVal – prin valoare; − ByRef – prin adres ă (referină); Implicit, transferul parametrilor se face prin adresă.
I.6.3.2.Func i i [Public|Private][Static]Function NumeF-cie[(ParFormali)] [As TipFuncie] [declaraii locale de: variabile, constante, etc. ] [instruciuni]
[Exit Function] [instruciuni] End Function
Se observă că singura deosebire esenială faă de proceduri se datorează faptului că numele funciei are două semnificaii, fiind în acelaşi timp şi numele rutinei şi parametru de ieşire al rutinei. Din această cauză acestuia trebuie să i se precizeze tipul de date. Dacă acest lucru nu se face atunci tipul funciei se va considera implicit Boolean. Deci o funcie, după ce este executată, se va comporta practic ca o variabil ă – care s-a încărcat cu valoarea parametrului de ieşire – putând fi introdus ă direct în partea dreaptă a oricărei expresii. În loc de Exit Sub şi End Sub, la funcii sunt Exit Function şi End Function, evident cu acelaşi rol. Exemplu. Următorul exemplu reprezintă o funcie care va testa două valori primite ca parametri şi va întoarce suma sau diferen a dintre ele. Function TestF (Numar1 As Integer, Numar2 As Integer) As Integer If Numar1 > Numar2 Then TestF = Numar1 - Numar2' valoarea de retur se introduce în numele_ funciei Else TestF = Numar1 + Numar2' valoarea de retur se introduce înnumele_ funciei End If End Function
……. Se va folosi această funcie astfel…. MsgBox TestF (20, 5) ' afişează 15 MsgBox TestF (2, 5) ' afişează 7
I.6.4. Apelarea unei rutine
Orice funcie poate fi apelată ca o procedură, dar o procedură nu poate fi folosită ca o funcie (în partea din dreapta a unei expresii).
I.6.4.1.Apelarea unei proceduri
(subrutine)
Există două modalităi de apelare a unei proceduri: prin instruciunea Call: Call NumeProcedură (ListaParametrilorActuali) direct, folosind numele procedurii, urmat eventual de lista parametrilor actuali: NumeProcedură ListaParametrilorActuali Parametrii se separă prin virgulă. I-32
Diferena între cele două forme este că la apelarea cu Call, parametrii actuali ai procedurii trebuie scrişi între paranteze, pe când la apelarea directă prin numele procedurii nu se foloseasc parantezele.
I.6.4.2.Apelarea unei func
ii
O funcie se apelează dintr-o expresie, folosindu-se numele ei urmat de lista parametrilor actuali incluşi între paranteze. Numele funciei, se va comporta în expresie ca o variabilă, încărcată după execuia funciei cu o valoare, ca şi cum ar fi un parametru de ie şire al unei proceduri. Spunem c ă funcia întoarce (returnează) o valoare după execuia ei. Această valoare va participa la evaluarea expresiei respective. O procedură nu poate fi folosită într-o expresie în locul unei funcii, deoarece nu întoarce valori prin numele ei (chiar dacă are parametri de ieşire). Funciile pot fi apelate şi ca pe o procedură în oricare din cele două modalităi prezentate. Exemplu. Refacem exemplul prezentat înainte folosind o procedură TestS în locul funciei TestF. Sub (Numar1 As Integer, If TestS Numar1 > Numar2 Then Numar2 As Integer, Rezultat As Integer) Rezultat = Numar1 - Numar2 ' valoarea calculată se introduce în _ parametrul de ie şire Else Rezultat = Numar1 + Numar2 ' valoarea calculată se introduce în _ parametrul de ie şire End If End Sub
……. Se va folosi această procedură astfel…. Dim Rez As Integer Call TestS (20, 5, Rez) ' calculează în Rez MsgBox Rez ' afişează 15 TestS 2, 5, Rez ' calculează în Rez MsgBox Rez ' afişează 7
I.6.5. Domeniul de vizibilitate al rutinelor
Regulile prezentate la variabile privind această problemă sunt valabile şi pentru rutine. ăi numite rutine. Aceste rutine sunt p ăstrate fie în modulul VBAdeeste Codul în unit general (global) cod,scris fie înnumai modulele specifice din spatele formularelor sau rapoartelor (Code Behind Forms – CBF). Domeniul de valabilitate sau de vizibilitate a rutinei este determinat de cuvântul utilizat în declararea acesteia: Private sau Public şi de locul unde rutina e plasată. O rutină este publică dacă este declarată Public şi este plasată în modulul general de cod. Ea este vizibilă în toată aplicaia. Restul rutinelor sunt locale şi sunt vizibile numai din modulul unde au fost declarate.
I.6.6. Dur at a de via ţă a rutinelor
Durata de viaă a unei rutine, adică timpul în care ea se găseşte în memorie, este în funcie de locul unde a fost declarată şi anume: • pe toată durata aplicaiei dacă se găseşte în modulul general de cod; • cât timp este în execuie un formular sau raport, dacă se găseşte în codul din spatele acestuia. I.6.7. Rutine definite de util izator. Introduce rea codul ui VB A
Pentru a crea o rutin ă definită de utilizator într-un modul general (global) de cod, urma i paşii de mai jos: • executai clic pe marcajul de tabulare Modules din fereastra bazei de date; • începei un modul nou sau selecta i un modul existentşi executai clic pe opiunea Design; • selectai opiunea Insert Procedure (inserează rutină) de pe bara cu instrumente sau selectai opiunea Procedure din meniul Insert. Va apărea pe ecran caseta de dialog prezentată anterior. • introducei numele rutinei şi selectai tipul acesteia: funcie, procedură (subrutină) sau proprietate (se va prezenta în alt capitol).
I-33
Indicai dacă dorii ca rutina să fie publică (pentru întreaga aplicaie) sau privată (numai pentru acest modul). De asemenea, specificai dacă toate variabilele locale din rutină sunt statice sau nu. Terminai definirea rutinei cu clic pe OK. Pentru a crea o rutină definită de utilizator în modulul de cod din spatele unui formular sau raport se procedează la fel, în afară de afişarea modulului, care se face astfel:
• în timp ce vă aflai în modul de afişare Design al unui formular sau raport, vizualiza i codul din spatele formularului sau raportului executând clic pe butonul Code de pe bara de instrumente sau prin selectarea opiunii Code din meniul View, sau prin pictograma specifică de pe bara de instrumente.
I.6.8. Proce duri le eveni mente lor Procedurile evenimentelor sunt apelate automat când are loc un eveniment pentru un anumit
obiect. ă click butonacel de buton comand De, exemplu, cândautomat, un utilizator execut cu mouse-ulClick pe unpentru dintr-un formular este executat dacă exist ă, codul evenimentului deăcomand ă, cod care se va găsi plasat sub forma unei proceduri eveniment în modulul de cod din spatele formularului respectiv. Procedura unui eveniment al unui control este creată automat (prima şi ultima instruciune a procedurii, adică Sub şi End Sub) când se selectează dintre proprietăile controlului evenimentul respectiv. Numele procedurii va fi obligatoriu stabilit de sistem, în funcie de numele controlului şi al evenimentului respectiv. De asemenea, dacă este cazul, este ataşată, tot de către sistem, lista parametrilor formali. Exemplu. Într-un formular se găseşte un control de tip buton de comandă, cu numele cmdOkay (şi proprietatea Caption="Apasa") şi trei controale de tip textbox, cu numele txtNume, txtVirsta şi txtSex. Instruciunea de declarare a procedurii eveniment: Private Sub cmdOkay_Click, ca şi aceea de sfârşit (End Sub), sunt create automat atunci când se selectează evenimentul Click din lista proprietăilor butonului de comandă cmdOkay. În continuare programatorul introduce codul surs ă al procedurii eveniment:
Private Sub cmdOkay_Click () If IsNull(Me!txtNume) Or IsNull(Me!txtVirsta) _ Or isNull(Me!txtSex) Then MsgBox "Trebuie introduse numele, virsta şi sexul" Exit Sub 'Dacă nu sunt date în toate cele trei textbox-uri se afişează _ mesajul şi se termină
procedura Else 'Afişează val. din txtNume şi ce întoarce funcia CalculVirsta MsgBox "Numele d-tra este: " & Me!txtNume & _ Chr(10) & Chr(13) & "Virsta dv este acum de: " & _ CalculVirsta(Int(Val(Me!txtVirsta)), Me!txtSex) & " ani" End If End Sub
Procedura de mai sus va fi executată de fiecare dată când se va face click pe butonul de comandă cmdOkay al formularului. Dacă în toate cele trei controale textbox sunt introduse date, atunci se afişează un mesaj ca în figura al ăturată; altfel se va afişa mesajul: "Trebuie introduse numele, vârsta şi sexul" şte următoarele funcii ce se găsesc în bibliotecile folose sistemProcedura (prezentate în continuarea acestui capitol): • IsNull(pm) – întoarce TRUE dacă parametrul pm este Null; • Chr(10) – întoarce caracterul LF - Line Feed (rând nou); • Chr(13) – întoarce caracterul CR - Carriage Return (retur de car); • Val(pm) – întoarce valoarea numerică din stringul pm; • Int(pm) – întoarce partea întreagă din pm. Un control se comportă ca o variabilă de tip variant. Datele din control pot fi accesate cu sintaxa Me!NumeControl, dar numai din codul din spatele formularului respectiv. Dac ă nu sunt date introduse în control, atunci valoarea acestuia este Null.
I-34
Procedura eveniment utilizează o funcie utilizator, declarată în acelaşi modul de cod din spatele formularului respectiv, care are doi parametri formali de intrare şi anume: V – în care se va transfera valoarea numerică întreagă din textbox txtVirsta şi S – în care se va transfera valoarea din textbox txtSex. Function CalculVirsta (V As Integer, S As Variant) As Integer If V > 35 And S = "F" Then CalculVirsta = V - 10 ElseIf V > 25 And S = "F" Then CalculVirsta = V - 5 ElseIf V > 20 And S = "F" Then CalculVirsta = V - 2 ElseIf S = "M" Then CalculVirsta = V + 5 Else CalculVirsta = V End If End Function
Pentru a edita codul evenimentului, executai următorii paşi:
• executai click pe control (cmdOkay) în modul de afişare Design şi apoi pe butonul Properties din bara cu instrumente sau executai click cu butonul drept al mouse-ului pe obiectşi selectai opiunea Properties din meniul contextual; ăilor evenimentuluiEvent ( ); • executai click pe marcajul de tabulare al propriet • selectai proprietatea pentru care dori i să scriei instruciuni de cod (de exemplu, evenimentul On Click); • selectai [Event Procedure] din lista derulantă; • executai clic pe butonul (…). Cursorul dumneavoastră va fi plasat în codul evenimentului pentru obiectul respectiv. Automat sistemul va crea instruciunea de declarare a procedurii, – eventual cu lista de parametri formali, dacă este cazul – şi instruciunea de sfârşit a procedurii. Proiectantul va introduce acum codul VBA necesar tratării evenimentului.
I.6.9. Utilizarea combinat
ă a procedurilor eveniment cu rutinele utilizator
Am arătat că atât subrutinele, cât şi funciile pot primi argumente (parametri), dar numai func iile pot întoarce valori. Exemplu. Subrutina următoare primeşte doi parametri, txtFirst şi txtLast. Aceasta afişează apoi un mesaj cu primul caracter al fiecăruia dintre cei primii. Private Sub Initialele (sFirst As String, sLast As String) MsgBox "Initialele dumneavostră sunt: " & _ Left (sFirst, 1) & Left (sLast, 1) ' Funcia Left întoarce caracterele_ de la începutul unui string End Sub • Ea va fi apelată din procedura eveniment On Click a butonului de comandă cmdNume. Private Sub cmdNume_Click () Initialele Me !txtFirstName, Me!txtLastName End Sub Observai că textul din controalele txtFirstName şi txtLastName din formularul curent (Me) sunt
Initialele transmise numele este Parametrii recepionai ca sFirst şi sLast. Primul caracter din stânga subrutinei al fiecărui cu parametru afişat. în caseta desunt mesaje. Codul precedent transmite pur şi simplu valori şi apoi operează cu ele. Exemplu. În continuare se ilustrează folosirea unei funcii care întoarce o valoare. Private Function ReturnInit (sFName As String, sLName As String) As String ReturnInit = Left (sFName, 1) & Left (sLName, 1) End Function • Ea va fi apelată din procedura eveniment On Click a butonului de comandă cmdNume. Private Sub cmdNume_Click () Dim sInitials As Integer sInitials = ReturnInit (Me!txtFirstName, Me!txtLastName) MsgBox "Initialele dumneavostra sunt: " & sInitials I-35
End Sub
Reinei c ă acest exemplu apelează o funcie ReturnInit, trimiând valorile celor două casete de text ca parametri ai funciei. Funcia asociază numelui funciei (ReturnInit) o valoare egală cu primele două caractere ale şirurilor. Apoi, funcia întoarce această valoare rutinei apelante (cmdNume_Click) şi o atribuie variabilei sInitials. I.6.10. Parametri op ţ ionali
Visual Basic vă permite să utilizai parametri opionali. Cu alte cuvinte, nu este necesar să ştii câ i parametri vor fi transmişi. Funcia numită ReturnInit din secvena de cod următoare primeşte ultimii doi parametri ca opionali. Apoi evaluează prezena sau nu a parametrilor şi acionează în consecină. Function ReturnInit (sFName As String, Optional sMI, Optional sLName) As String If IsMissing (sMI) Then ' IsMissing întoarce True dacă s-a apelat _ funcia fără parametrul
sMI SMI End If = InputBox ("Introducei initiala cuvantului din mijloc ") If IsMissing (sLName) Then ' IsMissing întoarce True dacă s-a _ apelat funcia fără
parametrul sLName
SLName = InputBox ("Introducei ultimul nume") End If ReturnInit = sLName & " " & sMI & " " sFName End Function •
Această funcie poate fi apelată de exemplu în felul urm ător:
sName = ReturnInit ("Bill",, "Gates")
Aşa cum ai putut vedea, lipseşte al doilea parametru. În loc s ă rezulte o eroare de compilare, funcia ReturnInit va sesiza acest lucru şi prin funcia InputBox va cere utilizatorului introducerea valorii respective. • Sau mai poate fi apelată şi: sName = ReturnInit ("Bill", "X", "Gates") În acest caz funcia, prin folosirea lui IsMissing, va sesiza prezena tuturor celor trei parametri actuali. Lucrul cu parametri opionali, deci care pot să lipsească la apelarea rutinei, necesită: − declararea ca opional a parametrului, prin folosirea clauzei Optional, în faa numelui parametrului. O restricie a limbajului este faptul c ă numai ultimii parametri pot fi declarai opionali. − testarea prin funcia IsMissing , dacă a fost sau nu introdus la apelare parametrul respectiv în lista parametrilor actuali. Dacă nu se doreşte introducerea în lista parametrilor actuali a unui parametru opional, atunci se va scrie numai separatorul (virgula) parametrului respectiv. Funcia IsMissing este valabilă numai pentru parametri de tip variant. − pentru parametrii declarai opional, se poate introduce o valoare implicit ă, cu care se va iniializa parametrul dacă acesta lipseşte din lista parametrilor actuali. Dacă se folosesc parametri opionali, declararea acestora în lista parametrilor formali este: [Optional] NumeParametru As TipDate [ = ValoareImplicita ]
I.7. Biblioteci standard de proceduri şi funcii O bibliotecă este un obiect de sine stătător care permite realizarea unei colecii de funcii, proceduri, clase de obiecte, coleciişidestandarde obiecte şiintroduse obiecte. de Microsoft permit ca modulele unei biblioteci să fie Noile tehnologii utilizate de toate aplicaiile client de pe platforma S.O. care respectă standardele de utilizare ale acestora. În Visual Basic, există posibilitatea creării mai multor tipuri de biblioteci. Microsoft Office, oferă mai multe biblioteci, care pot fi utilizate în Access, Visual Basic sau alte aplicaii. Pentru aceasta trebuie ca în prealabil aplicaia client să înregistreze şi să creeze referina (adresa) către biblioteca respectivă. Acest lucru se face prin comanda References. Implicit, o aplicaie are chiar din faza de instalare create referinele către cele mai utilizate biblioteci specifice. Aplicaiile Access au referine create către anumite biblioteci, ale căror module pot fi utilizate oriunde acestea sunt permise. În acest subcapitol, vor fi prezentate în special cele mai utilizate funcii şi proceduri ale acestor biblioteci. I-36
Un bun programator trebuie să cunoască şi să folosească cât mai multe din obiectele puse la dispoziie de biblioteci. De exemplu dacă se realizează o aplicaie care la un moment dat trebuie s ă calculeze sinusul dintr-o valoare, un programator neexperimentat ar putea să creeze un modul care să rezolve acest lucru, pe când un bun programator, ştiind că există în biblioteci funcia Sin, care calculează sinusul unei valori, va rezolva imediat această problemă, folosind pur şi simplu funcia respectivă. Pentru a putea utiliza o funcie dintr-o bibliotecă, programatorul trebuie să cunoască trei lucruri: − numele funciei; − parametrii şi ce reprezintă fiecare; − ce reprezintă valoarea pe care o întoarce func ia (adică ce operaii efectuează funcia). În crearea expresiilor, în Access se poate folosi un constructor de funcii – Expressions Builder, lansat de obicei din meniul contextual (Build). Acesta este foarte util, prezentând toate funciile, parametrii acestora, modulul de Help, operaiile permise În etc. concluzie, în codul VBA, în controalele din formulare sau rapoarte, în proprietăile tabelelor sau cererilor, se pot folosi în crearea expresiilor atât funciile definite (create) de utilizator cât şi funciile din bibliotecile către care există referine. Toate acestea se pot vizualiza prin Expressions Builder (prin cele două foldere din Functions, aşa cum se vede din figură). Access are referine implicite către o bibliotecă de funcii şi proceduri, foarte bogată şi cuprinzătoare, din care vor fi prezentate în continuare cele mai utilizate. I.7.1. Func ţ ii matematice I.7.1.1. Int(num ă r); Fix(num ă r )
Ambele funcii întorc partea întreagă a numărului introdus ca parametru de intrare. Tipul de dată al rezultatului va fi acelaşi cu cel al parametrului de intrare. Ambele funcii Int şi Fix îndepărtează partea fracionară a numărului şi întorc valoarea întreagă care rezultă. Diferena între Int şi Fix se manifestă numai în cazul numerelor negative. Astfel: • Int întoarce primul număr negativ de tip întreg mai mic sau egal cu numărul; Int (–8. 4) = –9; • Fix întoarce primul număr negativ de tip întreg mai mare sau egal cu numărul; Fix (–8. 4) = –8. Exemplu. Dim Nr ' variabilă declarată fără specificarea tipului de dat ă-VARIANT. Nr = Int (99. 8) ' Întoarce 99. Nr = Fix (99. 2) ' Întoarce 99. Nr = Int (-99. 8) ' Întoarce -100. Nr = Fix (-99. 8) ' Întoarce -99.
I.7.1.2.Abs(num ă r )
Întoarce valoarea absolută a numărului introdus ca parametru de intrare. Tipul de dată al rezultatului va fi acelaşi cu cel al parametrului de intrare. Exemplu. Dim Nr Nr = Abs (50. 3) ' Întoarce 50. 3. Nr = Abs (-50. 3) ' Întoarce 50. 3.
I.7.1.3.Sgn(num ă r )
Întoarce un Variant (Integer) care reprezintă semnul unui număr. Dacă parametrul este: <0 >0 =0 –1 1 0 Sgn întoarce: Exemplu. Dim Semn aA Variant I-37
Const Valoare1= 12, Valoare2= -2. 4, Valoare3= 0 Semn = Sgn (Valoare1) ' Întoarce 1. Semn = Sgn (Valoare2) ' Întoarce -1. Semn = Sgn (Valoare3) ' Întoarce 0.
I.7.1.4.Sqr(num ă r )
Întoarce o valoare de tip Double (virgulă mobilă dublă precizie) care reprezintă radicalul (square root) unui număr pozitiv (≥ 0). Exemplu. Dim Radical Radical = Sqr(4) ' Întoarce 2. Radical = Sqr(23) ' Întoarce 4. 79583152331272. Radical = Sqr(0) ' Întoarce 0. Radical = Sqr(-4) ' Generează o eroare de execuie. I.7.1.5.Exp(num ă r )
Întoarce o valoare de tip Double care reprezintă constanta e ridicată la o putere (în care e este baza logaritmului natural). Exemplu. Dim Unghi, SinHiper Unghi = 1. 3 ' Defineşte unghiul în radiani SinHiper = (Exp (Unghi) - Exp (-1 * Unghi) ) / 2 ' Calcul sin hiperbolic
I.7.1.6.Log(num ă r )
Întoarce o valoare de tip Double care reprezintă logaritmul natural al unui număr (> 0). Logaritmul natural este logaritmul în baza e. Constanta e~2,718282. Exemplu. Dim Unghi, Logaritm Unghi = 1.3 ' Defineşte unghiul în radiani Logaritm=Log(Unghi+Sqr(Unghi*Unghi+1))' inversul sin hiperbolic
I.7.1.7.Rnd [(num ă r ) ]
Întoarce o valoare de tip Single (virgulă mobilă simplă precizie) care va conine un număr aleator. Valoarea întoarsă de Rnd este: Dacă parametrul este: <0 >0 =0 Fără (de obicei)
Rnd generează
Acelaşi număr de fiecare dată, folosind parametrul ca valoare de iniializare. Următorul număr din secvenă. Cel mai recent număr generat. Următorul număr din secvenă.
Argumentul (parametrul) este opional şi poate fi un Single sau o expresie numerică corectă. Funcia Rnd întoarce o valoare în intervalul [0.. 1). Valoarea parametrului determină cum Rnd generează un număr aleator. Pentru o anumită valoare iniială, este generată aceeaşi secvenă de numere, deoarece fiecare apel ş ă ă ă succesiv alăfunc din secven . iei Rnd folose te num rul generat anterior ca valoare pentru calculul urm torului num r Înainte de prima folosire a funciei Rnd, dacă se doreşte generarea unei secvene de numere aleatoare, atunci generatorul de numere aleatoare trebuie iniializat cu o valoare întâmplătoare. Pentru aceasta se va folosi procedura Randomize, fără parametri, care va folosi pentru iniializarea generatorului de numere aleatoare ceasul sistemului de calcul. Dacă se doreşte generarea unor numere întregi, în intervalul [a.. b], se foloseşte formula: Int(a + (b
- a + 1) * Rnd) Exemplu. Dim Valoare Randomize Valoare=Int(1+(6*Rnd)) ' Generează o valoare aleatoare între 1 şi 6. I-38
I.7.1.8.Sin(num ă r )
Întoarce o valoare de tip Double care este sinusul unui unghi în radiani. Rezultatul va fi în intervalul [–1.. 1]. Pentru a transforma gradele în radiani se înmul esc gradele cu pi/180. Invers se vor înmuli radianii cu 180/pi. Exemplu. Dim Unghi, Cosecanta Unghi = 1.3 ' Defineşte unghiul în radiani. Cosecanta = 1 / Sin(Unghi) ' Calculează cosecanta.
I.7.1.9.Cos(num ă r )
Întoarce o valoare de tip Double care este cosinusul unui unghi în radiani. Exemplu. Dim Unghi, S Unghi = 1. 3 ' Defineşte unghiul în radiani. S = 1 / Cos (MyAngle) ' Calculează secanta.
I.7.1.10.Tan(num ă r )
Întoarce o valoare de tip Double care este tangenta unui unghi în radiani. Pentru a transforma gradele în radiani se înmul esc gradele cu pi/180. Invers se vor înmuli radianii cu 180/pi. Exemplu. Dim Unghi, Cotangenta Unghi = 1. 3 ' Defineşte unghiul în radiani Cotangenta = 1 / Tan (Unghi) ' Calculează cotangenta
I.7.1.11.Atn(num ă r )
Întoarce o valoare de tip Double care reprezintă arctangenta unui număr. Exemplu. pi = 4 * Atn(1) ' Calculează valoarea lui pi. I.7.1.12.Calculul func iilor matematice derivate Secant Cosecant Cotangent Inverse Sine Inverse Cosine Inverse Secant Inverse Cosecant Inverse Cotangent Hyperbolic Sine Hyperbolic Cosine Hyperbolic Tangent Hyperbolic Secant Hyperbolic Cosecant Hyperbolic Cotangent Inverse Hyperbolic Sine Inverse Hyperbolic Cosine
Sec (X) = 1 / Cos (X) Cosec (X) = 1 / Sin (X) Cotan (X) = 1 / Tan (X) Arcsin (X) = Atn (X / Sqr (-X * X + 1) ) Arccos (X) = Atn (-X / Sqr (-X * X + 1) ) + 2 * Atn (1) Arcsec (X) = Atn(X / Sqr(X*X –1)) + Sgn( (X)–1) * (2*Atn(1)) Arccosec (X) = Atn(X / Sqr(X*X-1)) + (Sgn(X)–1) * (2*Atn(1)) Arccotan (X) = Atn (X) + 2 * Atn (1) HSin (X) = (Exp (X) – Exp (-X) ) / 2 HCos (X) = (Exp (X) + Exp (-X) ) / 2 HTan (X) = (Exp (X) – Exp (-X) ) / (Exp (X) + Exp (-X) ) HSec (X) = 2 / (Exp (X) + Exp (-X) ) HCosec (X) = 2 / (Exp (X) – Exp (-X) ) HCotan (X) = (Exp (X) + Exp (-X) ) / (Exp (X) – Exp (-X) ) HArcsin (X) = Log (X + Sqr (X * X + 1) ) HArccos (X) = Log (X + Sqr (X * X – 1) )
Inverse Hyperbolic Tangent Inverse Hyperbolic Secant Inverse Hyperbolic Cosecant Inverse Hyperbolic Cotangent Logarithm to base N
HArctan (X) = Log ( (1 + X) / (1 – X) ) / 2 HArcsec (X) = Log ( (Sqr (-X * X + 1) + 1) / X) HArccosec (X) = Log ( (Sgn (X) * Sqr (X * X + 1) + 1) / X) HArccotan (X) = Log ( (X + 1) / (X – 1) ) / 2 LogN (X) = Log (X) / Log (N)
I.7.2. Func ţ iile TEXT – pentru stringuri I.7.2.1.Asc(string)
Întoarce o valoare de tip Integer, în intervalul 0…255, care reprezintă codul în ASCII (ANSI) a primului caracter din şirul de caractere ce se află în argumentul (parametrul de intrare) funciei. Exemplu. Dim Numar Numar = Asc ("A")
' Întoarce 65. I-39
Numar = Asc ("a") ' Întoarce 97. Numar = Asc ("Apple") ' Întoarce 65.
I.7.2.2.Chr(CodCaracter)
Întoarce o valoare de tip string care reprezintă caracterul asociat codului caracterului în ASCII (ANSI), introdus ca argument al funciei. Codurile dintre 0-31 au ca corespondent în ASCII caractere netipăribile, care însă pot să determine anumite aciuni în timpul afişării. De exemplu: • Chr(10) întoarce caracterul Line Feed (LF) - trecerea pe linie nou ă; • Chr(13) întoarce Carriage Return (CR) - trecerea la început de linie. Intervalul normal pentru parametrul CodCaracter este: 0-255. Exemplu. Dim Caracter Caracter = Chr (65) Caracter = Chr (97) Caracter = Chr (62) Caracter = Chr (37)
' Întoarce A. ' Întoarce a. ' Întoarce >. ' Întoarce %.
I.7.2.3.AscB(string); AscW(string);
ChrB(CodCh); ChrW(CodCh)
Funciile AscB, AscW, ChrB, ChrW in seama că în memorie caracterele sunt codificate pe 2 octei în standardul UNICODE. Ele consideră şirul de caractere ca pe un tablou de octei, în care fiecare caracter ocupă doi octei (byte). • Funcia AscB – în loc să întoarcă codul pentru primul caracter, întoarce primul byte, din codul în UNICODE al primului caracter. • Funcia AscW – întoarce codul caracterului în UNICODE (pe 2 octei, în intervalul 0…2^16). • Funcia ChrB – în loc să întoarcă un caracter al cărui cod (aflat în parametrul funciei) poate fi pe 1 sau 2 bytes, ea va întoarce întotdeauna caracterul al cărui cod este pe primul byte. • Funcia ChrW – întoarce un string care con ine caracterul al cărui cod este introdus în argument în standardul UNICODE. Aceste func efect numai pe platformele care accept ă codul UNICODE. Dacă acesta nu este acceptat, atunci eleiiseaucomport ă la fel ca funciile Asc respectiv Chr.
Exemplu. Public Sub TestUnicode () MsgBox Asc ("A") MsgBox AscB ("A") MsgBox AscW ("A") MsgBox Asc ("Ş") MsgBox AscB ("Ş") MsgBox AscW ("Ş") MsgBox Chr (65) MsgBox ChrB (65) MsgBox ChrW (65) MsgBox Chr (170) MsgBox ChrB (94) MsgBox ChrW (350)
' Întoarce Cod Ascii = 65 ' Întoarce primul byte din Codul Unicode = 65 ' Întoarce Codul Unicode = 65 ' Întoarce Cod Ascii = 170 ' Întoarce primul byte din Codul Unicode = 94 ' Întoarce Codul Unicode = 350 ' Întoarce Caracterul = A ' Întoarce Caracterul = A ' Întoarce Caracterul = A ' Întoarce Caracterul = Ş ' Întoarce Caracterul = ^ ' Întoarce Caracterul = Ş
End Sub Caracterul
Cod ANSI (1 octet) Cod UNICODE (valoare) Cod UNICODE (2 octei)
65
A
Ş
65 65
170 350
0
94
1
Se observă că în codulUNICODE, primele 128 de coduri sunt ca în codul ASCII.
I.7.2.4.LCase(string)
Întoarce o valoare de tip Variant (String) în care literele mari au fost convertite în litere mici. Restul caracterelor rămân nemodificate. I-40
Exemplu. Dim Valoare, ValoareMica Valoare = "Nota EXAmen" ' String pentru a fi convertit. ValoareMica = LCase (Valoare) ' Întoarce "nota examen".
I.7.2.5.UCase(string)
Întoarce o valoare de tip Variant (String) în care literele mici au fost convertite în litere mari. Restul caracterelor rămân nemodificate. Exemplu. Dim Valoare, ValoareMare Valoare = "Nota EXAmen" ' String pentru a fi convertit. ValoareMare = UCase (Valoare) ' Întoarce "NOTA EXAMEN".
I.7.2.6.LTrim(string); RTrim(string); Trim(string)
Întoarce o valoare de tip Variant (String) care este copia stringului, dar: − la funcia LTrim: fără spaiile de început; − la funcia RTrim: fără spaiile de sfârşit; − la funcia Trim: fără spaiile din ambele capete. Exemplu. Dim Valoare, Modific Valoare = " <-Trim-> " ' Iniializează stringul. Modific = LTrim(Valoare) ' Modific= "<-Trim-> ". Modific = RTrim(Valoare) ' Modific= " <-Trim->". Modific = LTrim(RTrim(Valoare)) ' Modific = "<-Trim->".
' Utilizând funcia Trim se obine acelaşi rezultat. Modific = Trim(Valoare)' Modific = "<-Trim->"
I.7.2.7.Len(String | NumeVariabila)
Întoarce o valoare de tip Long cuprinzând: ă argumentul este un string, câte caractere are; dac dacă argumentul este o variabilă, câte caractere pot să fie introduse în ea. Dacă argumentul este NULL, funcia va întoarce tot NULL; această regulă, aşa cum am mai amintit, este comună şi celorlalte funcii. Unul (şi numai unul) din cele două argumente posibile trebuie specificat. Se poate utiliza funcia LenB, care ine cont de reprezentarea în memorie înUNICODE a stringului. În loc să întoarcă numărul de caractere dintr-un string, LenB întoarce numărul de bytes (octei) utilizai pentru a reprezenta acel string. • •
Exemplu. Type CustomerRecord ' Defineşte tipul de date dorit de utilizator. ID As Integer 'Această definiie este la nivelul modului de cod Name As String * 10 Address As String * 30 End Type
'-----------------------------Dim As CustomerRecord ' Declararea variabilelor. Dim Customer MyInt As Integer, MyBan As Currency Dim MyString, MyLen MyString = "Hello World" ' Iniializează variabila. MyLen = Len(MyString) ' Întoarce 11. MyLen = Len(Customer) ' Întoarce 42. MyLen = Len(MyInt) ' Întoarce 2. ' Întoarce 8. MyLen = Len(MyBan)
I.7.2.8.Left(string, lungime)
Întoarce un sub-şir de caractere din partea stângă a stringului al căror număr este stabilit de lungime. Lungimea este o expresie numerică indicând câte caractere se vor întoarce. Dac ă: I-41
Lungimea = 0 – se întoarce un string de lungime 0 – cunoscut cu numele de şir vid (""). Lungimea >= Len(string) – se întoarce întregul string dacă lungimea este mai mare decât numărul de caractere din string. Pentru a determina numărul de caractere dintr-un string se va utiliza func ia Len. − −
Exemplu. Dim Sir, Subsir Sir = "Nota examen" Subsir = Left(Sir, 1) Subsir = Left(Sir, 7) Subsir = Left(Sir, Len(Sir)-2) Subsir = Left("Sir",1)
' Defineşte stringul. ' Întoarce "N". ' Întoarce "Nota ex". ' Întoarce "Nota exam". ' Întoarce "S" A se face distincie între variabila Sir care este încărcată cu valoarea "Nota examen" şi stringul "Sir" care este scris între ghilimele, el fiind astfel tratat ca o valoare de tip String. I.7.2.9.Right(string, lungime)
Întoarce un sub-şir de caractere din partea dreaptă a stringului al căror număr este stabilit de lungime (vezi explicaia anterioară). Exemplu. Dim Sir, Subsir Sir = "Nota examen" ' Defineşte stringul. Subsir = Right(Sir, 1) ' Întoarce "n" (caracterul de la final)) Subsir = Right(Sir, 8) ' Întoarce "a examen". Subsir = Right(Sir, Len(Sir)-2) ' Întoarce "ta examen". Subsir = Right("Sir",1) ' Intoarce "r" (vezi observa ie funcia left)
I.7.2.10.Mid(string, start [,lungime])
Întoarce o valoare de tip Variant (String) cuprinzând un număr specificat de caractere dintr-un string. Parametrii reprezintă: − string (obligatoriu). Expresie string din care sunt întoarse caractere. Dacă stringul conine NULL, atunci NULL se va întoarce. − start (obligatoriu). Este de tip Long. Reprezintă poziia caracterului din string de la care începe partea ce va fi preluată. Dacă poziia este mai mare decât numărul de caractere din string, Mid va întoarce un string vid ("") – de lungime 0. Numerotarea caracterelor începe de la 1. − lungime (opional); Este de tip Variant (Long). Reprezintă numărul de caractere ce vor fi întoarse. Dacă lipseşte sau dacă este mai mare decât numărul maxim de caractere care mai sunt pân ă la sfârşitul stringului (inclusiv caracterul de început), vor fi întoarse toate caracterele de la pozi ia de start până la sfârşit. Determinarea numărului de caractere din string se face cu funcia Len.
Exemplu. Dim SirPrincipal, SubSir1, SubSir2, SubSir3 SirPrincipal = "Universitatea din Pitesti" ' Creează stringul. SubSir1 = Mid(SirPrincipal, 1, 13) ' Întoarce "Universitatea". SubSir2 = Mid(SirPrincipal, 19, 7) ' Întoarce "Pitesti". SubSir3 = Mid(SirPrincipal, 15) ' Întoarce "din Pitesti". Mid poate fi folosit şi în partea stângă a unei instruciuni de atribuire, caz în care va înlocui din
string subşirul specificat, cu stringul specificat de expresia din dreapta instruc iunii, dar în aşa fel încât să nu se modifice lungimea şirului de caractere. Această facilitate nu este implementată şi la funciile Left sau Right. Exemplu. Public Sub TestMid () Dim S As String S = "123456789" Mid(S, 4, 2) = "A" MsgBox S ' Afişează 123A56789 Mid(S, 4, 2) = "AB" MsgBox S ' Afişează 123AB6789 I-42
Mid(S, 4, 2) = "ABC" MsgBox S ' Afişează 123AB6789 End Sub
I.7.2.11.InStr([start,]string1,string2[,compare])
Întoarce o valoare de tip Variant (Long) reprezentând poziia primei apariii a string2 în string1. • start (opional). Expresie numerică care stabileşte poziia de început pentru fiecare c ăutare. Dacă este omis, căutarea începe de la poziia primului caracter. Argumentul este obligatoriu dacă se specifică o comparaie. • string1 (obligatoriu). Şirul de caractere în care se va face căutarea. • string2 (obligatoriu). Şirul de caractere care este căutat. • compare (opional). Prezintă modalitatea în care se poate face compararea a dou ă stringuri. Poate fi 0, 1, sau 2. − − − −
ă 0 implicit – comparare binară, senzitiv 1– – comparare textuală, ne-senzitiv ă, adică; fără să se ină cont de caracterele mari sau mici; 2 – comparare bazată pe informaiile din baza de date; dacă parametrul compare lipseşte, atunci setarea Option Compare din modulul de cod
determină tipul comparaiei. Dacă nu se găseşte şirul specificat se întoarce valoarea 0. Dacă unul din şiruri este NULL, atunci NULL se întoarce.
Exemplu. Dim Sir, SirCautat, Pozitie Sir = "Popescu Panait" ' String în care se caut ă. SirCautat = "P" ' Se caută "P". 'Următoarele 4 instruciuni încep cercetarea de la poziia 4 Pozitie = Instr (4, Sir, SirCautat, 1) ' Comparaie textuală. Întoarce 9. Pozitie = Instr (4, Sir, "P", 1) ' Comparaie textuală. Întoarce 9. Pozitie = Instr (4, Sir, "p", 1) ' Comparaie textuală. Întoarce 9. Pozitie = Instr (4, Sir, "p", 0) ' Comparaie binară. Întoarce 0. Pozitie Instr (1, Sir, "W") ' Implicit (lipse argument).Întoarce 0. compara ia e binară _ şte=ultimul Exemplu. Private Sub cmdInstr_Click () Debug.Print InStr ("Alison Balter", "Balter") ' întoarce 8 Debug.Print InStr ("Hello", "1") ' întoarce 3 End Sub
I.7.2.12.String(num ă r,caracter)
Întoarce un şir de caractere, care conine de număr de ori caracterul specificat. Dacă în loc de caracter este un num ăr N caracterul multiplicat va fi Chr(N). Dacă N>255 se va
folosi Chr(N Mod 256). Dacă al doilea argument conine un şir de mai multe caractere se va multiplica primul. Exemplu. Dim MyString MyString = String(5, "*") ' Întoarce "*****" MyString = String(5, 42) ' Întoarce "*****" – codul Ascii al lui * este 42 MyString = String(10, "ABC") ' Întoarce "AAAAAAAAAA".
I.7.2.13.Space(num ă r )
Întoarce un şir de caractere care conine de număr de ori caracterul spaiu. Exemplu. Dim MyString MyString = Space(8) ' întoarce un string cu 8 spaii MyString = "Hello" & Space(10) & "World" ' Inserează 10 spaii _ între cele dou ă cuvinte.
I-43
I.7.2.14. Format(expresie[,format])
Funcia Format transformă o expresie într-un şir de caractere care respectă un şablon (format). • Expresie – este expresia pe care dorii să o formatai. • Format (opional) reprezintă tipul de format, şablon, pe care dorii să îl aplicai. El este ori un nume valid de format (de ex. "Long Time" sau "hh:mm:ss AMPM") ori un format creat (definit) de utilizator. Exemplu. Private Sub cmdFormat_Click () Dim MyTime, MyDate, MyStr MyTime = #5:04:23 PM# MyDate = #1/27/93#
' Se vor folosi şi următoarele funcii care întorc timpul şi data _ curentă a sistemului de calcul: ' NOW () =întoarce data şi timpul ' TIME () =întoarce timpul ' DATE () =întoarce data MyStr = Format(Time (), "Long Time") MsgBox MyStr ' Afişează timpul curent al sistemului de calcul, în _ formatul definit în Windows
pentru "Long Time"
MyStr = Format(Date, "Long Date") MsgBox MyStr ' Afişează data curentă a sistemului de calcul, în _ formatul definit în Windows
pentru "Long Date"
MyStr = Format(MyTime, "h:m:s") ' Întoarce "17:4:23". MsgBox MyStr MyStr = Format(MyTime, "hh:mm:ss AMPM") ' Întoarce _ "05:04:23 PM". MsgBox MyStr MyStr = Format(MyDate, "dddd, mmm d yyyy") ' Întoarce _ "Miercuri, Ian 27 1993". MsgBox MyStr
' Dacă parametrul format lipseşte se va întoarce un string. MyStr = Format(23) ' Întoarce "23".
'MsgBox FormateMyStr definite de utilizator. Se folosesc în continuare următoarele _ caractere pentru format: _ # – Întoarce cifra dacă există. Dacă nu există se întoarce "blanc" _ 0 – Întoarce cifra dacă există. Dacă nu există se întoarce 0 _ , – Întoarce separatorul de grupe de cifre (în sistemul românesc,_ virgula sau american, punctul) definit în Windows (System settings). _ . – Întoarce semnul pentru punctul zecimal definit în Windows _ % – Întoarce în procente MyStr = Format(5459.4, "##, ##0.00") ' Întoarce "5,459.40" - _ System settings în Windows este U.S. MsgBox MyStr MyStr = Format(334.9, "###0.00") ' Întoarce "334.90". MsgBox MyStr MyStr = Format(5, "0.00%") ' Întoarce "500.00%". MsgBox MyStr
' Formate definite de utilizator. Se folosesc în continuare următoarele _ caractere pentru format: '< > – Întoarce stringul cu litere mici mari
MyStr = Format("HELLO", "<") ' Întoarce "hello". MsgBox MyStr MyStr = Format("This is it", ">") ' Întoarce "THIS IS IT". MsgBox MyStr MsgBox Format(50, "Currency") '50.00 LEI – Afişează în sistemul _ de valut ă definit în
Windows (System settings)
MsgBox Format(Now(), "Short Date") ' 8/5/95 – Afişează în _ formatul definit pentru "dată
scurtă"
MsgBox Format(Now(), "DDDD") 'Afişează cuvântul pentru zi MsgBox Format(Now(), "DDD") 'Afişează ziua prescurtat (pe 2, 3 _ caractere) MsgBox Format(Now(), "YYYY") 'Afişează anul din patru cifre End Sub I-44
I.7.3. Func ţ ii pentru tablouri (array) - UBound
ş i LBound
UBound (arrayname[,dimension]) LBound (arrayname[,dimension])
Întorc o valoare de tip Long, care va conine, pentru o anumită dimensiune a unui tablou: Pentru UBound: valoarea indicelui celui mai mare disponibil (marginea superioară). Pentru LBound: valoarea indicelui celui mai mic disponibil (marginea inferioară). Sintaxa celor două funcii cuprind: − arrayname (obligatoriu). Denumirea variabilei care defineşte tabloul. − dimension (opional). Este de tip Variant (Long). Indică dimensiunea a cărei margine (superioară sau inferioară) este întoarsă. Se utilizează 1 pentru prima dimensiune, 2 pentru a doua etc. Dacă lipseşte, automat va fi 1. Funcia UBound se utilizează împreună cu funcia LBound pentru a determina mărimea unui tablou,• şiLBound anume: – pentru a găsi cea mai joasă valoare a dimensiunii unui tablou. • UBound – pentru a găsi cea mai mare valoare a dimensiunii unui tablou. Exemplu. Pentru tabloul cu dimensiunile: Dim A(1 To 100, 0 To 3, -3 To 4) UBound şi LBound întorc următoarele valori: Funcia Parametrii Valoarea întoarsă UBound
LBound
(A, 1) (A, 2) (A, 3) (A, 1) (A, 2) (A, 3)
100 3 4 1 0 –3
Marginea cea mai de jos, implicit ă, pentru orice dimensiune a unui tablou creat prin declaraie (Dim, Private, Public, ReDim sau Static), este 0 sau 1. Ea depinde de setarea declara iei Option Base (de obicei 0). ia setate ă deDim, ie. Baza Array folosind Option Base. Public, unuicare tablou creat cu func este 0, eaTo nefiind afectatiile Excep Tablourile pentru dimensiunile sunt în declara Private, ReDim sau Static pot lua orice valoare întreagă ca fiind marginea cea mai de jos (cel mai mic indice).
I.7.4. Func ţ ii de conversie I.7.4.1.Str(Num ă r )
Transformă un număr într-un şir de caractere. • Număr – argumentul funciei, de tip Long, va conine o expresie numerică ce va fi convertită într-un şir de caractere. • După conversie, la începutul stringului va fi un spaiu pentru numerele pozitive sau semnul (–) pentru numerele negative. • Punctul zecimal va fi reprezentat întotdeauna de semnul punct(.), indiferent de cum este setat acesta în Windows (ca punct sau ca virgulă). • Pentru transformarea numerelor în stringuri, cu folosirea altor reguli de prezentare, se folose şte funcia Format. Exemplu. Dim MyString MyString = Str(459) MyString = Str(-459.65) MyString = Str(459.001)
' Întoarce "459". ' Întoarce "-459.65". ' Întoarce " 459.001".
I.7.4.2.Val(string)
Întoarce numărul coninut în string, ca pe o valoare numerică de tipul cel mai apropiat reprezent ării valorii respective. • Funcia Val, în momentul în care întâlneşte un caracter care nu poate face parte din reprezentarea unui număr, opreşte inspecia şi face conversia numai pân ă la acest caracter. • Printre caracterele care nu sunt recunoscute de func ia Val, sunt şi virgula (,) sau semnul dolar ($). I-45
• &O şi &H, sunt considerate ca r ădăcină pentru numere în reprezentarea octală, respectiv hexazecimală. • Spaiile, tab-ul şi LF nu se iau în considerare (se sar). • Punctul zecimal va fi reprezentat întotdeauna de semnul punct (.).
Exemplu. Dim MyValue MyValue = Val("2457") MyValue = Val(" 2 45 7") MyValue = Val("24 and 57") MyValue = Val(" 1615 198th Street N. E.") I.7.5. Func ţ ii pentru mesaje I.7.5.1.MsgBox(prompt[,buttons][,title])
' Întoarce 2457. ' Întoarce 2457. ' Întoarce 24. ' Întoarce 1615198
Afişează un mesaj într-o căsuă de dialog, aşteaptă utilizatorul să apese un buton şi întoarce o valoare de tip Integer care indică codul butonului apăsat. Sintaxa funciei MsgBox cuprinde următoarele argumente: • Prompt (obligatoriu). Expresie de tip string afişată ca mesaj în caseta de dialog. Lungimea sa maximă este de aproximativ 1024 caractere, depinzând de m ărimea caracterelor folosite. Dacă promptul este compus din mai mult de un rând, se pot separa liniile utilizând un caracter CR= Chr(13), un caracter LF=Chr(10), sau o combinaie (Chr(13) & Chr(10) ) după fiecare rând. În VBA, există definită constanta de tip string: vbCr=Chr(13) & Chr(10) • Buttons (opional - implicit este 0). Expresie numerică care este suma valorilor reprezentând patru caracteristici ale căsuei de mesaj şi anume: − ce butoane se afişează (OK, Cancel, Yes, No, Retry, Ignore); − care este butonul care se va considera implicit; − ce pictogramă se afişează; − faă de ce este modală caseta de mesaj: aplicaie sau sistem (nu se poate ieşi din aceasta în aplicaie/ sistem până nu se închide). Setările pentru butoanele argument sunt: Constanta
Val
Descrierea
VbOKOnly VbOKCancel VbAbortRetryIgnore VbYesNoCancel VbYesNo VbRetryCancel VbCritical VbQuestion VbExclamation VbInformation VbDefaultButton1 VbDefaultButton2 VbDefaultButton3 VbDefaultButton4
0 1 2 3 4 5 16 32 48 64 0 256 512 768
Afişează numai butonul OK. Afişează butoanele OK şi Cancel. Numărul şi tipul Afişează butoanele Abort, Retry şi Ignore. butoanelor afişate Afişează butoanele Yes, No şi Cancel. în caseta de dialog Afişează butoanele Yes şi No. Afişează butoanele Retry şi Cancel. Afişează pictograma Critical Message. Felul pictogramei Afişează pictograma Warning Query. utilizate în partea Afişează pictograma Warning Message din stânga sus Afişează pictograma Information Message. Primul buton este implicit. Al doilea buton este implicit. Care este butonul implicit Al treilea buton este implicit. Al patrulea buton este implicit.
VbApplicationModal
0
Aplicaie modală – utilizatorul trebuie s ă Dacă caseta de text răspundă casetei de mesaj înainte de a continua să lucreze în aplicaia curentă. este modală la Sistem modal – toate aplica iile sunt
VbSystemModal
4096 blocate până când utilizatorul răspunde
Ce reprezintă
nivelul aplica curente sau aiei tuturor taskurilor
casetei de mesaj. − Title (opional). Expresie de tip string afişată pe bara de titlu a casetei de dialog. Dacă lipseşte,
se va plasa pe bara de titlu numele aplicaiei. Valoarea întoarsă de funcie este:
I-46
Constanta
Valoare
vbOK vbCancel vbAbort vbRetry vbIgnore vbYes vbNo
1 2 3 4 5 6 7
Butonul pe care s-a apăsat OK Cancel Abort Retry Ignore Yes No
Aceste constante sunt definite în VBA. În consecină, numele acestea pot fi utilizate oriunde în program în locul valorilor respective. MsgBox poate fi utilizat ă şi ca procedură. În acest caz parametrii nu se mai scriu între paranteze. În această formă este folosită numai pentru afişarea unui mesaj.
Exemplu. Public Sub TestMsgBox () Dim Rasp As Integer Dim Nr As Integer Const LimInf = -100 Const LimSup = 100
' Generează o valoare aleatoare întreagă între LimInf şi LimSup Randomize Nr = Int((LimSup - LimInf + 1) * Rnd + LimInf)
' MsgBox folosit ca funcie ' Afişează mesaj, şi introduce în Rasp, butonul apăsat de utilizator _ ( @ ) ca separator de rânduri!!
Se observă folosirea lui at
Rasp = MsgBox("Doriti modificarea semnului numarului " & _ Nr & " extras? @ -Yes=Il face pozitiv; @ -No=Il face negativ; ", _ vbYesNoCancel + vbQuestion + vbDefaultButton3 + vbSystemModal, _
"Exemplu parametrii MsgBox") If Rasp = vbYes Then Nr =Rasp Abs(Nr) ElseIf = vbNo Then Nr = Abs(Nr) * -1 Else 'Cancel - Lasă numărul neschimbat End If MsgBox "Numarul prelucrat este: " & Nr, vbInformation End Sub 'Se observă mai sus folosirea lui MsgBox ca pe o procedură
I.7.5.2.InputBox(prompt[,title][,default][,X][,Y])
Afişează un mesaj într-o casetă, aşteaptă ca utilizatorul să introducă un text sau/şi să apese un buton şi întoarce o valoare (string) ce conine acest text. Sintaxa funciei InputBox cuprinde următoarele argumente: • Prompt (obligatoriu). Expresie de tip string afişată ca mesaj în caseta de dialog. Lungimea sa maximă este de aproximativ 1024 caractere, depinzând de m ărimea caracterelor folosite. Dacă promptul este compus din mai mult de un rând, se pot separa liniile utilizând un caracter CR(carriage return) Chr(13), un caracter LF(line feed) Chr(10), sau o combinaie (Chr(13) & Chr(10) ) după fiecare rând. • Title (opional). Expresie de tip string afi şată pe bara de titlu a casetei de dialog. Dac ă titlul lipseşte, se va plasa pe bara de titlu numele aplica iei. • Default (opional). Expresie de tip string afi şată în caseta de text ca r ăspuns implicit dacă utilizatorul nu introduce nimic. Dacă lipseşte, caseta de text va fi afi şată goală. • X (opional). Expresie numeric ă care reprezintă, în twips, distana pe orizontală de la marginea din stânga a casetei de dialog la marginea din stânga a ecranului. Dac ă lipseşte, caseta de dialog este centrat ă orizontal. • Y (opional). Expresie numerică care reprezintă, în twips, distana pe verticală de la marginea de sus a casetei de dialog la marginea de sus a ecranului. Dac ă lipseşte, caseta de dialog este poziionată vertical la aproximativ o treime din distana până în subsolul ecranului. Exemplu.
I-47
Următorul exemplu utilizează InputBox pentru a citi o dată introdusă de utilizator şi folosirea lui MsgBox şi ca funcie şi ca procedură (pentru afişarea unor mesaje). Se observă utilizarea semnului @ pentru a delimita diversele pări ale şirului de caractere. Sub CustomMessage () Dim strMsg As String, strInput As String
' Iniializează stringul.
strMsg = "Număr în afara intervalului. @ A i introdus un număr _ care este mai mic decât 1 şi mai mare ca 10. @ Apăsai OK pentru a _ introduce numărul din nou." ' @ - rol de delimitator de rânduri
' Se cere utilizatorului să introducă o valoare.
strInput = InputBox("Introducei un număr între 1 şi 10. ") If strInput <> "" Then ' Testează ca valoarea intodusă să nu fie şir vid Do While (strInput < 0 Or strInput > 10) If MsgBox(strMsg, vbOKCancel, "Error!") vbOK strInput = InputBox("Introduce 1şi Then 10") i număr =între Else Exit Sub End If Loop
' Afişează data corectă introdusă de utilizator.
MsgBox "Ai introdus numărul" & strInput & ". " Else ' nu s-a introdus nimic Exit Sub End If End Sub
I.7.6. Func ţ ii cu tipul: Date/ Time I.7.6.1.DatePart(interval,date)
Funcia DatePart întoarce o parte dintr-o dată, care este specificată de argumentul interval. Argumentul interval, de tip string, poate lua urm ătoarele valori: interval yyyy q m y d
Descriere Anul Trimestrul Luna Ziua din an Ziua
Exemplu. Private Sub cmdDatePart_Click () MsgBox DatePart("YYYY", Now) MsgBox DatePart("M", Now) MsgBox DatePart("Q", Now) MsgBox DatePart("Y", Now) End Sub
interval w ww h n s
Descriere Ziua din săptămână Săptămâna Ora Minute Secunde
' Afişează anul curent ' Afişează numărul lunii curente ' Afişează nr. trimestrului curent ' Afişează ziua din anul curent
I.7.6.2.DateDiff(interval,date1,date2)
Funcia ăDateDiff întoarce intervalul de timp dintre dou ă date, deci date2-date1. Unitatea de timp este specificat de argumentul interval. Exemplu. Private SubcmdDateDiff_Click () MsgBox DateDiff("d",Now,#12/31/02#) ' Nr. zile până la 12/31/02 MsgBox DateDiff("m",Now,#12/31/02#) ' Nr. luni până la 12/31/02
' Numărul de ani până la 12/31/02
MsgBox DateDiff("yyyy",Now,#12/31/02#)
' Numarul trimestrelor până la 12/31/02
MsgBox DateDiff("q",Now,#12/31/02#) End Sub
I-48
I.7.6.3.DateAdd(interval,number,date)
Funcia DateAdd întoarce rezultatul adăugării sau scăderii unei perioade specifice de timp, precizate prin argumentul interval, la o (dintr-o) dată stabilită. Private Sub cmdDateAdd_Click () MsgBox DateAdd("d", 3, Now) ' Ziua de azi plus 3 zile MsgBox DateAdd("m", 3, Now) ' Ziua de azi plus 3 luni MsgBox DateAdd("yyyy", 3, Now) ' Ziua de azi plus 3 ani MsgBox DateAdd("q", 3, Now) ' Ziua de azi plus 3 trimestre End Sub
I.7.6.4.Day(date); Month(date); Year(date)
Întoarce un Variant (Integer), care conine ziua sau luna sau anul, din data care se găseşte în argumentul funciei. I.7.6.5.Second(date); Minute(date); Hour(date)
Întoarce un Variant (Integer), care conine secunda sau minutul sau ora, din data care se găseşte în argumentul func iei. I.7.6.6.Now(); Date(); Time() Now() - întoarce un Variant (Date), care conine data şi timpul curent (cu care este setat în momentul respectiv sistemul de calcul). Date() - întoarce un Variant (Date), care conine data curentă (cu care este setat în momentul respectiv sistemul de calcul). Time() - întoarce un Variant (Date), care conine timpul curent (cu care este setat în momentul respectiv sistemul de calcul).
I.7.6.7.DateSerial(year, month, day)
Întoarce un Variant(Date) care va conine data calendaristică specificată în argumentele: year, month şi day. Descrierea argumentelor: − Year (obligatoriu); Integer. Număr între 100 şi 9999 inclusiv, sau expresie numerică. − Month (obligatoriu); Integer. Orice expresie numerică. − Day (obligatoriu); Integer. Orice expresie numerică. Pentru a specifica o dată, de exemplu December 31, 1991, valoarea fiecărui parametru trebuie să fie
validă, adică ziua între 1-31 şi luna între 1-12. Exemplul următor va întoarce o dată, exprimată relativ faă de altă dată. Se observă că operaiile se fac specific pentru zile şi luni, inându-se cont de numărul de zile şi luni. Astfel ziua (1 - 1) din luna (8 2), ar trebui să fie 0/6, dar practic dac ă scădem o zi din 1 iunie, avem 31/Mai. Deci, DateSerial(1990 10, 8 - 2, 1 - 1) va fi: 31/Mai/1980. Dacă argumentul pentru an este între 0 şi 99, se vor considera anii din dou ă cifre setai în Windows. Pentru ceilali ani trebuiesc introduse 4 cifre. Dacă un argument este dat în afara intervalului acceptat, atunci se va întoarce o dată care este practic mărită cu numărul de zile sau luni care depăşesc valoarea maximă pentru argumentul respectiv. De exemplu MsgBox (DateSerial(1998, 11, 32) ) va afişa 2/12/1998 . Exemplu. Dim OData As Date OData = DateSerial(1969, 2, 12) 'Întoarce data - February 12, 1969.
I.7.6.8.TimeSerial(hour
, minute, second)
Întoarce un Variant(Date) care va conine timpul pentru o anumită oră, minut şi secundă, specificată în argumentele: hour, minute, second. Exemplu. Dim Timpul As Date Timpul = TimeSerial(16, 35, 17) 'Reprezentatre timp - 4:35:17 PM
I-49
I.7.7. Func ţ ii: structuri de control I.7.7.1.IIf(condi ie, TruePart, FalsePart)
Funcia IIf are o aciune asemănătoare cu a instruciunii If…Then…Else Funcia IIf întoarce unul din cele două argumente, TruePart sau FalsePart, în funcie de rezultatul evaluării condiiei ce se găseşte în primul argument. Astfel, dacă: − condiie = true – funcia întoarce parametrul TruePart; − condiie = false – funcia întoarce parametrul FalsePart. Toi cei trei parametri ai funciei sunt obligatorii. TruePart sau FalsePart pot la rândul lor s ă conină o altă funcie, deci şi un alt IIF, ceea ce permite realizarea unor structuri complexe de teste. Exemplu. Function TestIF(TestMe As Integer) as String TestIF = IIf(TestMe > 1000, "Large", "Small") End Function
Dacă va fi folosită în: MsgBox TestIF(1500) ' afişează Large MsgBox TestIF(500) ' afişează Small
I.7.7.2.Choose(index, caz-1[,caz-2,... [,caz-n]])
Funcia Choose întoarce unul din argumentele listei (caz-1 sau caz-2, sau … caz_n) în funcie de valoarea pe care o are argumentul index, şi anume: − dacă index = 1 atunci se întoarce caz-1; − dacă index = 2 atunci se întoarce caz-2; − dacă index = n atunci se întoarce caz-n. Dacă index < 1, sau index > n , atunci Choose întoarce valoarea Null. Exemplu. Function GetChoice(Ind As Integer) as String GetChoice = Choose(Ind, "Speedy", "United", "Federal") End Function 'La apelul funciei vom avea: MsgBox GetChoice(2) ' afişează United Dim X As Variant X = GetChoice(5) ' X se va face Null
I.7.7.3.Switch(expr-1,valu e-1[,expr-2,value- 2… [,expr-n,value-n] ]..])
Această funcie are o aciune asemănătoare cu a instruciunii: If…Then…ElseIf…Else Funcia Switch va evalua în ordine condiiile expr-1, expr-2, expr-n, pînă când va obine o valoare
True. În acest moment, cercetarea se opre şte, şi funcia întoarce valoarea pereche care se găseşte în argumentul value_?. Deci: − Dacă expr-1 = True atunci se întoarce value-1, şi gata… − Dacă expr-1 = False atunci trece la evaluarea urm ătoare − Dacă expr-2 = True atunci se întoarce value-2, şi gata… − Dacă expr-2 = False atunci trece la evaluarea urm ătoare, etc. Dacă nici una din expresiile evaluate nu este True, Switch întoarce Null. Exemplu. Function MatchUp(CityName As String) as String MatchUp = Switch(CityName = "London","English",CityName _ = "Rome", "Italian", CityName = "Paris", "French") End Function 'La apelul funciei vom avea: MsgBox MatchUp("Paris") ' afişează French
I-50
I.7.8. Func ţ ii de inspec ţ i e I.7.8.1.IsNull(expresie)
Întoarce o valoare de tip Boolean care indică dacă expresia transmisă ca parametru de intrare conine date care nu sunt valide, adică au valoarea Null. Parametrul este de tipVariant şi conine o expresie de tip numeric sau string. Funcia IsNull întoarce: True – dacă parametrul are valoarea Null; False – dacă parametrul nu are valoarea Null; Aşa cum am mai arătat, dacă un termen al expresiei este Null, atunci expresia va fi tot Null, şi funcia va întoarce evident True. Valoarea Null, îndică faptul că un Variant nu conine date valide. Mai exist ă încă două valori speciale, Empty şi String vid (gol) care pot fi uşor confundate cu Null, ceea ce constituie o eroare. Deci reamintim că: • NULL – variabilă variant în care datele nu sunt valide ; EMPTY – variabilă variant care nu a fost îniializată; String de lungime 0 (vid, gol) – string care nu are nimic în el , adică este "". Exemplu. Dim Valoare, Situatie ' variabile variant Situatie = IsNull(Valoare) ' Întoarce False, deoarece este Empty Valoare = "" Situatie = IsNull(Valoare) ' Întoarce False, deoarece este string vid _ (de lungime 0). Valoare = Null Situatie = IsNull(Valoare) ' Întoarce True. • •
I.7.8.2.IsEmpty(NumeVariabila)
Întoarce o valoare de tip Boolean care indică dacă o variabilă, transmisă ca parametru de intrare, este sau nu EMPTY, adică iniializată. Parametrul este de tip variant şi conine o dată de tip numeric sau string. Funcia IsEmpty întoarce: True – dacă variabila NumeVariabila nu este iniializată, sau a fost introdus ă în ea direct Empty; False – variabila a fost iniializată (chiar cu Null sau un string vid). Exemplu. Dim Valoare, Situatie Situatie = IsEmpty(Valoare) Valoare = Null Situatie = IsEmpty(Valoare) Valoare = Empty Situatie = IsEmpty(Valoare)
' variabile variant ' Întoarce True. ' Assign Null. ' Întoarce False. ' Assign Empty. ' Întoarce True.
I.7.8.3.IsMissing(NumeParametru) IsMissing se foloseşte într-o rutină, pentru a testa dacă un parametru opional al acesteia a fost sau nu introdus în lista parametrilor actuali de la apelarea acestei rutine. Parametrul funciei IsMissing , NumeParametru, este de tip variant. Aceste (NumeParametru) reprezintă parametrul formal optional care se testeaz ă dacă a fost introdus sau nu în lista parametrilor actuali la apelul func iei. Funcia IsMissing întoarce o valoare de tip Boolean, care va avea valoarea TRUE numai dacă parametrul opional testat nu a fost introdus în lista parametrilor actuali, deci el practic lipseşte. Exemplu. Apelarea funciei ReturnTwice, definită cu un parametru opional. Dim ReturnValue ReturnValue = ReturnTwice() ReturnValue = ReturnTwice(2)
' Declararea funciei.
' Întoarce Null. ' Întoarce 4.
Function ReturnTwice(Optional A) If IsMissing (A) Then ' Funcia a fost apelată fără parametrul A ReturnTwice = Null Else ' Funcia a fost apelată cu parametrul A I-51
ReturnTwice = A * 2 End If End Function Funcia IsMissing se aplică numai dacă parametrul opional este de tip variant. Dacă parametrul
opional nu este de tip variant ea va întoarce întotdeauna (fie că parametrul opional este sau nu este folosit la apelarea funciei) valoarea FALSE. I.7.8.4.VarType(NumeVariabil
ă)
Întoarce un Integer, care precizează tipul de date ce se găseşte în variabila de tip variant: NumeVariabilă (care este argumentul funciei). Reamintim că variabilele de tip variant se caracterizează prin faptul că în ele se pot introduce valori de diferite tipuri. Funcia VarType tocmai acest rol are, să ne indice la un moment dat ce tip de date se găsesc într-o variabilă de tip variant. Rezultatul întors de funcia VarType: Constanta vbEmpty vbNull vbInteger vbLong vbSingle vbDouble vbCurrency vbDate vbString
Val
Descriere
Constanta
Val
Descriere
0 1 2 3 4 5 6 7 8
Empty (neiniializat) Null (lipsa datelor valide) Integer Long integer Single-precision Double-precision Currency – valoare Date – val. de tip Date/Text String
vbObject vbError vbBoolean vbVariant vbDataObject vbDecimal vbByte vbArray
9 10 11 12 13 14 17 8192
Object Error Boolean – valoare Variant (în tablouri) Obiect de acces la date Decimal – valoare Byte – valoare Array – Tablou
Constantele fiind definite în VBA, ele pot fi utilizate oriunde în loc de valorile specificate.
Exemplu.
' Variabile declarate variant, deoarece lipseşte tipul de data Dim IntVar, StrVar, DateVar, MyCheck
' Iniializarea variabilelor IntVar = 459: StrVar = "Hello World": DateVar = #2/12/69#
' !!! Aşa se pot scrie mai multe instruciuni pe un rând, separându-le, _ puncte. ' Întoarce 2. MyCheck = VarType(IntVar) ' Întoarce 8. MyCheck = VarType(StrVar) MyCheck = VarType(DateVar) ' Întoarce 7.
aşa cum se vede, cu două
I.7.9. Func ţ iile agregate SQL
O funcie agregată SQL este specifică prin faptul că datele ei de intrare sunt valorile unui câmp dintr-o tabelă (cerere) – care este legată de obiectul în care se foloseşte, adică cerere, tabel, formular sau raport –, din toate sau o parte din înregistrări. Ele calculează expresii al căror domeniu de aplicabilitate este un câmp al tabelei (cererii) care se utilizează în obiectul unde sunt folosite. În cazul rapoartelor sau formularelor, func iile agregate SQL se calculează pe tabela (cererea) legată la acesta. Funciile agregate SQL au ca argument numele câmpului pe care sunt definite. Totu şi, în cazul
cererilor cu defini clauzăie,total , înfolosesc care introducerea funciei agregate SQL se face într-o coloană ataşată câmpului de ele se fără argument. Funciile agregate SQL sunt: − Sum – calculează suma valorilor pe un câmp; − Max, Min – întoarce valoarea maximă/ minimă a unui câmp; − Avg – calculează media aritmetică a valorilor unui câmp; − Count – numărul de înregistrări ale câmpului (diferite de NULL). Dacă se doreşte să se ia în calcul şi câmpurile cu valoarea NULL, atunci se va folosi expresia COUNT(*). − Var, VarP, StDev, StDevP–calcule statistice (varian a şi deviaia standard).
I-52
Valoarea NULL, în funciile agregate (SQL sau de domeniu), nu se ia în considerare. În celelalte funcii sau operaii, valoarea NULL a unui termen duce la rezultatul NULL al expresiei, indiferent de felul în care e constituită aceasta.
I.7.10. Fu nc ţ iile agregate de domeniu
Funciile agregate de domeniu întorc date de calcul agregate, la fel ca şi funciile agregate SQL. Diferena rezultă din faptul că domeniul de definiie al acestor funcii este reprezentat de un câmp al unei tabele (cereri) – din baza de date curentă – asupra căruia se aplică, eventual, un criteriu de selecie a înregistrărilor. Domeniul de definiie este stabilit de valorile ce se g ăsesc în parametrii (argumentele) funciei. Funciile agregate de domeniu, (au aceiaşi denumire ca a funciilor agregate SQL, dar cu litera D în faă) sunt: − DSum – calculează suma valorilor pe un câmp; − DMax, Dmin – întoarce valoarea maximă/ minimă a unui câmp; − DAvg – calculează media aritmetică a valorilor unui câmp; − DCount – numărul de înregistrări ale câmpului (diferite de NULL); − DVar, DVarP, DStDev, DStDevP – calcule statistice (variana şi deviaia standard); − DLookUp – întoarce prima valoare întâlnită în domeniul selecionat. (aceasta nu are echivalent în funciile agregate SQL). Argumentele folosite sunt aceleaşi în toate aceste funcii şi stabilesc, aşa cum am mai arătat, care este domeniul de definiie pe care se calculează valoarea agregată. DFuncie (NumeCâmp, NumeTabela[, Criteriu]) • NumeCâmp, NumeTabela – sunt stringuri care stabilesc care este câmpul şi tabela (cererea) asupra căreia se fac calculele agregate. • Criteriu – este un string prin care se introduce un criteriu de selec ie a înregistr ărilor din domeniul specificat de primii doi parametri. Dac ă nu este prezent acest parametru, se vor lua în calcul datele din câmpul respectiv din toate înregistrările tabelei specificate. Dacă nu se selecionează datorită criteriului nici o înregistrare, funcia întoarce valoarea NULL. Exemplu. Dim varX As Variant, iNr As Integer, sSir As String ' cazul 1 – selecia înregistrărilor din tabela Studenti cu CodStudent _ având valoarea <100 – întoarce dintre acestea valoarea Nume cea mai mare în ordinea de _ sortare. – CodStudent (care e folosit în criteriu) este de tip numeric şi a fost _ comparat cu un LITERAL varX = DMax ("[Nume]", "Studenti", "[CodStudent]<100") ' cazul 2 – selecia înregistrărilor cu Nume având valoarea 'Doru' _ – întoarce dintre acestea valoarea Anul cea mai mică – Nume (care e folosit în criteriu) este de tip text şi a fost comparat cu un _ LITERAL varX = DMin ("[Anul]", "Studenti", "[Nume]='Doru' ") ' cazul 3 – selecia înregistrărilor cu CodStudent având valoarea < cea din _ variabila numerică iNr – întoarce dintre acestea valoarea Nume cea mai mare în ordinea de _ sortare. – CodStudent (care e folosit în criteriu) este de tip numeric şi a fost _ comparat cu o dată care se
găseşte într-o variabilă iNr = 100 varX = DMax ("[Nume]", "Studenti", "[CodStudent]<" & Nr) ' cazul 4 – selecia înregistrărilor cu Nume având valoarea ce se găseşte _ în variabila string sSir – întoarce dintre acestea valoarea Anul cea mai mică – Nume (care e folosit în criteriu) este de tip text şi a fost comparat cu o dată care se găseşte într-o
variabilă sSir = "Doru" varX = DMin ("[Anul]", "Studenti", "[Nume]='" & sSir & "'")
Se observă că în formarea criteriului este foarte important dac ă criteriul se va aplica pe un câmp numeric sau de tip text. În cazul când avem de-a face cu un câmp text valoarea cu care se face compararea trebuie la rândul ei să fie string, deci încadrată din nou între ghilimele (2 ghilimele într-un string delimitat I-53
de ghilimele sunt considerate ca un semn ghilimea) sau un apostrof. Deci "[Nume]='Doru' " este echivalent cu "[Nume]=""Doru"" " Lucrurile se complică în momentul în care criteriul pe care îl introducem va compara un câmp cu o valoare ce se află într-o variabilă, ca în cazurile 3 şi 4. Important este să ştim că forma de scriere a criteriului este diferită în funcie de natura câmpului folosit de criteriu, număr sau text. Reamintesc că valoarea NULL, în funciile agregate (de domeniu sau SQL), nu se ia în considerare. În celelalte funcii sau operaii, valoarea NULL a unui termen duce la rezultatul NULL al expresiei, indiferent de felul în care e constituit ă aceasta.
I-54