2.vba_sc4

208
Şerban CRIŞCOTĂ Programarea în VISUAL BASIC for Application Editura CARMINIS Piteşti, 2003

Upload: padelin6274

Post on 23-Oct-2015

37 views

Category:

Documents


7 download

DESCRIPTION

Baze de date

TRANSCRIPT

Page 1: 2.VBA_SC4

Şerban CRIŞCOTĂ

Programarea în VISUAL BASIC for Application

Editura CARMINIS Piteşti, 2003

Page 2: 2.VBA_SC4

I-2

ISBN 973-8418-60-7

Editura CARMINIS Piteşti, 2003

Reproducerea parţială sau integrală a prezentei lucrări fără acordul editurii se sancţionează conform legii.

� REFERENT ŞTIINŢIFIC: Profesor universitar dr. Gheorghe SECARĂ

� REFERENT ŞTIINŢIFIC: Lector universitar Viorel PĂUN

� ………………………

� REDACTOR: Şerban CRIŞCOTĂ

� COPERTA GRAFICĂ: Raluca CRIŞCOTĂ

� TEHNOREDACTARE: Marius HÎRZOIU, Marius-Gabriel DUMITRU

� EDITARE CD-ROM: Marius-Gabriel DUMITRU

Page 3: 2.VBA_SC4

I-3

NOTĂ INTRODUCTIVĂ

"Programarea în Visual Basic for Application" este o lucrare destinată în special utilizatorilor de baze de date Access.

Lucrarea este structurată în două părţi:

• În prima parte, "Elementele de bază ale limbajului de programare VBA - Visual Basic for Application" sunt prezentate:

− principiile de bază ale programării; − elementele de bază ale limbajului de programare Visual Basic; − bibliotecile de proceduri şi funcţii din Access; − interfaţa de dezvoltare şi depanere a VBA;

• În a doua parte, "Utilizarea obiectelor în limbajul de programare VBA" sunt prezentate:

− principiile definirii şi utilizării obiectelor în VBA; − modelul ierarhic-arborescent Access; − modelul ierarhic-arborescent Data Access Object; − tehnologiile OLE şi Automation-OLE; − utilizarea în aplicaţiile Access a ActiveX-urilor; − utilizarea în aplicaţiile Access a obiectelor Word şi Excel; − crearea şi utilizarea claselor de obiecte în VBA;

Pentru însuşirea elementelor de bază ale programării în Visual Basic sunt necesare numai cunoştinţe minime despre sistemele de operare Windows. Totuşi, pentru a înţelege partea a doua a lucrării referitoare la programarea prin obiecte, noţiunile despre baze de date relaţionale şi despre interfaţa Access sunt obligatorii.

În decursul lucrării sunt prezentate exemple comentate de cod VBA. Acestea împreună cu alte exerciţii specifice grupate pe categorii şi împreună cu alte două aplicaţii demonstrative comentate, se găsesc în format Mdb, pe suportul ataşat la carte.

"Programarea în Visual Basic for Application" face parte dintr-un ciclu de lucrări referitoare la informatica de gestiune, care mai conţine:

− "Funcţionarea şi utilizarea calculatoarelor PC" − "Utilizarea bazelor de date relaţionale Access în realizarea aplicaţiilor economice" − "Reţele de calculatoare interconectate" − "Proiectarea aplicaţiilor Web" − "Principiile proiectării sistemelor informatice de gestiune"

Page 4: 2.VBA_SC4

I-4

Modul de utilizare a CD-ROM-ului inclus în carte

La sfârşitul acestei cărţi veţi găsi un CD-ROM ce conţine următoarele fişiere:

• DAO.MDB - conţine toate fragmentele de cod VBA prezentate în carte, împreună cu toate formularele, cererile şi tabelele necesare executării lor. În modulul general de cod, veţi găsi sursele grupate după natura lor, în module distincte de cod. Pentru transferurile prin tehnica AUTOMATION, se va folosi fişierul Excel, FOAIE.XLS

• PROBLEME.MDB* - este o aplicaţie ACCESS, care conţine un set de exerciţii rezolvate în VBA. Aplicaţia permite vizualizarea tuturor problemelor grupate pe categorii şi accesarea printr-o simplă apăsare pe un buton, a modulului de cod sau a formularului ce va conţine codul sursă.

• CURS.MDB - este o aplicaţie demonstrativă cu un grad de dificultate mai ridicat şi în care codul sursă VBA este comentat în detaliu. Această aplicaţie permite prezentatea grafică a unor analize asupra dinamicii cursului valutelor USD şi EURO. Pentru grafice s-a folosit ActiveX-ul, Microsoft Graph, iar pentru introducerea datelor calendaristice controlul MS Calendar Control. În modulul general de cod, se găsesc două colecţii de rutine parametrizate, foarte utile în realizarea de aplicaţii.

• AGENDA.MDB - este o aplicaţie mai simplă, cu codul sursă VBA comentat, care permite stocarea şi regăsirea informaţiilor referitoare la o bază de date relaţionale de persoane.

Deoarece execuţia aplicaţiilor ACCESS nu se poate efectua direct de pe CD-ROM, se va copia în prealabil pe hard disck directorul cu acestea: EXEMPLE_VBA.

Aplicaţiile sunt realizate în ACCESS 97. Pentru execuţia lor în versiuni superioare este necesar ca mai întâi să se efectueze conversia lor.

* Aplicaţia PROBLEME.MDB este realizată de Marius-Gabriel Dumitru

Page 5: 2.VBA_SC4

I-5

C U P R I N S

CAP.I ELEMENTELE DE BAZĂ ALE LIMBAJULUI DE PROGRAMARE VBA - VISUAL BASIC FOR APPLICATION I-11

I.1. Noţiuni generale despre VBA .......................................................................... I-11 I.1.1. Utilizarea limbajului de programare VBA ................................................... I-11 I.1.2. Necesitatea utilizării codului VBA în aplicaţii Access................................. I-12 I.1.3. Modulele de cod VBA în Access ................................................................. I-13 I.1.4. Elementele generale ale limbajului VBA ..................................................... I-14 I.1.5. Structura rutinelor VBA ............................................................................... I-15 I.1.6. VBA – mediul de dezvoltare şi depanare ..................................................... I-15

I.2. Tipuri de date .................................................................................................... I-21 I.2.1. Tipuri de date elementare ............................................................................. I-22

I.2.1.1. Date numerice întregi.......................................................................................... I-22 I.2.1.2. Date numerice reale ............................................................................................ I-22 I.2.1.3. Tipul de date BOOLEAN – logic ......................................................................... I-23 I.2.1.4. Tipul de date STRING – şir de caractere ............................................................ I-23 I.2.1.5. Tipul de date DATE – data calendaristică şi timpul ........................................... I-24

I.2.2. Tipuri de date structurate.............................................................................. I-25 I.2.2.1. Tipul de date ARRAY – tablou............................................................................. I-25 I.2.2.2. TYPE – Crearea tipurilor de date definite de utilizator ...................................... I-26

I.2.3. Tipul de date VARIANT .............................................................................. I-27

I.3. Variabile ............................................................................................................ I-27 I.3.1. Declararea variabilelor ................................................................................. I-28 I.3.2. Caractere folosite ca Type-declaration ......................................................... I-29 I.3.3. Option Explicit (declararea explicită a variabilelor) .................................... I-29 I.3.4. Variabile Locale şi Globale .......................................................................... I-30 I.3.5. Variabile Publice şi Private .......................................................................... I-31 I.3.6. Variabile Statice ........................................................................................... I-32 I.3.7. Variabile – domeniul şi durata de valabilitate .............................................. I-32 I.3.8. Declararea şi folosirea variabilelor ARRAY................................................ I-33

I.4. Constante ........................................................................................................... I-37

I.5. Limbajul VBA – Instrucţiuni executabile....................................................... I-38 I.5.1. Instrucţiunea de atribuire .............................................................................. I-39 I.5.2. Structurile de control .................................................................................... I-41

I.5.2.1. Structura secvenţială ........................................................................................... I-41 I.5.2.2. Structura alternativă ........................................................................................... I-41

I.5.2.2.a) Structura alternativă simplă .......................................................................... I-41 I.5.2.2.b) Structura alternativă multiplă ....................................................................... I-42

I.5.2.3. Structura repetitivă.............................................................................................. I-45

Page 6: 2.VBA_SC4

I-6

I.5.2.3.a) Structura repetitivă cu test. Instrucţiunea Do…Loop ................................... I-45 I.5.2.3.b) Structura repetitivă cu contor. Instrucţiunea For…Next .............................. I-47

I.6. Rutine – proceduri şi funcţii ............................................................................ I-49 I.6.1. Ce este o rutină şi ce elemente o definesc?................................................... I-49 I.6.2. Transmiterea datelor prin parametri ............................................................. I-50 I.6.3. Crearea (definirea) unei rutine...................................................................... I-52

I.6.3.1. Proceduri (Subrutine).......................................................................................... I-52 I.6.3.2. Funcţii ................................................................................................................. I-53

I.6.4. Apelarea unei rutine...................................................................................... I-54 I.6.4.1. Apelarea unei proceduri (subrutine) ................................................................... I-54 I.6.4.2. Apelarea unei funcţii ........................................................................................... I-54

I.6.5. Domeniul de vizibilitate al rutinelor............................................................. I-55 I.6.6. Durata de viaţă a rutinelor ............................................................................ I-55 I.6.7. Rutine definite de utilizator. Introducerea codului VBA ........... I-55 I.6.8. Procedurile evenimentelor............................................................................ I-56 I.6.9. Utilizarea combinată a procedurilor eveniment cu rutinele utilizator .......... I-58 I.6.10. Parametri opţionali ..................................................................................... I-59

I.7. Biblioteci standard de proceduri şi funcţii ..................................................... I-60 I.7.1. Funcţii matematice ....................................................................................... I-62

I.7.1.1. Int(număr); Fix(număr)....................................................................................... I-62 I.7.1.2. Abs(număr).......................................................................................................... I-62 I.7.1.3. Sgn(număr).......................................................................................................... I-62 I.7.1.4. Sqr(număr) .......................................................................................................... I-63 I.7.1.5. Exp(număr).......................................................................................................... I-63 I.7.1.6. Log(număr).......................................................................................................... I-63 I.7.1.7. Rnd [(număr)] ..................................................................................................... I-63 I.7.1.8. Sin(număr)........................................................................................................... I-64 I.7.1.9. Cos(număr).......................................................................................................... I-64 I.7.1.10. Tan(număr)........................................................................................................ I-64 I.7.1.11. Atn(număr) ........................................................................................................ I-65 I.7.1.12. Calculul funcţiilor matematice derivate ............................................................ I-65

I.7.2. Funcţiile TEXT – pentru stringuri ................................................................ I-65 I.7.2.1. Asc(string) ........................................................................................................... I-65 I.7.2.2. Chr(CodCaracter) ............................................................................................... I-65 I.7.2.3. AscB(string); AscW(string); ChrB(CodCh); ChrW(CodCh) ............ I-66 I.7.2.4. LCase(string)....................................................................................................... I-67 I.7.2.5. UCase(string) ...................................................................................................... I-67 I.7.2.6. LTrim(string); RTrim(string); Trim(string)......................................................... I-67 I.7.2.7. Len(String | NumeVariabila) ............................................................................... I-67 I.7.2.8. Left(string, lungime) ............................................................................................ I-68 I.7.2.9. Right(string, lungime).......................................................................................... I-69 I.7.2.10. Mid(string, start [,lungime]) ............................................................................. I-69 I.7.2.11. InStr([start,]string1,string2[,compare]) ........................................................... I-70 I.7.2.12. String(număr,caracter)...................................................................................... I-71 I.7.2.13. Space(număr) .................................................................................................... I-71 I.7.2.14. Format(expresie[,format]) ................................................................................ I-71

Page 7: 2.VBA_SC4

I-7

I.7.3. Funcţii pentru tablouri (array) - UBound şi LBound.................................... I-73 I.7.4. Funcţii de conversie...................................................................................... I-74

I.7.4.1. Str(Număr) .......................................................................................................... I-74 I.7.4.2. Val(string) ........................................................................................................... I-74

I.7.5. Funcţii pentru mesaje.................................................................................... I-75 I.7.5.1. MsgBox(prompt[,buttons][,title])........................................................................ I-75 I.7.5.2. InputBox(prompt[,title][,default][,X][,Y]) .......................................................... I-76

I.7.6. Funcţii cu tipul: Date/ Time.......................................................................... I-78 I.7.6.1. DatePart(interval,date) ....................................................................................... I-78 I.7.6.2. DateDiff(interval,date1,date2) ............................................................................ I-78 I.7.6.3. DateAdd(interval,number,date)........................................................................... I-79 I.7.6.4. Day(date); Month(date); Year(date) ................................................................... I-79 I.7.6.5. Second(date); Minute(date); Hour(date)............................................................. I-79 I.7.6.6. Now(); Date(); Time() ......................................................................................... I-79 I.7.6.7. DateSerial(year, month, day) .............................................................................. I-79 I.7.6.8. TimeSerial(hour, minute, second) ....................................................................... I-80

I.7.7. Funcţii: structuri de control .......................................................................... I-80 I.7.7.1. IIf(condiţie, TruePart, FalsePart) ....................................................................... I-80 I.7.7.2. Choose(index, caz-1[,caz-2,... [,caz-n]])............................................................. I-80 I.7.7.3. Switch(expr-1,value-1[,expr-2,value-2… [,expr-n,value-n]]..]) ........... I-81

I.7.8. Funcţii de inspecţie....................................................................................... I-81 I.7.8.1. IsNull(expresie) ................................................................................................... I-81 I.7.8.2. IsEmpty(NumeVariabila)..................................................................................... I-82 I.7.8.3. IsMissing(NumeParametru) ................................................................................ I-82 I.7.8.4. VarType(NumeVariabilă) .................................................................................... I-83

I.7.9. Funcţiile agregate SQL................................................................................. I-84 I.7.10. Funcţiile agregate de domeniu.................................................................... I-85

CAP.II UTILIZAREA OBIECTELOR ÎN LIMBAJUL DE PROGRAMARE VBA II-87

II.1. Obiecte ............................................................................................................ II-87 II.1.1. Obiecte, clase de obiecte şi colecţii de obiecte .......................................... II-87 II.1.2. Provenienţa obiectelor utilizate într-o aplicaţie Access ............. II-89 II.1.3. Ierarhia obiectelor dintr-o aplicaţie ............................................................ II-89 II.1.4. Utilizarea în VBA a proprietăţilor şi metodelor obiectelor ........... II-91 II.1.5. Exemple de referire a obiectelor din modelul Access ................................ II-92 II.1.6. Instrucţiunea With...................................................................................... II-94 II.1.7. Variabile obiect .......................................................................................... II-95

II.1.7.1. Tipuri de variabile obiect ..................................................................................II-95 II.1.7.2. SET – Instrucţiunea de atribuire pentru variabile obiect......................II-98 II.1.7.3. Eliberarea resurselor folosite de o variabilă obiect. Cuvântul cheie

NOTHING. .........................................................................................................II-98 II.1.7.4. Crearea unei instanţe noi pentru o clasă de obiecte. Cuvântul cheie NEW ......II-99

II.1.8. Parcurgerea colecţiilor de obiecte. Instrucţiunea For…Each............... II-100

II.2. Modelul Access-Application........................................................................ II-101

Page 8: 2.VBA_SC4

I-8

II.2.1. Obiectul Application ................................................................................ II-101 II.2.2. Colecţia Forms ......................................................................................... II-103

II.2.2.1. Obiectul Form .................................................................................................II-104 II.2.2.1.a) Cuvântul cheie ME ...................................................................................II-105 II.2.2.1.b) Proprietăţile formularului .........................................................................II-106 II.2.2.1.c) Evenimentele formularului .......................................................................II-110 II.2.2.1.d) Metodele formularului..............................................................................II-113 II.2.2.1.e) Obiectele secţiunilor formularului: Detail, Form_Header, Form_Footer .II-115 II.2.2.1.f) Referirea Subformularelor şi a controalelor sale .......................................II-115

II.2.2.2. Obiectul Control – Text_Box (caseta de text)..................................................II-115 II.2.2.2.a) Proprietăţile controlului Text Box............................................................II-116 II.2.2.2.b) Proprietăţile dinamice ale controlului Text Box.......................................II-121 II.2.2.2.c) Evenimentele controlului Text Box ..........................................................II-121 II.2.2.2.d) Metodele controlului Text Box.................................................................II-122

II.2.2.3. Obiectul Control – Combo_Box (lista ascunsă) ..............................................II-123 II.2.2.3.a) Proprietăţile specifice controlului Combo Box ........................................II-124 II.2.2.3.b) Evenimentul specific controlului Combo Box..........................................II-126

II.2.2.4. Obiectul Control – List_Box (listă derulantă) .................................................II-127 II.2.2.5. Obiectul Control boolean – Option_Button, Check_Box, Toggle_Button.......II-127 II.2.2.6. Obiectul Control – Option_Group...................................................................II-128 II.2.2.7. Obiectul Control – Label (etichetă).................................................................II-128 II.2.2.8. Obiectul Control grafic – Line, Rectangle, Picture.........................................II-128 II.2.2.9. Obiectul Control – Command_Button .............................................................II-128

II.2.3. Obiectul DoCmd ...................................................................................... II-129 II.2.4. Obiectul Screen ........................................................................................ II-130

II.3. Modelul DAO – Data Access Objects......................................................... II-133 II.3.1. Modelul DAO – Structura ierarhic arborescentă...................................... II-133 II.3.2. Obiectul DBEngine .................................................................................. II-134 II.3.3. Colecţia Workspaces – Spaţiul (mediul) de lucru .................................... II-135 II.3.4. Tratarea erorilor de execuţie în VBA....................................................... II-137

II.3.4.1. Tratarea standard a erorilor de execuţie produse în VBA ..............................II-137 II.3.4.2. Tratarea erorilor de execuţie prin module specializate ..................................II-138

II.3.4.2.a) Instrucţiunea: On Error.............................................................................II-139 II.3.4.2.b) Instrucţiunea: Resume ..............................................................................II-140 II.3.4.2.c) Obiectul: Err .............................................................................................II-140 II.3.4.2.d) Structura unei rut ine care are modul de Error–handling .......II-140 II.3.4.2.e) Colecţia Errors şi obiecte Error ................................................................II-142

II.3.5. Colecţia Databases ................................................................................... II-143 II.3.6. Colecţia Containers .................................................................................. II-145 II.3.7. Colecţia TableDefs................................................................................... II-151 II.3.8. Colecţia QueryDefs .................................................................................. II-155 II.3.9. Colecţia Relations .................................................................................... II-158 II.3.10. Colecţia Recordsets – Set de înregistrări................................................ II-159

II.3.10.1. Funcţionarea unui set de înregistrări............................................................II-159 II.3.10.2. Tipuri de seturi de înregistrări ......................................................................II-161 II.3.10.3. Deschiderea unui set de înregistrări – Metoda OpenRecordset ..........II-161

Page 9: 2.VBA_SC4

I-9

II.3.10.4. Proprietăţile unui set de înregistrări .............................................................II-162 II.3.10.5. Accesarea secvenţială a unui set de înregistrări ...........................................II-164 II.3.10.6. Accesul direct într-un set de înregistrări.......................................................II-165

II.3.10.6.a) Metoda Seek ...........................................................................................II-165 II.3.10.6.b) Metodele FindFirst, FindLast, FindNext, FindPrevious .........................II-167

II.3.10.7. Prelucrarea datelor dintr-un Recordset ........................................................II-169 II.3.10.7.a) Citirea datelor din câmpurile unui Recordset .........................................II-169 II.3.10.7.b) Actualizarea datelor din câmpurile unui Recordset ................................II-170

II.3.11. Recordseturi definite pe cereri ............................................................... II-175 II.3.12. Recordseturi definite pe alte Recordseturi ............................................. II-176 II.3.13. Accesul la obiecte externe de date ......................................................... II-177

II.4. Obiecte provenite din clase externe............................................................ II-179 II.4.1. Standarde de utilizare a obiectelor externe............................................... II-179

II.4.1.1. Tehnologia OLE ..............................................................................................II-179 II.4.1.2. Tehnologia Automation. Obiecte ActiveX........................................................II-179

II.4.2. Crearea referinţei către un obiect extern .................................................. II-184 II.4.3. Folosirea unui control ActiveX, într-un formular sau raport ................... II-185 II.4.4. Controlul ProgressBar .............................................................................. II-186 II.4.5. Controlul Common Dialog....................................................................... II-188

II.5. Module de clase de obiecte .......................................................................... II-191 II.5.1. Programarea prin clase de module ........................................................... II-191 II.5.2. Crearea prin clasele de module a obiectelor programabile ...................... II-191 II.5.3. Instanţe implicite şi instanţe neimplicite .................................................. II-192 II.5.4. Proprietăţile unei instanţe a clasei de module .......................................... II-196

II.5.4.1. Definirea proprietăţilor prin variabile publice ...............................................II-196 II.5.4.2. Definirea proprietăţilor prin rutine Property..................................................II-197

II.5.5. Metodele unei instanţe a clasei de module............................................... II-200 II.5.6. Asignarea de metode la evenimentele unei instanţe a clasei de module .II-201

II.5.6.1. Evenimentul Initialize ......................................................................................II-201 II.5.6.2. Evenimentul Terminate....................................................................................II-202

ANEXA I - Structura ierarhică a obiectelor din MS Word............................. II-203

Anexa II - Structura ierarhică a obiectelor din MS Excel .............................. II-206

Bibliografie........................................................................................................... II-208

Page 10: 2.VBA_SC4

I-10

Page 11: 2.VBA_SC4

I-11

Cap.I Elementele de bază ale limbajului de programare VBA - Visual Basic for Application

I.1. Noţiuni generale despre VBA

I.1.1. Util izarea 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ştinţe aprofundate despre sistemele de calcul.

Basic a fost implementat iniţial, în sistemele de operare, ca un interpretor, adică ca un sistem care în momentul în care preia o instrucţiune sursă Basic, o transformă imediat în instrucţiuni 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, aplicaţiile 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 instrucţiuni sursă Basic într-un fişier care conţine instrucţiuni direct executabile, în cod obiect. În felul acesta s-au separat cele două acţiuni efectuate de un interpretor în acelaşi timp şi anume: compilarea programului sursă şi execuţia programului obiect.

Firma Microsoft a realizat o versiune de Basic, numită Visual Basic, care pe lângă principiile iniţiale s-a dorit a rezolva următoarea problemă – un limbaj de programare universal, unic, care să poată fi folosit atât în aplicaţiile 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 programare Basic, trei sisteme: � Microsoft Visual Basic (VB), ca limbaj universal de programare; � Visual Basic for Application (Visual Basic pentru aplicaţii), pres-

curtat uzual VBA, ca un limbaj complex pentru dezvoltarea aplicaţiilor î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 aplicaţiile Internet.

Page 12: 2.VBA_SC4

I-12

I.1.2. Necesitatea utilizării codului VBA în aplicaţii Access

Aplicaţiile 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 aplicaţiilor de bază, realizarea unor aplicaţii 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 aplicaţii pot interveni diverse erori (de exemplu o împărţire la zero sau ieşirea din domeniul de definiţie al unei variabile etc.) pe care sistemul le tratează în general prin stoparea modulului unde apar sau chiar a întregii aplicaţii. VBA oferă posibilitatea ca la apariţia unei erori, controlul să fie dat unui modul de cod VBA, realizat de proiectant, care să rezolve în funcţie de context situaţia apărută, fără a mai fi necesară stoparea modulului respectiv sau a aplicaţiei.

• crearea unor structuri ciclice pentru parcurgerea seturilor de înre-gistrări. Datele unei tabele sau cereri de selecţie se pot manipula ca pe un fişier specific, numit set de înregistrări;

• execuţia proceselor tranzacţionale. Acestea reprezintă practic posibi-litatea 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 funcţiilor Windows API, prin care se pot folosi module ale sistemului de operare;

• utilizarea variabilelor, constantelor şi a literalilor; • crearea şi manipularea prin program a obiectelor necesare aplicaţiei; • crearea de clase de obiecte; De asemenea VBA uşurează scrierea bibliotecilor de funcţii reutilizabile,

precum şi proiectarea şi depanarea proceselor complexe de către programatori. În concluzie, deşi comenzile macro pot da soluţii rapide problemelor

simple, limitările lor determină necesitatea folosirii limbajului VBA pentru dezvoltarea soluţiilor mai complexe.

Page 13: 2.VBA_SC4

I-13

I.1.3. Modulele de cod VBA în Access

Codul VBA este scris în unităţi numite rutine, care pot fi proceduri (subrutine) sau funcţii. Aceste proceduri şi funcţii 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 acţionarea pictogramei specifice codului VBA (după selecţia obiectului respectiv) sau prin apăsarea celor trei puncte (…) din dreptul unui eveniment al paginii respective a unui obiect aparţinând formularului sau raportului respectiv.

� Dacă procedura eveniment nu este creată, atunci automat un Wizard va crea structura acesteia, adică instrucţiunile 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 porţiunea din pagina de cod a formularului sau raportului care conţine respectiva procedură.

� Modulele globale (generale), se pot afişa prin acţionarea 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 funcţie 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ărţi: � În prima parte se introduc declaraţiile generale ale modulului, valabile

în întreg modulul. Acestea sunt: − Opţiunile modulului. De exemplu: Option Explicit, care forţează declararea tuturor variabilelor folosite în modul. − Declararea tipurilor, variabilelor şi constantelor, vizibile în tot modulul de cod.

Page 14: 2.VBA_SC4

I-14

� În a doua parte se introduc rutinele (proceduri sau funcţii) modulului de cod.

O procedură (subrutină) este o rutină care execută o acţiune: − la apariţia unui eveniment al unui obiect al aplicaţiei; − la apelarea (lansarea) ei dintr-o altă rutină VBA;

O funcţie 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; Î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; • instrucţiuni:

− instrucţiunea de atribuire; − structuri de control;

• rutine (proceduri şi funcţii); • 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 (instanţe ale claselor de obiecte); • crearea şi manipularea colecţiilor de obiecte.

Page 15: 2.VBA_SC4

I-15

Limbajele de programare dezvoltate mai pun la dispoziţie programatorilor: • proceduri specifice de tratare a erorilor; • modalităţi de verificare şi depanare a erorilor de programare; • proceduri de import/ export de obiecte exterioare aplicaţiei; • interacţiunea cu sistemul de operare; • manipularea datelor organizate în fişiere sau baze de date.

I.1.5. Structura rutinelor VBA

Scrierea rutinelor se face respectând următoarele reguli: • prima instrucţiune defineşte tipul rutinei, procedură sau funcţie; • ultima instrucţiune executabilă este End Sub | Function; • la început se pun de obicei (dar nu este obligatoriu) instrucţiunile

declarative (tipuri de date, variabile, constante); • toate instrucţiunile 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, spaţiu

ş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 – mediul de dezvoltare ş i depanare

Odată intrat într-un modul de cod, Access oferă proiectantului de aplicaţii un sistem complex pentru realizarea şi asistarea activităţii de programare în VBA. Printre cele mai utilizate instrumente ale acestui sistem sunt:

� 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 combinaţii de litere mari şi mici, (după anumite convenţii), atunci când se vor introduce 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.

Page 16: 2.VBA_SC4

I-16

� Compilarea rutinelor

Există 3 comenzi de compilare (vezi figura): − compilarea întregii aplicaţii şi salvarea codului obiect rezultat; − compilarea întregii aplicaţii dar fără modificarea codului obiect existent; − compilarea numai a modulelor de cod deschise (încărcate în memorie).

Prezenţa erorilor de compilare este marcată punctual şi este însoţită de informaţiile 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 corec-titudinea sintaxei instrucţiunilor).

� Execuţia 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 instrucţiunea de la care se doreşte începerea execuţiei; în felul acesta rutina se poate executa pornind de la oricare dintre instrucţiunile sale executabile;

• prin acţionarea uneia dintre cele 4 comenzi de RUN (vezi figura) şi anume: − Run: execuţia tuturor instrucţiunilor rutinei (eventual şi a rutinelor apelate) fără oprire; − Step Into: execuţia tuturor instrucţiunilor rutinei (eventual şi a rutinelor apelate) cu oprire după fiecare instrucţiune executată; − Step Over: execuţia tuturor instrucţiunilor rutinei (eventual şi a rutinelor apelate) cu oprire după fiecare instrucţiune executată în rutina apelantă, dar fără oprire în rutinele apelate; − Step Out: execuţia tuturor instrucţiunilor 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 execuţiei dintr-o rutină apelată, dar fără oprire la instrucţiunile din aceasta.

� În rutine se pot introduce breakpoint-uri (puncte de oprire) printr-un click pe marginea formularului modulului de cod în dreptul instrucţiunii pe care se doreşte oprirea execuţiei. Acest marcaj se vizualizează printr-un punct de cu-loare 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 instrucţiunea STOP.

Page 17: 2.VBA_SC4

I-17

� Urmărirea traseului programului şi evoluţiei î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 instrucţiune sau la un breakpoint. Pentru a marca acest lucru (program în execuţie şi oprit) sistemul va face galben fondul instrucţiunii pe care s-a oprit.

După oprirea programului pe o instrucţiune, 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 instrucţiunea: Debug.Print expresie. Vizualizarea obiectului Debug Windows se poate face la un moment dat prin Ctrl + G sau prin pictograma specifică (vezi figura).

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

Execută instrucţiune cu instrucţiune dar cursorul galben de execuţie se va opri numai pe:

Toate instr.

Nu va mai intra în rutinele apelate

Nu se va mai opri în rutina în care este

Resetează toate variabilele globale ale aplicaţiei.

Bara Visual Basic

Run Stop

Comenzi de compilare

Punctul de întrerupere(Breakpoint) Va determina oprirea rulării

programului acolo unde este întâlnit. Se recunoaşte prin culoarea maro a instrucţiunii şi a unui punct în faţa ei.

Cursorul de marcare a instrucţiunii care se va executa.

Page 18: 2.VBA_SC4

I-18

Lansarea unei acţiuni de pe bara Debug se face printr-un click pe opţiunea dorită, sau în unele cazuri, prin utilizarea grupurilor de comenzi rapide ce se găsesc în dreptul lor.

� Urmărirea execuţiei pas cu pas a unei rutine

• În Debug Windows | Locals se permite vizualizarea informaţiilor de stare în momentul lansării în execuţie a unei rutine.

Informaţiile vizează: − numele variabilelor folosite în cadrul rutinei curente; − valorile acestora în momentul execuţiei rutinei; − tipurile de date corespunzătoare variabilelor folosite.

� În momentul executării unei proceduri apelate, utilizatorul are posibi-litatea vizualizării informaţiilor de stare din cadrul procedurii apelante.

Pentru o bună înţelegere prezentăm un exemplu (suma a două numere): Public Sub SumaNumere()

Dim A As Byte Dim B As Byte Dim C As 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 execuţie a rutinei.

Se vor efectua următoarele două acţiuni: − se plasează cursorul în cadrul procedurii în locul de unde va porni execuţia acesteia (pe primul rând pentru execuţia de la început); − se execută instrucţiunea prin folosirea tastei Step Into ( sau F8).

Page 19: 2.VBA_SC4

I-19

Apariţia culorii galbene pe instrucţiunea Sub arată începutul execuţiei rutinei (cursorul a fost plasat iniţial pe această instrucţiune). Dacă se va deschide fereastra Debug Windows | Locals (Ctrl + G) se va 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 iniţializează cu 0.

Pas 2. Se accesează din nou Step Into (sau comanda rapidă F8).

Cursorul (culoarea galbenă) s-a mutat pe instrucţiunea A = 10. Execuţia rutinei a sărit peste cele trei instrucţiuni de declarare a variabilelor, deoarece acestea determină alocarea pentru variabile a spaţiului de memorie necesar înainte de execuţia 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 instrucţiune, aceasta nu este încă executată.

Pas 3. Se accesează din nou Step Into (sau comanda rapidă F8)

Culoarea galbenă s-a mutat pe instrucţiunea B = 16 iar în panoul Locals se

observă că valoarea variabilei A este în acest moment 10 iar valoarea variabilei B este tot 0 (instrucţiunea nu este executată).

Pas 4. Se accesează din nou Step Into (sau comanda rapidă F8).

Page 20: 2.VBA_SC4

I-20

Culoarea galbenă s-a mutat pe instrucţiunea 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 instrucţiune, aceasta nu este executată, ci numai după ce culoarea galbenă a trecut de instrucţiunea respectivă ea se execută.

� Pentru vizualizarea valorii unei variabile în momentul execuţiei rutinei se poate utiliza şi o altă metodă prezentată deja: se poziţionează cursorul mouse-ului pe variabila căreia dorim să-i aflăm valoarea şi se aşteaptă un interval scurt de timp. Se va observa apariţia unei casete imediat sub variabilă în care este specificată valoarea acesteia.

Pas 5. Se accesează din nou Step Into (sau comanda rapidă F8)

Dacă se poziţionează cursorul mouse-ului pe variabila C se observă cum valoarea acesteia în acest moment este 26 (suma valorilor celor două variabile A şi B: 10 + 16).

Pas 6. Se accesează din nou Step Into (sau comanda rapidă F8).

După executarea instrucţiunii <<MsgBox "Suma="& C>> va apărea un mesaj (o casetă) cu stringul "Suma=" la care este concatenată valoarea variabilei C (valoarea 26 – calculată anterior).

De asemenea dacă poziţionăm cursorul mouse-ului pe variabila C din cadrul instrucţiunii <<MsgBox "Suma=" & C>>, se afişează valoarea 26.

La o nouă accesare a butonului Step Into se observă dispariţia culorii galbene, semn că execuţia rutinei s-a încheiat.

Page 21: 2.VBA_SC4

I-21

În continuare vom crea un punct de întrerupere cu ajutorul mouse-ului prin click în partea stângă pe bara verticală în dreptul instrucţiunii dorite.

Dacă se operează la lansarea în execuţie a procedurii conform cu pasul nr. 1 se va observa apariţia culorii galbene pe prima instrucţiune (semn că execuţia rutinei a început). După lansarea în execuţie a rutinei, dacă se va folosi opţiunea RUN (comanda rapidă F5) se va observa că marcajul galben trece direct pe instrucţiunea care are punctul de întrerupere (sărind peste instrucţiunile A = 10, B = 16, C = A + B).

Analizând acum valorile variabilelor, observăm că s-au executat totuşi

toate instrucţiunile până la punctul de întrerupere. La o nouă accesare a opţiunii RUN se va afişa mesajul specific (Suma = 26) după care execuţia se va încheia.

Pentru demarcarea punctului de întrerupere vom face click pe acesta. În concluzie, din cele prezentate putem afirma că mediul de depanare

reprezintă un instrument foarte eficient în determinarea erorilor de execuţie şi a optimizării aplicaţiilor.

I.2. Tipuri de date

Prin dată se înţelege orice entitate asupra căreia poate opera calculatorul. În cod maşină datele se reprezintă sub forma unei secvenţe 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 biţi. 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.

Bara verticală

Punctul de întrerupere

Page 22: 2.VBA_SC4

I-22

Un tip de date este noţiunea folosită pentru a defini mulţimea valorilor pe care le pot avea datele ce aparţin acestui tip, dimensiunea efectivă pe care o ocupă în memorie datele, precum şi operaţiile ce se pot efectua asupra acestor date.

VBA pune la dispoziţia 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 instrucţiunii Type.

Tipurile de date pot fi: − elementare (simple) – o variabilă de acest tip va conţine o singură valoare; − structurate – o variabilă de acest tip va conţine mai multe valori elementare.

I.2.1. Tipuri de date elementare

I.2.1.1. Date numerice întregi

Numele tipului de date

Memoria ocupată

Domeniul de valori

Numărul de valori

Valoarea iniţială

Ex. de nume variabilă

Byte (octet) 1 octet 0 … 255 2^8 0 btValue

Integer (întreg) 2 octeţi –32.768…+32.767 2^16 0 iCounter

Long (întreg lung)

4 octeţi – 2.147.283.648 +2.147.483.647

2^32 0 lAmount

Currency (valută)

8 octeţi +/– 922.337.203.

685.477,5808 15 cifre şi 4 zecimale

0 cValuta

Literalii numere întregi se scriu funcţie de sistemul de numeraţie 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 tipului de date

Memoria ocupată

Domeniu Mantisa(M)

Domeniu Exponent(E)

Valoare iniţială

Ex. de nume variabilă

Single (precizie simplă) 4 octeţi aprox 7 cifre

zecimale E-45…E38 0 sngValue

Double (precizie dublă) 8 octeţi aprox 14 cifre

zecimale E-324…E308 0 dValue

� Datele numerice reale se exprimă sub forma: +/–M * 10^+/–E

Page 23: 2.VBA_SC4

I-23

I.2.1.3. Tipul de date BOOLEAN – logic

Numele tipului de date

Spaţiul de memorare

Domeniu de valori

Valoarea iniţială

Ex. de nume variabilă

Boolean (logic)

2 octeţi True (–1) False (0)

False (0) bRaspuns

� Tipul de date BOOLEAN este compatibil cu tipul de date INTEGER.

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 conţine până la 2^31 caractere

(aproximativ 2 miliarde); − string de lungime fixă, care poate conţine 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 internaţionale etc.

Literalii string se scriu între ghilimele ("…."). La iniţializare 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 numeraţie zecimal – în celule, înaintea fiecărui caracter; • sistemul de numeraţie hexazecimal – pe cele 2 margini, astfel:

− prima cifră hexazecimală pe primul rând; − a doua cifră hexazecimală pe prima coloană.

Page 24: 2.VBA_SC4

I-24

H 0 1 2 3 4 5 6 7 0 0 · 16 · 32 [space] 48 0 64 @ 80 P 96 ` 112 p

1 1 · 17 · 33 ! 49 1 65 A 81 Q 97 a 113 q

2 2 · 18 · 34 " 50 2 66 B 82 R 98 b 114 r

3 3 · 19 · 35 # 51 3 67 C 83 S 99 c 115 s

4 4 · 20 · 36 $ 52 4 68 D 84 T 100 d 116 t

5 5 · 21 · 37 % 53 5 69 E 85 U 101 e 117 u

6 6 · 22 · 38 & 54 6 70 F 86 V 102 f 118 v

7 7 Bell 23 · 39 ' 55 7 71 G 87 W 103 g 119 w

8 8 BS 24 · 40 ( 56 8 72 H 88 X 104 h 120 x

9 9 Tab 25 · 41 ) 57 9 73 I 89 Y 105 i 121 y

A 10 LF 26 · 42 * 58 : 74 J 90 Z 106 j 122 z

B 11 · 27 · 43 + 59 ; 75 K 91 [ 107 k 123 {

C 12 · 28 · 44 , 60 < 76 L 92 \ 108 l 124 |

D 13 CR 29 · 45 - 61 = 77 M 93 ] 109 m 125 }

E 14 · 30 · 46 . 62 > 78 N 94 ^ 110 n 126 ~

F 15 · 31 · 47 / 63 ? 79 O 95 _ 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 spaţiul 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 octeţi şi care conţine 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.2.1.5. Tipul de date DATE – data calendaristică şi timpul

Numele tipului de date

Spaţiul de memorare

Domeniu de valori

Ex. de nume variabilă

Date (data + timpul) 8 octeţi 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 convenţia:

Page 25: 2.VBA_SC4

I-25

− 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. Tipuri de date structurate

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 esenţial în programare.

I.2.2.1. Tipul de date ARRAY – tablou

Un Tablou – Array defineşte o mulţime 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ă defi-

nesc 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 operaţii 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 octeţi constituie o excepţie la ultima afirmaţie.

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 conţine 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

Page 26: 2.VBA_SC4

I-26

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 instrucţiunea TYPE astfel: [Public | Private] Type NumeTip

NumeElement1 As type 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.

Page 27: 2.VBA_SC4

I-27

� Caracterele ( _ ) se folosesc pentru continuarea unei instrucţiuni 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ă performanţele programului, atât ca memorie ocupată cât şi ca timp de execuţie.

Numele tipului de date

Spaţiul de memorare

Domeniu Valoarea iniţială

Ex. de nume variabilă

Variant (numere)

16 octeţi ca la numeric Empty (Gol) vntValue

Variant (string)

22 octeţi ca la stringuri Empty (Gol) vntNume

Valorile EMPTY, NULL, STRING VID

− EMPTY – reprezintă valoarea pe care o are o variabilă variant care nu este iniţializată. 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 conţine nici o valoare (nici un caracter), adică este "".

� Tipul de date OBJECT – va fi prezentat în următorul capitol.

I.3. Variabile

Variabilele sunt nume de locaţii de memorie care conţin valori de un anumit tip, ce se modifică în timpul execuţiei programului. Variabilele se carac-terizează 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 funcţie de domeniul lor de vizibilitate. În momentul când variabilele apar (devin vizibile), li se pot atribui

Page 28: 2.VBA_SC4

I-28

valori de un anumit tip şi pot fi folosite în cadrul instrucţiunilor. Î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ă înţelegeţi mai bine declararea variabilelor în limbajul Visual Basic.

I.3.1. Declararea variabilelor

Declararea variabilelor se face de obicei cu instrucţiunea declarativă DIM. Forma acestei instrucţiuni 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 convenţional 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 declaraţia 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

O greşeală obişnuită este declararea mai multor variabile pe aceeaşi linie, fără a se specifica tipul pentru 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.

Page 29: 2.VBA_SC4

I-29

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 declaraţia Dim. Astfel:

Tipul de date Integer Long Currency Single Double String Variant

Caracterele de tip % & @ ! # $ implicit

Acest tip de declaraţii este importat din variantele mai vechi de Basic, dar nu este recomandabil. Exemplu. Următoarele declaraţii sunt echivalente.

Dim Nume As String ~ Dim Nume$ Dim Virsta As Integer ~ Dim Virsta% Dim Anul As Variant ~ Dim Anul

I.3.3. Option Explicit (declararea explicită a variabilelor)

Este o instrucţiune declarativă care poate fi inclusă în secţiunea 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.

Introducerea instrucţiunii declarative Option Explicit în fiecare modul, formular sau raport se poate face automat prin activarea opţiunii Require Variable Declarations (cere declaraţii de variabile) din meniul Tools | Options | Module. Este foarte important ca această instrucţiune (Option Explicit) să fie plasată în toate modulele de cod. Asiguraţi-vă că aţi configurat opţiunea 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, instrucţiunea: 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 instrucţiunea declarativă Dim, pentru fiecare variabilă, ca în exemplul următor:

Dim iCounter As Integer Dim sName As String

Page 30: 2.VBA_SC4

I-30

Aşa cum se vede, acest tip de declaraţie conţine atât numele variabilei, cât şi tipul datelor pe care le poate conţine. Acest lucru permite compilatorului să 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 substanţial resursele necesare executării programului.

I.3.4. Variabile Locale ş i Globale

În funcţie 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 secţia de declaraţii 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ă declaraţie se face: • într-o rutină – ea va putea fi folosită numai în aceasta, fiind o variabilă

locală; • în secţiunea de declaraţii generale ale modulului de cod – ea este

globală ş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ă aparţinând modulului în care au fost declarate. Valoarea variabilei poate fi schimbată de orice subrutină sau funcţie 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

Page 31: 2.VBA_SC4

I-31

� Reţineţi câteva observaţii: − convenţia de numire a variabilei modale prin folosirea literei m ca

prefix al numelui acesteia. Aceasta o face să fie uşor recunoscută de progra-mator ca o variabilă de nivel modul (globală);

− folosiţi declaraţiile de nivel modul numai pentru variabilele care trebuie să fie văzute din mai multe rutine;

− încercaţi să evitaţi (atunci când este posibil) utilizarea variabilelor globale. Aceast lucru 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 aplicaţie. 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 aplicaţie. Declaraţiile variabilelor publice trebuie să fie plasate în secţiunea General Declarations a modulului general de cod.

Pentru declararea variabilelor publice se foloseşte cuvântul cheie PUBLIC, în loc de DIM.

Exemplu. O declaraţie de variabilă publică arată aşa: Option Explicit Public piCounter As Integer

De obicei, convenţional 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 secţiunea de declaraţii generale a modulului de cod, adică variabile care nu sunt vizibile decât de rutinele aparţinând modulului respectiv de cod. Exemplu. Private MyName As String

� Cuvântul cheie DIM este echivalent cu PRIVATE atunci când se foloseşte la declararea variabilelor în modulele de cod. Este totuşi indicată folosirea formei Private, pentru a face codul mai lizibil (mai uşor de citit şi mai rapid de interpretat).

Page 32: 2.VBA_SC4

I-32

I.3.6. Variabile Statice

Variabile statice se pot declara numai în rutine, prin folosirea cuvântului cheie STATIC, î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ă diferenţa dintre variabilele locale şi cele statice. Deoarece variabilele locale sunt iniţializate la fiecare apel al codului, de fiecare dată când executaţi 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, instrucţiunea declarativă Dim

defineşte variabila iCounter şi o iniţializează cu 0. Ea este puţin 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 reţinută. Deci la prima execuţie 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.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ă faceţi 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 spaţiu în memorie. Fără alte instruc-

Page 33: 2.VBA_SC4

I-33

ţiuni speciale, o variabilă se creează în momentul în care modulul în care este declarată este apelat (executat) şi dispare (se distruge, eliberează spaţiul de memorie ocupat) în momentul terminării modulului respectiv.

Astfel: − o variabilă locală, declarată într-o procedură eveniment, va fi alocată

numai în timpul execuţiei procedurii respective (bineînţeles 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 execuţie;

− o variabilă publică, declarată într-un modul general de cod va fi alocată în tot timpul execuţiei aplicaţiei.

I.3.8. Declararea ş i folosirea variabilelor ARRAY

Variabilele Array (tablou) se declară la fel ca orice altă variabilă folosindu-se instrucţiunile declarative Dim, Static, Private, sau Public. Diferenţa 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 secţiunea de declaraţii generale, instrucţiunea declarativă Option Base 1.

Exemplu. Declaraţia 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 declaraţie 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 puţin _ 176 bytes (11 el. * 16 bytes). Dim MyIntegerArray (10) As Integer ' Tablou Integer foloseşte _ 22 bytes (11 elemenste * 2 bytes).

Page 34: 2.VBA_SC4

I-34

Dim MyDoubleArray (10) As Double ' Tablou Double-precision _ 88 bytes (11 el. * 8 bytes). Dim MyVariantArray (10) ' Tablou Variant – cel puţin _ 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 puţin _ 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, iar cu N marginea de sus a indicelui.

� Declararea tablourilor cu dimensiuni variabile – dinamice

În timp ce tablourile cu dimensiuni fixe vor ocupa din etapa de compilare o anumită dimensiune de memorie care nu mai poate fi modificată în timpul execuţiei, 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 instrucţiunea 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 execuţiei 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.

� Instrucţiunea 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 instrucţiunii;

− funcţia Ubound întoarce indicele superior maxim al unui tablou;

Page 35: 2.VBA_SC4

I-35

� 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 octeţi

Un tablou de octeţi 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 octeţi 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 octeţi şi stringuri.

� Trebuie remarcat că în această operaţie fiecare caracter al strigului va ocupa 2 elemente din tabloul de octeţi, deoarece, aşa cum am mai arătat, caracterele sunt memorate în UNICODE (deci pe 2 octeţi). Exemplu. Pentru înţelegerea acestei secvenţe 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 octeţi, va avea 6 elemente deoarece pentru un caracter din _ string sunt necesare 2 elemente de 1 octet ReDim X(5) Dim k As Integer, j As Integer, i As Integer Sir = "1AŞ" X = Sir

Page 36: 2.VBA_SC4

I-36

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–poziţia î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ă execuţie 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 mulţi octeţi

(de exemplu o variabilă integer ocupă 2 octeţi), 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.

Page 37: 2.VBA_SC4

I-37

Din tabelul de mai jos, se observă cum se găseşte în memoria internă, într-o variabilă de tip tablou de octeţi, datele dintr-un string.

Caracterele din string ‘1’ ‘A’ ‘Ş’

Cod ANSI 1octet/caracter - zecimal 49 65 170

Cod UNICODE 2 octeţi/caracter-zecimal 49 65 350

Memorie -Tabloul X 6 octeţi - binar

0011.0001 0000.0000 0100.0001 0000.0000 0101.1110 0000.0001

Memorie -Tabloul X 6 octeţi - hexa 31 00 41 00 5E 01

Memorie -Tabloul X 6 octeţi - zecimal 49 0 65 0 94 1

I.4. Constante

Prin declararea unei constante, se poate atribui unui nume, o valoare. Aceasta se face prin instrucţiunea declarativă Const.

După declarare, o constantă nu îşi mai poate modifica valoarea. Forma instrucţiunii declarative CONST este:

[Public | Private] Const NumeConstantă [As TipData] = Valoare O constantă se comportă practic ca o variabilă, iniţializată cu o anumită

valoare, care nu se mai poate schimba în timpul execuţiei aplicaţiei. Regulile aplicate variabilelor privind domeniul şi durata de valabilitate

sunt efective şi în cazul constantelor. Deci vom avea: − constante locale sau globale, în funcţie de locul de declarare (în rutină

sau secţiunea de declaraţii 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 declaraţiile: 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.

Page 38: 2.VBA_SC4

I-38

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 – Instrucţiuni executabile

Limbajele de programare au un set de instrucţiuni care constituie lista completă a posibilităţilor de care dispune programatorul pentru a determina rezolvarea unei probleme (aplicaţie) pe un sistem de calcul.

Instrucţiunile unui limbaj de programare sunt de două feluri: − Instrucţiuni declarative, care practic nu determină executarea unei

acţiuni de către sistemul de calcul, ci numai nişte indicaţii care se dau compilatorului. De exemplu instrucţiunile de declarare ale tipurilor de date, variabilelor sau constantelor (Dim, Const, Type etc.), opţiunile de compilare (Option Explicit, Option Base, Option Compare Database, etc.)

− Instrucţiuni executabile, care reprezintă descrierea unei acţiuni pe care o va efectua sistemul de calcul, în special privind datele aplicaţiei (If, For, Do etc.).

Execuţia unei instrucţiuni reprezintă efectuarea operaţiei specificate de codul instrucţiunii, interpretate la un moment dat de unitatea centrală a unui sistem de calcul sau de un procesor. De obicei, execuţia instrucţiunii presupune obţinerea 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 operaţii pe care le face unitatea centrală a sistemului de calcul sunt operaţiile de adunare, scădere, citire, scriere, comparaţie, etc.

Limbajele moderne de programare au un set redus de instrucţiuni complexe:

− declararea structurilor de date; − instrucţiunea de atribuire – prin care se calculează expresii; − structurile de control – prin care se determină "traseul" printre

instrucţiuni, adică ordinea în care se execută instrucţiunile; − declararea şi apelarea rutinelor; − crearea modulelor de clase de obiecte; − crearea şi manipularea obiectelor. Practic, instrucţiunile executabile ale limbajelor moderne de programare

sunt instrucţiunea de atribuire şi instrucţiunile prin care se realizează structurile de control. Alte operaţii necesare unei aplicaţii (ca de exemplu executarea operaţiilor de Input/ Output), sunt realizate prin rutine din bibliotecile de obiecte, funcţii şi proceduri disponibile limbajului respectiv de programare.

Page 39: 2.VBA_SC4

I-39

I.5.1. Instrucţ iunea de atribuire

Forma acestei instrucţiuni este: NumeVariabilă = Expresie Acţiunea acestei instrucţiuni constă în calcularea expresiei (din dreapta

semnului =) şi depunerea rezultatului în variabilă (din stânga semnului =). Pentru a se executa cu succes instrucţiunea, este necesar ca rezultatul

expresiei să aparţină unui tip de date compatibil cu cel al variabilei. În caz contrar se va produce o eroare de execuţie (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 execuţie; ' efectuează adunarea după care transformă constanta numerică 291 _ în stringul "291" Vnr = Vstr ' nu produce o eroare de execuţie; ' 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 execuţie – TYPE MISMATCH

End Sub

� Formarea expresiilor în Visual Basic

O expresie este formată din termeni asupra cărora se efectuează anumite operaţii.

O expresie a cărei evaluare este o valoare logică (True sau False) se mai numeşte condiţie.

• Termenii pot fi: variabile, constante, literali (valori date direct) sau funcţii (proprii sau din biblioteci).

Page 40: 2.VBA_SC4

I-40

• Operatorii sunt de trei tipuri şi anume: − aritmetici, care acţionând asupra unor termeni scalari (numere,

stringuri, date calendaristice, etc.) vor determina tot un rezultat de aceeaşi natură (scalar):

^ * / \ Mod + - & Ridicare la

putere Înmulţire

Împărţire reală

Împărţire întreagă

Restul împărţirii

Adunare Scădere Concate-

nare şiruri

5^2=25 5*2=10 5/2=2,5 10\3=3 10 Mod 3=1 5+2=7 5-2=3 "Ab" &

2="Ab2"

− relaţionali, care acţionând asupra unor termeni scalari (numere, stringuri, date calendaristice, etc. ) vor determina un rezultat logic (boolean):

< <= > >= = <>

mai mic mai mic sau egal

mai mare mai mare sau egal

egal ne egal

(1<1) =False (5<=5) =True (5>4) =True (5>=5) =True (5=5) =True (5<>5) = False

Is Like apartenenţa la o mulţime 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 mulţime de caractere astfel: ? Un singur caracter. ("a2B3a" Like "a?a") = False

* Zero sau mai multe caractere. ("a2B3a" Like "a*a") = True

# Un singur număr (0-9). ("a2a" Like "a#a") = True

[Listă char] ex. [A-R]

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:

Op NOT Op 1 Op 2 AND Op 1 Op 2 OR Op 1 Op 2 XOR

True False True True True True True True True True False

False True True False False True False True True False True

False True False False True True False True True

False False False False False False False False False

Mai există două funcţii logice, mai puţin folosite, şi anume: • EQV – utilizată pentru verificarea echivalenţei logice a două expresii; • IMP – utilizată pentru verificarea implicării logice între două expresii.

� Operatorii sunt aşezaţi de la stânga la dreapta în ordinea priorităţii lor în execuţie, care este în general cea obişnuită din matematică. Parantezele rotunde

Page 41: 2.VBA_SC4

I-41

sunt folosite pentru stabilirea unei ordini explicite a priorităţii în execuţie a operaţiilor.

� 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 excepţie, ş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 funcţie de tipul de date pe care îl reprezintă, chiar valoarea cu care se iniţializează 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. Structurile de control

Aşa cum am mai arătat, structurile de control stabilesc ordinea în care se execută instrucţiunile. Există trei structuri de control, şi anume: structura secvenţială, structura alternativă (decizională) şi structura repetitivă (în buclă, în ciclu).

I.5.2.1. Structura secvenţială

Reprezintă execuţia secvenţială a instrucţiunilor, în ordinea în care au fost scrise. Nu necesită folosirea unei instrucţiuni.

I.5.2.2. Structura alternativă

Reprezintă execuţia din mai multe grupuri de instrucţiuni, numai a unuia singur, în funcţie de evaluarea unor condiţii.

I.5.2.2.a) Structura alternativă simplă

� Instrucţiunea: If... Then... Else

If condiţie Then Grup 1 de instrucţiuni

[Else Grup 2 de instrucţiuni]

End IF Structura If... Then... Else evaluează dacă condiţia este adevărată sau falsă.

Dacă: • condiţia este adevărată, vor fi executate toate instrucţiunile dintre If şi

Else (Grup 1 de instrucţiuni); • condiţia este falsă, vor fi executate toate instrucţiunile dintre Else şi

End If (Grup 2 de instrucţiuni).

Page 42: 2.VBA_SC4

I-42

� Folosirea clauzei Else este opţională.

� O condiţie 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 ' Condiţia testează dacă în controlul _ txtValue, este introdusă o valoare. Acest lucru se face cu funcţia _ IsNULL, studiată în alt modul

MsgBox "Trebuie sa introduceti o valoare" Else

MsgBox "Ati introdus:" & Me!txtValue 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 instrucţiuni If... Then... Else, atunci când decizia se ia prin evaluarea mai multor condiţii (Structura alternativă multiplă), este mult mai simplă, fără îndoială, utilizarea instrucţiunii Select Case sau a instrucţiunii If... Then... ElseIF…Else

� Instrucţiunea Select Case

Select Case NumeVariabilă Case Valoare1

Grup 1 de instrucţiuni [Case Valoare2

Grup 2 de instrucţiuni] [Case ValoareX

Grup X de instrucţiuni] ………………………

[Case Else Grup else de instrucţiuni]

End Select

Această instrucţiune evaluează mai multe condiţii formate prin verificarea egalităţilor între valoarea variabilei ataşate instrucţiunii (NumeVariabilă) şi valorile din dreptul cuvintelor cheie CASE (Valoare1, Valoare2, etc.). Deci:

Condiţia I va fi: NumeVariabilă=ValoareI Condiţiile sunt evaluate pe rând, în ordinea plasării lor în instrucţiune,

până când se găseşte una adevărată.

Page 43: 2.VBA_SC4

I-43

După găsirea unei condiţii advărate atunci se va executa grupul corespunzător de instrucţiuni, după care instrucţiunea Select Case se termină, programul continuând cu prima instrucţiune plasată după aceasta.

� Dacă toate condiţiile sunt false atunci se vor executa – dacă există – instrucţiunile dintre Else …. End Select (Grup else de instrucţiuni).

� Dacă mai multe condiţii sunt adevărate, atunci se va executa numai un singur grup de instrucţiuni şi anume cel aflat după prima condiţie găsită adevărată.

� În ValoareI se pot introduce şi: − reuniuni de mulţimi – prin operatorul virgulă (ex: 1, 2, 5); − intervale – prin operatorul TO (ex: 1 To 7); − submulţimi – prin operatorul IS (ex: Is > 7).

� Folosirea clauzei Case Else este opţională.

� O condiţie 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 'condiţia: NumeV=7 - False MsgBox "Grup 1 de instrucţiuni"

Case 5, 9 'condiţia: (NumeV=5) OR (NumeV=9) - True MsgBox "Grup 2 de instrucţiuni" 'execuţia instrucţiunii(lor) la care condiţia=True 'după execuţie, instrucţiunea Case se termină

Case 1 To 9 'condiţia: (NumeV>=1) AND (NumeV<=9) - True 'deşi şi această condiţie=true, acest grup nu va fi executat MsgBox "Grup 3 de instrucţiuni"

Case Else MsgBox "Grup else de instrucţiuni"

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.

Page 44: 2.VBA_SC4

I-44

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. ' Dacă controlul este NULL atunci nu este introdusă nici o valoare. If 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 instrucţiune If pentru a evalua dacă txtValue este Null, caz în care se memorează un zero într-o variabilă numită iResponse. În caz contrar, valoarea conţinută în controlul txtValue este memorată în iResponse. Instrucţiunea Case evaluează conţinutul variabilei iResponse. Dacă valoarea este 0, este afişată o casetă de text cu mesajul: "Trebuie să introduceţi un număr". Dacă valoarea este între 1 şi 5 inclusiv, este afişată o casetă de text conţinând mesajul: "Aţi 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.

� Instrucţiunea If... Then... ElseIF…Else

If condiţie-1 Then [grup 1 de instrucţiuni]

ElseIf condiţie-n Then [grup n de instrucţiuni] ……………. …..

Else [grup else de instrucţiuni]

End If

Page 45: 2.VBA_SC4

I-45

Instrucţiunea funcţionează similar instrucţiunii Select Case, numai că: − condiţiile introduse sunt independente, ne mai fiind obligatorie prezenţa

unei variabile ca un termen al condiţiei. Deci instrucţiunea va evalua pe rând, în ordine, condiţia 1, 2 etc. • Prima condiţie găsită adevărată va determina execuţia grupului

respectiv de instrucţiuni şi terminarea instrucţiunii. • Dacă toate condiţiile sunt false, vor fi executate toate instrucţiunile

dintre Else şi End If (Grup else de instrucţiuni).

� Folosirea clauzei Else este opţională.

� O condiţie 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ă execuţia repetată a unui anumit grup de instrucţiuni, numit ciclu sau buclă, până când o condiţie 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 condiţie este TRUE sau • până când (Until) o condiţie devine TRUE Există două forme ale instrucţiunii Do, în funcţie de locul unde se găseşte

plasată condiţia şi anume la început sau sfârşit: Do [{While | Until} condiţie] Do

[grup instrucţiuni] [grup instrucţiuni] [Exit Do] sau [Exit Do] [grup instrucţiuni] [grup instrucţiuni]

Loop Loop [{While | Until} condiţie]

Page 46: 2.VBA_SC4

I-46

� Instrucţiunea Exit Do provoacă ieşirea forţată din ciclu. De obicei se execută în funcţie de evaluarea unei condiţii într-o instrucţiune IF.

� Este permisă folosirea instrucţiunii Do şi fără nici o condiţie. În acest caz este obligatorie inserarea în ciclul Do a unei instrucţiuni Exit Do sau Exit Sub | Function, pentru a nu se genera un ciclu fără sfârşit.

� Condiţia este evaluată în funcţie de locul unde este plasată în instrucţiune şi anume:

− la prima formă a instrucţiunii (cea din stânga) – înaintea executării ciclului; − la a doua formă a instrucţiunii (cea din dreapta) – după executarea ciclului.

� Numărul minim de cicluri care se execută este: − la prima formă a instrucţiunii (cea din stânga) – se poate ca ciclul să nu

se execute de loc; − la a doua formă a instrucţiunii (cea din dreapta) – ciclul se va executa

minim o dată.

� O condiţie 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 secvenţei 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ă.

Dacă secvenţa de cod trebuie să fie executată necondiţionat cel puţin 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

Page 47: 2.VBA_SC4

I-47

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 condiţiei se face după executatea ciclului.

� Structura Do While|Until... Loop face evaluarea condiţiei înainte de executarea ciclului şi de aceea nu asigură execuţia acestuia.

� Structura Do... Loop While|Until face evaluarea condiţiei după executarea ciclului şi de aceea execuţia acestuia este asigurată cel puţin 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ă colecţiilor de obiecte sau tablourilor şi care va fi prezentată în următorul capitol. Această instrucţiune permite parcurgerea automată a tuturor elementelor unei colecţii sau tablou.

Forma instrucţiunii FOR este: For contor = start To end [Step pas] [grup instrucţiuni] [Exit For]

[grup instrucţiuni] Next [contor] în care: − contor – variabilă numerică folosită pentru stabilirea numărului de

execuţii ale ciclului; − start – valoarea iniţială a contorului; − end – valoarea finală a contorului; − pas – valoarea cu care contorul se incrementează; poate fi pozitivă sau

negativă (implicit este 1); incrementarea se efectuează după execuţia fiecărui ciclu. Funcţionarea instrucţiunii FOR se face prin parcurgerea următoarelor

etape: a) se determină în funcţie de valoarea (pozitivă sau negativă) pe care o are

pasul (step), condiţia de terminare a ciclului şi anume:

− Dacă PAS >=0, condiţia va fi: contor > end; − Dacă PAS < 0, condiţia va fi: contor < end;

b) se evaluează condiţia de terminare a ciclului;

c) în continuare, dacă condiţia este:

− FALSE – se execută ciclul şi se continuă instrucţiunea FOR cu etapa d); − TRUE – nu se execută ciclul şi se termină instrucţiunea FOR. Programul continuă cu instrucţiunile de după NEXT;

Page 48: 2.VBA_SC4

I-48

d) după executarea ciclului se adună pasul la contor. După această operaţie instrucţiunea FOR continuă cu repetarea evaluării condiţiei, 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 puţin un ciclu, trebuie ca la început start<=end; − numărul de cicluri efectuate va fi: end-start+1.

• negativ, atunci: − dinamica contorului va fi descrescătoare, prin scăderea valorii absolute a pasului la fiecare ciclu; − pentru ca să se execute cel puţin un ciclu, trebuie ca la început start>=end; − numărul de cicluri efectuate va fi: start-end+1.

� Instrucţiunea Exit For provoacă ieşirea forţată din ciclu şi continuarea programului cu instrucţiunile de după NEXT. De obicei se execută în funcţie de evaluarea unei condiţii într-o instrucţiune 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 iteraţii de executat. Exemplu.

Private Sub cmdForNext_Click () Dim iCounter As Integer For iCounter = 1 To 5

MsgBox iCounter Next iCounter

End Sub

Page 49: 2.VBA_SC4

I-49

Procedura va afişa cinci mesaje, cu numere de la 1 la 5.

� Observaţi 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 funcţii

I.6.1. Ce este o rutină ş 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ă acţiune. Ea este executată numai atunci când este lansată (apelată), de către un obiect al aplicaţiei 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 aplicaţiei; − un macro. Rutina poate fi apelată de un număr nelimitat de ori din diferite locuri. După execuţia unei rutine, controlul revine obiectului care a provocat

apelarea rutinei. Toate declaraţiile (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 execuţie. La terminarea rutinei, are loc automat eliberarea din memorie a tuturor variabilelor şi constantelor locale ale acesteia.

� Î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 interacţionează 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:

Page 50: 2.VBA_SC4

I-50

� 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 (opţional). Parametrii definiţi î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 definiţie îşi pot schimba valoarea în timpul execuţiei 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 operaţia de transfer:

Page 51: 2.VBA_SC4

I-51

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.)

Deci în acest caz se transferă anumite valori, în ambele sensuri, între perechile de parametri formal şi actuali. Spunem că transmisia parametrilor se face prin valoare.

� Apelarea rutinelor şi transmitera parametrilor prin adresă

Î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

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 Parametrii formali: Intrare: A1, A2 Ieşire: B1 Instr1 ………... ..= A1 + A2 ' folosirea 'parametrilor de intrare ……….. B1= …… ' folosirea 'parametrilor de ieşire ……….. Sfârşit rutină

X1,X2

A1,A2

Y

B1

M1,M2

A1,A2

T

B1

Parametri actuali

X1 X2 Y

a d r e s e

A1 A2 B1 Parametri formali

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 Parametrii formali: Intrare:A1,A2 Ieşire:B1 Instr1 ……….. ..= A1+A2 'folosirea 'parametrilor de intrare ……….. B1= ….. 'folosirea 'parametrilor de ieşire ……….. Sfârşit rutină

Parametri actuali

X1 X2 Y

a d r e s e

A1 A2 B1 Parametri formali

Page 52: 2.VBA_SC4

I-52

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. Crearea (definirea) unei rutine

Rutinele sunt de două feluri: proceduri (sau subrutine) şi funcţii. Dife-renţa dintre ele constă în faptul că:

• Funcţiile au un parametru implicit de ieşire care este chiar numele funcţiei. • Procedurile sunt apelate prin instrucţiuni, iar funcţiile sunt apelate prin

introducerea numelui acesteia într-o expresie (ca şi cum ar fi o variabilă sau constantă).

� Funcţiile pot fi folosite direct oriunde este cerută o expresie, cu condiţia 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)] [declaraţii locale de: variabile, constante, etc. ] [instrucţiuni] [Exit Sub] [instrucţiuni]

End Sub • Instrucţiunea Exit Sub provoacă, dacă este întâlnită, terminarea

procedurii şi redarea controlului modulului apelant, la instrucţiunea care se găseşte imediat după cea de apelare. În mod normal procedurile se termină la instrucţiunea End Sub.

• Opţiunile 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 aplicaţiei, iar cea declarată Private va fi vizibilă numai din modulul în care este declarată. Dacă nu se foloseşte nici una din cele două opţiuni, procedura va fi considerată Public.

• Opţiunea Static determină ca toate variabilele locale declarate în procedură să funcţoineze ca variabilele statice.

• Toate instrucţiunile sunt permise în proceduri,folosind date care pot fi: − parametrii formali; − variabilele şi constantele globale; − variabilele şi constantele locale;

Page 53: 2.VBA_SC4

I-53

� 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 puţin lizibilă, greu de depanat sau de întreţinut.

• 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

Opţiunile 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ţii

[Public|Private][Static]Function NumeF-cţie[(ParFormali)] [As TipFuncţie] [declaraţii locale de: variabile, constante, etc. ] [instrucţiuni] [Exit Function] [instrucţiuni]

End Function Se observă că singura deosebire esenţială faţă de proceduri se datorează

faptului că numele funcţiei are două semnificaţii, 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 funcţiei se va considera implicit Boolean.

Deci o funcţie, 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 funcţii sunt Exit Function şi End Function, evident cu acelaşi rol.

Exemplu. Următorul exemplu reprezintă o funcţie 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_ funcţiei

Else

Page 54: 2.VBA_SC4

I-54

TestF = Numar1 + Numar2 ' valoarea de retur se introduce în numele_ funcţiei

End If End Function

……. Se va folosi această funcţie astfel…. MsgBox TestF (20, 5) ' afişează 15 MsgBox TestF (2, 5) ' afişează 7

I.6.4. Apelarea unei rutine

� Orice funcţie poate fi apelată ca o procedură, dar o procedură nu poate fi folosită ca o funcţie (î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 instrucţiunea Call:

Call NumeProcedură (ListaParametrilorActuali) � direct, folosind numele procedurii, urmat eventual de lista parametrilor

actuali: NumeProcedură ListaParametrilorActuali

� Parametrii se separă prin virgulă.

� Diferenţa î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 funcţie se apelează dintr-o expresie, folosindu-se numele ei urmat de lista parametrilor actuali incluşi între paranteze. Numele funcţiei, se va comporta în expresie ca o variabilă, încărcată după execuţia funcţiei cu o valoare, ca şi cum ar fi un parametru de ieşire al unei proceduri. Spunem că funcţia întoarce (returnează) o valoare după execuţia ei. Această valoare va participa la evaluarea expresiei respective.

� O procedură nu poate fi folosită într-o expresie în locul unei funcţii, deoarece nu întoarce valori prin numele ei (chiar dacă are parametri de ieşire).

� Funcţiile 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 funcţiei TestF.

Sub TestS (Numar1 As Integer, Numar2 As Integer, Rezultat As Integer) If Numar1 > Numar2 Then

Page 55: 2.VBA_SC4

I-55

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.

Codul VBA este scris numai în unităţi numite rutine. Aceste rutine sunt păstrate fie în modulul general (global) de cod, fie în modulele specifice din spatele formularelor sau rapoartelor (Code Behind Forms – CBF).

Domeniul de vizibilitate (sau de valabilitate) 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ă aplicaţia.

Restul rutinelor sunt locale şi sunt vizibile numai din modulul unde au fost declarate.

I.6.6. Durata de viaţă a rutinelor

Durata de viaţă a unei rutine, adică timpul în care ea se găseşte în memorie, este în funcţie de locul unde a fost declarată şi anume:

• pe toată durata aplicaţiei dacă se găseşte în modulul general de cod; • cât timp este în execuţie un formular sau raport, dacă se găseşte în

codul din spatele acestuia.

I.6.7. Rutine definite de utilizator. Introducerea codului VBA

� Pentru a crea o rutină definită de utilizator într-un modul general (global) de cod, urmaţi paşii de mai jos:

• executaţi clic pe marcajul de tabulare Modules din fereastra bazei de date;

Page 56: 2.VBA_SC4

I-56

• începeţi un modul nou sau selectaţi un modul existent şi executaţi clic pe opţiunea Design;

• selectaţi opţiunea Insert Procedure (inserează rutină) de pe bara cu instrumente sau selectaţi opţiunea Procedure din meniul Insert. Va apărea pe ecran caseta de dialog prezentată anterior.

• introduceţi numele rutinei şi selectaţi tipul acesteia: funcţie, procedură (subrutină) sau proprietate (se va prezenta în alt capitol). Indicaţi dacă doriţi ca rutina să fie publică (pentru întreaga aplicaţie) sau privată (numai pentru acest modul). De asemenea, specificaţi dacă toate variabilele locale din rutină sunt statice sau nu. Terminaţi 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ă aflaţi î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 opţiunii Code din meniul View, sau prin pictograma specifică de pe bara de instrumente.

I.6.8. Procedurile evenimentelor

Procedurile evenimentelor sunt apelate automat când are loc un eveniment pentru un anumit obiect.

De exemplu, când un utilizator execută click cu mouse-ul pe un buton de comandă dintr-un formular, este executat automat, dacă există, codul evenimen-tului Click pentru acel buton 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 instrucţiune a procedurii, adică Sub şi End Sub) când se selectează dintre proprietăţile controlului evenimentul respectiv. Numele procedurii va fi obli-gatoriu stabilit de sistem, în funcţie 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. Instrucţiunea 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

Page 57: 2.VBA_SC4

I-57

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 funcţia 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"

� Procedura foloseşte următoarele funcţii ce se găsesc în bibliotecile sistem (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.

Procedura eveniment utilizează o funcţie 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

Page 58: 2.VBA_SC4

I-58

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, executaţi următorii paşi:

• executaţi click pe control (cmdOkay) în modul de afişare Design şi apoi pe butonul Properties din bara cu instrumente sau executaţi click cu butonul drept al mouse-ului pe obiect şi selectaţi opţiunea Properties din meniul contextual;

• executaţi click pe marcajul de tabulare al proprietăţilor evenimentului (Event); • selectaţi proprietatea pentru care doriţi să scrieţi instrucţiuni de cod (de

exemplu, evenimentul On Click); • selectaţi [Event Procedure] din lista derulantă; • executaţi clic pe butonul (…). Cursorul dumneavoastră va fi plasat în

codul evenimentului pentru obiectul respectiv. Automat sistemul va crea instrucţiunea de declarare a procedurii, – eventual cu lista de parametri formali, dacă este cazul – şi instrucţiunea de sfârşit a procedurii. Proiectantul va introduce acum codul VBA necesar tratării evenimentului.

I.6.9. Util izarea combinată a procedurilor eveniment cu rutinele utilizator

Am arătat că atât subrutinele, cât şi funcţiile 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 primiţi.

Private Sub Initialele (sFirst As String, sLast As String) MsgBox "Initialele dumneavostră sunt: " & _ Left (sFirst, 1) & Left (sLast, 1) ' Funcţia Left întoarce caracterele_ de la începutul unui string

End Sub • Ea va fi apelată din procedura eveniment On Click a butonului de

comandă cmdNume.

Page 59: 2.VBA_SC4

I-59

Private Sub cmdNume_Click () Initialele Me !txtFirstName, Me!txtLastName

End Sub Observaţi că textul din controalele txtFirstName şi txtLastName din

formularul curent (Me) sunt transmise subrutinei cu numele Initialele. Parametrii sunt recepţionaţi ca sFirst şi sLast. Primul caracter din stânga al fiecărui parametru este afişat în caseta de mesaje.

Codul precedent transmite pur şi simplu valori şi apoi operează cu ele.

Exemplu. În continuare se ilustrează folosirea unei funcţii 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

End Sub Reţineţi că acest exemplu apelează o funcţie ReturnInit, trimiţând valorile

celor două casete de text ca parametri ai funcţiei. Funcţia asociază numelui funcţiei (ReturnInit) o valoare egală cu primele două caractere ale şirurilor. Apoi, funcţia întoarce această valoare rutinei apelante (cmdNume_Click) şi o atribuie variabilei sInitials.

I.6.10. Parametri opţionali

Visual Basic vă permite să utilizaţi parametri opţionali. Cu alte cuvinte, nu este necesar să ştiţi câţi parametri vor fi transmişi. Funcţia numită ReturnInit din secvenţa de cod următoare primeşte ultimii doi parametri ca opţionali. Apoi evaluează prezenţa sau nu a parametrilor şi acţionează în consecinţă.

Function ReturnInit (sFName As String, Optional sMI, Optional sLName) As String

If IsMissing (sMI) Then ' IsMissing întoarce True dacă s-a apelat _ funcţia fără parametrul sMI

SMI = InputBox ("Introduceţi initiala cuvantului din mijloc") End If If IsMissing (sLName) Then ' IsMissing întoarce True dacă s-a _ apelat funcţia fără parametrul sLName

Page 60: 2.VBA_SC4

I-60

SLName = InputBox ("Introduceţi ultimul nume") End If ReturnInit = sLName & " " & sMI & " " sFName

End Function • Această funcţie poate fi apelată de exemplu în felul următor: sName = ReturnInit ("Bill",, "Gates") Aşa cum aţi putut vedea, lipseşte al doilea parametru. În loc să rezulte o

eroare de compilare, funcţia ReturnInit va sesiza acest lucru şi prin funcţia InputBox va cere utilizatorului introducerea valorii respective.

• Sau mai poate fi apelată şi: sName = ReturnInit ("Bill", "X", "Gates") În acest caz funcţia, prin folosirea lui IsMissing, va sesiza prezenţa tuturor

celor trei parametri actuali.

� Lucrul cu parametri opţionali, deci care pot să lipsească la apelarea rutinei, necesită:

− declararea ca opţional a parametrului, prin folosirea clauzei Optional, în faţa numelui parametrului. O restricţie a limbajului este faptul că numai ultimii parametri pot fi declaraţi opţionali.

− testarea prin funcţia IsMissing, dacă a fost sau nu introdus la apelare parametrul respectiv în lista parametrilor actuali. Dacă nu se doreşte introdu-cerea în lista parametrilor actuali a unui parametru opţional, atunci se va scrie numai separatorul (virgula) parametrului respectiv. Funcţia IsMissing este valabilă numai pentru parametri de tip variant.

− pentru parametrii declaraţi opţional, se poate introduce o valoare implicită, cu care se va iniţializa parametrul dacă acesta lipseşte din lista parametrilor actuali.

Dacă se folosesc parametri opţionali, declararea acestora în lista parametrilor formali este:

[Optional] NumeParametru As TipDate [ = ValoareImplicita ]

I.7. Biblioteci standard de proceduri şi funcţii

O bibliotecă este un obiect de sine stătător care permite realizarea unei colecţii de funcţii, proceduri, clase de obiecte, colecţii de obiecte şi obiecte.

Noile tehnologii şi standarde introduse de Microsoft permit ca modulele unei biblioteci să fie utilizate de toate aplicaţiile 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 aplicaţii. Pentru aceasta trebuie ca în prealabil aplicaţia client să înregistreze şi să creeze referinţa (adresa) către biblioteca respectivă.

Page 61: 2.VBA_SC4

I-61

Acest lucru se face prin comanda References. Implicit, o aplicaţie are chiar din faza de instalare create referinţele către cele mai utilizate biblioteci specifice.

Aplicaţiile Access au referinţe 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 funcţii şi proceduri ale acestor biblioteci.

Un bun programator trebuie să cunoască şi să folosească cât mai multe din obiectele puse la dispoziţie de biblioteci. De exemplu dacă se realizează o aplicaţie 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 funcţia Sin, care calculează sinusul unei valori, va rezolva imediat această problemă, folosind pur şi simplu funcţia respectivă.

Pentru a putea utiliza o funcţie dintr-o bibliotecă, programatorul trebuie să cunoască trei lucruri:

− numele funcţiei; − parametrii şi ce reprezintă fiecare; − ce reprezintă valoarea pe care o întoarce funcţia (adică ce operaţii

efectuează funcţia). În crearea expresiilor, în Access se

poate folosi un constructor de funcţii – Expressions Builder, lansat de obicei din meniul contextual (Build). Acesta este foarte util, prezentând toate funcţiile, parametrii acestora, modulul de Help, operaţiile permise etc.

În concluzie, în codul VBA, în controalele din formulare sau rapoarte, în proprietăţile tabelelor sau cererilor, se pot folosi în crearea expresiilor atât funcţiile definite (create) de utilizator cât şi funcţiile din bibliotecile către care există referinţe. Toate acestea se pot

vizualiza prin Expressions Builder (prin cele două foldere din Functions, aşa cum se vede din figură).

Access are referinţe implicite către o bibliotecă de funcţii şi proceduri, foarte bogată şi cuprinzătoare, din care vor fi prezentate în continuare cele mai utilizate.

Page 62: 2.VBA_SC4

I-62

I.7.1. Funcţii matematice

I.7.1.1. Int(număr); Fix(număr)

Ambele funcţii î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 funcţii Int şi Fix îndepărtează partea fracţionară a numărului şi

întorc valoarea întreagă care rezultă. Diferenţa î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 Sgn întoarce: –1 1 0

Exemplu. Dim Semn aA Variant Const Valoare1= 12, Valoare2= -2. 4, Valoare3= 0

Semn = Sgn (Valoare1) ' Întoarce 1. Semn = Sgn (Valoare2) ' Întoarce -1. Semn = Sgn (Valoare3) ' Întoarce 0.

Page 63: 2.VBA_SC4

I-63

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 execuţie.

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 conţine un număr aleator. Valoarea întoarsă de Rnd este:

Dacă parametrul este: Rnd generează

< 0 Acelaşi număr de fiecare dată, folosind parametrul ca valoare de iniţializare.

> 0 Următorul număr din secvenţă. = 0 Cel mai recent număr generat.

Fără (de obicei) Următorul număr din secvenţă.

Argumentul (parametrul) este opţional şi poate fi un Single sau o expresie numerică corectă.

Funcţia Rnd întoarce o valoare în intervalul [0.. 1). Valoarea parametrului determină cum Rnd generează un număr aleator.

Page 64: 2.VBA_SC4

I-64

Pentru o anumită valoare iniţială, este generată aceeaşi secvenţă de numere, deoarece fiecare apel succesiv al funcţiei Rnd foloseşte numărul generat anterior ca valoare pentru calculul următorului număr din secvenţă.

Înainte de prima folosire a funcţiei Rnd, dacă se doreşte generarea unei secvenţe de numere aleatoare, atunci generatorul de numere aleatoare trebuie iniţializat cu o valoare întâmplătoare. Pentru aceasta se va folosi procedura Randomize, fără parametri, care va folosi pentru iniţializarea 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.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 înmulţi 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 înmulţi radianii cu 180/pi.

Exemplu. Dim Unghi, Cotangenta

Unghi = 1. 3 ' Defineşte unghiul în radiani Cotangenta = 1 / Tan (Unghi) ' Calculează cotangenta

Page 65: 2.VBA_SC4

I-65

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 Sec (X) = 1 / Cos (X)

Cosecant Cosec (X) = 1 / Sin (X) Cotangent Cotan (X) = 1 / Tan (X) Inverse Sine Arcsin (X) = Atn (X / Sqr (-X * X + 1) ) Inverse Cosine Arccos (X) = Atn (-X / Sqr (-X * X + 1) ) + 2 * Atn (1) Inverse Secant Arcsec (X) = Atn(X / Sqr(X*X –1)) + Sgn( (X)–1) * (2*Atn(1)) Inverse Cosecant Arccosec (X) = Atn(X / Sqr(X*X-1)) + (Sgn(X)–1) * (2*Atn(1)) Inverse Cotangent Arccotan (X) = Atn (X) + 2 * Atn (1) Hyperbolic Sine HSin (X) = (Exp (X) – Exp (-X) ) / 2 Hyperbolic Cosine HCos (X) = (Exp (X) + Exp (-X) ) / 2 Hyperbolic Tangent HTan (X) = (Exp (X) – Exp (-X) ) / (Exp (X) + Exp (-X) ) Hyperbolic Secant HSec (X) = 2 / (Exp (X) + Exp (-X) ) Hyperbolic Cosecant HCosec (X) = 2 / (Exp (X) – Exp (-X) ) Hyperbolic Cotangent HCotan (X) = (Exp (X) + Exp (-X) ) / (Exp (X) – Exp (-X) ) Inverse Hyperbolic Sine HArcsin (X) = Log (X + Sqr (X * X + 1) ) Inverse Hyperbolic Cosine HArccos (X) = Log (X + Sqr (X * X – 1) ) Inverse Hyperbolic Tangent HArctan (X) = Log ( (1 + X) / (1 – X) ) / 2 Inverse Hyperbolic Secant HArcsec (X) = Log ( (Sqr (-X * X + 1) + 1) / X) Inverse Hyperbolic Cosecant HArccosec (X) = Log ( (Sgn (X) * Sqr (X * X + 1) + 1) / X) Inverse Hyperbolic Cotangent HArccotan (X) = Log ( (X + 1) / (X – 1) ) / 2 Logarithm to base N 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) funcţiei. Exemplu.

Dim Numar Numar = Asc ("A") ' Întoarce 65. 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 funcţiei.

� Codurile dintre 0-31 au ca corespondent în ASCII caractere netipăribile, care însă pot să determine anumite acţiuni î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.

Page 66: 2.VBA_SC4

I-66

Intervalul normal pentru parametrul CodCaracter este: 0-255. Exemplu.

Dim Caracter Caracter = Chr (65) ' Întoarce A. Caracter = Chr (97) ' Întoarce a. Caracter = Chr (62) ' Întoarce >. Caracter = Chr (37) ' Întoarce %.

I.7.2.3. AscB(string); AscW(string); ChrB(CodCh); ChrW(CodCh)

Funcţiile AscB, AscW, ChrB, ChrW ţin seama că în memorie caracterele sunt codificate pe 2 octeţi în standardul UNICODE. Ele consideră şirul de caractere ca pe un tablou de octeţi, în care fiecare caracter ocupă doi octeţi (byte).

• Funcţia AscB – în loc să întoarcă codul pentru primul caracter, întoarce primul byte, din codul în UNICODE al primului caracter.

• Funcţia AscW – întoarce codul caracterului în UNICODE (pe 2 octeţi, în intervalul 0…2^16).

• Funcţia ChrB – în loc să întoarcă un caracter al cărui cod (aflat în parametrul funcţiei) poate fi pe 1 sau 2 bytes, ea va întoarce întotdeauna caracterul al cărui cod este pe primul byte.

• Funcţia ChrW – întoarce un string care conţine caracterul al cărui cod este introdus în argument în standardul UNICODE.

� Aceste funcţii au efect numai pe platformele care acceptă codul UNICODE. Dacă acesta nu este acceptat, atunci ele se comportă la fel ca funcţiile Asc respectiv Chr. Exemplu.

Public Sub TestUnicode () MsgBox Asc ("A") ' Întoarce Cod Ascii = 65

MsgBox AscB ("A") ' Întoarce primul byte din Codul Unicode = 65

MsgBox AscW ("A") ' Întoarce Codul Unicode = 65

MsgBox Asc ("Ş") ' Întoarce Cod Ascii = 170

MsgBox AscB ("Ş") ' Întoarce primul byte din Codul Unicode = 94

MsgBox AscW ("Ş") ' Întoarce Codul Unicode = 350

MsgBox Chr (65) ' Întoarce Caracterul = A

MsgBox ChrB (65) ' Întoarce Caracterul = A

MsgBox ChrW (65) ' Întoarce Caracterul = A

MsgBox Chr (170) ' Întoarce Caracterul = Ş

MsgBox ChrB (94) ' Întoarce Caracterul = ^

MsgBox ChrW (350) ' Întoarce Caracterul = Ş

End Sub

Page 67: 2.VBA_SC4

I-67

Caracterul A Ş Cod ANSI (1 octet) 65 170 Cod UNICODE (valoare) 65 350 Cod UNICODE (2 octeţi) 65 0 94 1

� Se observă că în codul UNICODE, 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.

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 funcţia LTrim: fără spaţiile de început; − la funcţia RTrim: fără spaţiile de sfârşit; − la funcţia Trim: fără spaţiile din ambele capete.

Exemplu. Dim Valoare, Modific

Valoare = " <-Trim-> " ' Iniţializează stringul. Modific = LTrim(Valoare) ' Modific = "<-Trim-> ". Modific = RTrim(Valoare) ' Modific = " <-Trim->". Modific = LTrim(RTrim(Valoare)) ' Modific = "<-Trim->". ' Utilizând funcţia Trim se obţine acelaşi rezultat. Modific = Trim(Valoare)' Modific = "<-Trim->"

I.7.2.7. Len(String | NumeVariabila)

Întoarce o valoare de tip Long cuprinzând: • dacă argumentul este un string, câte caractere are; • dacă argumentul este o variabilă, câte caractere pot să fie introduse în ea.

Page 68: 2.VBA_SC4

I-68

� Dacă argumentul este NULL, funcţia va întoarce tot NULL; această regulă, aşa cum am mai amintit, este comună şi celorlalte funcţii.

� Unul (şi numai unul) din cele două argumente posibile trebuie specificat.

� Se poate utiliza funcţia LenB, care ţine cont de reprezentarea în memorie în UNICODE a stringului. În loc să întoarcă numărul de caractere dintr-un string, LenB întoarce numărul de bytes (octeţi) utilizaţi pentru a reprezenta acel string. Exemplu.

Type CustomerRecord ' Defineşte tipul de date dorit de utilizator. ID As Integer 'Această definiţie este la nivelul modului de cod Name As String * 10 Address As String * 30

End Type '------------------------------ Dim Customer As CustomerRecord ' Declararea variabilelor. Dim MyInt As Integer, MyBan As Currency Dim MyString, MyLen

MyString = "Hello World" ' Iniţializează variabila. MyLen = Len(MyString) ' Întoarce 11. MyLen = Len(Customer) ' Întoarce 42. MyLen = Len(MyInt) ' Întoarce 2. MyLen = Len(MyBan) ' Întoarce 8.

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ă: − 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" ' Defineşte stringul. Subsir = Left(Sir, 1) ' Întoarce "N". Subsir = Left(Sir, 7) ' Întoarce "Nota ex". Subsir = Left(Sir, Len(Sir)-2) ' Întoarce "Nota exam". Subsir = Left("Sir",1) ' Întoarce "S"

Page 69: 2.VBA_SC4

I-69

� A se face distincţie î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 explicaţia 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 funcţia 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 conţine NULL, atunci NULL se va întoarce. − start (obligatoriu). Este de tip Long. Reprezintă poziţia caracterului din

string de la care începe partea ce va fi preluată. Dacă poziţia 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 (opţional); 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 funcţia 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 instrucţiuni 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 funcţiile Left sau Right.

Page 70: 2.VBA_SC4

I-70

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 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 poziţia primei apariţii a string2 în string1.

• start (opţional). Expresie numerică care stabileşte poziţia de început pentru fiecare căutare. Dacă este omis, căutarea începe de la poziţia primului caracter. Argumentul este obligatoriu dacă se specifică o comparaţie.

• string1 (obligatoriu). Şirul de caractere în care se va face căutarea. • string2 (obligatoriu). Şirul de caractere care este căutat. • compare (opţional). Prezintă modalitatea în care se poate face compa-

rarea 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 informaţiile din baza de date; − dacă parametrul compare lipseşte, atunci setarea Option Compare din modulul de cod determină tipul comparaţiei.

� 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 instrucţiuni încep cercetarea de la poziţia 4 Pozitie = Instr (4, Sir, SirCautat, 1) ' Comparaţie textuală. Întoarce 9. Pozitie = Instr (4, Sir, "P", 1) ' Comparaţie textuală. Întoarce 9. Pozitie = Instr (4, Sir, "p", 1) ' Comparaţie textuală. Întoarce 9. Pozitie = Instr (4, Sir, "p", 0) ' Comparaţie binară. Întoarce 0. Pozitie = Instr (1, Sir, "W") ' Implicit comparaţia e binară _ (lipseşte ultimul argument).Întoarce 0.

Page 71: 2.VBA_SC4

I-71

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 conţine 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 conţine 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 conţine de număr de ori caracterul spaţiu. Exemplu.

Dim MyString MyString = Space(8) ' întoarce un string cu 8 spaţii MyString = "Hello" & Space(10) & "World" ' Inserează 10 spaţii _ între cele două cuvinte.

I.7.2.14. Format(expresie[,format])

Funcţia Format transformă o expresie într-un şir de caractere care respectă un şablon (format).

• Expresie – este expresia pe care doriţi să o formataţi. • Format (opţional) reprezintă tipul de format, şablon, pe care doriţi să îl

aplicaţi. 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 funcţii care întorc timpul şi data _

Page 72: 2.VBA_SC4

I-72

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 MyStr ' Formate 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 ' > – Întoarce stringul cu litere mari MyStr = Format("HELLO", "<") ' Întoarce "hello". MsgBox MyStr MyStr = Format("This is it", ">") ' Întoarce "THIS IS IT". MsgBox MyStr

Page 73: 2.VBA_SC4

I-73

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.7.3. Funcţii pentru tablouri (array) - UBound ş i LBound

UBound (arrayname[,dimension]) LBound (arrayname[,dimension])

Întorc o valoare de tip Long, care va conţine, 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ă funcţii cuprind: − arrayname (obligatoriu). Denumirea variabilei care defineşte tabloul. − dimension (opţional). 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.

Funcţia UBound se utilizează împreună cu funcţia LBound pentru a determina mărimea unui tablou, şi anume:

• LBound – 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:

Funcţia Parametrii Valoarea întoarsă (A, 1) 100 (A, 2) 3 UBound (A, 3) 4 (A, 1) 1 (A, 2) 0 LBound (A, 3) –3

Marginea cea mai de jos, implicită, pentru orice dimensiune a unui tablou creat prin declaraţie (Dim, Private, Public, ReDim sau Static), este 0 sau 1. Ea depinde de setarea declaraţiei Option Base (de obicei 0).

Page 74: 2.VBA_SC4

I-74

Excepţie. Baza unui tablou creat cu funcţia Array este 0, ea nefiind afectată de Option Base.

Tablourile pentru care dimensiunile sunt setate folosind To în declaraţiile Dim, Private, Public, 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 funcţiei, de tip Long, va conţine o expresie

numerică ce va fi convertită într-un şir de caractere. • După conversie, la începutul stringului va fi un spaţiu 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 funcţia Format. Exemplu.

Dim MyString MyString = Str(459) ' Întoarce "459". MyString = Str(-459.65) ' Întoarce "-459.65". MyString = Str(459.001) ' Întoarce " 459.001".

I.7.4.2. Val(string)

Întoarce numărul conţinut în string, ca pe o valoare numerică de tipul cel mai apropiat reprezentării valorii respective.

• Funcţia Val, în momentul în care întâlneşte un caracter care nu poate face parte din reprezentarea unui număr, opreşte inspecţia ş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 ($).

• &O şi &H, sunt considerate ca rădăcină pentru numere în reprezen-tarea octală, respectiv hexazecimală.

• Spaţiile, 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") ' Întoarce 2457. MyValue = Val(" 2 45 7") ' Întoarce 2457. MyValue = Val("24 and 57") ' Întoarce 24. MyValue = Val(" 1615 198th Street N. E.") ' Întoarce 1615198

Page 75: 2.VBA_SC4

I-75

I.7.5. Funcţii pentru mesaje

I.7.5.1. MsgBox(prompt[,buttons][,title])

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 funcţiei 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 combinaţie (Chr(13) & Chr(10) ) după fiecare rând.

� În VBA, există definită constanta de tip string: vbCr=Chr(13) & Chr(10) • Buttons (opţional - implicit este 0). Expresie numerică care este suma

valorilor reprezentând patru caracteristici ale căsuţei 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: aplicaţie sau sistem (nu se poate ieşi din aceasta în aplicaţie/ sistem până nu se închide).

Setările pentru butoanele argument sunt: Constanta Val Descrierea Ce reprezintă

VbOKOnly 0 Afişează numai butonul OK. VbOKCancel 1 Afişează butoanele OK şi Cancel. VbAbortRetryIgnore 2 Afişează butoanele Abort, Retry şi Ignore. VbYesNoCancel 3 Afişează butoanele Yes, No şi Cancel. VbYesNo 4 Afişează butoanele Yes şi No. VbRetryCancel 5 Afişează butoanele Retry şi Cancel.

Numărul şi tipul butoanelor afişate în caseta de dialog

VbCritical 16 Afişează pictograma Critical Message. VbQuestion 32 Afişează pictograma Warning Query. VbExclamation 48 Afişează pictograma Warning Message VbInformation 64 Afişează pictograma Information Message.

Felul pictogramei utilizate în partea din stânga sus

VbDefaultButton1 0 Primul buton este implicit. VbDefaultButton2 256 Al doilea buton este implicit. VbDefaultButton3 512 Al treilea buton este implicit. VbDefaultButton4 768 Al patrulea buton este implicit.

Care este butonul implicit

VbApplicationModal 0 Aplicaţie modală – utilizatorul trebuie să răspundă casetei de mesaj înainte de a continua să lucreze în aplicaţia curentă.

VbSystemModal 4096 Sistem modal – toate aplicaţiile sunt blocate până când utilizatorul răspunde casetei de mesaj.

Dacă caseta de text este modală la nivelul aplicaţiei curente sau a tuturor taskurilor

− Title (opţional). 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 aplicaţiei.

Page 76: 2.VBA_SC4

I-76

Valoarea întoarsă de funcţie este:

Constanta Valoare Butonul pe care s-a apăsat

vbOK 1 OK vbCancel 2 Cancel vbAbort 3 Abort vbRetry 4 Retry vbIgnore 5 Ignore vbYes 6 Yes vbNo 7 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 funcţie ' Afişează mesaj, şi introduce în Rasp, butonul apăsat de utilizator _ Se observă folosirea lui at ( @ ) ca separator de rânduri!! 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 = Abs(Nr) ElseIf Rasp = 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 conţine acest text.

Page 77: 2.VBA_SC4

I-77

Sintaxa funcţiei 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 combinaţie (Chr(13) & Chr(10) ) după fiecare rând.

• Title (opţional). 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 (opţional). 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 (opţional). Expresie numerică care reprezintă, în twips, distanţa 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 (opţional). Expresie numerică care reprezintă, în twips, distanţa pe verticală de la marginea de sus a casetei de dialog la marginea de sus a ecranului. Dacă lipseşte, caseta de dialog este poziţionată vertical la aproximativ o treime din distanţa până în subsolul ecranului. Exemplu.

Următorul exemplu utilizează InputBox pentru a citi o dată introdusă de utilizator şi folosirea lui MsgBox şi ca funcţie şi ca procedură (pentru afişarea unor mesaje). Se observă utilizarea semnului @ pentru a delimita diversele părţi ale şirului de caractere.

Sub CustomMessage () Dim strMsg As String, strInput As String ' Iniţializează 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ăsaţi OK pentru a _ introduce numărul din nou." ' @ - rol de delimitator de rânduri ' Se cere utilizatorului să introducă o valoare. strInput = InputBox("Introduceţi 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 Then

strInput = InputBox("Introduceţi număr între 1şi 10") Else

Exit Sub End If

Page 78: 2.VBA_SC4

I-78

Loop ' Afişează data corectă introdusă de utilizator.

MsgBox "Aţi 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)

Funcţia DatePart întoarce o parte dintr-o dată, care este specificată de argumentul interval.

Argumentul interval, de tip string, poate lua următoarele valori: interval Descriere interval Descriere

yyyy Anul w Ziua din săptămână q Trimestrul ww Săptămâna m Luna h Ora y Ziua din an n Minute d Ziua s Secunde

Exemplu. Private Sub cmdDatePart_Click ()

MsgBox DatePart("YYYY", Now) ' Afişează anul curent MsgBox DatePart("M", Now) ' Afişează numărul lunii curente MsgBox DatePart("Q", Now) ' Afişează nr. trimestrului curent MsgBox DatePart("Y", Now) ' Afişează ziua din anul curent

End Sub

I.7.6.2. DateDiff(interval,date1,date2)

Funcţia 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

Page 79: 2.VBA_SC4

I-79

I.7.6.3. DateAdd(interval,number,date)

Funcţia 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 conţine ziua sau luna sau anul, din data care se găseşte în argumentul funcţiei.

I.7.6.5. Second(date); Minute(date); Hour(date)

Întoarce un Variant (Integer), care conţine 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 conţine data şi timpul curent (cu care este setat în momentul respectiv sistemul de calcul).

Date() - întoarce un Variant (Date), care conţine data curentă (cu care este setat în momentul respectiv sistemul de calcul).

Time() - întoarce un Variant (Date), care conţine 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 conţine 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ă operaţiile 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.

Page 80: 2.VBA_SC4

I-80

Dacă argumentul pentru an este între 0 şi 99, se vor considera anii din două cifre setaţi în Windows. Pentru ceilalţi 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 conţine 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.7.7. Funcţii: structuri de control

I.7.7.1. IIf(condiţie, TruePart, FalsePart)

Funcţia IIf are o acţiune asemănătoare cu a instrucţiunii If…Then…Else Funcţia IIf întoarce unul din cele două argumente, TruePart sau

FalsePart, în funcţie de rezultatul evaluării condiţiei ce se găseşte în primul argument. Astfel, dacă:

− condiţie = true – funcţia întoarce parametrul TruePart; − condiţie = false – funcţia întoarce parametrul FalsePart.

� Toţi cei trei parametri ai funcţiei sunt obligatorii.

� TruePart sau FalsePart pot la rândul lor să conţină o altă funcţie, 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]])

Funcţia Choose întoarce unul din argumentele listei (caz-1 sau caz-2, sau … caz_n) în funcţie de valoarea pe care o are argumentul index, şi anume:

− dacă index = 1 atunci se întoarce caz-1;

Page 81: 2.VBA_SC4

I-81

− 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 funcţiei 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,value-1[,expr-2,value-2… [,expr-n,value-n]]..])

Această funcţie are o acţiune asemănătoare cu a instrucţiunii: If…Then…ElseIf…Else Funcţia Switch va evalua în ordine condiţiile expr-1, expr-2, expr-n, pînă

când va obţine o valoare True. În acest moment, cercetarea se opreşte, şi funcţia î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 funcţiei vom avea: MsgBox MatchUp("Paris") ' afişează French

I.7.8. Funcţii de inspecţ ie

I.7.8.1. IsNull(expresie)

Întoarce o valoare de tip Boolean care indică dacă expresia transmisă ca parametru de intrare conţine date care nu sunt valide, adică au valoarea Null.

Parametrul este de tip Variant şi conţine o expresie de tip numeric sau string. Funcţia IsNull întoarce: � True – dacă parametrul are valoarea Null; � False – dacă parametrul nu are valoarea Null;

Page 82: 2.VBA_SC4

I-82

� Aşa cum am mai arătat, dacă un termen al expresiei este Null, atunci expresia va fi tot Null, şi funcţia va întoarce evident True.

� Valoarea Null, îndică faptul că un Variant nu conţine 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 îniţializată; • 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ă iniţializată.

Parametrul este de tip variant şi conţine o dată de tip numeric sau string. Funcţia IsEmpty întoarce: � True – dacă variabila NumeVariabila nu este iniţializată, sau a fost

introdusă în ea direct Empty; � False – variabila a fost iniţializată (chiar cu Null sau un string vid).

Exemplu. Dim Valoare, Situatie ' variabile variant Situatie = IsEmpty(Valoare) ' Întoarce True. Valoare = Null ' Assign Null. Situatie = IsEmpty(Valoare) ' Întoarce False. Valoare = Empty ' Assign Empty. Situatie = IsEmpty(Valoare) ' Întoarce True.

I.7.8.3. IsMissing(NumeParametru)

IsMissing se foloseşte într-o rutină, pentru a testa dacă un parametru opţional al acesteia a fost sau nu introdus în lista parametrilor actuali de la apelarea acestei rutine.

Parametrul funcţiei IsMissing, NumeParametru, este de tip variant.

Page 83: 2.VBA_SC4

I-83

Aceste (NumeParametru) reprezintă parametrul formal optional care se testează dacă a fost introdus sau nu în lista parametrilor actuali la apelul funcţiei.

Funcţia IsMissing întoarce o valoare de tip Boolean, care va avea valoarea TRUE numai dacă parametrul opţional testat nu a fost introdus în lista parametrilor actuali, deci el practic lipseşte. Exemplu. Apelarea funcţiei ReturnTwice, definită cu un parametru opţional.

Dim ReturnValue ReturnValue = ReturnTwice() ' Întoarce Null. ReturnValue = ReturnTwice(2) ' Întoarce 4. ' Declararea funcţiei. Function ReturnTwice(Optional A)

If IsMissing (A) Then ' Funcţia a fost apelată fără parametrul A ReturnTwice = Null

Else ' Funcţia a fost apelată cu parametrul A ReturnTwice = A * 2

End If End Function

� Funcţia IsMissing se aplică numai dacă parametrul opţional este de tip variant. Dacă parametrul opţional nu este de tip variant ea va întoarce întotdeauna (fie că parametrul opţional este sau nu este folosit la apelarea funcţiei) 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 funcţiei).

Reamintim că variabilele de tip variant se caracterizează prin faptul că în ele se pot introduce valori de diferite tipuri. Funcţia 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 funcţia VarType:

Constanta Val Descriere Constanta Val Descriere

vbEmpty 0 Empty (neiniţializat) vbObject 9 Object

vbNull 1 Null (lipsa datelor valide) vbError 10 Error

vbInteger 2 Integer vbBoolean 11 Boolean – valoare

vbLong 3 Long integer vbVariant 12 Variant (în tablouri)

vbSingle 4 Single-precision vbDataObject 13 Obiect de acces la date

vbDouble 5 Double-precision vbDecimal 14 Decimal – valoare

vbCurrency 6 Currency – valoare vbByte 17 Byte – valoare

vbDate 7 Date – val. de tip Date/Text vbArray 8192 Array – Tablou

vbString 8 String

Page 84: 2.VBA_SC4

I-84

� 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 ' Iniţializarea variabilelor IntVar = 459: StrVar = "Hello World": DateVar = #2/12/69# ' !!! Aşa se pot scrie mai multe instrucţiuni pe un rând, separându-le, _ aşa cum se vede, cu două puncte. MyCheck = VarType(IntVar) ' Întoarce 2. MyCheck = VarType(StrVar) ' Întoarce 8. MyCheck = VarType(DateVar) ' Întoarce 7.

I.7.9. Funcţiile agregate SQL

O funcţie 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.

Funcţiile agregate SQL au ca argument numele câmpului pe care sunt definite. Totuşi, în cazul cererilor cu clauză total, în care introducerea funcţiei agregate SQL se face într-o coloană ataşată câmpului de definiţie, ele se folo-sesc fără argument.

Funcţiile 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 deviaţia standard).

� Valoarea NULL, în funcţiile agregate (SQL sau de domeniu), nu se ia în considerare. În celelalte funcţii sau operaţii, valoarea NULL a unui termen duce la rezultatul NULL al expresiei, indiferent de felul în care e constituită aceasta.

Page 85: 2.VBA_SC4

I-85

I.7.10. Funcţiile agregate de domeniu

Funcţiile agregate de domeniu întorc date de calcul agregate, la fel ca şi funcţiile agregate SQL. Diferenţa rezultă din faptul că domeniul de definiţie al acestor funcţii este reprezentat de un câmp al unei tabele (cereri) – din baza de date curentă – asupra căruia se aplică, eventual, un criteriu de selecţie a înregistrărilor. Domeniul de definiţie este stabilit de valorile ce se găsesc în parametrii (argumentele) funcţiei.

Funcţiile agregate de domeniu, (au aceiaşi denumire ca a funcţiilor 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 (varianţa şi

deviaţia standard); − DLookUp – întoarce prima valoare întâlnită în domeniul selecţionat.

(aceasta nu are echivalent în funcţiile agregate SQL). Argumentele folosite sunt aceleaşi în toate aceste funcţii şi stabilesc, aşa

cum am mai arătat, care este domeniul de definiţie pe care se calculează valoarea agregată.

DFuncţie (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 selecţionează datorită criteriului nici o înregistrare, funcţia întoarce valoarea NULL.

Exemplu. Dim varX As Variant, iNr As Integer, sSir As String ' cazul 1 – selecţia î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 – selecţia înregistrărilor cu Nume având valoarea 'Doru' _

Page 86: 2.VBA_SC4

I-86

– î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 – selecţia î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 – selecţia î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 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 funcţie de natura câmpului folosit de criteriu, număr sau text.

� Reamintesc că valoarea NULL, în funcţiile agregate (de domeniu sau SQL), nu se ia în considerare. În celelalte funcţii sau operaţii, valoarea NULL a unui termen duce la rezultatul NULL al expresiei, indiferent de felul în care e constituită aceasta.

Page 87: 2.VBA_SC4

II-87

Cap.II Utilizarea obiectelor în limbajul de programare VBA

II.1. Obiecte

II.1.1. Obiecte, clase de obiecte ş i colecţii de obiecte

Din cele prezentate până acum, referitor la noţiunea de obiect, putem sintetiza astfel:

� Obiectul este o entitate bine definită (adică există), care are o anumită structură, anumite caracteristici şi anumite funcţii (realizează una sau mai multe acţiuni).

Un obiect se caracterizează prin: − proprietăţi – structura şi atributele sale; − metode – acţiunile pe care poate să le efectueze; − evenimente – condiţiile care determină momentul când se lansează o anumită acţiune (de exemplu Click pe un obiect).

Exemplu. Într-o aplicaţie Access, într-un formular, există un obiect cu numele Cmd. Acesta este un control buton de comandă, cu anumite proprietăţi (culoare, dimensiuni, poziţia în formular, textul afişat etc.), care are ataşat evenimentului Click o acţiune (metodă), materializată printr-o procedură eveniment, prin care se închide formularul respectiv.

� Clasa de obiecte conţine toate definiţiile unui obiect, adică tipurile de proprietăţi, metode şi evenimente care vor determina structura unui obiect. Prin setarea caracteristicilor unei clase de obiecte (de exemplu atribuirea de valori proprietăţilor) se obţine un obiect nou.

Prin definirea unei clase de obiecte se creează practic un format, o structură pe care o vor avea toate obiectele ce se vor crea din aceasta.

Relaţia dintre o clasă de obiecte şi obiectele care provin din ea este asemănătoare cu aceea dintre tipurile de date şi variabile de tipul respectiv. Aşa cum tipul de date este un concept, iar o variabilă este materializarea (în memoria calculatorului) acestuia, tot aşa clasa de obiecte este un concept, iar obiectele ce provin din ea reprezintă materializarea acesteia.

Crearea unui nou obiect al unei clase se numeşte instanţă a clasei respective. În Access există definite diferite clase de obiecte. De exemplu clasa Form

stabileşte care este structura unui obiect formular, adică proprietăţile (nume, culoare, dimensiuni, caption etc.), evenimentele (open, close, click etc.) şi metode (refresh, requery etc.). Un formular creat este o materializare (o instanţă) a clasei Form, având setate proprietăţile cu anumite valori şi ataşate la anumite evenimente metode specifice prin scrierea unui cod de program în VBA.

Page 88: 2.VBA_SC4

II-88

� Colecţia de obiecte este constituită din totalitatea obiectelor care provin din aceeaşi clasă de obiecte şi care au din această cauză aceleaşi tipuri de proprietăţi şi metode. Aceste obiecte constituie deci instanţe ale aceleiaşi clase de obiecte.

Obiectele dintr-o colecţie pot fi privite şi folosite ca un tablou de obiecte. Ele vor crea o structură de tip tablou, la care este posibilă referirea la un anumit obiect prin indexul acestuia, deci printr-un număr care reprezintă poziţia acestuia în tablou. Astfel, la crearea primului obiect, acesta va primi indexul 0, la crearea celui de-al doilea indexul va fi 1, etc.

O colecţie de obiecte reprezintă la rândul ei o entitate, cu propriile sale proprietăţi. Din această cauză ea constituie, în totalitatea ei, un obiect specific.

Astfel o colecţie de obiecte va avea printre altele următoarele două proprietăţi: − Count – care conţine numărul de obiecte din colecţie; − Parent – care conţine obiectul superior din ierarhie de care aparţine colecţia.

Numele obiectului colecţie este format din numele clasei de unde provin obiectele la care se adaugă sufixul "s".

Exemplu. Într-o aplicaţie Access, în formularul F_CDialogContainer, colecţia de obiecte Controls conţine toate obiectele control din formular. Procedura următoare, lansată de evenimentul DblClick al secţiunii "Header" a formularului tratează colecţia Controls, ca pe un tablou, afişând elementele componente ale acesteia (numărul acestora se găseşte în proprietatea Count) cât şi obiectul de care aparţine (proprietatea Parent).

Private Sub FormHeader_DblClick(Cancel As Integer) ' Afişează numele obiectelor ce se află în _ colecţia de controale a formularului Dim ST As String Dim i As Integer Dim N As Integer ST = "" ' Proprietatea Count a colecţiei conţine _ numărul de obiecte din colecţie N = Me.Controls.Count - 1 For i = 0 To N 'Primul element dintr-o colecţie are indexul 0 ST = ST & i & ": " & Me.Controls(i).NAME & vbCr Next i ' Propritatea Parent a colecţiei conţine obiectul _ de care aparţine colecţia MsgBox " Controalele din formularul parinte:" _

Page 89: 2.VBA_SC4

II-89

& vbCr & """ " & Me.Controls.Parent.NAME & _ " "", sunt în ordine:" & vbCr & vbCr & ST ' vbCr este o constantă care determină saltul de rând nou _ la afişare vbCr = Chr(10) & Chr(13) End Sub

II.1.2. Provenienţa obiectelor utilizate într-o aplicaţie Access

Un obiect, aşa cum am arătat, este format atât din date (proprietăţi) cât şi din cod de program (metode). Realizarea unei aplicaţii prin crearea şi utilizarea unor obiecte reprezintă o metodă modernă de programare, denumită progra-marea la nivel de obiect.

Cel mai important avantaj al acestei metode este acela al utilizării obiectelor create în mai multe aplicaţii, ceea ce duce, în afară de o creştere semnificativă a productivităţii, la standardizarea aplicaţiilor realizate.

În Access obiectele din care se realizează o aplicaţie pot proveni din mai multe surse:

• instanţe ale claselor de obiecte aflate în bibliotecile standard ale pachetului Access: DAO, Access Application şi VBA;

• instanţe ale claselor de obiecte proprii (utilizator), create special de proiectant (prin modulele de clase de obiecte);

• instanţe ale unor clase de obiecte externe, realizate de aplicaţii server sub forma unor controale sau biblioteci ActiveX realizate cu tehnologia (standardul industrial) Automation. Utilizarea acestor clase de obiecte externe implică în prealabil, aşa cum se va arăta, crearea în aplicaţia client (care foloseşte obiectele produse de clasa respectivă) a unei referinţe către acestea.

II.1.3. Ierarhia obiectelor dintr-o aplicaţie

Obiectele folosite într-o aplicaţie se găsesc într-o structură ierarhic-arbo-rescentă.

Fiecare element al acestei structuri aparţine unei structuri superioare şi la rândul său conţine unul sau mai multe elemente de nivel inferior.

De asemenea un element al acestei structuri poate fi constituit dintr-un obiect individual sau dintr-o colecţie de obiecte.

O aplicaţie Access este realizată în cea mai mare parte din obiectele şi colecţiile de obiecte care provin din clasele de obiecte ale următoarelor bibli-oteci standard (modele):

− DAO – privind structurile de date; − Access (Application) – privind interfaţa utilizator;

şi respectând ierarhiile create în acestea.

Page 90: 2.VBA_SC4

II-90

Obiectele, ca şi proprietăţile sau metodele lor, au un nume, care poate fi implicit (adică stabilit de sistem) sau dat de utilizator.

� În decursul acestui capitol termenul model va referi realizarea unei structuri ierarhice de obiecte şi colecţii de obiecte ce provin dintr-o bibliotecă standard ce conţine clase de obiecte.

� Referirea la un obiect.

Deoarece există posibilitatea ca mai multe obiecte să aibă acelaşi nume, atunci când se referă un obiect (sau proprietăţile şi metodele sale), este necesară calificarea numelui cu întreaga structură ascendentă a obiectelor de care acesta este dependent (asemănător cu descrierea căii unui fişier sau folder de pe un disc). Acest lucru nu este însă obligatoriu dacă nu se creează ambiguităţi.

Semnele de calificare folosite în toate obiectele unei aplicaţii Access (deci şi în VBA) sunt punctul (.) sau semnul exclamării-bang (!), specificul utilizării lor fiind următorul:

− punctul (.): se foloseşte când în faza de scriere a structurii ierarhice, aceasta este deja cunoscută de sistem; − semnul exclamării (!): se foloseşte când se doreşte ca descrierea structurii respective să se analizeze de abia în faza de execuţie, deoarece în faza de scriere ea nu este încă cunoscută de sistem;

Explicaţie. Se ştie că într-o aplicaţie Access execuţia unui formular (sau raport) care are introdus cod VBA în modulul său de cod, se va face numai după ce se compilează fără eroare acesta. În faza de compilare a modulelor de cod, sistemul va analiza numai structurile ierarhice care au ca semn de calificare punctul (.) şi ignoră pe cele care au ca semn de calificare semnul exclamării (!), urmând ca acestea din urmă să fie analizate abia în faza de execuţie. Deci pentru ca operaţia de compilare să se termine cu succes este necesar ca toate structurile ierarhice care nu sunt cunoscute în momentul respectiv să fie introduse cu semnul de calificare semnul exclamării (!) pentru a nu fi analizate (structurile ierarhice cunoscute în faza de compilare pot fi introduse cu semnul de calificare punct).

Exemplu. Astfel, dacă în codul din spatele unui formular legat la un tabel se foloseşte numele unui câmp al acestuia, atunci, deoarece în faza de compilare obiectul respectiv, tabelul, este deja cunoscut de sistem, semnul de calificare folosit poate fi punctul (.); dacă însă formularul nu este legat iniţial la o tabelă, urmând a se efectua această operaţie printr-o instrucţiune VBA (deci în faza de execuţie), atunci referirea la câmpurile acesteia trebuie făcută cu semnul de calificare semnul exclamării (!), pentru ca analiza acesteia să nu se mai facă în momentul compilării (când nu este cunoscută) ci în momentul execuţiei instrucţiunii care foloseşte structura respectivă.

Page 91: 2.VBA_SC4

II-91

� Se poate înlocui oricând semnul de calificare punct (.) cu semnul de calificare semnul exclamării (!), dar nu şi invers.

� Folosirea structurilor ierarhice descrise cu semnul de calificare semnul exclamării (!) încetineşte execuţia codului VBA, deoarece analiza acestora nu se mai face în faza de compilare.

� Referirea unei colecţii se face folosind acelaşi sistem, deoarece colecţia este, aşa cum am văzut, la rândul ei, un obiect.

� Referirea la un obiect dintr-o colecţie se poate face în 3 feluri:

− Fie folosind tot metoda prezentată, utilizând calificarea obiectului cu colecţia din care face parte: <referirea la colecţie> <semn de calificare> <numele obiectului> Exemplu. Me.Controls!CForm

− Fie folosind indexarea colecţiei cu un număr care reprezintă poziţia în colecţie a obiectului respectiv (asemănător cu referirea unui element dintr-un tabel).

Numerotarea elementelor unei colecţii de obiecte se porneşte de la 0 (zero).

<referirea la colecţie> <(> <număr în cadrul colecţiei> <)> Exemplu. Me.Controls(0)

− Fie la fel ca mai sus dar folosind – ca pe un şir de caractere – numele obiectului în loc de index. <referirea la colecţie> <(> <"nume obiect"> <)> Exemplu. Me.Controls("CForm")

� Dacă se doreşte să se facă referire în codul VBA la formularul sau raportul "părinte", fără a se mai face descrierea structurii ierarhice superioare, se poate folosi cuvântul cheie ME.

� Semnele care se pot folosi pentru a se specifica un obiect sunt parantezele drepte <[nume_obiect]>. Ele sunt folosite obligatoriu atunci când în numele obiectului se găsesc spaţii.

II.1.4. Utilizarea în VBA a proprietăţilor şi metodelor obiectelor

Referirea la proprietăţile sau metodele unui obiect se face prin: − metoda descrisă la punctul precedent pentru referirea obiectului; − urmat de numele proprietăţii sau metodei, folosind semnul de calificare

punct. • Utilizarea proprietăţii unui obiect, în codul VBA, se face la fel ca şi

cum s-ar lucra cu o variabilă obişnuită, în citire sau scriere.

Page 92: 2.VBA_SC4

II-92

− Dacă se doreşte atribuirea unei valori proprietăţii unui obiect, atunci aceasta se introduce în partea din dreapta a unei instrucţiuni de atribuire.

Exemplu de scriere a proprietăţii Caption a unui formular: Me.Caption="Nume Nou Form"

sau a proprietăţii Index, a unui Recordset: Rs.Index="PrimaryKay" − Dacă se doreşte citirea proprietăţii unui obiect, atunci aceasta va face parte dintr-o expresie obişnuită.

Exemplu de citire a proprietăţii Caption a unui formular: MsgBox "Numele formularului este: " & Me.Caption

La utilizarea proprietăţilor unui obiect trebuie să se ţină cont de urmă-toarele trei restricţii:

� Nu toate proprietăţile au posibilitatea să li se schimbe valoarea. Aceste proprietăţi se numesc Read Only, şi se folosesc numai în citire;

� Ca şi o variabilă, o proprietate este de un anumit tip de date, de care trebuie ţinut cont în utilizarea ei;

� Modificarea proprietăţilor unui obiect prin cod durează numai în timpul fazei respective de execuţie, urmând ca la terminarea acesteia să se refacă proprietatea iniţială;

• Utilizarea metodelor unui obiect în codul VBA se face la fel ca şi cum s-ar lucra cu o procedură, folosindu-se metoda de apelare fără Call, prin scrierea sub forma unei instrucţiuni a metodei, urmată, dacă este cazul, de parametrii acesteia (fără a fi introduşi între paranteze) separaţi prin virgulă.

Exemplu de apelare a unei metode cu doi parametri de tip string: Rs.Seek "=", "unu".

II.1.5. Exemple de referire a obiectelor din modelul Access

� Pentru înţelegerea acestor exemple este necesară urmărirea structurii ierar-hice a modelului Access Application ce se găseşte tot în cadrul acestui capitol.

• Forms!Date – se face referire la formularul deschis cu numele Date. • Forms![date de bilant] – se referă formularul deschis date de bilant.

Observaţi parantezele drepte folosite pentru că numele formularului conţine spaţii.

• Forms![vinzari].RecordSource – se face referire la proprietatea Record Source al formularului deschis vinzari. Parantezele drepte pot fi scoase. Observaţi punctul, semnul de calificare pentru o proprietate sau metodă.

• Forms![vinzari]!valoare – se referă controlul cu numele valoare din formularul deschis vinzari.

Page 93: 2.VBA_SC4

II-93

• Forms!("vinzari")!valoare – identic cu mai sus, dar se foloseşte altă posibilitate de precizare a unui obiect dintr-o colecţie şi anume printr-un string care reprezintă numele obiectului.

• Forms!(0)!valoare – identic cu mai sus, dar se foloseşte precizarea unui obiect dintr-o colecţie prin folosirea numărului de ordine al obiectului în cadrul colecţiei (am presupus că formularul vinzari a fost primul deschis, primind indexul 0 in cadrul colecţiei Forms).

• Me.FilterOn – se referă proprietatea FilterOn a formularului în care se găseşte codul VBA.

• Me!Altul.Visible – se referă proprietatea Visible a controlului Altul a formularului în care se găseşte codul VBA.

Exemplul prezentat anterior este reluat, dar el nu se mai găseşte în codul din spatele formularului, ci extern în modulul de cod al aplicaţiei. Din el se observă în special cum funcţionează colecţia Forms, a formularelor deschise.

Public Sub Col_Form_Controale() ' Afişează obiectele ce se află în colecţia de controale a primului formular deschis Dim ST As String Dim i As Integer Dim N As Integer ST = "" ' Proprietatea Count a colecţiei conţine numărul de obiecte din colecţie On Error GoTo Fis ' Dacă nu este nici un formular deschis se produce _ eroare controlabilă de către utilizator N = Forms(0).Controls.Count ' Numărul de obiecte din colecţia de _ controale a primului formular deschis On Error GoTo 0 ‘ În continuare, dacă se produce o eroare aceasta _ va fi tratată de sistemul standard de erori. For i = 0 To N -1 'Primul element dintr-o colecţie are indexul 0 ST = ST & i & ": " & Forms(0).Controls(i).NAME & vbCr Next i ' Propritatea Parent a colecţiei conţine obiectul de care aparţine colecţia MsgBox " Controalele din formularul parinte:" & vbCr & _ """ " & Forms(0).Controls.Parent.NAME & _ " "", sunt în ordine:" & vbCr & vbCr & ST Sfirsit: Exit Sub Fis: MsgBox "Nu exista nici un formular deschis", vbCritical Resume Sfirsit End Sub

Page 94: 2.VBA_SC4

II-94

II.1.6. Instrucţ iunea With

Instrucţiunea With este folosită pentru a scrie diferite instrucţiuni ce se referă la prorietăţile sau metodele unui obiect, fără a le mai califica cu numele obiectului.

Forma lui With este: With object [instrucţiuni] End With

în care instrucţiunile plasate în interiorul acesteia vor referi proprietăţile sau metodele obiectului object, direct, fără calificarea acestora cu obiectul respectiv.

� În object se poate folosi numele unui obiect sau o variabilă obiect. Exemplu. Următoarea secvenţă modifică câteva dintre proprietăţile formula-rului deschis cu numele Datt.

With Forms!Datt .RecordSource = "Tabela_A" .Caption = "Formularul Datt" .ScrollBars = 0 .NavigationButtons = True

End With

� Instrucţiunea With se poate folosi şi pentru tipurile de date definite de utilizator cu instrucţiunea Type. Exemplu. Următoarea secvenţă introduce date în variabila vPersoana, declarată ca tip de date tPrs, definit de utilizator.

Type tPers Nume As String Virsta As Integer DataNastere As Date End Type Dim vPersoana as tPers …………….. With vPersoana .Nume=InputBox("Introduceti numele:") .Virsta=30 .DataNastere=InputBox("Introduceti data nasterii:") End With

Page 95: 2.VBA_SC4

II-95

II.1.7. Variabile obiect

În programare variabilele sunt elementele prin care se fac referiri la date. Deoarece în programarea la nivel de obiect, există o entitate specifică, obiectul, care încapsulează atât date cât şi prelucrări, este necesară definirea unei variabile specifice, variabila obiect, prin care să se poată manipula mai eficient acesta.

O variabilă obiect este asemănătoare unei variabile obişnuite ce conţine un anumit tip de date. Declararea ei se face cu aceleaşi instrucţiuni (Dim, Public, Private sau Static) ca şi la celelalte variabile.

Variabilele obiect ocupă o zonă de memorie de 32 biţi (4 octeţi). Deşi lucrul cu variabile obiect nu este deosebit de cel cu variabilele

obişnuite, totuşi ele au o caracteristică specifică şi anume: într-o variabilă obiect nu se va găsi efectiv obiectul respectiv, ci o referire (adresă) la acesta.

Astfel, dacă avem o variabilă de tip integer AI şi executăm AI=3, atunci în AI vom avea efectiv, pe 16 biţi, numărul 3. Dacă mai declarăm o variabilă de acelaşi tip, BI şi o facem egală cu AI, vom avea şi în aceasta numărul 3. Acum, executând AI=5, se va schimba valoarea din AI, dar cea din BI va rămâne neschimbată. AI şi BI au deci existenţe separate, independente.

Nu acelaşi lucru se întâmplă şi în cazul variabilelor obiect. Dacă (vezi următorul exemplu) avem o variabilă obiect FM1 şi introducem în ea un obiect, formularul F_CDialogContainer, atunci în FM1 nu vom avea formularul respectiv, ci o referire (adresă) la acesta. Tot aşa, dacă mai declarăm o variabilă obiect, FM2 şi introducem în ea ce se găseşte în FM1, atunci vom avea acum două variabile obiect care vor referi acelaşi obiect. Să modificăm acum o proprietate a lui FM1. Dacă vom citi aceeaşi proprietate din FM2, vom observa că modificarea este efectuată şi în acesta. Deci, cele două variabile obiect nu au existenţe independente, ele referind practic acelaşi obiect.

Evident, în anumite prelucrări, acest lucru are importanţă (ca în exemplu). Totuşi în majoritatea prelucrărilor manifestarea variabilelor obiect este similară cu a celor clasice.

II.1.7.1. Tipuri de variabile obiect

O variabilă obiect se poate declara în mai multe feluri şi anume ca:

� Variabilă obiect generică: Dim nume_var As Object

Variabila declarată în acest fel este o variabilă obiect generică, deoarece în ea se poate introduce orice obiect.

Page 96: 2.VBA_SC4

II-96

� Variabilă obiect specifică

Pentru fiecare obiect care se obţine dintr-o clasă vizibilă în aplicaţie, indiferent că aceasta provine din bibliotecile standard, prin referinţe la obiecte externe sau este creată de utilizator, există tipuri specifice de variabile obiect, cu acelaşi nume ca al clasei respective. De asemenea, acelaşi lucru se întâmplă şi pentru colecţiile de obiecte, existând tipuri specifice de variabile obiect cu numele acestora.

Astfel, pentru obiectele provenite din biblioteca Access Application, există următoarele tipuri de variabile obiect:

• Forms – colecţia formularelor deschise; • Form – pentru un obiect formular; • Reports – colecţia rapoartelor deschise; • Report – pentru un obiect raport; • Controls – pentru colecţia tuturor controalelor dintr-un formular sau

raport; • Control – pentru un control dintr-un formular sau raport etc.

Deoarece controalele, la rândul lor, provin din clase diferite de obiecte, există pentru fiecare tip din acestea variabile obiect specifice. Astfel mai sunt pentru controale următoarele tipuri specifice de variabile obiect:

• TextBox – pentru controlul casetă de text; • ComboBox – pentru controlul listă ascunsă; • ListBox – pentru controlul listă derulantă; • CheckBox – pentru controlul boolean casetă de validare; • Button – pentru controlul boolean buton radio; • ToggleButton – pentru controlul boolean de tip tastă; • CommandButton – pentru controlul buton de comandă; • Label – pentru controlul etichetă etc.

Declararea unei variabile obiect specifice se face folosind numele clasei sau colecţiei care va fi referită de variabila respectivă.

Dim nume_var As tip_obiect Diferenţa dintre utilizarea unei variabile obiect specifice sau generice se

referă la următorul aspect: La declararea unei variabile obiect generice, sistemul nu ştie ce fel de

obiect va fi în aceasta. Acest lucru se va cunoaşte la prima încărcare cu un obiect al variabilei. În acest moment, se va configura variabila obiect cu proprietăţile şi metodele specifice tipului de obiect respectiv. Deci această configurare este realizată în partea de execuţie a aplicaţiei.

Page 97: 2.VBA_SC4

II-97

La declararea unei variabile obiect specifice, sistemul ştie de la început care sunt proprietăţile şi metodele tipului de obiect respectiv. Deci configurarea variabilei este realizată în partea de compilare a aplicaţiei şi nu în cea de execuţie. Din această cauză, execuţia cu acest tip de variabile este mai rapidă.

� Un alt avantaj, determinat de utilizarea variabilelor obiect specifice, se referă la momentul în care este folosită, în partea de editare a programului, variabila obiect respectivă.

Editorul de VBA este dotat cu instrumente puternice de recunoaştere şi marcare a diferitelor cuvinte rezervate, a instrucţiunilor, a variabilelor, a obiectelor, a procedurilor şi funcţiilor vizibile din locul unde sunt folosite.

Astfel, dacă se introduce în text o funcţie (reamintesc că mă refer la partea de editare, de introducere a sursei unui modul de cod în VBA), atunci, după scrierea ei, automat se afişează o listă cu parametrii acesteia, ceea ce reprezintă un instrument foarte util al asistării activităţii de programare.

Similar, la introducerea în codul VBA a denumirii unui obiect (sau colecţii de obiecte), editorul afişează o listă ce conţine atât proprietăţile şi metodele acestuia cât şi obiectele (sau colecţiile de obiecte) pe care acesta le conţine. Acelaşi lucru se va întâmpla şi dacă programatorul va introduce numele unei variabile obiect specifice.

Dacă se lucrează însă cu variabile obiect generice, această facilitate nu poate fi activată în momentul respectiv (al editării programului), deoarece sistemul nu cunoaşte încă nimic despre structura obiectului pe care îl referă variabila respectivă.

� Nu toate obiectele sau colecţiile utilizate în Access au asociate şi declaraţiile de tipul respectiv pentru definirea variabilelor. În acest caz, evident se vor declara generic, variabilele care referă aceste obiecte.

De exemplu, pentru controalele folosite într-un formular sau raport, există tipurile de variabile obiect specifice:

− "Controls" – care se referă la colecţia controalelor din formularul sau raportul respectiv; − "Control" – care se referă la un obiect control din formularul sau raportul respectiv;

dar pentru toate controalele de un anumit tip (de exemplu TextBox) sunt definite numai tipurile pentru acest obiect (TextBox), dar nu şi pentru colecţia formată din aceste controale (nu există tipul TextBoxs).

Din cele prezentate se deduce că este indicat ca atunci când este posibil, să se folosească numai variabile obiect specifice.

� Deşi nu s-a folosit în prezentare, pentru declararea variabilelor obiect, decât forma instrucţiunii Dim, celelalte forme şi anume Public, Private sau Static, sunt valabile şi funcţionează la fel ca la variabilele clasice.

Page 98: 2.VBA_SC4

II-98

II.1.7.2. SET – Instrucţiunea de atribuire pentru variabile obiect

Deşi am folosit mereu forma de mai jos pentru instrucţiunea de atribuire pentru variabilele clasice:

var = expresie totuşi forma completă a acesteia este:

Let var = expresie în care cuvântul cheie Let, introdus implicit, arăta că este atribuită o valoare unei variabile clasice.

Pentru variabilele obiect, la care atribuirea constă practic în crearea unei referinţe către un obiect, este obligatorie folosirea la instrucţiunea respectivă a cuvântului cheie SET.

Deci pentru variabilele obiect instrucţiunea de atribuire este:

Set var_obiect = expresie_obiect

• în care expresie obiect este o expresie al cărui rezultat este un obiect. Efectul instrucţiunii de atribuire este introducerea în variabila obiect a

adresei obiectului (referirea la acesta) care rezultă din expresia din dreapta şi nu realizarea unei copii a obiectului respectiv.

Din această cauză dacă mai multe variabile referă acelaşi obiect, orice modificare a acestuia (cauzată eventual prin una din variabile) va fi reflectată imediat de toate aceste variabile care referă obiectul respectiv (vezi exemplul care va urma).

II.1.7.3. Eliberarea resurselor folosite de o variabilă obiect. Cuvântul cheie NOTHING.

O variabilă obiect are nevoie de un spaţiu (memorie) de lucru pentru a funcţiona. Acesta este eliberat automat, ca la orice variabilă, la terminarea modulului în care a fost declarată variabila obiect.

Dacă totuşi se doreşte eliberarea imediată a spaţiului ocupat de o variabilă obiect se foloseşte instrucţiunea:

Set var_obiect = Nothing

Public Sub Var_Obiect() ' Demonstrează că o variabilă obiect reprezintă referinţa către un obiect Dim ST As String Dim FM1 As Form Dim FM2 As Form On Error GoTo Fis 'Lipsa unui formular deschis produce o eroare

Page 99: 2.VBA_SC4

II-99

Set FM1 = Forms(0) ' Var. obiect FM1, va conţine referinţa către _ primul formular deschis MsgBox "Primul formular deschis este: " & FM1.NAME On Error GoTo 0 Set FM2 = Forms(0) ' Var. obiect FM2, va conţine aceeaşi referinţă ca _ variabila FM1 ST = FM1.Caption ' Proprietatea Caption a variabilei obiect FM1 _ este salvată în ST FM1.Caption = "TEST Variabile Obiect" ' Se schimbă proprietatea _ Caption în FM1 MsgBox FM2.Caption ' Schimbarea se face practic în obiectul referit. _ Deci şi în FM2 prop. Caption va fi: "TEST Variabile Obiect" FM1.Caption = ST ' Se reface proprietatea Caption. MsgBox FM2.Caption ' Această schimbare se produce şi în FM2 Set FM1 = Nothing ' Se eliberează spaţiul ocupat de FM1 Sfirsit: Exit Sub ' La terminarea rutinei, se eliberează spaţiul ocupat de toate variabilele _ obiect declarate în ea. Deci spaţiul ocupat de FM2 se eliberează şi el. Fis: MsgBox "Nu exista nici un formular deschis", vbCritical Resume Sfirsit End Sub

II.1.7.4. Crearea unei instanţe noi pentru o clasă de obiecte. Cuvântul cheie NEW

Cuvântul cheie New se poate folosi atât la declararea unei variabile obiect cât şi la instrucţiunea de atribuire Set.

Dim nume_var As New tip_obiect

Set var_obiect = New expresie_obiect

Efectul acestuia se manifestă numai la clasele de obiecte create prin modulele de cod ale aplicaţiei. El produce crearea unei noi instanţe pentru clasa respectivă, adică practic al unui spaţiu separat de existenţă pentru variabila respectivă.

Nu trebuie confundată folosirea acestui cuvânt cheie cu aceea de creare a unor obiecte noi în modelele standard ale Access (de exemplu nu se poate crea prin New un control nou într-un formular).

Page 100: 2.VBA_SC4

II-100

II.1.8. Parcurgerea colecţiilor de obiecte. Instrucţiunea For…Each

În primul exemplu din acest capitol s-a arătat cum pot fi parcurse cu o instrucţiune FOR obişnuită obiectele unei colecţii, folosindu-se proprietatea Count a colecţiei pentru stabilirea numărului de cicluri necesar.

Acelaşi lucru se poate face mai eficient cu forma specială a instrucţiunii For…Each:

For Each var_obiect In colecţie_obiecte [instrucţiuni] [Exit For] [instrucţiuni]

Next [var_obiect]

� Variabila obiect folosită trebuie să fie compatibilă cu tipul colecţiei specificate după cuvântul cheie IN.

Funcţionarea buclei For constă în faptul că la fiecare iteraţie, variabilei obiect, var_obiect, i se va atribui pe rând câte un element al colecţiei specificate.

Deci instrucţiunea For…Each va avea atâtea cicluri câte obiecte conţine colecţia specificată în instrucţiune. Exemplu.

Public Sub Afis_Forms() 'Afişează toate formularele deschise Dim FM As Form Dim ST As String ST = "" For Each FM In Forms ' FM referă la fiecare ciclu un formular deschis ST = ST & " " & FM.NAME & vbCr Next If Len(ST) > 0 Then MsgBox "Formulare deschise: " & vbCr & vbCr & ST Else ' Nu s-a executat nici un ciclu din For...Each MsgBox "Nici un formular nu eeste deschis" End If End Sub

� Instrucţiunea For ... Each se poate folosi şi pentru variabile de tip tablou (Array). În acest caz, variabila contor trebuie să fie declarată de tip variant.

Page 101: 2.VBA_SC4

II-101

II.2. Modelul Access-Application

Modelul ierarhic arbores-cent Application, prin care se realizează instanţele obiectelor şi colecţiilor care constituie interfaţa utilizator a unei aplicaţii şi care provin din clasele de obiecte conţinute în biblioteca standard Access, este arătat succint în figura alăturată.

� În figura prezentată nu s-au detaliat colecţiile. De exemplu, dacă la un moment dat există două formulare deschise, FM_1 şi FM_2, care conţin controalele Cbox_1, Cbox_2 şi Cmd (FM_1), respectiv Comb1 şi Cbox_1 (FM_2), atunci colecţia Forms va arăta ca în figură.

------------------

II.2.1. Obiectul Application

Obiectul Application se referă la aplicaţia Microsoft Access activă şi are două funcţii de bază:

1) Conţine următoarele obiecte şi colecţii:

• colecţia Forms – a formularelor deschise; • colecţia Reports – a rapoartelor deschise (cu aceiaşi structură ca Forms); • colecţia Modules – a modulelor de cod; • colecţia References – a referinţelor către alte obiecte ActiveX (obiecte

sau biblioteci); • obiectul Screen – conţine proprietăţi şi metode ce se referă la

formularul, raportul sau controlul care la un moment dat are focusul; • obiectul DoCmd – care conţine metode prin care se pot executa din

codul VBA aproape toate comenzile care se pot folosi în aplicaţiile Access. 2) Prin metodele şi proprietăţile sale, obiectul Application poate accesa

oricare dintre componentele (colecţii, obiecte, proceduri, funcţii, clase etc.)

Forms

Application

Legendă ♦ Obiecte

♦ Colecţii

Reports Controls

Controls Modules

Screen

DoCmd

formularele deschise

rapoartele deschise

Forms

colecţia formularelor deschise

Controls FM_1

Cbox_1

Cbox_2

Cmd

Controls FM_1 Cbox_1

Comb1

Page 102: 2.VBA_SC4

II-102

aplicaţiei Microsoft Access. De asemenea există posibilitatea referirii acestui obiect şi dintr-o aplicaţie externă prin tehnica Automation.

� Oricare obiect Access are o proprietate specială-Application, prin care se poate accesa obiectul Application.

------------------

Dintre metodele obiectului Application prezentăm câteva: � Metoda SetOption a obiectului Application este folosită pentru a seta

opţiunile generale ale bazei de date (o parte din acestea se găsesc definite în meniul Tools|Options).

Astfel opţiunea Status Bar, care permite sau nu vizualizarea barei de stare, se poate activa prin următoarea metodă:

Application.SetOption "Show Status Bar", True Aşa cum se observă, metoda SetOption are doi parametri:

− primul este un string care conţine numele opţiunii ce se va seta; − al doilea este de un tip de dată specific opţiunii (boolean în cazul prezentat) şi este folosit pentru a da o valoare opţiunii;

� Metoda GetOption – întoarce valoarea unei opţiuni generale a bazei de date;

� Metoda Quit – determină terminarea aplicaţiei Access; � Metoda Echo – determină blocarea refacerii ecranului.

………. Application.Echo False,"Ecranul este blocat" DoCmd.Hourglass True ' …prelucrări în cursul cărora ecranul nu se va mai modifica _

Stringul introdus în al doilea argument este afişat pe bara de stare Application.Echo True DoCmd.Hourglass False ' Se reface starea normală a ecranului ……………

� CreateForm şi CreateReport Funcţii ce permit crearea unui formular sau raport în aplicaţia Access, din

codul VBA, ca în exemplul următor: Sub NewForm() Dim fm As Form Set fm = Application.CreateForm ' Crează un formular nou a cărei _ referinţă se introduce în variabila obiect specifică de tip Form, fm With fm ' Setează cîteva proprietăţi ale formularului

.RecordSource = "Tabela_A"

Page 103: 2.VBA_SC4

II-103

.Caption = "Numele Formularului" .AllowAdditions = False .AllowDeletions = False

End With DoCmd.Restore ' afişează formularul creat End Sub

� O aplicaţie Access este un ActiveX. Aceasta înseamnă că ea poate fi accesată şi din alte aplicaţii care folosesc tehnologia OLE Automation, ca MS Visual Basic, MS Excel sau altă aplicaţie Access. Pentru aceasta trebuie creată o nouă instanţă a obiectului Application, în care se poate deschide o bază de date.

În exemplul următor se deschide dintr-o aplicaţie Access o bază de date cu numele DAO.mdb, ce se află în directorul Teste a discului C:

Sub ExempluAccess() Dim appAccess As Object Dim strDB As String strDB = "C:\Teste\DAO.mdb" ' introduce adresa bazei de date Set appAccess = New Access.Application ' creează o nouă instanţă a _ obiectului Application, a cărei referinţă se introduce în variabila obiect _ appAccess, în scopul folosirii acesteia ' Deschide în instanţa creată în MS Access baza de date DAO.mdb appAccess.OpenCurrentDatabase strDB appAccess.DoCmd…… ' efectuează diferite acţiuni în DAO.mdb appAccess.CloseCurrentDatabase ' închide baza de date DAO.mdb Set appAccess = Nothing ' anulează instanţa creată End Sub

� În descrierea structurii ierarhic arborescente a modelului Access-Appli-cation din aplicaţia Access, folosirea obiectului Application este opţională, el fiind considerat implicit.

II.2.2. Colecţia Forms

Colecţia Forms conţine toate formularele deschise la un moment dat. Indexarea colecţiei începe de la 0 – Forms(0) reprezentând primul formular deschis. În continuare, fiecare nou formular deschis va avea indexul următor din secvenţă, iar închiderea unui formular va determina o renumerotare a formularelor deschise, în aşa fel ca mulţimea indecşilor să fie mereu continuă şi în ordinea deschiderii formularelor.

Membrii colecţiei Forms – a formularelor deschise – sunt obiecte Form. Pentru colecţia Forms şi obiectele Form, există definite tipuri de date

obiect specifice.

� Formularele deschise pot fi şi în proiectare (design).

Page 104: 2.VBA_SC4

II-104

Exemplu. Procedura următoare, ce se găseşte în modulul general de cod, afişează numărul formularelor deschise în momentul execuţiei sale. Ea va folosi proprietatea Count a unei colecţii de obiecte, care conţine, aşa cum s-a mai arătat, numărul de obiecte ce se găsesc în aceasta.

Sub TestForms Dim N as Integer Dim FS as Forms Set FS = Application.Forms N = FS.Count If N = 1 Then MsgBox "Există un formular deschis" ElseIf N>1 Then MsgBox "Există " & N & " formulare deschise" Else MsgBox "Nu există nici un formular deschis" End If End Sub

II.2.2.1. Obiectul Form

Un obiect Form reprezintă un formular deschis. El are proprietăţi, metode şi evenimente (la care se pot ataşa metode) descrise tot în cadrul acestui capitol.

Un obiect Form conţine o colecţie de controale numită Controls, formată din obiecte Control.

Fiecare obiect Control va fi de un anumit tip şi va avea proprietăţile, metodele şi evenimentele specifice acestuia.

Pentru colecţia Controls şi obiecte Control, există tipuri de date obiect specifice, definite.

De asemenea, pentru diferite tipuri de controale sunt definite tipuri de date obiect specifice (dar nu şi colecţii) ca de exemplu:

− TextBox – pentru controlul casetă de text; − ComboBox – pentru controlul listă ascunsă; − ListBox – pentru controlul listă derulantă; − CheckBox – pentru controlul boolean casetă de validare; − Button – pentru controlul boolean buton radio; − ToggleButton – pentru controlul boolean de tip tastă; − CommandButton – pentru controlul buton de comandă; − Label – pentru controlul etichetă.

Page 105: 2.VBA_SC4

II-105

II.2.2.1.a) Cuvântul cheie ME

Me este folosit pentru a face referire direct, din modulul de cod din spatele unui formular, la obiectul (formular) al cărui cod este executat.

În acest fel Me se comportă asemănător cu o variabilă obiect de tip Form, declarată implicit.

Me este utilizat în general în două scopuri: • Pentru a referi direct obiectele din formularul al cărui cod se execută

(opţional). De exemplu: − Me.Cbox_1, se referă la un control din formularul în execuţie. − Me.RecordSource="Tabela_A" ' se leagă formularul la _ tabela Tabela_A; aceasta are un câmp A

MsgBox Me!A ' se observă semnul de calificare folosit; la _ compilare, formularul nefiind legat de Tabela_A, câmpul A nu era _ cunoscut de sistem.

• Pentru a trimite într-o rutină aflată în alt modul de cod, ca parametru, instanţa al cărui cod este executat. Exemplu. În formularele unei aplicaţii există un buton de comandă, BC, care la evenimentul click, va închide toate formularele deschise cu excepţia celui care este activ (cel în care s-a apăsat BC).

− În modulul de cod din spatele unui formular la evenimentul Click al butonului ce comandă BC, va fi următoarea procedură eveniment:

Private Sub BC_Click() ' proc. Evenimentului Click al controlului BC ' Închide toate formularele deschise din aplicaţie CloseForms Me ' parametrul va fi o referinţă la un obiect de tip form _ şi anume chiar formularul în al cărui cod ne găsim End Sub

− În modulul general de cod va fi următoarea procedură publică: Public Sub CloseForms(pF As Form) Dim vF As Form Dim cF As Forms Dim NrClose As Integer Dim Afis As String Dim NF As Integer Dim i As Integer Set cF = Application.Forms ' colecţia Formularelor deschise NF = cF.Count MsgBox "Formulare deschise=" & NF For i = NF - 1 To 0 Step -1 Set vF = cF(i) ' un obiect Formular If vF.NAME = pF.NAME Then MsgBox "Formularul activ este:" & pF.NAME

Page 106: 2.VBA_SC4

II-106

Else Application.DoCmd.Close acForm, vF.NAME ' Metodă a obiectului DoCmd prin care se închide _ obiectul de tip formular (constanta acForm) _ şi cu numele conţinut în al doilea parametru. NrClose = NrClose + 1 End If Next Afis = IIf(NrClose = 0, "Nu s-au inchis formulare", "Formulare inchise=" & NrClose) MsgBox Afis End Sub

� Se observă că s-a parcurs colecţia formularelor deschise (Forms) de la ultimul formular deschis către primul. Acest lucru se datorează faptului că închiderea unui formular va produce modificări în colecţia formularelor deschise, atât asupra numărului de membri ai colecţiei cât şi asupra numărului de ordine (de indexare) în cadrul colecţiei unui formular dacă a fost închis un formular cu un index mai mic; de exemplu dacă există 3 formulare deschise, cu indecşii: 0, 1, 2 – închiderea formularului 1 va face ca formularul cu indexul 2 să ia indexul 1.

II.2.2.1.b) Proprietăţile formularului

Majoritatea proprietăţilor formula-rului se pot accesa atât static (prin cele 3 pagini ale controlului TAB al formularului) cât şi dinamic, prin cod VBA.

� Numele formularului

Stabilirea numelui formularului se face în fereastra Database la fel ca la tabele sau cereri. Acesta este foarte important deoarece se va folosi pentru a se face referire la acest obiect de oriunde, dar evident calificat dacă este necesar.

� Pagina FORMAT

Cele mai utilizate proprietăţi din această pagină, referitoare la forma de prezentare a formularului, sunt:

• Caption – Titlul formularului. Apare în bara de titlu a acestuia. Nu trebuie confundat cu numele formularului.

Page 107: 2.VBA_SC4

II-107

Implicit, dacă proprietatea nu este completată, numele formularului se va folosi şi ca titlu.

• Default View – Tipul formularului, care poate fi Continous sau Single. • Scroll Bars – Specifică dacă există sau nu bare de derulare, orizontale

şi/sau verticale. • Record Selectors – Specifică dacă există sau nu în stânga înregistrării,

buton de selecţie a acesteia. • Navigation Buttons – Specifică

dacă există sau nu în partea de jos a formularului butoane pentru accesarea anumitor înregistrări. Prin acesta se poate ajunge la prima sau la ultima înregistrare a formularului – se consideră ordinea de afişare şi nu aceea a plasării fizice a înregistrărilor în tabelele legate – la înregistrarea precedentă sau următoare sau la o nouă înregistrare în vederea adăugării. De asemenea se afişează numărul curent al înregistrării, câte înregistrări sunt în formular şi dacă formularului i se aplică un filtru de selecţie.

• Dividing Lines – Specifică dacă există sau nu linii de separare a înregistrărilor.

• Auto Resize – Specifică dacă formularul îşi modifică forma, prin tragere, dacă se recalculează sau nu dimensiunile obiectelor care sunt cuprinse în acesta.

• Auto Center – Specifică dacă se poziţionează sau nu formularul la mijlocul ecranului.

• Border Style – există următoarele posibilităţi: − Sizable – Formularul poate fi maximizat, minimizat sau i se poate schimba forma prin tragere de margini. − None – Nici una din facilităţile de mai sus nu este valabilă, şi de asemenea nu are nici buton X de închidere. − Thin – E ca Sizable, dar nu are margini de tragere. − Dialog – E ca None, dar are buton X de închidere.

• Control Box – Specifică dacă există sau nu caseta de butoane din stânga barei de titlu.

• Min Max Button - Specifică dacă există sau nu butoanele de maximizare/ minimizare în Control Box.

• Close Button – Specifică dacă există sau nu buton X de închidere. • Width – Lăţimea efectivă a formularului (nu a ferestrei de vizualizare a

acestuia), în unitatea de măsură stabilită în Windows | Control Panel | Regional Settings.

• What’s This Button – Se poate seta pe Yes numai dacă Min Max Button este No, şi duce la introducerea în Control Box a butonului specific de Help assistant din MS Office.

Page 108: 2.VBA_SC4

II-108

• Picture – Formularele pot avea eventual, o imagine de fundal, Background. Adresa fişierului care conţine imaginea (sunt acceptate mai multe tipuri: bmp, ico, wmf, emf, dib) se introduce în această proprietate.

• Picture Type – Se stabileşte dacă fişierul respectiv este încapsulat (embedded) sau legat (linked). Încapsularea în mai multe formulare a aceluiaşi fişier grafic duce totuşi la ocuparea spaţiului pentru fiecare fişier în parte.

• Picture Size Mode – există următoarele posibilităţi: − Clip – imaginea este preluată la dimensiunile ei reale; − Zoom – imaginea va fi mărită până la dimensiunea ferestrei formularului dar îşi păstrează proporţiile; − Stretch – Imaginea va fi mărită pentru a ocupa întreaga fereastră dar nu îşi păstrează proporţiile.

• Picture Alignement – Se stabileşte unde se plasează în fereastra formularului imaginea grafică.

• Picture Tiling – Setată pe Yes, duce la repetarea imaginii grafice pentru a ocupa întreaga fereastră a formularului.

• Grid X, Grid Y – Distanţa dintre liniile grilei de proiectare, în pixeli. Afişarea grilei de proiectare se face din View | Grid. Alinierea controalelor la această grilă se face din Format | Snap To Grid.

� Pagina DATA, conţine proprietăţile referitoare la datele formularului.

• Record Source – Tabela sau cererea, de care este legat formularul. • Filter – Se poate introduce o expresie – folosind regulile prezentate la

cereri - care are rolul de a face o selecţie a înregistrărilor din sursă. Dacă se creează un filtru prin meniul Records, atunci când formularul este în execuţie, atunci acesta va fi introdus automat în această proprietate.

• Order By – Se introduc câmpurile după care se sortează înregistrările din formular (aranjarea tuturor înregistrărilor din formular după ordinea ascendentă sau descendentă a unuia sau mai multor câmpuri). Dacă se doreşte sortare descendentă se introduce după numele câmpului respectiv un spaţiu şi DESC. Implicit se consideră sortarea ascendentă. Dacă sunt mai multe câmpuri de sortare, acestea se separă prin virgulă. Ca şi la filtre, dacă se stabileşte un câmp de sortare prin meniul Records, atunci când formularul este în execuţie, acesta va fi introdus automat în această proprietate.

� Crearea unui filtru sau al unui criteriu de sortare nu implică şi activarea automată a acestuia. Activarea sau dezactivarea lor se poate face în timpul execuţiei formularului în două moduri:

− Fie din meniul de comenzi prin Records | Apply Filter, Sort sau Records | Remove Filter, Sort;

Page 109: 2.VBA_SC4

II-109

− Fie din cod VBA, prin setarea la True sau False, a proprietăţilor dinamice ale formularului:

− FilterOn − OrderByOn

• Allow Filters, Allow Edits, Allow Deletions, Allow Additions – Setate pe No, blochează comanda respectivă.

• Record Locks – Se întâlneşte şi la cereri. Are rolul de a stabili ce înregistrări se blochează, când se lucrează în reţea şi mai mulţi utilizatori accesează aceeaşi tabelă sau cerere încercând să scrie în ea. Blocarea se referă la faptul că numai primul utilizator care modifică zona respectivă poate să o facă, ceilalţi fiind Read Only. Posibilităţile de blocare oferite de sistem sunt:

− No Loks – Înregistrările nu sunt blocate, toţi utilizatorii putând scrie în acelaşi timp în aceeaşi înregistrare, ceea ce face ca sistemul să ceară ce modificare rămâne valabilă, printr-un mesaj specific. Se foloseşte când aplicaţia nu este folosită în reţea; − All Records – Întreaga tabelă este blocată, numai un singur utilizator având dreptul să efectueze modificări, ceilalţi putând numai să citească din tabela respectivă; − Edited Record – Numai înregistrarea curentă este blocată. Practic se blochează o zonă de 2KB, ceea ce poate duce şi la blocarea altor înregistrări;

� Pagina OTHER

• Pop Up – Specifică dacă fereastra formularului va fi sau nu deasupra celorlalte ferestre.

• Modal – Un formular modal se caracterizează prin faptul că, o dată preluat controlul, nu îl mai cedează decât la închiderea lui. Acest lucru poate fi valabil numai pentru aplicaţia Access sau pentru toate aplicaţiile aflate în execuţie în momentul respectiv.

• Cycle – Stabileşte care este ordinea de accesare a înregistrărilor când se trece cu <Enter> sau <Tab> de la un control la altul şi se ajunge la ultimul control din secţiunea de detail, stabilit conform ordinii tab (care se lansează din meniul contextual al formularului şi prin care se fixează care este ordinea de parcurgere a controalelor dintr-o secţiune atunci când se trece de la un control la altul prin tastatură – cu <Enter> sau <Tab>). Dacă proprietatea este setată pe All Records, se va continua cu înregistrarea următoare, iar dacă este Current Record, se va reveni la primul control din aceeaşi înregistrare.

• Menu Bar – Numele unei alte bare de meniu creată de proiectant, care să înlocuiască meniul standard din Access.

Page 110: 2.VBA_SC4

II-110

• Toolbar – Numele unei alte bare de pictograme creată de proiectant, care să înlocuiască bara de pictograme standard din Access, care apare la execuţia unui formular, şi anume Form View.

• Shortcut Menu – Specifică dacă se va permite sau nu apariţia meniului contextual al formularului.

• Shortcut Menu Bar – Numele unui meniu contextual creat de proiec-tant, care să înlocuiască pe cel standard care apare la execuţia unui formular.

II.2.2.1.c) Evenimentele formularului

� Pagina Even

Cele mai importante sunt: • On Open şi On Close – Se produc la deschiderea, respectiv închiderea

formularului. Aceste evenimente pot fi anulate, adică nu se va mai produce deschiderea/

închiderea formularului. În general se folosesc pentru ca utilizatorul să confirme aceste acţiuni.

Ţinând cont că sunt prima/ ultima acţiune care se produce în "existenţa" unui formular, ele pot fi folosite şi la anumite setări necesare în codul VBA. Exemplu. On Open – Pentru a se crea o acţiune care să se execute la deschiderea unui formular (adică se ataşează o metodă evenimentului On Open) se va selecta în pagina de evenimente a obiectului FORM, "Event Procedure". Prin apăsarea pe cele trei puncte din dreapta, se va lansa un Wizard care va afişa modulul de cod VBA al acestui formular, în care va însera prima şi ultima linie a procedurii corespunzătoare aces-tui eveniment, urmând ca utilizatorul să scrie secvenţa de instrucţiuni în cod VBA.

' procedura ataşată evenimentului open a formularelor Private Sub Form_Open(Cancel As Integer) ' Se foloseşte MsgBox ca funcţie. ' Ea va afişa o casetă cu mesajul respectiv şi cu doua butoane, Yes şi No

Page 111: 2.VBA_SC4

II-111

' Dacă utilizatorul apasă pe: ' – Yes – funcţia va întoarce valoarea "vbYes" ' – No – funcţia va întoarce valoarea "vbNo" If MsgBox("Doriti deschiderea formularului.... ?", vbYesNo) = vbYes Then ' Ramura TRUE a instrucţiunii IF.... utilizatorul a apăsat pe Yes. ' Folosirea MsgBox ca procedură pentru afişarea unui mesaj

MsgBox "Se deschide formularul.... " Else ' Ramura FALSE a instrucţiunii IF.... utilizatorul a apăsat pe No.

Cancel = True ' Se anulează deschiderea formularului prin _ setarea la TRUE a parametrului CANCEL al procedurii MsgBox "Ati anulat deschiderea formularului... "

End If End Sub

� O procedură eveniment va avea un nume care va conţine numele obiectului (în cazul nostru FORM) şi numele evenimentului (OPEN), pe care sistemul îl va crea automat.

� Procedurile eveniment pot avea parametri (declaraţi în aceeaşi linie de definire a procedurii, între paranteze rotunde), pe care sistemul îi va introduce dacă este cazul.

Aceşti parametri pot fi de: − intrare – conţin nişte valori pe care sistemul îi încarcă în funcţie de un anumit context şi care pot fi folosiţi în interiorul procedurii; − ieşire – care vor fi eventual setaţi de utilizator, pentru ca la terminarea procedurii (instrucţiunea END SUB sau EXIT) sistemul să execute anumite acţiuni.

Astfel parametrul CANCEL, atunci când apare într-o procedură eveniment, arată că dacă se va seta pe TRUE, evenimentul respectiv va anula acţiunea care l-a produs, iar dacă se setează pe FALSE, atunci acţiunea care a declanşat evenimentul se va termina normal.

• On Load şi On Unload – Se produc la încărcarea în memorie a formularului, respectiv eliberarea spaţiului ocupat de el. Se produc după, respectiv înainte de On Open/ On Close. Nu pot fi anulate.

• Before Update – Se produce după modificarea unei înregistrări, atunci când se iese din înregistrarea respectivă. Poate fi anulat. Se foloseşte în general pentru a verifica anumite corelaţii între câmpurile unei înregistrări şi a nu permite utilizatorului trecerea la o altă înregistrare (deci modificările efectuate) dacă acestea nu sunt corespunzătoare (se va face parametrul CANCEL=TRUE).

Page 112: 2.VBA_SC4

II-112

Exemplu. BeforeUpdate Private Sub Form_BeforeUpdate(Cancel As Integer)

If (Me!DataNasterii.Value < Me!DataAbsolvireLiceu) And _ (Me!DataAbsolvireLiceu<Me!DataAbsolvireFacultate) Then

Else MsgBox "Corectati corelatiile intre date" Cancel = True ' Nu se va permite trecerea la o nouă înregistrare ' deoarece condiţia testată nu este adevărată

End If End Sub

� În exemplul de mai sus s-au folosit obiectele DataNasterii, DataAbsolvireLiceu şi DataAbsolvireFacultate, care sunt nişte controale text box, legate de câmpurile tabelei ataşate formularului şi care, în proprietatea VALUE, conţin datele din câmpurile respective ale înregistrării curente.

� Proprietatea VALUE fiind implicită la controalele text box, poate fi omisă. • After Update – Se produce după modificarea unei înregistrări, atunci

când se iese din înregistrarea respectivă. Acest eveniment nu se poate anula, modificarea devenind definitivă.

Se foloseşte în general pentru a calcula anumite valori şi a le introduce în controale, la terminarea modificărilor dintr-o înregistrare (în formulare single, de obicei). Exemplu. AfterUpdate – Avem un single formular legat la o tabelă care conţine două câmpuri, legate la rândul lor de controale tip text box, cu numele Cantitate şi Pret. Al treilea control, Valoare, nu este legat de tabelă şi este Read Only, nepermiţând utilizatorului să modifice datele în el. Totuşi dorim ca în cazul în care cantitatea sau preţul se modifică, să se schimbe corespunzător şi valoarea din acest control, la terminarea modificării înregistrării.

Private Sub Form_AfterUpdate () Me!Valoare = Me!Cantitate * Me!Pret ' Proprietatea Value a controalelor nu este obligatorie, fiind implicită. Se poate folosi această proprietate atât pentru citirea, cât şi pentru introducerea datelor în control, funcţionarea fiind deci asemănătoare cu a unei variabile.

End Sub

� Dacă un control nelegat se găseşte în secţiunea Detail a unui formular (sau raport) atunci valoarea care se găseşte în el (calculată cu datele din înregistrarea curentă – cea care are cursorul) va fi afişată în toate detail-urile care se văd pe ecran (deci aceeaşi valoare la toate înregistrările). Din această cauză s-a specificat un formular single.

Page 113: 2.VBA_SC4

II-113

Totuşi, exemplul prezentat, deşi corect, este cam ilogic. Gândiţi-vă de ce!! • Before Insert şi After Insert – Este la fel ca cele dinainte dar se

produc numai când se introduc înregistrări noi. • On Current – Se produce când se trece pe o altă înregistrare. Se

foloseşte în general, pentru a efectua calcule, la întrarea într-o înregistrare, cu datele din aceasta. Exemplu. On Current – La aceeaşi aplicaţie prezentată mai sus, dorim să facem acelaşi calcul al valorii şi la intrarea în înregistrare.

Private Sub Form_Current () Me!Valoare = Me!Cantitate * Me!Pret

End Sub

� Dacă nu am fi creat această metodă pentru acest eveniment, atunci la intrarea într-o înregistrare am fi avut în controlul Valoare, rezultatul calculului anterior.

• On Timer – Se produce dacă proprietatea Timer Interval este diferită de zero. Dacă în Timer Interval este o valoare numerică, atunci acesta va specifica, în milisecunde, intervalele de timp la care se lansează procedura eveniment introdusă la On Timer. Exemplu. On Timer

Private Sub Form_Timer () ' Se va executa la intervalul de timp care se găseste în proprietatea _ TimerInterval de pe pagina de evenimente a formularului. Aceasta _ având valoarea 60.000, înseamnă că această procedură se va _ executa la fiecare minut.

MsgBox "A mai trecut 1 minut !!" End Sub • On Click, On Dbl Click, On Mouse Down, On Mouse Up, On

Mouse Move – Se produc la acţiunea respectivă a mouse-ului pe formular. • On Key Down, On Key Up, On Key Press – Se produc la acţiunea

respectivă a tastaturii. • On Error – Se produce la o eroare datorată datelor. • On Got Focus, On Lost Focus – Se produc la primirea, respectiv

pierderea focusului formularului.

II.2.2.1.d) Metodele formularului

Activarea acestor metode se face de obicei din modulul de cod VBA ataşat formularului.

În continuare prezentăm cele mai utilizate metode ale formularelor.

Page 114: 2.VBA_SC4

II-114

� Metoda Refresh

Metoda Refresh – va determina o reîmprospătare a unui formular cu datele actualizate ale tabelei ataşate, dacă aceasta se modifică printr-un proces din afara modificărilor directe efectuate în tabelă prin formular (acestea evident vor fi imediat sesizate).

Un astfel de proces se poate efectua de exemplu dacă: − printr-o cerere acţiune se modifică tabela ataşată formularului; − aplicaţia rulează într-un mediu multiutilizator (într-o reţea de calcu-latoare) şi un alt utilizator modifică această tabelă.

� Refresh se poate face şi direct în view prin acţionarea comenzii Records | Refresh.

� Această acţiune sistemul o face şi automat la un interval de timp care se stabileşte pentru toate formularele deschise, prin completarea proprietăţii bazei de date Refresh Interval (în sec) din meniul Tools | Advanced. Evident, când se doreşte o reîmprospătare imediată a afişajului unui formular, se va folosi metoda sus amintită.

� Metoda aceasta acţionează numai asupra setului de înregistrări care exista la lansarea formularului, ea neavând efect asupra:

− înregistrărilor noi introduse sau şterse; − cererilor folosite în diferite controale. (De exemplu avem un control combo Box care afişează date dintr-o altă tabelă care se modifică după lansarea formularului. Metoda refresh nu va actualiza acest control.)

� Metoda Requery

Metoda Requery acţionează ca şi metoda Refresh dar este mult mai puternică deoarece ea re-execută toate cererile aferente formularului. Această metodă este destul de lentă, deoarece ea se comportă ca şi cum s-ar lansa din nou formularul (inclusiv poziţionarea focusului pe prima înregistrare).

� Metoda Recalc

Aşa cum am mai arătat, într-un formular pot exista controale calculate, care vor afişa expresii în care pot interveni date din alte controale legate la câmpurile tabelei ataşate formularului. În momentul în care se modifică definitiv (se iese din control sau se trece la altă înregistrare) un control (câmp), se vor reface şi calculele controalelor calculate în care acesta intervine. Sunt însă cazuri în care este necesară refacerea imediată a calculelor controalelor calculate, fără a modifica poziţia cursorului dintr-un control. Metoda Recalc face această acţiune. Deci ea se comportă ca şi cum s-ar da o comandă de trecere pe un alt control şi o altă înregistrare, cu menţinerea însă a cursorului pe poziţia sa.

Page 115: 2.VBA_SC4

II-115

� Metoda Set Focus

Cu această metodă se poate muta focusul (cursorul) într-un formular, care evident este în execuţie.

În general este folosită pentru mutarea focusului între două formulare care se află în execuţie. Exemplu. Forms("form1").SetFocus

Această instrucţiune va ceda cursorul (focus) formularului form1, evident cu condiţia ca acesta să fie deschis (obiectul Forms recunoaşte numai formularele care sunt deschise!).

II.2.2.1.e) Obiectele secţiunilor formularului: Detail, Form_Header, Form_Footer

Toate aceste secţiuni ale formularului au aceleaşi proprietăţi şi eveni-mente. Pagina de Date, evident, nu are proprietăţi.

Configurarea acestor obiecte este puţin uilizată în practica proiectării formularelor. Singura proprietate mai folosită este Back Color – prin care se stabileşte culoarea de fundal a unei secţiuni.

II.2.2.1.f) Referirea Subformularelor şi a controalelor sale

Un Subformular este un obiect inclus într-un formular, care conţine: • Proprietăţi specifice, ce pot fi referite după schema uzuală. De exemplu: MsgBox Me.SF.RecordSource – va afişa numele tabelei

legate de Subformularul cu numele SF, ce se găseşte în formularul în al cărui cod se află instrucţiunea.

• Controale, a căror referire se face prin utilizarea unei proprietăţi specifice unui Subformular şi anume FORM.

De exemplu, dacă în formularul deschis DesX, există un Subformular cu numele SFm, în care există un control text box TBB, atunci introducerea unei valori în acest control printr-o instrucţiune aflată în modulul general de cod va fi: Forms!DesX!SFm.Form!TBB=100

II.2.2.2. Obiectul Control – Text_Box (caseta de text)

Cele mai utilizate tipuri de controale, folosite în proiectarea formularelor (ca şi a rapoartelor) sunt prezentate în continuare prin prisma proprietăţilor, metodelor şi evenimentelor lor.

Text Box este cel mai utilizat control folosit atât în formulare cât şi în rapoarte. Este un control care se poate lega la un câmp al unui tabel. Reprezintă practic o

casetă în care se vor vizualiza datele din câmpul de care este legat, permiţând actualizarea acestora. De obicei este însoţit de un control label (etichetă), în care se va specifica ce reprezintă datele din Text Box.

Page 116: 2.VBA_SC4

II-116

II.2.2.2.a) Proprietăţile controlului Text Box

Prezentăm în continuare proprietăţile cele mai utilizate ale acestui control, cu observaţia că există o serie de proprietăţi pe care le-am mai studiat anterior (la obiectul Form).

� Pagina FORMAT

Pagina de Format conţine proprietăţile prin care se configurează formatul şi stilul textului din casetă.

• Font Name – Felul fontei, adică tipul de literă folosit. Fontele care acceptă diacriticele româneşti sunt cele cu terminaţia 'CE'. (Altă fontă care acceptă caractere româneşti este şi 'MS Sans Serif'.)

� Pentru a se putea lucra cu diacritice româneşti, tastatura trebuie setată corespunzător, pentru a doua limbă, în Control_Panel | Keyboard.

• Fore Color – Culoarea fontei. • Font Size – Mărimea în pixeli a

fontei. • Font Weight – Grosimea fontei • Font Italic – Litera aplecată. • Font Underline – Subliniere. • Text Align – Alinierea textului în

căsuţă • Border Style, Border Color,

Border Width – Se folosesc pentru confi-gurarea marginii controlului.

• Special Effect Stabileşte un tip standardizat de margine pentru control. Uneori setarea

acestei proprietăţi are efect şi asupra celor trei proprietăţi de mai sus. Există 6 tipuri: − Flat – plat; − Raised – în relief; − Sunken – îngropat; − Etched – poansonat, zgâriat; − Shadowed – cu umbră; − Chiseled – subliniat.

• Back Color – Culoarea fundalului. • Back Style – Dacă fundalul este sau nu transparent. În cazul

transparenţei se va vedea obiectul de sub control, de obicei culoarea secţiunii în care se găseşte acesta.

Page 117: 2.VBA_SC4

II-117

� În bara de meniu, în format, există două proprietăţi, care atunci când sunt activate vor seta toate obiectele selectate în momentul respectiv, în felul următor:

− Bring to Front – aduce obiectele la suprafaţă; − Send to Back – duce obiectele la fund; Prin aceste proprietăţi se poate stabili cum "se văd" obiectele suprapuse.

� Această proprietate poate fi folosită pentru a se marca explicit care este controlul în care se găseşte cursorul (este activ). Aceasta se va realiza prin folosirea unei culori unice pentru controlul activ. Pentru aceasta se procedează astfel:

− Se face controlul cu Back Color – culoarea controlului activ (de exemplu verde) şi Back Style – transparent.

− Se creează un control grafic, Rectangle, "umplut" cu culoarea pe care vrem să o aibă controlul (de exemplu galben) şi de dimensiunile acestuia, care se aşează dedesubt.

În felul acesta controlul fiind transparent, va avea culoarea dreptunghiului de dedesubt (galben), iar când va primi focusul, culoarea setată pentru el (verde).

� Toate proprietăţile prezentate mai sus se pot configura direct de pe bara cu pictograme "Formatting".

• Format – În căsuţa de text avem o dată de tipul câmpului de care controlul este eventual legat. Avem posibilitatea să alegem între mai multe tipuri de afişare specifice tipului respectiv de dată. De asemenea acesta se poate crea şi cu caracterele specifice de construire a formatelor.

• Decimal Places – Numărul de zecimale al datelor de tip numeric. • Visible – Permite ca un control construit să poată fi făcut vizibil sau nu,

în funcţie de un anumit context. • Scroll Bars – Există posibilitatea ca acest control să poată conţine mai

multe linii de date. În acest caz este indicat să i se ataşeze bara derulantă verticală.

• Can Grow, Can Shrink – Permite ajustarea controlului pe verticală, în cazul în care în control sunt un număr variabil de linii.

� Aceste proprietăţi sunt valabile numai la tipărire nu şi la afişarea pe ecran. Deci ele sunt folosite în special la rapoarte.

• Left, Top, Width, Height – Poziţia (relativă la secţiunea unde se găseşte) şi mărimea controlului pe ecran, dată în cm sau inches, în funcţie de cum e setată unitatea de măsură în Windows. Ele se vor completa automat în momentul în care se va "aşeza" pe ecran controlul.

Page 118: 2.VBA_SC4

II-118

� Access foloseşte şi celelalte setări din Widows | Control Panel | Regional Settings ca punctul zecimal, formatul pentru oră şi dată, perioada anului din 2 cifre etc.

� Unităţile de măsură folosite în Access sunt: − Pixel – unitate dependentă de rezoluţia ecranului. − Inches sau Cm – în funcţie de setarea din Windows. Se foloseşte de

obicei în paginile de proprietăţi – 1 Inch=2,54 cm. − Punct – 72/ inch − Twips – 1440/inch, 567/cm, 20/punct. Se folosesc când se introduc prin

VBA dimensiuni pentru controale.

� Pagina DATA

• Control Source – Numele câmpului (din tabela sau cererea ataşată la formular sau raport) de care se leagă controlul. Este cea mai importantă proprietate a controlului.

Este posibilă şi legarea controlului de o expresie (câmp calculat). Pentru aceasta se va pune <=expresie> la Control Source. În felul acesta se pot introduce calcule cu câmpurile din înregistrare, se pot folosi funcţii standard sau utilizator (publice, din obiectul Module) sau chiar funcţii agregate de domeniu cu date din alte tabele. Exemplu. Avem un formular care în zona de Detail are două controale legate, Pret şi Cantitate şi un control Valoare, care la Control Source are: =[Pret]*[Cantitate]. În acest fel mereu vom avea în controlul Valoare produsul datelor din celelalte două controale, care la rândul lor vor avea valorile câmpurilor din înregistrările tabelei ataşate.

De asemenea putem lucra cu controale nelegate (unbound). În acest caz de obicei vom introduce date în control prin cod VBA, prin proprietatea dinamică (nu se poate seta decât când formularul este în execuţie) – Value, care este implicită (dacă nu se specifică explicit nici o proprietate atunci cea implicită –Value – va fi folosită). Această proprietate este Input / Output.

� În faza de proiectare, în interiorul controlului este afişată valoarea proprietăţii Control Source.

• Input Mask, Default Value, Validation Rule, Validation Text – Funcţionează la fel ca la proprietăţilor tabelelor. Dacă nu se completează se preiau setările făcute câmpului respectiv la crearea tabelei. Dacă se setează în formular aceste proprietăţi atunci acestea sunt valabile numai în acest obiect (formular), nemodificându-se proprietăţile tabelei.

Page 119: 2.VBA_SC4

II-119

� La Default Value, Validation Rule, Validation Text putem să ne referim şi la alte nume de obiecte accesibile, spre deosebire de tabele în care nu puteam să ne referim la alt câmp.

• Enabled, Locked: Permisiunea de intrare în control, respectiv de modificare a datelor din el. Deci există posibilitatea să se creeze controale Read Only (numai citeşte). Sunt mai multe posibilităţi:

− Dacă Enabled = Yes şi Locked = No – putem să intrăm în control (poziţionez cursorul în control) şi să modificăm datele din el;

− Dacă Enabled =No – nu putem să plasăm cursorul în control (evident nici să modificăm);

− Dacă Enabled = Yes şi Locked = Yes – se poate poziţiona cursorul în control dar nu se pot modifica datele;

− Dacă Enabled = No şi Locked = No (nu are sens) controlul apare şters;

� Pagina OTHER

• Name – Nume control. Acesta este numele obiectului pe care îl folosim când vrem să ne referim la acest control. Deşi nu este obligatoriu este bine ca în cazul controlului legat numele lui şi al câmpului să fie acelaşi.

• Status Bar Text – Când focusul ajunge în control, pe bara de stare (care se găseşte în partea de jos a ecranului) va apare textul introdus aici.

• Tab Stop – În momentul în care se termină introducerea datelor într-un control, focusul se va poziţiona pe următorul control din secţiune care are setată această proprietate cu Yes.

� Ordinea de parcurgere a controalelor se stabileşte prin comanda Tab Order. Aceasta se găseşte în meniul contextual sau în View şi permite aşezarea controa-lelor din secţiuni în ordinea dorită prin "tragere".

• Auto Tab – Trecerea de la un control la altul se face când: − se apasă pe tasta <ENTER> sau <TAB>. − dacă Auto Tab = Yes atunci trecerea la următorul control se va face şi automat în momentul în care s-au completat toate datele din acesta conform formatului specificat. Astfel dacă avem un control legat la un câmp de tip text cu lungimea de 3 caractere, după introducerea celui de-al treilea caracter, fără să se apese pe <ENTER> sau <TAB> se va trece automat la următorul control stabilit prin ordinea tab.

Page 120: 2.VBA_SC4

II-120

• Enter Key Behavior – Dacă această proprietate este = New Line in Field, atunci la apăsarea lui <ENTER> cursorul se va poziţiona pe următoarea linie din control, iar trecerea la următorul control se va face numai prin apăsarea tastei <TAB>. Evident proprietatea are sens dacă controlul are mai multe rânduri.

• Shortcut Menu Bar – Se poate crea un meniu contextual specific pentru control. Acesta se face prin comanda Customize.

• Control Tip Text – Va apare textul introdus în această proprietate când se poziţionează mouse-ul deasupra controlului.

• Allow Auto Correct – Setată pe Yes, va determina efectuarea automată a corecţiilor textului introdus, conform specificaţiilor stabilite prin meniul Tools | AutoCorrect.

� Proprietăţile implicite ale controlului Text Box

Generarea obiectelor dintr-o clasă de obiecte se face prin setarea corespunzătoare a proprietăţilor obiectului şi prin ataşarea de metode evenimentelor. În momentul în care se creează o clasă de obiecte se stabilesc practic care sunt proprietăţile, metodele şi evenimentele obiectelor care sunt create din aceasta. Obiectele provenite dintr-o clasă vor avea evident aceleaşi metode, evenimente şi tipuri de proprietăţi. Ele vor forma o colecţie de obiecte, care este privită ca un tablou cu o dimensiune (vector), în care elementele sunt indexate (de la 0). Crearea controlului Text Box se face prin generarea acestuia din clasa de obiecte cu acelaşi nume, prin luarea şi plasarea controlului din ToolsBox. În momentul creării acestui obiect, evident proprietăţile lui trebuie setate la anumite valori, implicite (default), urmând ca proiectantul să le personalizeze ulterior în funcţie de contextul în care va fi folosit. Aceste proprietăţi implicite se pot modifica prin acţionarea în caseta tab: Default Text Box, care se poate obţine prin selecţia de pe ToolsBox a controlului şi acţionarea pictogramei de proprietăţi.

Evident la generare, controlul trebuie să primească un nume, unic, care va fi constituit din numele controlului plus un număr de ordine în cadrul formularului sau raportului unde este plasat.

Din proprietăţile implicite mai interesante sunt: − Auto Label – yes, ataşează o etichetă controlului; − Add Colon – yes, eticheta se va termina cu două puncte; − Label X, Label Y – poziţia etichetei faţă de control;

Page 121: 2.VBA_SC4

II-121

II.2.2.2.b) Proprietăţile dinamice ale controlului Text Box

Proprietăţile unui obiect pot fi statice şi/ sau dinamice. Proprietatea statică este proprietatea care se poate modifica când formu-

larul este în proiectare, prin caseta tab. Proprietatea dinamică este proprietatea care poate fi modificată în

momentul când obiectul este în execuţie, în general prin cod VBA, lansat de obicei printr-o procedură eveniment.

Majoritatea proprietăţilor sunt atât statice cât şi dinamice. Anumite pro-prietăţi sunt numai dinamice, ele neregăsindu-se în caseta tab a controlului.

Dintre proprietăţile dinamice, cea mai importantă este VALUE. Această proprietate este implicită, numele ei putând fi omis. Ea este Input/ Output, putând fi deci şi citită şi scrisă. Reprezintă valoarea care se găseşte în control. Dacă acesta este legat, această valoare se va găsi şi în câmpul ataşat.

� Dacă controlul este calculat, atunci Value nu mai poate fi decât citită. • SelLength, SelStart, SelText – Se folosesc pentru a manevra cursorul

şi valoarea din interiorul unui control Text Box. Sunt proprietăţi Input/ Output. − SelStart – reprezintă poziţia de start a cursorului în control; − SelLength – reprezintă lungimea textului selectat din control; − SelText – reprezintă valoarea textului selectat.

Exemplu. Următoarea secvenţă de instrucţiuni înlocuieşte în controlul UM, primele 3 caractere dacă sunt "xxx" cu "buc".

UM.SetFocus ' plasează focusul în cursor Me!UM.SelStart = 0 ' numerotarea începe de la 0 Me!UM.SelLength = 3 ' selectează primele 3 caractere din control _ (0, 1, 2) If Me!UM.SelText = "xxx" Then Me!UM.SelText = "buc" ' proprietatea SelText folosită şi Input şi Output

II.2.2.2.c) Evenimentele controlului Text Box

• Before Update – Acest eveniment se produce după ce a avut loc o modificare a datelor în control, dar care nu este definitivă, putând fi anulată prin setarea parametrului procedurii eveniment ataşate, Cancel=True. În acest caz, la terminarea procedurii eveniment, focusul rămâne în control până când utilizatorul introduce o altă valoare care nu mai produce Cancel=True.

Acest eveniment se foloseşte de obicei pentru a executa o metodă mai complexă de verificare a datelor introduse în control, care depăşeşte posibilităţile oferite de proprietatea Validation Rule.

• After Update – Se produce imediat după evenimentul Before Update, modificările fiind acum însă definitive, nemaiputând fi anulate. Se foloseşte când

Page 122: 2.VBA_SC4

II-122

valoarea introdusă aici va furniza datele necesare calculelor din alte controale. • On Change – Se produce după fiecare tastare în interiorul controlului. • On Enter şi On Exit – Se produc la intrarea şi la ieşirea din control. • Got Focus şi Lost Focus – Se produc la primirea/ pierderea cursorului

în/ din control. • On Click, On Dbl Click, On Mouse Down, On Mouse Up, On

Mouse Move – Se produc la acţiunea respectivă a mouse-ului pe control. • On Key Down, On Key Up, On Key Press – Se produc la acţiunea

respectivă a tastaturii când focusul se găseşte în control.

II.2.2.2.d) Metodele controlului Text Box

Metodele cele mai folosite sunt: • Set Focus – plasează focusul în controlul text. • Requery, Recalc – acelaşi efect ca şi la metodele similare de la

formulare, dar referitoare numai la controlul asupra căruia se aplică metoda. Exemplu. Before Update, After Update, Set Focus

În formularul de mai sus dorim ca în câmpul "Cantitate" să avem o

valoare în intervalul: − [10. 000.. 100. 000] dacă "UM" = buc; − [100.. 10. 000] dacă "UM" = Kg; − [1.. 10] dacă "UM" = Tone. Dacă "UM" nu e completată corespunzător atunci se va introduce "null" la

"Cantitate" şi "UM" şi se va trimite focusul în controlul "UM". Private Sub Cantitate_BeforeUpdate (Cancel As Integer)

If Me!UM = "buc" Then If Me!Cantitate>=10000 And Me!Cantitate<=100000 Then ' corect… instr. vidă Else

Cancel = True ' incorect se anulează evenimentul, deci focusul _ rămâne în control

End If ElseIf Me!UM = "Kg" Then ' o altă formă a instrucţiunii IF _ asemănătoare CASE

If Me!Cantitate >= 100 And Me!Cantitate <= 10000 Then ' corect… instr. vidă

Page 123: 2.VBA_SC4

II-123

Else ' incorect Cancel = True'anulează evenimentul - focusul rămâne în control

End If ElseIf Me!UM = "Tone" Then 'corect… instr. vidă

If Me!Cantitate >= 1 And Me!Cantitate <= 10 Then Else ' incorect

Cancel = True'anulează evenimentul - focusul rămâne în control End If

Else ' partea ELSE de la instr. IF, ELSEF…se ajunge aici numai dacă _ UM este incorectă

' Me!Cantitate = Null Această instrucţiune nu se poate executa _ deoarece nu se poate schimba valoarea din control până când _ modificarea nu devine definitivă. Deci vom fi nevoiţi să introduce _ această instrucţiune în procedura eveniment AfterUpdate, a _ aceluiaşi control. Me!UM = Null ' această instrucţiune funcţionează pentru că se _ modifică datele din alt control

End If If Cancel Then MsgBox "Cantitatea nu este corelată cu UM" ' se afişează un mesaj dacă în acest moment CANCEL = TRUE _ pentru ca utilizatorul să ştie că a greşit

End Sub

Private Sub Cantitate_AfterUpdate () If IsNull (Me!UM) Then ' testarea valorii null se poate face numai _ cu funcţia IsNULL

Me!Cantitate = Null ' Numai în acest moment se pot modifica _ datele din acest control Me!UM. SetFocus ' Metodă a controlului UM, prin care acesta _ preia focusul MsgBox "Completati corect mai intii UM"

End If End Sub

II.2.2.3. Obiectul Control – Combo_Box (lista ascunsă)

Acest control este asemănător cu Text Box, dar are posibilitatea derulării unei liste din care se pot prelua datele care se introduc.

� În momentul când într-o tabelă un câmp a fost creat cu proprietatea Look Up, iar acel câmp e legat într-un formular la un control Combo Box,

Page 124: 2.VBA_SC4

II-124

proprietăţile definite în tabelă nu trec automat şi în formular. Acest lucru se face însă automat dacă formularul este creat cu WIZARD-ul de formulare.

Controlul Combo Box are aceleaşi proprietăţi şi evenimente ca ale lui Text Box. În plus mai sunt proprietăţi şi evenimente, care se referă la lista ascunsă.

II.2.2.3.a) Proprietăţile specifice controlului Combo Box

� În pagina DATA sunt:

• Row Source Type – Tipul sursei de date care va fi afişat în lista derulantă.

Aici se foloseşte de obicei: − Table/ Query – câmpuri din altă

tabelă sau cerere (sau o cerere introdusă direct în SQL);

− Value List – listă de valori ca în exemplu; • Row Source – În cazul în care Row Source Type= − Table/ Query – este numele unei tabele, cereri sau direct o instrucţiune

SQL care generează o cerere (ca la legarea formularului la o tabelă); − Value List – este o listă de valori, separate prin <;> • Bound Column – Numărul coloanei de legătură (datele din această

coloană vor fi preluate ca valoare pentru control) • Limit To List – Dacă proprietatea este Yes nu se vor putea introduce în

control decât datele care se găsesc în lista derulantă iar dacă este No, se pot introduce şi alte date decât cele din listă.

• Auto Expand – Dacă proprietate este Yes, atunci se caută şi se afişează cea mai apropiată denumire din listă care să aibă în partea de început caracterele introduse în control, până în acel moment, de la tastatură.

� În pagina FORMAT sunt următoarele proprietăţi:

• Column Count – Numărul de coloane care apar la desfacerea listei.

• Column Head – Dacă se afişează sau nu denumirea coloanelor. • Column Widths – Lăţimea coloanelor. Se separă cu <;>. • List Rows – Numărul de rânduri care se afişează când se desface lista.

Dacă lista are mai multe rânduri decât sunt setate a se afişa, vor apare barele de derulare verticale.

Page 125: 2.VBA_SC4

II-125

• List Width – Lăţimea listei derulante. Dacă aceasta este mai mică decât suma tuturor coloanelor afişate, vor apare barele de derulare verticale. Setată pe Auto, lăţimea listei va fi la fel ca lăţimea controlului Combo Box.

� Toate dimensiunile se dau în unitatea de măsură setată în Windows. Această caracteristică este generală în tot mediul Access. Reamintim că în VBA, dimensiunile sunt cerute în Twips. Exemplu. Într-un formular se găsesc două controale Combo Box, cu numele: CFm şi CControl.

La deschiderea formularului (evenimentul Open) se va introduce în lista ascunsă a lui CFm – proprietatea RowSource – numele tuturor formularelor deschise din acel moment.

La introducerea unei valori în CFm (evenimentul AfterUpdate a lui CFm), se va introduce în lista ascunsă a lui CControl – proprietatea RowSource – numele tuturor controalelor din formularul al cărui nume este în CFm.

Private Sub Form_Open(Cancel As Integer) ' La deschiderea formularului – evenimentul Open al formularului _ se va configura lista ascunsă a controlului Combo Box CFm Dim FM As Form Dim sForm As Variant ' Într-un string sForm, se introduc formularele deschise (separate cu ;) _ Acesta se va introduce în proprietatea RowSource _ a controlului ComboBox CFm, configurat ca listă de valori _ (proprietatea RowSourceType="Value List") sForm = Empty For Each FM In Forms ' Se parcurge toată colecţia formularelor deschise sForm = sForm & FM.NAME & ";" Next FM If IsEmpty(sForm) Then ' Nu există nici un formular deschis _ – acest lucru nu este posibil deoarece cel puţin _ formularul în care se găseşte codul acesta e deschis Me.CFm.RowSource = "Nici un formular deschis??!!" Else ' Se configurează cu numele formularelor deschise _ lista de valori a controlului Combo Box Me.CFm.RowSource = Left(sForm, Len(sForm) - 1) End If

Page 126: 2.VBA_SC4

II-126

End Sub Private Sub CFm_AfterUpdate() ' Evenimentul AfterUpdate al lui CFm _ Se produce după ce se introduce definitiv _ o valoare în CFm – aceasta reprezentând _ numele unui formular deschis Dim Ct As Control Dim sCtl As Variant 'Se configurează un string cu controalele existente (separate cu ;) _ în formularul deschis al cărui nume este în Me.CFm _ şi cu care se configurează proprietatea _ RowSource a controlului Combo Box CControl configurat _ ca listă de valori (proprietatea RowSourceType="Value List") sCtl = Empty For Each Ct In Application.Forms(Me.CFm).Controls 'Se parcurge toată colecţia de controale a formularului _ al cărui nume este în Me.CFm sCtl = sCtl & Ct.NAME & ";" Next Ct If IsEmpty(sCtl) Then ' Nu există nici un control Me.CControl.RowSource = "Nu este nici un Control??!!" Else ' Se configurează cu numele controalelor _ lista de valori a controlului Combo Box CControl Me.CControl.RowSource = Left(sCtl, Len(sCtl) - 1) End If End Sub

II.2.2.3.b) Evenimentul specific controlului Combo Box.

• Not In List – Evenimentul se produce dacă Limit To List=Yes. Se foloseşte când dorim ca atunci când utilizatorul încearcă introducerea unei valori din afara listei, după o confirmare, această valoare să completeze lista derulantă,

Page 127: 2.VBA_SC4

II-127

şi să poată fi folosită în continuare, ca în EXEMPLUL următor, care va crea această posibilitate pentru controlul combo "UM" prezentat mai sus.

Private Sub UM_NotInList(NewData As String,Response As Integer) Dim RaspunsUtilizator As Integer ' variabila în care stocăm răspunsul _ utilizatorului: NewData – parametru de intrare care va avea valoarea datei introduse în control şi care nu s-a găsit în listă. Response – parametru de ieşire care poate lua 3 valori care vor fi explicate mai jos RaspunsUtilizator = MsgBox ("Doriti introducerea în lista _ derulanta a valorii " & NewData & " ?", _ vbQuestion + vbYesNoCancel) ' generează o casetă cu 3 butoane If RaspunsUtilizator = vbYes Then

' completez proprietatea cu noua valoare Me!UM. RowSource = Me!UM. RowSource & ";" & NewData Response = acDataErrAdded

' dacă se dă valoarea de mai sus se va determina: _ – blocarea mesajului standard al sistemului, _ – se va face automat requery pe control pentru ca acesta să-şi modifice lista derulantă

ElseIf RaspunsUtilizator = vbNo Then ' în cazul în care se dă NO, atunci se va bloca mesajul standard de_ eroare

Response = acDataErrContinue Me!UM = Null ' se şterge valoarea din control, aşteptându-se o nouă _ valoare

Else ' cazul cancel ' în cazul în care se dă NO, atunci se va afişa mesajul standard de _ eroare şi se va cere introducerea unei date din lista derulantă Response = acDataErrDisplay ' e implicită această valoare, deci _ poate lipsi instrucţiunea

End If End Sub

II.2.2.4. Obiectul Control – List_Box (listă derulantă)

List Box este asemănătoare cu combo box, dar lista nu este ascunsă, ci este afişată tot timpul.

II.2.2.5. Obiectul Control boolean – Option_Button, Check_Box, Toggle_Button

Sunt controale booleene. În Access valoarea booleană poate lua 3 valori şi anume:

Page 128: 2.VBA_SC4

II-128

− True (adevărat); − False (fals); − NULL (nedeterminat – nu se ştie). Pentru aceasta aceste butoane au o proprietate: Triple State. Dacă Triple State are valoarea No, butonul are 2 stări: True şi False; iar

dacă este setată pe Yes, butonul va avea toate cele trei stări. În acest din urmă caz controlul trebuie legat numai de un câmp integer sau long. Valoarea NULL se va reprezenta printr-o imagine ştearsă a controlului.

II.2.2.6. Obiectul Control – Option_Group

Option Group este un control în care se pot introduce două sau mai multe dintre controale booleene prezentate mai sus (toate vor fi de acelaşi fel).

Specific acestui grup este că numai unul dintre controalele din interiorul lui se poate poziţiona pe True, celelalte devenind automat False.

Un control individual boolean se leagă aşa cum am văzut la câmpuri de tip boolean sau integer, putând lua două sau trei valori booleene.

Câmpul de care se leagă Option Group este o dată de tip integer. Valoarea introdusă va fi în general numărul de ordine în grup al controlului boolean care este pe True.

Pe Tools Box se află un buton pentru activarea unui Wizard. Dacă este apăsat atunci când se face controlul grup de opţiuni, sistemul va îndruma configurarea lui, punând întrebări referitoare la numele controlului Option Group, la ce fel şi câte controale booleene să conţină, la ordinea şi valoarea butoanelor în grup, la câmpul de legătură şi care dintre butoane va fi implicit pe True.

II.2.2.7. Obiectul Control – Label (etichetă)

Este cel mai utilizat control nelegat de un câmp. Proprietatea cea mai importantă a controlului este Caption, care va conţine textul afişat de control. Forma controlului se configurează la fel ca la Text Box.

II.2.2.8. Obiectul Control grafic – Line, Rectangle, Picture

Aceste controale nu sunt legate de câmpuri. Ele vor crea figura specificată în titlu. Controlul Rectangle poate fi şi umplut în interior.

II.2.2.9. Obiectul Control – Command_Button

În general se ataşează evenimentului Click o metodă care să efectueze o comandă specifică.

Page 129: 2.VBA_SC4

II-129

II.2.3. Obiectul DoCmd

Obiectul DoCmd conţine metode care permit execuţia majorităţii comen-zilor puse la dispoziţie în MS Access.

Astfel există posibilitatea deschiderii sau închiderii unor obiecte (formulare sau rapoarte), transferului de date cu alte aplicaţii (Excel, Access, Fox etc.), setării valorilor unor controale, schimbării cursorului mouse-ului într-o clepsidră (hourglass) etc.

Execuţia unei comenzi Access se face astfel:

[Application.]DoCmd.NumeMetoda [arg1, arg2, ...] în care argumentele sunt în funcţie de metoda executată; aceştia pot fi obligatorii sau opţionali, caz în care există valori implicite pentru ei.

Câteva metode ale obiectului DoCmd sunt prezentate în continuare: • OpenForm,OpenReport,OpenQuery,OpenTable,OpenModule –

permit deschiderea obiectului Access specificat. • Close – închid un obiect Access precizat în argument (Form, Report,

Query, Table, Module). • DeleteObject – şterg un obiect Access, precizat în argument (Form,

Report, Query, Table, Module). • TransferDatabase, TransferSpreadsheet, TransferText – exportă/

importă obiecte între MS Access şi MS Access, MS Excel sau MS-DOS text. • Maximize – permite mărirea la maxim a ferestrei active. • Minimize – permite micşorarea şi plasarea pe bară a ferestrei active. • GoToRecord – permite ca într-o tabelă, formular sau cerere să se mute

cursorul înregistrării curente pe o anumită înregistrare. • GoToControl – permite ca într-o tabelă, formular sau cerere, să se

mute focusul pe un anumit control (câmp) din cadrul înregistrării curente. • FindRecord – permite poziţionarea pe prima înregistrare care respectă

un criteriu de selecţie. • FindNext – permite poziţionarea pe următoarea înregistrare care

respectă un criteriu de selecţie. • RunCommand – permite execuţia unei comenzi Access care se găseşte

pe bara de meniuri, pe toolbar sau în meniul contextual. • RunMacro, RunSQL – permite execuţia unui Macro sau a unei cereri

acţiune. • Hourglass – transformă cursorul mouse-ului într-o clepsidră. • SetWarnings – anulează mesajele care apar la execuţia unei acţiuni. • SelectObject – permite setarea focusului pe un obiect Access care îl

poate primi, făcându-l eventual şi vizibil.

Page 130: 2.VBA_SC4

II-130

• CopyObject – permite copierea unui obiect de date în aceeaşi (cu alt nume) sau altă aplicaţie Access.

• Save – permite salvarea unui obiect Access în diferite formate (vezi comanda Save As din meniul File)

• OutputTo – permite trimiterea unor date Access (datasheet, form, report, module) în fişiere de tip Microsoft Excel 97 (*.xls), MS-DOS text (*.txt), rich-text (*.rtf), HTML, Microsoft ActiveX Server (*.asp) etc.

• SendObject – permite ataşarea unor date Access (datasheet, form, report, module) la un e-mail.

• Restore – permite restaurarea la dimensiunea anterioară a unei ferestre maximizate sau minimizate. Dacă o fereastră este minimizată, înainte de aplicarea metodei Restore, trebuie selectată cu SelectObject.

• Quit – provoacă ieşirea din MS Access, cu eventuala salvare a obiec-telor modificate.

• Requery – efectuează metoda requery pentru un control specificat în argumente.

• Rename – redenumeşte un obiect de date. • ApplyFilter – permite aplicarea unei selecţii asupra unor înregistrări,

printr-un filtru, cerere sau clauza Sql Where. • ShowAllRecords – elimină selecţia produsă prin ApplyFilter. • Beep – emite un semnal sonor. • Echo – permite sau nu afişarea mesajelor sistem (Echo) pe bara de

stare. Dacă Echo este off, atunci se poate plasa un text propriu pe bara de stare. • CancelEvent – permite anularea evenimentului care a produs execuţia

acestei acţiuni. • ShowToolbar – face On/ Off un anumit toolbar.

Exemplu. ' deschide formularul For şi se poziţionază înregistrarea curentă pe_ adăugare de înregistrare

DoCmd.OpenForm "For", acNormal DoCmd.GoToRecord,, acNewRec DoCmd.Hourglass True ' face mouse-ul clepsidră

' închide formularul For DoCmd.Close acForm, "For"

II.2.4. Obiectul Screen

Obiectul Screen, prin proprietăţile sale, accesează obiectele Access (form, report, control, datasheet) care deţin în acel moment focusul, deci sunt în fereastra activă.

Page 131: 2.VBA_SC4

II-131

Aceste proprietăţi sunt Read Only şi în ele se va găsi referinţa către obiectele specificate care deţin focusul.

� Cu obiectul Screen, nu este posibil ca să se determine ca un anumit obiect să preia focusul. Acest lucru este posibil prin metoda SelectObject a obiectului DoCmd, sau prin metoda SetFocus a unor obiecte.

Printre proprietăţile obiectului Screen, enumerăm: • ActiveForm – identifică şi creează o referinţă către obiectul Form,

care deţine în acel moment focusul. • ActiveReport – identifică şi creează o referinţă către obiectul Report,

care deţine în acel moment focusul. • ActiveDatasheet – identifică şi creează o referinţă către obiectul

Datasheet, care deţine în acel moment focusul. • ActiveControl – identifică şi creează o referinţă către obiectul

Control, care deţine în acel moment focusul. • PreviousControl – crează o referinţă către ultimul control care a avut

focusul.

� Aceste proprietăţi, aşa cum s-a arătat, întorc referinţe către obiectele specificate. Ele se vor comporta în continuare ca nişte variabile obiect, permiţând accesarea proprietăţilor şi metodelor acestora.

� Există posibilitatea ca proprietatea specificată în obiectul Screen să nu poată fi accesată. În acest caz sistemul va provoca o eroare de execuţie. De exemplu, ca PreviousControl să întoarcă o referinţă este necesar să se fi deschis cel puţin un formular şi focusul să fi fost deţinut de cel puţin două controale din acesta. Dacă nu sunt îndeplinite cele două condiţii se produce eroarea de execuţie cu nr. 2483. Exemplu. Într-un formular, la apăsarea butonului de comandă BCMD, se va afişa un mesaj prin care se specifică, dacă se poate, numele ultimului control care a fost accesat şi valoarea din acesta.

Private Sub BCMD_Click() Dim Ctl As Control Dim NumeCtl As Variant Dim ValCtl As Variant ' Nr. Eroare 2483 – nu s-au accesat minim două controale, deci nu există _ un control precedent Const NoPrevious = 2483 ' Nr. Eroare 2427 – controlul nu are definită proprietate VALUE Const NoValue = 2427 On Error GoTo Process_Err ' dacă va apare o eroare de execuţie, _ se va continua rutina de la eticheta Process_Err

Page 132: 2.VBA_SC4

II-132

' Var. obiect Ctl, va referi, dacă se poate, precedentul control Set Ctl = Application.Screen.PreviousControl NumeCtl = Ctl.NAME ValCtl = Ctl.Value MsgBox "Precedentul control " & vbCr & _ "-Nume=" & NumeCtl & vbCr & _ "-Valoare=" & ValCtl Process_Bye: ' Aşa se declară o etichetă Exit Sub Process_Err: If err.Number = NoPrevious Then MsgBox "Focusul nu a fost pe cel puţin două controale" ElseIf err.Number = NoValue Then MsgBox "Controlul " & NumeCtl & "nu are proprietatea VALUE" Else MsgBox "Alta Eroare " & err.Number & "/ " & err.Description End If Resume Process_Bye 'Anulează eroarea şi se duce la etichetă Process_Bye End Sub

Exemplu. La apăsarea pe butonul de comandă CtActiv, să se afişeze formularul şi controlul care au focusul.

Private Sub CtActiv_Click() Dim Frm As Form, Ctl As Control ' Întoarce referinţa către obiectul Form activ Set Frm = Screen.ActiveForm MsgBox Frm.NAME & "este formularul activ" ' Întoarce referinţa către controlul care are focusul Set Ctl = Screen.ActiveControl MsgBox Ctl.NAME & "este controlul activ " & vbcr _ "-din formularul " & Frm.NAME End Sub

Page 133: 2.VBA_SC4

II-133

II.3. Modelul DAO – Data Access Objects

II.3.1. Modelul DAO – Structura ierarhic arborescentă

Modelul DAO – Data Access Objects (obiecte pentru acces la date) permite ca printr-un limbaj de programare să se acceseze o bază de date – locală (din aplicaţia curentă) sau din altă aplicaţie (fişier mdb/ mde). Ea permite gestionarea structurii (schema) şi a informaţiilor acesteia.

Modelul DAO conţine toate colecţiile de obiecte şi obiectele bazei de date, precum şi o serie de rutine, constante, tipuri de date, help-uri etc., necesare manipulării acestora.

Structura acesteia este dată în figura de mai jos.

DBEngine

Workspace(1)

Errors

Workspace(0)

Workspaces

Tabela_A

N

A

Tabela_A Tabela_B

N Numar

PrimaryKey

N

A

N

Legendă • Obiecte

• Colecţii

Groups Users Databases

Current DB

TableDefs QueryDefs Relations RecordSets Containers

Tabela_B Cerere_A 0-Databases Tabela_A Tabela_B Tabela_A

1-Forms

4-Reports

3-Relationships

2-Modules

7-Tables

5-Scripts

6-SysRel

Fields Fields Fields Fields

Fields

Fields

Indexes Parameters

Documents

A

A

A

N

A1

Page 134: 2.VBA_SC4

II-134

Câteva din caracteristicile modelului DAO sunt prezentate în continuare. • În primul rând modelul DAO are o structură ierarhic arborescentă, al

cărui nivel superior îl constituie obiectul DBEngine. Acesta este deosebit faţă de celelalte obiecte din modelul DAO. El este singular şi nu aparţine nici unei colecţii, fiind tratat ca o excepţie.

• Fiecare obiect din structura DAO face parte dintr-o colecţie de obiecte. De asemenea el conţine la rândul său una sau mai multe colecţii de obiecte. Exemplu. Obiectul Tabela_A, este un obiect de tip TableDef, care face parte din colecţia TableDefs, a bazei de date locale a aplicaţiei. El conţine două colecţii de obiecte, Fields şi Indexes.

• Obiectele (cu excepţia celor din colecţia Errors) au proprietăţi Property care sunt constituite în colecţia de proprietăţi a obiectului respectiv – Properties.

• Fiecare obiect are o proprietate implicită. De obicei aceasta este propri-etatea Value.

• Toate obiectele îşi păstrează numele în proprietatea Name. • Obiectele (excepţie obiectele Error) au posibilitatea ca prin metode de

tip Create şi Append să creeze şi adauge obiecte la colecţiile de obiecte din structura lor. De asemenea cu metoda Delete se pot şterge obiecte din colecţii.

• Unele obiecte sunt create deja (TableDef de exemplu) şi se folosesc ca atare indicându-se numele lor (cu regulile obişnuite de calificare), pe când altele (Database sau Recordset), ca să fie folosite, mai întâi trebuie deschise cu metode de tip Open.

• Obiectele care se deschid au metode de închidere Close. Totuşi acestea se pot închide şi automat, atunci când se termină modulul în care au fost declarate.

• DAO conţine 17 tipuri diferite de obiecte. • VBA va conţine pentru toate tipurile de colecţii, tipuri de date care au

chiar numele colecţiei. (De exemplu se pot creea variabile de tip TableDefs, pentru colecţia care conţine structura tuturor tabelelor din baza de date.)

• Pentru obiectele care aparţin unei colecţii, VBA are definite alte tipuri de date care au tot numele colecţiei, dar la singular. (De exemplu se poate folosi o variabilă de tip TableDef, pentru a se introduce structura unei tabele).

II.3.2. Obiectul DBEngine

DBEngine, aşa cum am arătat, este obiectul din vârful modelului ierarhic arborescent DAO.

Folosirea lui într-o aplicaţie Access pentru referirea obiectelor din DAO este opţională, el fiind considerat implicit.

DBEngine conţine întreaga structură DAO. El este obiectul către care trebuie făcut transferul de date, dacă se doreşte folosirea unei baze de date Access, din alte aplicaţii care au implementată tehnologia Automation (de exemplu: MS Excel, MS Word, Visual Basic etc.)

Page 135: 2.VBA_SC4

II-135

DAO nu oferă posibilitatea creării altor obiecte DBEngine. DBEngine conţine două colecţii de obiecte: Workspaces şi Errors.

II.3.3. Colecţia Workspaces – Spaţiul (mediul) de lucru

Workspace reprezintă suportul în care o bază de date poate fi utilizată, împreună cu sistemul de securitate folosit.

DAO poate funcţiona în două medii specifice unor anumite tipuri de baze de date, şi anume:

• Microsoft Jet Workspace, care permite folosirea motorului Microsoft Jet, în care se pot utiliza baze de date Access (fişiere .mdb) sau surse ISAM: FoxPro, DBase, Paradox, Lotus.

În felul acesta se pot crea aplicaţii care pot "lega" mai multe tipuri de baze de date.

• ODBCDirect Workspace, prin care se pot accesa servere specializate de baze de date (de exemplu Microsoft SQL) prin metoda ODBC (Open Data Base Connectivity).

� Aplicaţia server/ client

Este o metodă de realizare a unei aplicaţii, în care cereri sau proceduri sunt formulate de aplicaţia client, urmând ca execuţia lor să se facă pe serverul de aplicaţie, care va conţine baza de date (back-end server).

Între un server de aplicaţie şi un server de fişiere există o diferenţă clară. Următorul exemplu va lămuri acest lucru.

Presupunem că avem o bază de date (o colecţie de date specifice unei anumite activităţi) şi nişte programe (aplicaţii) care gestionează datele respective, adică le actualizează (adăugări, ştergeri sau modificări) sau extrag informaţiile necesare derulării activităţii respective.

Această aplicaţie va trebui accesată de mai mulţi utilizatori. Astfel putem avea o companie de aviaţie şi pentru rezervarea locurilor la

un zbor, mai multe agenţii ale acesteia, răspândite geografic, trebuie să ştie precis care este starea ocupării locurilor, iar în cazul unei noi rezervări, să informeze imediat acest lucru.

Evident trebuie să avem o reţea de calculatoare, cu baza de date a zborurilor plasată pe un anumit calculator, de unde să fie accesată "on line", de clienţi (în special agenţiile de turism).

Există în continuare două posibilităţi de realizare a acestui lucru şi anume cu un server de fişiere sau un server de aplicaţii.

− În primul caz, al serverului de fişiere, vom plasa pe un server baza de date, iar pe toate staţiile de lucru de la agenţii, programele aplicaţiei. O cerere de prelucrare se va desfăşura în felul următor: se vor aduce prin reţea, de la serverul cu datele la staţia de lucru, toate informaţiile de la toate zborurile companiei, aici se vor extrage datele de la zborul

Page 136: 2.VBA_SC4

II-136

care interesează, după care, dacă s-a făcut o rezervare, va fi trimis acest lucru imediat la serverul de date. Observăm că pe reţea se vor transmite atât informaţii utile cât şi cele care nu sunt necesare la un moment dat. O astfel de aplicaţie se numeşte aplicaţie client. − În al doilea caz, al serverului de aplicaţii, în afara bazei de date, pe server, vom avea şi o parte din programele aplicaţie şi anume cele care accesează direct baza de date. La o staţie de lucru – unde există cealaltă parte a programelor aplicaţiei şi anume interfaţa cu utilizatorul – o cerere de prelucrare (datele despre un zbor) va fi trimisă serverului de aplicaţii. Acesta va efectua extragerea din baza de date numai a informaţiilor necesare, pe care le va trimite pe reţea înapoi utilizatorului. Observăm în acest caz, reducerea substanţială a informaţiei transmise prin reţea, ceea ce face aplicaţia mult mai performantă, chiar dacă este mult mai complexă. O astfel de aplicaţie se numeşte server/ client.

� În cadrul acestui capitol, se va prezenta numai Microsoft Jet Workspace. Implicit, DAO are un spaţiu (mediu) de lucru, #Default Workspace#

{care fiind primul din colecţia Workspaces – se poate referi şi Workspaces(0)} de tip Microsoft Jet, în care este plasată şi baza de date locală.

� Când se face referire la baza de date locală, referirea obiectelor poate să nu conţină nici DBEngine nici spaţiul (mediul) de lucru – Workspaces(0), deoarece amândouă sunt implicite.

Prin metoda DBEngine, CreateWorkspace, se pot creea şi alte obiecte Workspace, ce pot fi ataşate în memoria colecţiei Workspaces prin metoda Append. Exemplu. De creare a două obiecte Workspace, unul de tip Microsoft Jet, celălalt ODBCDirect şi de vizualizare a proprietăţilor acestora.

Sub Prop_Workspace() Dim WS1 As Workspace Dim WS2 As Workspace Dim WS As Workspace Dim PR As Property ' obiect din colecţia Properties ' Se crează două spaţii de lucru cu metoda CreateWorkspace _ – Microsoft Jet _ – ODBCDirect ' Parametrii sunt în ordine: _ 1. Numele spaţiului de lucru _ 2. Numele utilizatorului care are acces la el _ 3. Parola _ 4. Tipul mediului de lucru, şi anume se foloseşte constanta: _ – dbUseODBC – Mediu ODBCDirect _ – dbUseJet – Mediu Jet

Page 137: 2.VBA_SC4

II-137

Set WS1 = DBEngine.CreateWorkspace("WorkspaceODBC", _ "admin", "", dbUseODBC) Set WS2 = DBEngine.CreateWorkspace("WorkspaceJet", _ "admin", "", dbUseJet) ' După crearea unui spaţiu de lucru ODBC acesta se ataşează _ în memoria colecţiei Workspaces cu metoda Append Workspaces.Append WS1 ' Nu s-a folosit DBEngine, deoarece e implicit Workspaces.Append WS2 ' Colecţia Workspace şi proprietăţile obiectelor din aceasta For Each WS In Workspaces If MsgBox("Spatiul:" & WS.NAME, _ vbOKCancel + _ vbCritical) = vbOk Then On Error Resume Next ' ignoră erorile care pot apărea.... Vezi colecţia Errors For Each PR In WS.Properties MsgBox " Proprietatea:" & PR.NAME & " = " & _ PR.Value Next PR On Error GoTo 0 ' Reface sistemul de erori standard End If Next WS End Sub

Un obiect Workspace conţine 3 colecţii de obiecte, şi anume: − Databases – care va conţine unul sau mai multe obiecte Database, în fiecare putându-se deschide câte o bază de date, locală sau din afară. − Users şi Groups, prin care se implementează sistemul de protecţie al spaţiului (mediului) de lucru. Aceste obiecte nu vor fi prezentate în acest modul.

II.3.4. Tratarea erorilor de execuţie în VBA

Colecţia Errors funcţionează în contextul sistemului general de erori implementat în VBA, care va fi prezentat în cele ce urmează.

II.3.4.1. Tratarea standard a erorilor de execuţ ie produse în VBA

În momentul producerii unei erori de execuţie într-o rutină, sistemul va întrerupe execuţia şi va afişa mesajul din căsuţa alăturată, în care se poate vedea numărul erorii şi o descriere sumară a acesteia (dacă se lucrează într-un mediu Run Time – mediu de lucru pentru Access similar unui program executabil – nu se va mai afişa nici această descriere).

Page 138: 2.VBA_SC4

II-138

În continuare utilizatorul poate apăsa pe:

• Butonul End – se opreşte execuţia codului şi se reiniţializează toate variabilele aplicaţiei. Este evident că sunt şanse mici ca aplicaţia să poată fi reluată de utilizator în condiţii corecte.

• Butonul Debug – se va afişa codul de program care a generat eroarea, cursorul de instrucţiuni (linia galbenă) poziţionându-se pe instrucţiunea care a produs eroarea şi permiţând utilizatorului să depaneze eventual programul prin modificarea instrucţiunilor. Acest sistem se poate folosi numai în perioada de testare de către proiectant a aplicaţiei, păstrarea lui în exploatarea aplicaţiei fiind extrem de periculoasă.

� Butonul Debug este activ numai dacă se lucrează pe un fişier MDB, care are codul de program şi în limbajul sursă (dacă aplicaţia este într-un fişier de tip MDE, butonul este inactiv).

� Dacă se introduce în variabila A2, de tip numeric, un caracter alfabetic, atunci se va afişa mesajul prezentat mai sus. De asemenea dacă se va introduce 0 în A2 se va afişa mesajul de eroare datorită împărţirii la 0.

Public Function Eroare_Standard() As Variant ' Funcţie care va trata o eventuală eroare prin _ sistemul standard VBA de control al erorilor Dim A1 As Double Dim A2 As Double Dim R As Double A1 = 1000 A2 = InputBox("A2=") R = A1 / A2 'Dacă o eroare se va produce până aici, _ instrucţiunile ce urmează nu se vor mai executa!! MsgBox "Rezultatul lui " & A1 & "/" & A2 & "=" & R Eroare_Standard = R End Function

II.3.4.2. Tratarea erorilor de execuţie prin module specializate

VBA oferă posibilitatea ca la producerea unei erori de execuţie sistemul să dea controlul la un modul special creat de proiectant prin care să se trateze în mod corespunzător eroarea. Un astfel de modul se numeşte rutină de tratare a erorilor (Error-handling).

Page 139: 2.VBA_SC4

II-139

De asemenea, proiectanţii de aplicaţii pot folosi producerea unor erori previzibile, în vederea rezolvării mai "elegante" a unor cazuri normale de prelucrare.

Controlul erorilor de execuţie se realizează prin două instrucţiuni şi două obiecte create special în acest scop:

II.3.4.2.a) Instrucţ iunea: On Error

On Error este o instrucţiune care atunci când este întâlnită şi executată, produce asupra codului VBA care urmează după aceasta două acţiuni (indirecte):

� Dezactivarea sistemului standard de tratare a erorilor de execuţie.

Dacă după execuţia instrucţiunii On Error, în rutina respectivă se produce o eroare de execuţie, atunci nu mai este afişat mesajul standard de eroare pe care l-am prezentat înainte. De asemenea inversa acestei afirmaţii este şi ea valabilă, adică dacă într-o rutină se produce o eroare de execuţie înainte de a se executa instrucţiunea On Error, se va continua prelucrarea prin sistemul standard de tratare a erorilor prin afişarea mesajului respectiv.

� Poziţia pe care se va plasa cursorul de instrucţiuni, în cazul apariţiei unei erori de execuţie. Dacă după execuţia instrucţiunii On Error, în rutina respectivă se produce la un moment dat o eroare de execuţie, atunci instrucţiunea On Error va preciza şi care este următoarea instrucţiune care se va executa în cazul producerii unui asemenea eveniment.

Există trei forme ale instrucţiunii On Error, în funcţie de locul de unde se va continua execuţia în cazul apariţiei erorii de execuţie:

a) On Error GoTo etichetă – la producerea unei erori, prelucrarea va continua cu instrucţiunile care se găsesc după etichetă.

Această formă este folosită atunci când se va folosi un modul specializat pentru tratarea erorii, Error-handling, care se va găsi după această etichetă.

� O etichetă se declară printr-un nume scris la începutul unei linii urmat de sem-nul două puncte (:). O etichetă este vizibilă numai în rutina în care a fost declarată.

b) On Error Resume Next – la producerea unei erori, prelucrarea va continua cu următoarea instrucţiune care se găseşte după aceea care a produs eroarea. Deci practic prin această formă prelucrarea va continua fără a se mai executa instrucţiunea care a produs eroarea.

c) On Error GoTo 0 – reinstalează sistemul standard de tratare a erorilor.

� În procedura prezentată mai înainte, Prop_Workspace, existenţa unor proprietăţi fără valoare determină eroare la execuţia instrucţiunii MsgBox care afişează mesajul cu valoarea proprietăţii. Încadrarea lui MsgBox între instrucţiunile On Error Resume Next şi On Error GoTo 0, va determina practic ignorarea instrucţiunii MsgBox în cazul producerii unei erori.

Page 140: 2.VBA_SC4

II-140

II.3.4.2.b) Instrucţiunea: Resume

Resume este instrucţiunea prin care se iese din rutina de tratare a erorilor (Error-handling).

Există trei forme ale instrucţiunii Resume, în funcţie de locul de unde se va continua execuţia, după ce se termină execuţia rutinei de tratare a erorilor.

a) Resume etichetă – prelucrarea va continua cu instrucţiunile care se găsesc după etichetă.

b) Resume Next – prelucrarea va continua cu următoarea instrucţiune care se găsesc după aceea care a produs eroarea. Deci practic prin această formă prelucrarea va continua după tratarea erorii, fără a se mai executa instrucţiunea care a produs eroarea.

c) Resume 0 sau Resume – prelucrarea va continua chiar cu instrucţiunea care a produs eroarea. Deci, după execuţia rutinei de tratare a erorii, se va relua execuţia instrucţiunii care nu s-a putut executa.

II.3.4.2.c) Obiectul: Err

Err este un obiect care se găseşte în VBA şi căruia în momentul producerii unei erori i se vor seta automat de sistem proprietăţile, în funcţie de eroarea produsă.

Cele mai importante proprietăţi ale acestui obiect sunt: − Number – care va conţine numărul* erorii produse. Această proprietate este implicită. − Description – care va conţine un text care explicitează această eroare.

Pentru ca sistemul să încarce proprietăţile la producerea unei erori, este necesar ca obiectul Err să fie iniţializat (golit). Acest lucru se face numai la:

− execuţia instrucţiunilor: On Error sau Resume; − la terminarea rutinei care a produs ultima eroare, prin instrucţiunile: Exit Sub, Exit Function sau Exit Property; − la comandă, prin execuţia metodei Clear, a obiectului Err.

Explicaţie. * Numărul tuturor erorilor posibile se găseşte în Help, şi se păstrează în cazul trecerii la noi versiuni.

II.3.4.2.d) Structura unei rutine care are modul de Error–handling

Function XYZ() On Error GoTo Fis ' activarea rutinei Error-handling ' Codul care poate genera eroarea. Sfirsit: Exit Function ' Ieşirea normală din rutină, în cazul în care nu se _ produce nici o eroare se va face prin această instrucţiune Fis:

Page 141: 2.VBA_SC4

II-141

' Modulul de tratare a erorii (Error-handling) Resume …. ' Instrucţiunea care urmează după execuţia modulului de_ tratare a erorii End Function

Exemplu. În continuare se prezintă aceeaşi funcţie de la început dar în care se prelucrează eventuala eroare printr-un modul specializat.

Public Function Eroare_Handling() As Variant ' Exemplu de control al erorilor printr-un modul specializat. Const Er_Div0 = 11 ' codul erorii de împărţire la 0 Const Er_Tip = 13 ' codul erorii de dată de alt tip Dim A1 As Double Dim A2 As Double Dim R As Double A1 = 1000 On Error GoTo Fis ' Producerea unei erori în continuare se va trata prin _ modulul care se află după eticheta FIS Reia: A2 = InputBox("A2=") R = A1 / A2 MsgBox "Rezultatul lui " & A1 & "/" & A2 & "=" & R Eroare_Handling = R Sfirsit: Exit Function ' Ieşirea din funcţie se face numai pe aici Fis: If err.Number = 11 Or err.Number = 13 Then If MsgBox(" - S-a produs o eroare datorită datei introduse" _ & vbCr & "Reintroduce-ti data?", vbExclamation + vbYesNo) = _ vbYes Then Resume Reia ' Se reia de la introducerea valorii pentru A2 _ se resetează ERR, pentru a fi funcţional în cazul producerii unei alte erori Else

Eroare_Handling = Null Resume Sfirsit

' Se termină funcţia fără a se reintroduce data _ funcţia va întoarce NULL în acest caz End If Else

Page 142: 2.VBA_SC4

II-142

' Se produce o altă eroare care va fi afişată, _ după care se opreşte execuţia funcţiei MsgBox "Eroare Nr=" & err & " - " & err.Description Resume Sfirsit End If End Function

� În cazul în care se produce o eroare într-o rutină (A) care nu are modul de tratare a erorii şi dacă aceasta este apelată de o altă rutină (B) care are un astfel de modul, eroarea va fi tratată de modulul de eroare al acesteia din urmă (B).

II.3.4.2.e) Colecţia Errors şi obiecte Error

În cazul în care un obiect DAO va provoca o eroare de execuţie, există posibilitatea generării mai multor erori în cascadă.

După producerea unei asemenea erori, în colecţia Errors se va crea un obiect Error – similar obiectului prezentat anterior Err din VBA – pentru fiecare eroare generată.

În acelaşi timp, prima eroare produsă va seta şi obiectul VBA – Err. Deoarece Err reprezintă un singur obiect, acesta nu va putea prelua decât datele despre o singură eroare, şi anume prima produsă.

Colecţia Errors, pentru a funcţiona corect, trebuie să aibă şterse toate obiectele Error componente. Această acţiune sistemul o efectuează în momentul execuţiei unei noi operaţii DAO.

În cazul în care se doreşte o prezentare detaliată a erorilor de execuţie produse de un obiect DAO, se pot folosi obiectele Error ale colecţiei Errors ca în exemplul următor:

Sub Eroare_DAO() Dim WS0 As Workspace Dim WS1 As Workspace Dim DB1 As Database Dim DB2 As Database Dim RS As Recordset Dim A As Integer Dim EROARE As String Dim ER As Error ' Obiect al colecţiei Errors

On Error GoTo Fis ' Producerea unei eventuale erori va da controlul la instrucţiunile _ de la eticheta FIS Set WS0 = Workspaces(0) ' DAO – corect Set WS1 = Workspaces(1) ' eroare DAO – nu este creat obiectul Set DB1 = CurrentDb ' DAO – corect

Page 143: 2.VBA_SC4

II-143

Set RS = DB1.OpenRecordset("NoTable") ' eroare DAO Set DB2 = OpenDatabase("NuExistaBaza") ' eroare DAO Set RS = DB1.OpenRecordset("Tabela_A") ' DAO – corect A = 10 / 0 ' eroare dar nu din DAO Sfirsit: Exit Sub Fis: EROARE = "" ' Introduce în variabila Eroare, pentru fiecare obiect din colecţia _ Errors, cîte un rând For Each ER In Errors EROARE = "Eroare DAO nr=" & ER.Number & " - " & _ ER.Description & vbCr Next If Errors(0).Number = err.Number Then ' Eroare ce provine din DAO, deoarece şi primul obiect din colecţia _ Errors şi obiectul Err au acelaşi număr de eroare MsgBox EROARE, vbCritical Else ' Eroare ce nu se produce în DAO MsgBox "Eroare VBA nr=" & err.Number & " - " & _ err.Description, vbExclamation End If Resume Next ' trece la execuţia următoarei instrucţiuni End Sub

II.3.5. Colecţia Databases

Colecţia Databases conţine obiecte Database, care conţin descrierea completă a structurii şi informaţiile dintr-o bază de date.

Pentru ca o bază de date (sau un obiect component) să fie accesată, aceasta trebuie mai întâi deschisă, operaţie care produce crearea unui obiect Database, care se va adăuga automat la colecţia Databases.

VBA, conţine tipurile de date Databases şi Database care permit declararea de variabile specifice.

Deschiderea unei baze de date se poate face în următoarele două moduri: � Cu funcţia CurrentDb, care întoarce un obiect de tip Database, care

conţine baza de date locală, adică aceea definită în aplicaţie.

Dim Db As Database Set Db = CurrentDb

Page 144: 2.VBA_SC4

II-144

� Prin metoda Workspace, OpenDatabase, care permite deschiderea unei baze de date externe (care poate să fie chiar în format ISAM – FoxPro, Dbase, Paradox).

Dim Db As Database Set Db = [workspace].OpenDatabase(dbNume [, options] [, read-only] [, connect])

Aşa cum se observă, singurul parametru obligatoriu este: − dbNume – numele complet (cu extensie şi cale) al fişierului care conţine baza de date.

Dacă nu se precizează, spaţiul (mediul) de lucru este cel implicit (Default Workspace)

------------------

Obiectul Database conţine următoarele colecţii în care sunt incluse toate informaţiile referitoare la baza de date respectivă.

• TableDefs – Structura tabelelor bazei de date. • QueryDefs – Cererile din baza de date. • Relations – Relaţiile din baza de date. • Recordsets – Înregistrările (datele) din tabelele bazei de date. • Containers – Informaţii de securitate despre obiectele din baza de date.

� Referirea colecţiilor şi a obiectelor din baza de date se face prin calificarea acestora, de jos în sus, trecând prin toate colecţiile şi obiectele ascendente până la cel puţin nivelul bazei de date (obligatoriu). Exemplu. În baza de date DAO.Mdb, pentru a se referi obiectul câmpul 'N' al tabelei 'Tabela_A' în vederea afişării proprietăţilor Name şi Type, se face:

Dim Db As Database Dim Fd as Field

Set Db = CurrentDb ' În variabila Fd se introduce obiectul câmpul N Set Fd = Db.TableDefs!Tabela_A.Fields!N Msgbox "Câmpul cu numele:" & Fd.Name & " este de tip:" & _ Fd.Type ------------------

Obiectul Database conţine metode prin care: • se pot crea obiecte noi şi ataşa colecţiilor din structura sa:

− CreateTableDef – pentru crearea unui obiect cu structura unei tabele noi şi adăugarea acestuia la colecţia TableDefs; − CreateRelation – pentru crearea unei relaţii noi şi adăugarea acesteia la colecţia Relations;

Page 145: 2.VBA_SC4

II-145

− CreateQueryDef – pentru crearea unei cereri noi şi adăugarea acesteia la colecţia QueryDefs; − CreateProperty – pentru definirea unei noi proprietăţi a bazei de date sau a altui obiect DAO (adăugarea acesteia la colecţia de proprietăţi a bazei de date se face prin metoda Append, a colecţiei Properties);

• se pot defini şi deschide obiecte Recordset prin metoda OpenRecordset. Exemplu.

Public Sub Prop_Database(Optional BazaDate as Variant) ' Afişează proprietăţile bazei de date locale – dacă lipseşte parametrul _ "BazaDate" sau a unei baze de date externe – cu numele fişierului în _ parametrul "BazaDate" Dim DB As Database Dim PR As Property ' Dacă parametrul "BazaDate" lipseşte atunci se lucrează cu baza de _ date interna, locală If IsMissing(BazaDate) Then Set DB = CurrentDb ' Baza de date din aplicaţia curentă Else Set DB= OpenDatabase(BazaDate) ' Baza de date din alta aplicatie End If '---------------------------- MsgBox "Proprietăţile bazei de date:" & DB.NAME, vbCritical ' Proprietatea Name a bazei de date conţine _ numele complet (cu extensie şi path) al fişierului care o conţine On Error Resume Next ' Pentru a nu se opri prelucrarea dacă apare o eroare _ datorată faptului că unele proprietăţi nu au valoare For Each PR In DB.Properties MsgBox " Proprietatea:" & PR.NAME & " = " & PR.Value, _ vbInformation Next PR On Error GoTo 0 ' Reface sistemul standard de tratare a erorilor End Sub

II.3.6. Colecţia Containers

Colecţia Containers a unei baze de date conţine informaţii despre toate obiectele existente (salvate) într-o bază de date Access, fie că provin din structura DAO fie din alte structuri de obiecte.

Page 146: 2.VBA_SC4

II-146

Ea este constituită din 8 obiecte Container. Fiecare din acestea conţine des-crierea tuturor obiectelor de un anumit tip din baza de date (de exemplu formulare).

Această descriere se face printr-o nouă colecţie, Documents, în care fiecare obiect Document va conţine prin proprietăţile sale informaţiile (nume, permi-siuni, etc.) despre un obiect de tipul respectiv existent (salvat) în baza de date.

Cele 8 obiecte Container provin din: • 3 din structura DAO:

− Databases – Baza de date curentă (deschisă); − Tables* – Toate tabelele şi cererile din baza de date; − Relationships – Toate relaţiile permanente.

• 4 din MS Access – Application: − Forms – Formularele salvate în baza de date; − Modules – Modulele de cod; − Reports – Rapoartele salvate în baza de date; − Scripts – Macro instrucţiunile.

• 1 din sistemul de administrare (protecţie): − SYSrel;

------------------

Deoarece colecţiile Containers şi Documents reflectă structura unei baze de date, este evident că nu este permisă crearea sau ştergerea de obiecte din aceste colecţii.

� În colecţia Tables, se va observa existenţa unor tabele, care încep cu prefixul "MSys". Acestea reprezintă tabelele sistem ale MS Access.

� Deşi au acelaşi nume nu trebuie confundat obiectul Container Forms sau Reports (care conţine informaţii despre toate formularele/ rapoartele din baza de date) şi colecţia Access (Application) Forms sau Reports (care conţine tot formulare/ rapoarte, dar deschise în momentul respectiv). Exemplu. Prin procedura de mai jos se pot cunoaşte care sunt toate obiectele existente într-o bază de date (locală sau externă). Acest lucru se obţine prin proprietatea Name a obiectelor Document din fiecare obiect Container a colecţiei Containers.

Public Sub Structua_Containers(Optional BazaDate) 'Structura colecţiei - Containers 'Obiectele colecţiei Containers sunt: ' 0=Databases ' 1=Forms ' 2=Modules ' 3=Relationships ' 4=Reports ' 5=Scripts – macro

Page 147: 2.VBA_SC4

II-147

' 6=SYSrel ' 7=Tables – tabele si query '----------------------------------------------- Dim DB As Database Dim CT As Container Dim DC As Document ' Dacă parametrul "BazaDate" lipseşte atunci se lucrează cu baza de date_ internă If IsMissing(BazaDate) Then Set DB = CurrentDb ' Baza de date din aplicaţia curentă Else Set DB= OpenDatabase(BazaDate) ' Baza de date din altă aplicaţie End If '---------------------------- For Each CT In DB.Containers ' Parcurge colecţia Containers If MsgBox("Container: " & CT.NAME, _ vbOKCancel + vbCritical) = vbOk Then ' Parcurge colecţia de Documente ale containerului For Each DC In CT.Documents If MsgBox("Documentul " & CT.NAME & " /" & _ DC.NAME, vbOKCancel +vbExclamation) = vbOk Then Else Exit For End If Next DC End If Next CT '----------------- DB.Close ' Nu e necesară deoarece la sfârşitul procedurii toate obiectele declarate_ în aceasta se închid şi eliberează automat variabilele obiect folosite End Sub

Exemplu. Formularul F_CDialogContainer are două controale Combo Box, CForm şi CRap şi un buton de comandă Cmd.

La acţionarea butonului Cmd, printr-un control Common Dialog CD, se poate alege o bază de date externă sau baza de date locală (dacă se iese din CD cu Cancel).

Page 148: 2.VBA_SC4

II-148

În urma acestei acţiuni cele două controale, CForm şi CRap, vor avea ca listă de valori numele formularelor, respectiv rapoartelor din baza de date specificată, al cărui nume se va afişa în titlul formularului.

Codul de program al acestui formular este: Private Sub Cmd_Click() Dim NF As Variant Dim DB As Database Dim DOC As Document Dim Formulare As Variant Dim Rapoarte As Variant Reia: NF = CitireCD ' foloseşte controlul Common Dialog pentru _ preluarea unui nume complet de fişier On Error GoTo Fis ' Deschide Baza de date precizată prin controlul Common Dialog _ - dacă nu se introduce un nume valid se va produce _ o eroare tratată prin modulul specializat 'FIS' If IsNull(NF) Then Set DB = CurrentDb ' Baza de date locala Me.Caption = "Baza de date locala" Else Set DB = OpenDatabase(NF) ' Bază de date din altă aplicaţie _ selecţionată prin CitireCD Me.Caption = "BD:" & NF End If On Error GoTo 0 ' din nou sistemul standard de erori '==Se configurează un string cu formularele existente (separate cu ;) _ în BD deschisă cu care se configurează proprietatea RowSource a _ controlului Combo CForm Formulare = Empty

' Se parcurg toate form. salvate For Each DOC In DB.Containers("Forms").Documents

Formulare = Formulare & DOC.NAME & ";" Next DOC If IsEmpty(Formulare) Then ' Nu există nici un formular în Baza de date deschisă Me!CForm.RowSource = "Nici un Formular!!" Else

Page 149: 2.VBA_SC4

II-149

' Se introduc numele formularelor în lista de valori a controlului Combo Me!CForm.RowSource = Left(Formulare, Len(Formulare) - 1) End If '==Se configurează un string cu rapoartele existente (separate cu ;) _ în BD deschisă cu care se configurează proprietatea RowSource a _ controlului Combo CRap Rapoarte = Empty ' Se parcurg toate rap. salvate For Each DOC In DB.Containers("Reports").Documents Rapoarte = Rapoarte & DOC.NAME & ";" Next DOC If IsEmpty(Rapoarte) Then ' Nu există nici un raport în Baza de date deschisă Me!CRap.RowSource = "Nici un Raport!!" Else ' Se introduc numele rapoartelor în lista de valori a controlului Combo Me!CRap.RowSource = Left(Rapoarte, Len(Rapoarte) - 1) End If Sfirsit: Exit Sub Fis: If MsgBox("- Fisierul introdus nu este o Baza de date Access!!" _ & vbCr & "Îl reintroduceti ?", vbExclamation + vbYesNo) _ = vbYes Then ' Se reia introducerea prin controlul Common Dialog Resume Reia Else ' Se renunţă Me.Caption = "????" Resume Sfirsit End If End Sub '========Funcţii interne========= Private Function CitireCD() As Variant ' Intoarce numele complet introdus prin controlul Common Dialog _ Dacă funcţia intoarce NULL atunci s-a ieşit _ prin butonul Cancel din Common Dialog

Page 150: 2.VBA_SC4

II-150

'------------------------------------------------- ' Parametrii de iniţializare pentru configurarea _ controlului Common Dialog: ' Intrare – Titlul pus în caseta Common Dialog Me!CD.DialogTitle = "Selectati fisierul cu Baza de date" ' Intrare – Extensia implicită a numelui de fişier introdus _ Se foloseşte de obicei la Comanda de salvare Me!CD.DefaultExt = "Mdb" ' Intrare – Directorul implicit _ pentru poziţionarea iniţială a casetei Common Dialog Me!CD.InitDir = "" ' Intrare – Filtrul de selecţie pentru fişierele afişate _ Se introduc câte două informaţii (separatorul este caracterul (|) _ pentru fiecare rând afişat în caseta de selecţie: _ 1- Numele afişat pentru precizarea selecţiei ce se efectuează _ 2- Mulţimea numelor care se vor selecţiona prin _ folosirea caracterelor generice (*) şi (?) Me!CD.Filter = "Fisier Access|*.Mdb|All|*.*" ' Comenzile posibile ce se pot efectua: _ Action = 1 - Open _ Action = 2 - Save _ Action = 3 - Color _ Action = 4 - Font _ Action = 5 - Print Me!CD.FileName = "" ' Iniţializare Me!CD.Action = 1 ' Open – Se dă controlul casetei Common Dialog ' Ieşire – Numele complet (cu cale şi extensie) a fişierului selecţionat _ Dacă se întoarce un string gol ("") _ atunci s-a ieşit prin apăsarea pe Cancel If Me!CD.FileName = "" Then CitireCD = Null ' ieşire prin Cancel Else CitireCD = Me!CD.FileName End If End Function

Page 151: 2.VBA_SC4

II-151

II.3.7. Colecţia TableDefs

Colecţia TableDefs conţine obiecte de tip TableDef, fiecare din acestea reprezentând structura (deci nu datele introduse) unei tabele din baza de date deschisă. Numele obiectului TableDef este chiar acela al tabelei respective.

Fiecare obiect TableDef conţine proprietăţile specifice tabelei (Validation Rule, Validation Text, şirul de conectare pentru tabelele legate etc.). Exemplu. Procedura următoare afişează numele (Name) şi valoarea (Value) proprietăţilor tuturor tabelelor din baza de date locală.

Sub Prop_TableDef() ' Proprietăţile tabelelor _ - Name: numele proprietăţii respective _ - Value (implicită): Valoarea pe care o are o proprietate Dim DB As Database Dim TD As TableDef Dim PR As Property

Set DB = CurrentDb For Each TD In DB.TableDefs If MsgBox("Tabela: " & TD.NAME, _ vbOKCancel + vbCritical) = vbOk Then On Error Resume Next ' nu toate prop. au valoare implicită For Each PR In TD.Properties MsgBox " Proprietatea:" & PR.NAME & " = " & PR Next PR On Error GoTo 0 End If Next TD DB.Close End Sub

Fiecare obiect TableDef conţine la rândul său alte două colecţii, şi anume: • Colecţia Fields – formată din obiecte Field, fiecare din acestea

descriind prin proprietăţile sale (Nume, Tip de dată, Regula de validare pentru câmp, Caption, Size, etc.) un câmp al tabelei.

• Colecţia Indexes – formată din obiecte Index, care la rândul lor conţin fiecare o colecţie de câmpuri Fields.

� Tabela_A din fişierul DAO.Mdb, prezentată schematic în figura de la începutul modulului, conţine: • Colecţia Fields cu 2 obiecte Field, [N] şi [A].

• Colecţia Indexes cu 2 obiecte, şi anume:

Page 152: 2.VBA_SC4

II-152

� PrimaryKey, care la rândul lui conţine:

− Colecţia Fields cu un obiect - [N] � A, care la rândul lui conţine:

− Colecţia Fields cu un obiect - [A] Explicaţie. Fiecare index reprezintă un obiect cu un nume (care este de obicei numele câmpului sau pentru cheia primară, PrimaryKey), urmând ca prin colecţia Fields a indexului să se specifice care este efectiv numele câmpului din tabelă. Deci se poate ca numele indexului şi al câmpului să nu fie acelaşi, sau chiar ca un index să fie definit pe mai multe câmpuri.

Exemplu. Public Sub Structua_TableDefs(Optional BazaDate) ' Structura colecţiei de tabele - TableDefs Dim DB As Database Dim TD As TableDef Dim FD As Field ' Câmpurile tabelei Dim ID As Index Dim FID As Field ' Câmpurile indexului ' Dacă parametrul "BazaDate" lipseşte _ atunci se lucrează cu baza de date internă If IsMissing(BazaDate) Then Set DB = CurrentDb ' Baza de date din aplicaţia curentă Else Set DB=OpenDatabase(BazaDate) ' Baza de date din altă aplicaţie End If '---------------------------- For Each TD In DB.TableDefs ' Parcurge colecţia de Tabele If MsgBox("Tabela:" & TD.NAME, vbOKCancel+vbCritical) _ = vbOk Then ' Parcurge colecţia de Câmpuri ale tabelei For Each FD In TD.Fields If MsgBox("Cimpul: " & TD.NAME & " /" & _ FD.NAME, vbOKCancel + vbExclamation) = vbOk Then Else Exit For End If Next FD '------------------------- For Each ID In TD.Indexes ' Parcurge colecţia de Indecşi a tabelei

Page 153: 2.VBA_SC4

II-153

If MsgBox("Indexul: " & TD.NAME & " /" & _ ID.NAME, vbOKCancel + vbInformation) = vbOk Then For Each FID In ID.Fields ' Parcurge colecţia de Câmpuri a indexului If MsgBox("Cimpul indexului: " & TD.NAME _ & " /" & ID.NAME & " /" & FID.NAME, _ vbOKCancel + vbExclamation) = vbOk Then Else Exit For End If Next FID End If Next ID End If Next TD '--------------- DB.Close ' Nu e necesară deoarece la sfârşitul procedurii toate obiectele _ declarate în aceasta se închid şi _ eliberează automat variabilele obiect folosite End Sub

Exemplu. Formularul F_TableDef are două controale Combo Box, CTabel şi CCimp.

La deschiderea formularului (evenimentul Open), CTabel va avea completată lista de valori cu numele tabelelor din baza de date locală.

La introducerea unui nume de tabel în CTabel (evenimentul After Update), se completează lista de valori a controlului CCimp cu numele câmpurilor tabelei respective.

Codul de program al acestui formular este: Private Sub Form_Open(Cancel As Integer) Dim DB As Database Dim TB As TableDef Dim sTabele As Variant Set DB = CurrentDb ' Baza de date locală '===Se configurează un string cu tabelele existente (separate cu ;) _ în BD deschisă cu care se configurează proprietatea RowSource a _ controlului Combo CTabel sTabele = Empty For Each TB In DB.TableDefs ' Se parcurg toate tabelele

Page 154: 2.VBA_SC4

II-154

sTabele = sTabele & TB.NAME & ";" Next TB If IsEmpty(sTabele) Then ' Nu există nici un tabel Me!CTabel.RowSource = "Nici un tabel??!!" Else ' Se configurează cu numele tabelelor lista de valori a controlului Combo Me!CTabel.RowSource = Left(sTabele, Len(sTabele) - 1) End If End Sub

Private Sub CTabel_AfterUpdate() Dim DB As Database Dim FD As Field Dim sCimpuri As Variant

Set DB = CurrentDb ' Baza de date locală ' === Se configurează un string cu câmpurile existente (separate cu ;) _ în tabela Me!CTabel cu care se configurează _ proprietatea RowSource a controlului Combo CCimp sCimpuri = Empty For Each FD In DB(Me!CTabel).Fields ' Se parcurg toate câmpurile tabelei sCimpuri = sCimpuri & FD.NAME & ";" Next FD If IsEmpty(sCimpuri) Then ' Nu există nici un câmp Me!CCimp.RowSource = "Nici un Câmp??!!" Else ' Se introduce în numele câmpurilor lista de valori a controlului Combo Me!CCimp.RowSource = Left(sCimpuri, Len(sCimpuri) - 1) End If End Sub

------------------

Aşa cum la nivelul obiectului bazei de date există metoda CreateTableDef, pentru crearea structurii unei tabele, tot aşa la nivelul unui obiect TableDef, există metoda CreateField, prin care se pot defini câmpuri, care după aceea se pot adăuga prin metoda Append, la colecţia de câmpuri a obiectului TableDef.

Page 155: 2.VBA_SC4

II-155

II.3.8. Colecţia QueryDefs

Colecţia QueryDefs este foarte asemănătoare colecţiei TableDefs, cu specificarea faptului că obiectele QueryDef componente, adică structura cererilor din baza de date curentă, nu au colecţia de indecşi, dar au o colecţie de parametri.

Colecţia QueryDefs conţine obiecte de tip QueryDef, fiecare din acestea reprezentând structura unei cereri salvate din baza de date deschisă, numele acestora fiind acelaşi cu al cererii respective.

Fiecare obiect QueryDef conţine proprietăţile specifice ale cererii. Exemplu.

Sub Prop_QueryDef() ' Proprietaţile cererilor _ -Name: numele proprietăţii respective _ -Value (implicită): Valoarea pe care o are o proprietate Dim DB As Database Dim Qry As QueryDef Dim PR As Property Set DB = CurrentDb For Each Qry In DB.QueryDefs If MsgBox("Cererea:" & Qry.NAME, _ vbOKCancel + vbCritical) = vbOk Then On Error Resume Next For Each PR In Qry.Properties MsgBox " Proprietatea:" & PR.NAME & " = " & PR Next PR On Error GoTo 0 End If Next Qry DB.Close End Sub

------------------ Fiecare obiect QueryDef conţine la rândul său alte două colecţii, şi anume: • Colecţia Fields – formată din obiecte Field, fiecare din acestea

reprezentând un câmp al cererii. • Colecţia Parameters – formată din obiecte Parameter, dacă cererea a

fost creată cu parametri. Exemplu. Cerere_A din fişierul DAO.Mdb, prezentată schematic în figura de la începutul modulului, conţine:

• Colecţia Fields cu 3 obiecte Field: [N], [A] şi [A1] • Colecţia Parameters cu 1 obiect Parameter: [Numar]

Page 156: 2.VBA_SC4

II-156

Exemplu. Public Sub Structua_QueryDefs(Optional BazaDate) ' Structura colecţiei de cereri – QueryDefs Dim DB As Database Dim Qry As QueryDef Dim FD As Field ' Câmpurile cererii Dim PT As Parameter ' Parametrii cererii ' Dacă argumentul "BazaDate" lipseşte - se lucrează cu baza de date internă If IsMissing(BazaDate) Then Set DB = CurrentDb ' Baza de date din aplicaţia curentă Else Set DB=OpenDatabase(BazaDate) ' Baza de date din altă aplicaţie End If '---------------------------- For Each Qry In DB.QueryDefs ' Parcurge colecţia de Cereri If MsgBox("Cererea: " & Qry.NAME, _ vbOKCancel + vbCritical) = vbOk Then For Each FD In Qry.Fields ' Parcurge colecţia de Câmpuri ale cererii If MsgBox("Cimpul: " & Qry.NAME & " /" & _ FD.NAME, vbOKCancel + vbExclamation) = vbOk Then Else Exit For End If Next FD '------------------------- For Each PT In Qry.Parameters ' Parcurge colecţia de Parametri ai cererii If MsgBox("Parametrul: " & Qry.NAME & " /" & _ PT.NAME, vbOKCancel + vbInformation) = vbOk Then Else Exit For End If Next PT End If Next Qry DB.Close End Sub

------------------

Page 157: 2.VBA_SC4

II-157

La nivelul obiectului bazei de date există metoda CreateQueryDef, pentru crearea unei cereri permanente prin cod VBA, descrierea cererii făcându-se direct în SQL. Exemplu. Cererea, Cerere_B, este creată dacă se execută următoarea secvenţă de instrucţiuni.

Public Sub Fac_Query() ' Creează o cerere Dim DB As Database ' Numele cu care va fi salvată cererea Const NumeCerere = "Cerere_B" ' Instrucţiunea SQL de descriere a cererii Const SQL = "SELECT Tabela_B.* FROM Tabela_B;" Set DB = CurrentDb 'Baza de date din aplicaţia curentă ' Se crează cererea şi se salvează în BD deschisă DB.CreateQueryDef NumeCerere, SQL End Sub

------------------

� Metoda Execute

Această metodă se aplică numai cererilor acţiune, şi are ca efect execuţia efectivă a cererii. Exemplu.

Public Sub Executa_Query() ' Execută o cerere acţiune cu parametrii / Update Query Dim DB As Database Dim QRY As QueryDef Const NumeCerere = "Cerere_C" ' Numele cererii Set DB = CurrentDb ' Bază de date din aplicaţia curentă ' Se introduce cererea în variabila obiect QRY Set QRY = DB.QueryDefs(NumeCerere) ' se dau valori parametrilor cererii QRY.Parameters("Text1") = "unu" QRY.Parameters("Text2") = "XXX" ' Execuţia cererii acţiune Update face ca toate înregistrările _ care au câmpul [A] = "unu" (parametrul: Text1) să şi-l modifice _ în "XXX" (parametrul: Text2) QRY.Execute End Sub

Page 158: 2.VBA_SC4

II-158

------------------

� Parametrii unei cereri pot fi introduşi direct prin cod VBA, ca în exemplul de mai sus.

� Cererile de selecţie (cu eventualii parametri), care evident nu se pot executa, pot să constituie suportul pentru crearea unor noi Recordseturi.

II.3.9. Colecţia Relations

Colecţia Relations conţine obiecte de tip Relation, fiecare din aceştia reprezentând o relaţie permanentă a bazei de date. Numele relaţiei va fi constituit din concatenarea numelor obiectelor între care se creează relaţia.

Fiecare obiect Relation conţine o colecţie Fields, ale cărui obiecte definesc câmpul de relaţie. Exemplu.

Public Sub Structura_Relations(Optional BazaDate) ' Structura colecţiei de relaţii - Relations Dim DB As Database Dim REL As Relation Dim FD As Field ' Câmpurile relaţiei ' Dacă parametrul "BazaDate" lipseşte _ atunci se lucrează cu baza de date internă If IsMissing(BazaDate) Then Set DB = CurrentDb ' Baza de date din aplicaţia curentă Else Set DB=OpenDatabase(BazaDate) ' Baza de date din altă aplicaţie End If '---------------------------- For Each REL In DB.Relations ' Parcurge colecţia de Relaţii If MsgBox("Relatia: " & REL.NAME, _ vbOKCancel + vbCritical) = vbOk Then For Each FD In REL.Fields ' Parcurge colecţia de Câmpuri ale relaţiilor If MsgBox("Cimpul: " & REL.NAME & " /" & _ FD.NAME, vbOKCancel + vbExclamation) = vbOk Then Else Exit For End If Next FD End If

Page 159: 2.VBA_SC4

II-159

Next REL End Sub

II.3.10. Colecţia Recordsets – Set de înregistrări

Colecţia Recordsets este formată din obiecte Recordset (set de înregis-trări). Un obiect Recordset conţine înregistrările care se găsesc într-o tabelă, sau cele care rezultă în urma executării unei cereri de selecţie (cererile de selecţie sunt considerate, aşa cum am mai arătat, tabele virtuale). Numele unui obiect Recordset este chiar numele tabelei sau cererii de selecţie la care se referă.

La rândul său, un obiect Recordset conţine colecţia Fields formată din obiecte Field, fiecare din acestea reprezentând un câmp al înregistrării respective şi având de asemenea acelaşi nume cu al câmpului.

II.3.10.1. Funcţionarea unui set de înregistrări

Deci dacă obiectele TableDef (sau QueryDef) definesc structura tabelelor (cererilor, ca tabele virtuale), obiectele Recordset sunt formate din datele (informaţiile) care se găsesc în acestea.

Aşa cum cererile sunt utilizate pentru a manipula datele dintr-o bază de date la nivel de mulţime (prin implementarea operaţiilor de algebră relaţională), obiectele Recordset sunt folosite în acelaşi scop dar la nivelul elementar, al înregistrării.

Obiectul Recordset permite accesul la datele din baza de date, prin parcurgerea unui tabel sau a unei cereri de selecţie, în modalitatea în care se procedează cu un fişier clasic.

Un Recordset este asemănător deci cu un fişier clasic. El este constituit din câmpuri (coloane) şi înregistrări (rânduri).

Pentru a manevra un Recordset (sau un fişier clasic) trebuie să se parcurgă nişte etape, prin lansarea unor metode ale obiectului Recordset (este o singură excepţie – metoda OpenRecorset este a obiectului Database):

� Să fie deschis – obligatoriu primul pas – adică să fie definit din punct de vedere fizic şi să i se atribuie un nume logic, prin care se va face în continuare referire la el.

Metoda folosită este OpenRecorset (a obiectului Database). Această metodă (ca şi metoda OpenDatabase sau funcţia CurrentDB) va crea obiectul Recordset al tabelei sau cererii de selecţie.

� Să fie închis – obligatoriu ultimul pas. În urma acestei acţiuni se efectuează operaţiile fizice de sfârşit şi se eliberează toate resursele (variabile, memorii tampon etc.) folosite de Recordset.

Metoda Recordset folosită este Close. Această metodă va produce ştergerea obiectului Recordset respectiv, din colecţia Recordsets.

Page 160: 2.VBA_SC4

II-160

Metoda Close este opţională, ea efectuându-se automat la terminarea rutinei în care a fost definit Recordset-ul.

Deci colecţia Recordsets este formată la un moment dat din toate obiectele Recordset deschise şi neînchise.

� Să fie accesată o anumită înregistrare. Un Recordset este format ca un tabel (matrice), din rânduri şi coloane.

Pentru a putea ajunge la datele dintr-o anumită celulă (element), mai întâi trebuie să se facă poziţionarea pe înregistrarea (rândul) respectiv.

Când se efectuau prelucrări prin cereri, se lucra cu mulţimi (mulţimea înregistrărilor dintr-o tabelă) pe care se efectuau nişte operaţii de algebră relaţională. Când se lucrează cu un Recordset, operaţiile se fac la nivel punctual ("mă duc" mai întâi pe înregistrarea respectivă pentru a face o prelucrare).

Termenul de pointer (cursor) de înregistrări se referă la acest aspect, al înregistrării care la un moment dat poate fi accesată. Înregistrarea pe care se găseşte la un moment dat pointerul de înregistrări se numeşte înregistrare curentă.

Deci un Recordset are un anumit număr de înregistrări, aşezate una după alta şi pentru a efectua orice prelucrare trebuie mai întâi să se poziţioneze pointerul de înregistrări pe respectiva înregistrare.

Poziţionarea pointerului de înregistrări se poate face în mai multe feluri: • acces secvenţial la o înregistrare – prin parcurgerea înregistrărilor una

după alta, în ordine, până la aceea care interesează. Metodele Recordset folosite, denumite Move, permit mărirea sau

micşorarea pointerului de înregistrări, cu o valoare fixă, ceea ce se materializează de obicei prin citirea înainte sau înapoi a următoarei înregistrări.

• acces direct la o înregistrare – plasarea directă pe o înregistrare în funcţie de un criteriu de căutare.

În funcţie de mecanismul de efectuare a acestei operaţii, sunt două categorii de metode, şi anume:

− Metoda Recordset Seek – poziţionare rapidă folosind cheia de indexare. − Metodele Recordset Find – poziţionare mai lentă, care nu foloseşte cheia de indexare.

� Se poate sintetiza ceea ce s-a prezentat la acest punct prin următoarea observaţie: Accesul nu este permis decât la câmpurile înregistrării curente.

� Prelucrarea înregistrării. Accesarea unei înregistrări se face în două scopuri: • Citirea datelor din câmpurile înregistrării. Se foloseşte proprietatea

Value, implicită, în citire, a obiectelor câmpuri (Field)*. • Actualizarea, adică:

Page 161: 2.VBA_SC4

II-161

− Modificarea datelor dintr-un câmp. Se foloseşte proprietatea Value, în scriere, a obiectelor câmpuri (Field) şi metodele Recordset: Edit şi Update. − Adăugarea unei înregistrări noi. Se folosesc proprietăţile Value, în scriere, a obiectelor câmpuri (Field) şi metodele Recordset: AddNew şi Update. − Ştergerea unei înregistrări. Metoda Recordset folosită: Delete.

II.3.10.2. Tipuri de seturi de înregistrări

Un obiect Recordset poate proveni din următoarele surse:

� datele dintr-o singură tabelă;

� datele din mai multe tabele – printr-o cerere care poate fi:

− actualizabilă (updatable), adică în care se pot actualiza înregistrările obţinute din execuţia cererii (câmpurilor din ieşirea cererii li se poate stabili precis originea şi anume: tabela, înregistrarea şi câmpul; de exemplu o cerere cu clauza Total sau în care este setată proprietatea Unique Value, nu este updatable); − neactualizabilă;

În momentul definirii (deschiderii) unui Recordset, trebuie precizat şi tipul acestuia, conform provenienţei sale, prezentate mai sus, ceea ce va permite efectuarea numai anumitor operaţii asupra sa.

Astfel există 4 tipuri de seturi de înregistrări:

− Table (dbOpenTable) – Set de înregistrări de tip tabel – Recordset ce provine din înregistrările unei singure tabele şi care permite actualizări în acestea.

− Dynaset (dbDynasetTable) – Set de înregistrări de tip de date dinamice - Recordset ce provine printr-o cerere actualizabilă din înregistrările mai multor tabele şi care, în consecinţă, permite actualizări în acestea.

− Snapshot (dbSnapshotTable) – Set de înregistrări de tip instantaneu de date - Recordset ce provine printr-o cerere neactualizabilă din înregistrările mai multor tabele şi care, în consecinţă, nu permite actualizări în acestea. Este folosit numai în scopul căutării sau al afişării unor date.

− OpenForwardOnly (dbOpenForwardOnly) – Recordset de tip Snapshot, dar care nu poate fi parcurs decât o dată şi numai înainte.

II.3.10.3. Deschiderea unui set de înregistrări – Metoda OpenRecordset

Obiectul Recordset se creează numai la lansarea metodei OpenRecordset a obiectului Database. El este adăugat automat la colecţia Recordsets, dar nu va fi salvat la închiderea acestuia. Este un obiect temporar care durează până la închiderea sa prin metoda Recordset, Close.

Page 162: 2.VBA_SC4

II-162

Obiectul Recordset va reprezenta practic o structură de tip înregistrări /câmpuri, care va ocupa un anumit spaţiu de memorare, şi care va avea o existenţă independentă. Din această cauză se pot deschide mai multe obiecte Recordset, care provin din aceeaşi sursă de date (tabelă).

În vederea prelucrărilor necesare, obiectul Recordset se introduce în variabile de tip Recordset.

Deschiderea unui Recordset se face în felul următor: Dim DB As Database Dim RS As Recordset Set DB = CurrentDb 'Baza de date locală Set RS = DB.OpenRecordset(Nume, {Tip})

în care: • Nume – este un string care reprezintă numele tabelei sau cererii de

selecţie din care se creează setul de înregistrări. • Tip – reprezintă o constantă care specifică tipul setului de înregistrări

care se creează, şi anume: − dbOpenTable − dbOpenDynaset − dbOpenSnapshot − dbOpenForwardOnly

Tipul este opţional. Dacă nu se foloseşte, atunci setul de înregistrări se creează pentru primul tip (în ordinea prezentată mai sus) pentru care se poate defini.

� 1. Pentru tabelele legate din alte baze de date nu se poate folosi tipul Table.

� 2. Tipurile Dynaset, Snapshot, ForwardOnly se creează în memoria temporară Access, dacă este loc. Din această cauză ele sunt mult mai rapide.

� 3. În parametrul "nume" se poate introduce direct o instrucţiune SQL. În acest caz obiectul (tabelă sau cerere) creat din aceasta va fi temporar, iar Recordsetul respectiv va funcţiona mai lent decât în cazul în care ar fi avut la bază un obiect (tabelă sau cerere) salvat în baza de date.

� 4. La deschidere, Recordsetul se poziţionează automat pe prima înregistrare.

II.3.10.4. Proprietăţile unui set de înregistrări

Câteva din cele mai utilizate proprietăţi ale unui obiect Recordset sunt: • RecordCount – se poate numai citi, şi reprezintă numărul de

înregistrări ale Recordsetului. • EOF – se poate numai citi, şi ia valoarea True, dacă pointerul de

înregistrări încearcă să depăşească ultima înregistrare. • BOF – se poate numai citi, şi ia valoarea True, dacă pointerul de

înregistrări încearcă să se plaseze în faţa primei înregistrări. • Type – se poate numai citi, şi arată care este tipul Recordsetului.

Page 163: 2.VBA_SC4

II-163

• Updatable – se poate numai citi, şi arată dacă Recordsetul este actualizabil.

• NoMatch – se poate numai citi, şi se poziţionează după o metodă Seek sau Find. Această proprietate va lua valoarea True, dacă în urma metodei respective de căutare nu s-a putut poziţiona pointerul de înregistrări (nu s-a găsit nici o înregistrare care să satisfacă condiţia de căutare).

� Pentru Recordsetul care nu are nici o înregistrare RecordCount=0 şi atât EOF cât şi BOF sunt True.

� Pentru a citi valoarea corectă a numărului de înregistrări ale unui Recordset este bine ca să se poziţioneze mai întâi pointerul de înregistrări pe ultima înregistrare (eventual cu metoda MoveLast). Exemplu.

Public Sub Rst_TipRecordset(Optional BazaDate) 'Deschiderea unui Recordset în toate tipurile Dim DB As Database Dim RS As Recordset Dim Tip(4) As Integer Dim Eroare As String Dim i As Integer ' Dacă parametrul "BazaDate" lipseşte _ atunci se lucrează cu baza de date internă If IsMissing(BazaDate) Then Set DB = CurrentDb ' Bază de date din aplicaţia curentă Else Set DB=OpenDatabase(BazaDate) ' Bază de date din altă aplicaţie End If '---------------------------- ' Tipuri de seturi de înregistrări

Tip(1) = dbOpenTable ' Constanta 1 ' pentru exemplul dat numai acest tip nu va fi admis Tip(2) = dbOpenDynaset ' Constanta 2

Tip(3) = dbOpenSnapshot ' Constanta 4 Tip(4) = dbOpenForwardOnly ' Constanta 8

For i = 1 To 4 ' Dacă nu se poate deschide în tipul respectiv se va produce o eroare On Error GoTo Fis Set RS = DB.OpenRecordset("Cerere_B", Tip(i)) On Error GoTo Fis1

Page 164: 2.VBA_SC4

II-164

RS.MoveLast ' Se poziţionează dacă poate pe ultima înregistrare MsgBox RS.RecordCount ' Afişează numărul de înregistrări al Recordsetului RS.Close Reia: Next i Sfirsit: Exit Sub Fis: Eroare = "Nu se poate deschide tipul de recorset " & Tip(i) _ & vbCr & "--Nr.eroare=" & err & " - " & err.Description MsgBox Eroare, vbCritical Resume Reia ' trece la încercarea deschiderii unui alt tip Fis1: MsgBox err & " - " & err.Description, vbCritical Resume Reia ' trece la încercarea deschiderii unui alt tip End Sub

II.3.10.5. Accesarea secvenţială a unui set de înregistrări

Există 5 metode pentru deplasarea în mod secvenţial într-un Recordset: • MoveFirst – pointerul de înregistrări se mută pe prima înregistrare; • MoveLast – pointerul de înregistrări se mută pe ultima înregistrare; • MoveNext – pointerul de înregistrări se mută pe următoarea înregis-

trare; • MovePrevious – pointerul de înregistrări se mută pe înregistrarea

anterioară; • Move(N) – pointerul de înregistrări se mută în funcţie de valoarea lui

N. Astfel dacă: − N este pozitiv – pointerul de înregistrări se mută înainte cu N înregistrări faţă de înregistrarea curentă; − N este negativ – pointerul de înregistrări se mută înapoi cu N înregistrări faţă de înregistrarea curentă; − N = 0 – pointerul de înregistrări nu se modifică. Se foloseşte de obicei pentru reactualizarea datelor din câmpurile unei înregistrări, în cazul modificării acestora printr-o operaţie externă celei curente (de exemplu executarea unei cereri acţiune asupra datelor din Recordsetul respectiv);

Page 165: 2.VBA_SC4

II-165

� Când se parcurge secvenţial un Recordset, trebuie testate proprietăţile BOF şi EOF, pentru a nu se depăşi limitele acestuia, la fiecare nouă poziţionare.

� Pentru tipul de înregistrări ForwardOnly, singura metodă acceptată este MoveNext.

II.3.10.6. Accesul direct într-un set de înregistrări

II.3.10.6.a) Metoda Seek

Metoda Seek a unui Recordset caută o înregistrare care să satisfacă un anumit criteriu şi în cazul găsirii acesteia, poziţionează pe ea pointerul de înregistrări.

Criteriul care se foloseşte cu metoda Seek, trebuie să se refere la un index al tabelei care stă la baza Recordsetului.

Deoarece Seek funcţionează numai pe indecşi, este evident că Recordsetul trebuie să fie obligatoriu numai de tip "table".

Aplicarea metodei se face în trei paşi:

1) Se introduce în proprietatea Index a Recordsetului, de tip string, numele indexului după care se doreşte efectuarea căutării. În cazul în care indexul este chiar cheia primară a tabelei, numele folosit va fi 'PrimaryKey'.

NumeRecordset.Index="NumeIndex" 2) Se aplică metoda Seek. Prin aceasta se introduce şi expresia de căutare,

prin doi parametri de tip string care reprezintă în ordine:

− Operatorul relaţional al expresiei ce se formează cu indexul precizat în etapa anterioară. Se pot folosi următorii operatori relaţionali: (=) (>) (<) (>=) (<=); − Un literal care reprezintă valoarea pe care trebuie să o aibă în înregistrare, indexul respectiv;

NumeRecordset.Seek "operator_relaţional", "valoare"

� O metodă este similară cu o procedură din punct de vedere al regulilor de sintaxă folosite. Ea se poate lansa şi cu parametri, caz în care aceştia sunt plasaţi în continuarea numelui metodei, separaţi prin virgulă şi fără să fie incluşi între paranteze.

3) Se verifică prin proprietatea NoMatch dacă operaţia s-a efectuat cu succes (în caz de reuşită proprietatea se setează pe False);

Exemplu. Public Sub Rst_MetodaSeek() ' Caută o înregistrare folosind metoda Seek, _

Page 166: 2.VBA_SC4

II-166

pe un câmp indexat şi pe un câmp cheie primară Dim DB As Database Dim RS As Recordset On Error GoTo Fis Set DB = CurrentDb ' Se deschide recordsetul în tipul Table Set RS = DB.OpenRecordset("Tabela_A", dbOpenTable) If RS.RecordCount = 0 Then ' Se verifică existenţa înregistrărilor. MsgBox "Nu exista inregistrari", vbInformation Exit Sub End If ' Setează indexul pentru care se face căutarea pe cheia primară RS.Index = "PrimaryKey" ' Caută înregistrarea cu cheia primară = 2 RS.Seek "=", "2" If RS.NoMatch Then MsgBox "Nu s-a gasit inregistrarea cautata" Else MsgBox "Ok - " & RS!N & ";" & RS!A End If '___________ ' Setează indexul pentru care se face o nouă căutare pe câmpul "A" RS.Index = "A" ' Caută înregistrarea cu valoarea "unu" RS.Seek "=", "unu" If RS.NoMatch Then MsgBox "Nu s-a gasit inregistrarea cautata" Else MsgBox "Ok - " & RS!N & ";" & RS!A End If RS.Close Sfirsit: Exit Sub Fis: MsgBox err & " - " & Err.Description, vbCritical Resume Sfirsit End Sub

Page 167: 2.VBA_SC4

II-167

------------------

� Când se referă un câmp al unui Recordset, este obligatorie utilizarea semnului de calificare – semn de exclamare (!), deoarece în faza de compilare sistemul nu "ştie" care sunt câmpurile unui Recordset. Acest lucru se va cunoaşte abia în faza de execuţie, după deschiderea respectivului Recordset prin metoda specifică.

� Un obiect index conţine, aşa cum am mai arătat, o colecţie Fields. Din această cauză un index poate fi format din unul sau mai multe cîmpuri. Metoda Seek permite introducerea unui criteriu de căutare şi în cazul indecşilor formaţi din mai multe câmpuri, prin folosirea mai multor perechi de parametri valoare, şi anume câte unul pentru fiecare câmp al indexului, în ordinea în care aceştia se găsesc în colecţia Fields.

II.3.10.6.b) Metodele FindFirst, FindLast, FindNext, FindPrevious

Aceste metode funcţionează asemănător metodei Seek, căutând o înregistrare care să satisfacă un anumit criteriu pentru a se poziţiona pe ea, dar nu foloseşte obligatoriu numai câmpurile indexate pentru efectuarea operaţiei.

Tipul Recordsetului pentru aceste metode trebuie să fie obligatoriu Dynaset sau Snapshot.

Este evident că deoarece căutarea nu se va face folosind numai indecşii, durata de execuţie a acestor metode este mult mai mare decât la metoda Seek.

Deoarece există posibilitatea ca să existe mai multe înregistrări care să satisfacă criteriul introdus, există 4 metode de căutare care vor efectua următoarele tipuri de operaţii:

• FindFirst – poziţionează pointerul pe prima înregistrare care îndeplineşte criteriul de căutare. La această metodă căutarea porneşte de la prima înregistrare a Recordsetului spre sfârşitul acestuia.

• FindLast – poziţionează pointerul pe ultima înregistrare care îndeplineşte criteriul de căutare. La această metodă căutarea porneşte de la ultima înregistrare a Recordsetului spre începutul acestuia.

• FindNext – se aplică de obicei după ce s-a efectuat o metodă Find. Ea poziţionează pointerul pe următoarea înregistrare care îndeplineşte criteriul de căutare. La această metodă căutarea porneşte de la înregistrarea curentă a Recordsetului, spre sfârşitul acestuia.

• FindPrevious – se aplică de obicei după ce s-a efectuat o metodă Find. Ea poziţionează pointerul pe înregistrarea anterioară care îndeplineşte criteriul de căutare. La această metodă căutarea porneşte de la înregistrarea curentă a Recordsetului, spre începutul acestuia.

------------------

Aplicarea metodei se face în doi paşi:

Page 168: 2.VBA_SC4

II-168

1) Se aplică una din metodele Find.

Toate metodele Find folosesc un parametru de tip string prin care se introduce o expresie care reprezintă criteriul de căutare.

Regulile de scriere ale expresiei sunt aceleaşi care au fost prezentate la formarea expresiilor din funcţiile agregate de domeniu.

Reamintim că se pot folosi în aceste expresii orice fel de operatori acceptaţi în VBA (aritmetici, relaţionali sau logici) cât şi orice fel de funcţii vizibile şi că termenii expresiei pot fi şi numele de câmpuri din Recordsetul pe care se face căutarea.

Recordset.FindFirst | FindLast | FindNext | FindPrevious "expresie" 2) Se verifică prin proprietatea NoMatch dacă operaţia s-a efectuat cu

succes (în caz de reuşită proprietatea se setează pe False).

Exemplu. Public Sub Rst_MetodeFind() ' Caută toate înregistrările care îndeplinesc un anumit criteriu _ folosind metode Find Dim DB As Database Dim RS As Recordset Dim I As Integer Dim Tp As String Dim Criteriu As String On Error GoTo Fis Set DB = CurrentDb ' Se deschide setul de înregistrări în tip Dynaset. Set RS = DB.OpenRecordset("Tabela_A", dbOpenDynaset) If RS.RecordCount = 0 Then ' Se verifică existenţa înregistrărilor. MsgBox "Nu exista inregistrari", vbInformation Exit Sub End If ' Caută prima înregistrare care are câmpul "A" la fel cu _ valoarea introdusă prin InputBox Tp = InputBox("Valoarea care se va cauta pentru Cimpul A") I = 0 Criteriu = "[A]=""" & Tp & """" ' TP este un string ' Atenţie la ghilimele funcţie de tipul lui TP (string sau numeric) RS.FindFirst Criteriu Do While RS.NoMatch = False ' a găsit o înregistrare cu criteriul introdus

Page 169: 2.VBA_SC4

II-169

MsgBox "Ok - " & RS!N & ";" & RS!A I = I + 1 RS.FindNext Criteriu ' caută următoarea înregistrare care respectă acelaşi criteriu Loop MsgBox "Nr. de inregistrari gasite care au Cimpul A = """ & _ Tp & """ este: " & I

RS.Close Sfirsit: Exit Sub Fis: MsgBox err & " - " & Err.Description, vbCritical Resume Sfirsit End Sub

II.3.10.7. Prelucrarea datelor dintr-un Recordset II.3.10.7.a) Citirea datelor din câmpurile unui Recordset

Un obiect Recordset conţine o colecţie de obiecte Fields. În această colecţie vor fi atâtea obiecte câte câmpuri are Recordsetul respectiv.

Proprietatea implicită a unui obiect câmp este Value care reprezintă valoarea care se găseşte în câmpul respectiv. Ea se poate folosi atât în citire cât şi în scriere (pentru a fi modificată). Exemplu.

Public Sub Rst_CitireSecveniala() ' Deschiderea unui Recordset şi citirea secvenţială a acestuia Dim DB As Database Dim RS As Recordset Dim Eroare As String On Error GoTo Fis Set DB = CurrentDb ' Se deschide în tipul implicit, _ adică cel mai semnificativ care se poate – Table. ' La deschidere, Recordsetul se poziţionează pe prima înregistrare. Set RS = DB.OpenRecordset("Tabela_A") If RS.RecordCount = 0 Then ' Se verifică existenţa înregistrărilor MsgBox "Nu exista inregistrari", vbInformation Exit Sub End If

Page 170: 2.VBA_SC4

II-170

' Se parcurge recordsetul de la prima la ultima înregistrare. Do While Not RS.EOF ' Ciclul se execută cât timp nu se atinge sfârşitul recordsetului. ' Se afişează valorile din câmpuri prin proprietatea implicită Value. ' Pentru referirea unui obiect de tip câmp – semnul de calificare este: (!) MsgBox RS!N & ";" & RS!A RS.MoveNext ' Poziţionare pe următoarea înregistrare. Loop ' Afişează numărul de înregistrări al Recordsetului MsgBox "Numarul de inregistrari = " & RS.RecordCount RS.Close ' Opţional. Se face automat la sfârşitul modulului _ în care s-a declarat Recordsetul. Sfirsit: Exit Sub Fis: MsgBox err & " - " & err.Description, vbCritical Resume Sfirsit End Sub

II.3.10.7.b) Actualizarea datelor din câmpurile unui Recordset

Pentru fiecare tip de actualizare (modificare, adăugare, ştergere) care se efectuează asupra datelor dintr-un Recordset, există metode specifice.

Pentru ca o actualizare să fie acceptată, în primul rând trebuie ca să se respecte următoarele trei condiţii:

• Recordsetul să fie actualizabil. Pentru verificarea acestei condiţii se poate folosi proprietatea Updatable (să fie True).

• Recordsetul să fie deschis în tip Table sau Dynaset, adică în tipurile care acceptă efectuarea de actualizări.

• Actualizarea efectuată să respecte condiţiile de integritate de domeniu, existenţială sau referenţială a tabelelor şi relaţiilor pe care setul de înregistrări este creat.

� Modificarea datelor dintr-un câmp al unui Recordset

Modificarea datelor dintr-un câmp al unei înregistrări dintr-un Recordset se efectuează folosind metodele Recordset Edit şi Update, şi proprietatea Field, Value, astfel:

• Modificarea efectivă a valorii dintr-un câmp al unui Recordset se efectuează prin proprietatea Value (implicită) a câmpului respectiv, în scriere. Pentru ca acest lucru să fie posibil trebuie ca să se procedeze în felul următor:

Page 171: 2.VBA_SC4

II-171

− pointerul de înregistrări se poziţionează pe înregistrarea ale cărui câmpuri se vor modifica; − se lansează metoda Recordset, Edit.

• După efectuarea modificării câmpurilor din înregistrare, aceasta trebuie efectiv rescrisă în Recordset, prin metoda Update.

Deci, modificarea unui câmp dintr-o înregistrare se face prin efectuarea acesteia între metodele Recordset Edit şi Update.

� Dacă modificarea efectuată nu va respecta proprietăţile de integritate setate, metoda Update nu se va executa şi va provoca o eroare de execuţie. Exemplu.

Public Sub Rst_Modificare() Dim DB As Database Dim RS As Recordset Dim I As Integer Dim Tp As String Dim TM As String Dim Criteriu As String On Error GoTo Fis Set DB = CurrentDb ' Se deschide setul de înregistrări în tip Dynaset, _ care permite efectuarea actualizărilor Set RS = DB.OpenRecordset("Tabela_A", dbOpenDynaset) If RS.RecordCount = 0 Then ' Se verifică existenţa înregistrărilor. MsgBox "Nu exista inregistrari", vbInformation Exit Sub End If ' Se verifică ca recordsetul să poată fi modificat If RS.Updatable = False Then MsgBox "Nu se pot efectua modificari", vbInformation Exit Sub End If ' ______Modificarea unui câmp_______ ' Introduce criteriul de selecţie pentru înregistrările ce se vor modifica Tp = InputBox("Valoarea care se va cauta pentru Cimpul A") ' Se introduce valoarea cu care se actualizează TM = InputBox("Valoarea care se va introduce in Cimpul A") I = 0 Criteriu = "[A]=""" & Tp & """"

Page 172: 2.VBA_SC4

II-172

RS.FindFirst Criteriu Do While RS.NoMatch = False ' a găsit o inregistrare ce respectă criteriul MsgBox "Înregistrare Veche:" & RS!N & ";" & RS!A RS.Edit RS!A = TM On Error GoTo Fis1 ' eroare – nu se poate face modificarea RS.Update On Error GoTo Fis I = I + 1 MsgBox "Înregistrare Noua:" & RS!N & ";" & RS!A RS.FindNext Criteriu ' caută următoarea înregistrare care respectă criteriul de selecţie Loop MsgBox "Nr. de inregistrari modificate este: " & I RS.Close Sfirsit: Exit Sub Fis: MsgBox err & " - " & err.Description, vbCritical Resume Sfirsit Fis1: MsgBox "Eroare Actualizare: " & vbCr & err & _ " - " & err.Description, vbCritical Resume Sfirsit End Sub

� Adăugarea unei înregistrări noi într-un Recordset

Adăugarea unei înregistrări noi într-un set de înregistrări se efectuează folosind metodele Recordset AddNew şi Update, şi proprietatea Field, Value, astfel:

• Se poziţionează pointerul pe o înregistrare nouă, prin metoda Recordset, AddNew.

• Se introduc în câmpurile înregistrării valorile dorite, prin folosirea în scriere a proprietăţi Field, Value.

• Se scrie în Recordset înregistrarea nouă prin metoda Update.

� Dacă înregistrarea adăugată nu va respecta proprietăţile de integritate setate, metoda Update nu se va executa şi va provoca o eroare de execuţie.

Page 173: 2.VBA_SC4

II-173

Public Sub Rst_Adaugare() Dim DB As Database Dim RS As Recordset Dim TN As String Dim TA As String On Error GoTo Fis Set DB = CurrentDb ' Se deschide setul de înregistrări în tip Dynaset, _ care permite efectuarea actualizărilor Set RS = DB.OpenRecordset("Tabela_A", dbOpenDynaset) ' Se verifică ca recordsetul să poată fi modificat If RS.Updatable = False Then MsgBox "Nu se pot efectua modificari", vbInformation Exit Sub End If ' ______Adăugarea unei înregistrări________ ' Se introduc de la tastatură valorile pentru câmpurile înregistrării TN = InputBox("Valoarea pentru Cimpul N") TA = InputBox("Valoarea pentru Cimpul A") RS.AddNew RS!N = Val(TN) RS!A = TA On Error GoTo Fis1 ' eroare dacă nu se poate face adăugarea RS.Update On Error GoTo Fis MsgBox "Adaugare efectuata" RS.Close Sfirsit: Exit Sub Fis: MsgBox err & " - " & err.Description, vbCritical Resume Sfirsit Fis1: MsgBox "Eroare Adaugare: " & vbCr & _ err & " - " & err.Description, vbCritical Resume Sfirsit End Sub

Page 174: 2.VBA_SC4

II-174

� Ştergerea unei înregistrări dintr-un Recordset

Ştergerea unei înregistrări dintr-un set de înregistrări se efectuează folosind metoda Recordset Delete, astfel:

• Se poziţionează pointerul pe înregistrare care se va şterge. • Se execută metoda Recordset, Delete.

� Dacă înregistrarea ştearsă va provoca o eroare de integritate referenţială (de exemplu se încearcă ştergerea unei înregistrări dintr-o tabelă părinte, care are copii printr-o relaţie cu integritatea referenţială setată dar nu şi cu ştergerea în cascadă) metoda Delete nu se va executa şi va provoca o eroare de execuţie. Exemplu.

Public Sub Rst_Stergere() Dim DB As Database Dim RS As Recordset Dim I As Integer Dim Tp As String Dim Criteriu As String On Error GoTo Fis Set DB = CurrentDb ' Se deschide setul de înregistrări în tip Dynaset,_ care permite efectuarea actualizărilor Set RS = DB.OpenRecordset("Tabela_A", dbOpenDynaset) If RS.RecordCount = 0 Then ' Se verifică existenţa înregistrărilor. MsgBox "Nu exista inregistrari", vbInformation Exit Sub End If ' Se verifică ca recordsetul să poată fi modificat If RS.Updatable = False Then MsgBox "Nu se pot efectua modificari", vbInformation Exit Sub End If ' ______Stergerea unor înregistrări_____________ ' Se introduce un criteriu de selecţie pentru înreg. ce se vor şterge Tp = InputBox("Valoarea care se va cauta pentru Cimpul A") I = 0 Criteriu = "[A]=""" & Tp & """" RS.FindFirst Criteriu Do While RS.NoMatch = False ' a găsit o înregistrare cu criteriul introdus

Page 175: 2.VBA_SC4

II-175

If MsgBox("Înregistrarea care se sterge:" & _ RS!N & ";" & RS!A, vbOKCancel) = vbOk Then

On Error GoTo Fis1 ' eroare – nu se poate face ştergerea RS.Delete

On Error GoTo Fis I = I + 1

End If RS.FindNext Criteriu ' caută următoarea înregistrare care respectă acelaşi criteriu Loop MsgBox "Nr. de inregistrari sterse este: " & I RS.Close Sfirsit:

Exit Sub Fis: MsgBox err & " - " & err.Description, vbCritical Resume Sfirsit Fis1: MsgBox "Eroare Stergere " & vbCr & _ err & " - " & err.Description, vbCritical Resume Sfirsit End Sub

II.3.11. Recordseturi definite pe cereri

O cerere de selecţie poate să fie obiectul de intrare al unui set de înre-gistrări în două moduri:

• Direct, definind ca obiect al setului de înregistrări cererea respectivă (ca în exemplele de până acum).

• Executând în prealabil anumite acţiuni asupra cererii. De exemplu dacă este necesară introducerea unor parametri în cerere, direct din cod.

Crearea Recordsetului în acest caz se face aplicând metoda OpenRecordset a cererii, ca în următorul exemplu. Exemplu.

Public Sub Rst_Query() ' Creează un recordset pe baza unei cereri de selecţii cu parametri Dim DB As Database Dim QRY As QueryDef Dim RS As Recordset

Page 176: 2.VBA_SC4

II-176

Const NumeCerere = "Cerere_A" ' Numele cererii Set DB = CurrentDb ' Baza de date din aplicaţia curentă ' Se introduce cererea în variabila obiect QRY Set QRY = DB.QueryDefs(NumeCerere) ' se dau valori parametrilor cererii QRY.Parameters("Numar") = "2" Set RS = QRY.OpenRecordset ' Se defineşte recordsetul pe cerere If RS.RecordCount = 0 Then MsgBox "Nu exista inregistrari selectate", vbInformation Exit Sub End If Do While Not RS.EOF ' se parcurge secvenţial RS MsgBox "Înregistrare selectată:" _ & RS!N & ";" & RS!A RS.MoveNext Loop End Sub

II.3.12. Recordseturi definite pe alte Recordseturi

Un set de înregistrări poate fi definit pe un alt set de înregistrări, după ce asupra acestuia se efectuează anumite prelucrări.

Această metodă se aplică de obicei dacă se doreşte sortarea sau filtrarea în prealabil a setului de înregistrări.

Crearea Recordsetului în acest caz se face aplicând metoda OpenRecordset a primului Recordset, ca în următorul exemplu, folosit pentru sortarea unui Recordset.

� Pentru sortarea unui Recordset, se foloseşte proprietatea Sort a Recordsetului, care are următoarea formă:

recordset.Sort="CheieSort_1 [Asc] | Desc[,CheieSort_2 [Asc] | Desc].."

� Aşa cum se observă se permite sortarea după mai multe chei, în ordine ascendentă (implicit) sau descendentă.

� Recordsetul de tip Table, nu se poate sorta. Exemplu.

Public Sub Rst_Sortare() ' Deschiderea unui Recordset şi sortarea acestuia Dim DB As Database Dim RS As Recordset

Page 177: 2.VBA_SC4

II-177

Dim RSS As Recordset On Error GoTo Fis Set DB = CurrentDb ' Se deschide în tipul Dynaset. Nu este permisă sortarea pe tipul Table Set RSS = DB.OpenRecordset("Tabela_A", dbOpenDynaset) If RSS.RecordCount = 0 Then ' existenţă înregistrări? MsgBox "Nu exista inregistrari", vbInformation Exit Sub End If RSS.Sort = "N Desc" ' Se sortează recordsetul după cheia N în ordine descrescătoare Set RS = RSS.OpenRecordset ' Se deschide al doilea recordset, pe primul care e acum sortat ' Se parcurge recordsetul sortat de la prima la ultima înregistrare. Do While Not RS.EOF ' MsgBox RS!N & ";" & RS!A RS.MoveNext ' Poziţionare pe următoarea înregistrare. Loop ' Afişează numărul de înregistrări al Recordsetului MsgBox "Numarul de inregistrari = " & RS.RecordCount Sfirsit: Exit Sub Fis: MsgBox err & " - " & err.Description, vbCritical Resume Sfirsit End Sub

II.3.13. Accesul la obiecte externe de date

În Access este posibil ca să se folosească obiecte de date (de tip tabel) de o multitudine de tipuri create în alte aplicaţii. Aceasta se poate face ori prin legare (Linked), ori prin încapsulare (Embedded).

Există două metode de realizare a acestui lucru: • Din meniu prin comanda File | Get External Data • Prin metodele obiectului DoCmd:

− DoCmd.TransferDatabase – pentru obiecte din baze de date Access, Fox, DBase etc. − DoCmd.TransferSpreadsheet – pentru foi de calcul din MS Excel.

Page 178: 2.VBA_SC4

II-178

− DoCmd.TransferText – pentru date introduse sub formă de înregistrări (cu separatori sau de lăţime fixă pentru stabilirea câmpurilor (coloanelor) în fişiere de tip text. Pentru acest tip de transfer este necesară definirea unei specificaţii de import/export, care se crează atunci când se efectuează manual o operaţie de import (Get External Data) sau export (Save As).

� Şi operaţia inversă, de export din Access a obiectelor acestuia, în diferite tipuri de baze de date, este posibilă.

Page 179: 2.VBA_SC4

II-179

II.4. Obiecte provenite din clase externe

II.4.1. Standarde de utilizare a obiectelor externe

Platforma Windows, permite utilizarea într-o aplicaţie (numită client) a obiectelor provenite din alte aplicaţii (numite server).

Există două tehnologii (standarde industriale) care permit acest lucru şi anume:

− Tehnologia OLE – Object Linked and Embedded; − Tehnologia Automation OLE (sau pe scurt Automation).

II.4.1.1. Tehnologia OLE

Tehnologia OLE permite ca într-o aplicaţie client să se folosească obiecte provenite dintr-o aplicaţie server, prin lansarea acesteia chiar în aplicaţia client, în scopul manipulării obiectului respectiv.

Lansarea aplicaţiei server prin care a fost creat obiectul se face din meniul contextual al acestuia sau prin dublu click.

Evident, în cazul tehnologiei OLE, este necesar ca aplicaţia server să fie instalată pe sistemul de calcul în care se utilizează aplicaţia client.

Există două forme de implementare a acestei tehnologii, în funcţie de locul unde va fi memorat obiectul respectiv şi anume:

• Embedded (încapsulare) – obiectul este memorat în aplicaţia client, având o existenţă independentă. Deci, obiectul respectiv va exista efectiv în ambele aplicaţii şi eventuala modificare a obiectului din aplicaţia server nu se va produce şi în aplicaţia client sau invers. În aplicaţia DAO.mdb, în formularul F_OLE, este prezent un astfel de obiect creat în Word, şi plasat în controlul ObiectOLE.

• Linked (legare) – obiectul va exista numai în aplicaţia server, în aplicaţia client memorându-se numai adresa acestuia, în scopul folosirii obiectului respectiv şi din aceasta. Deci, obiectul, dacă va fi modificat în oricare dintre aplicaţii, atunci această modificare se va regăsi şi în cealaltă aplicaţie (există un singur obiect folosit de ambele aplicaţii).

II.4.1.2. Tehnologia Automation. Obiecte ActiveX

Automation OLE (sau Automation) este un standard industrial, care permite crearea de către aplicaţiile server a unor obiecte independente (acestea nu mai au nevoie de aplicaţia server pentru a fi utilizate). Deci, un obiect creat prin această metodă va putea fi utilizat într-o aplicaţie client, indiferent dacă este sau nu instalată aplicaţia server.

Page 180: 2.VBA_SC4

II-180

Obiectele create prin tehnologia Automation se numesc ActiveX. Ele pot fi controale sau biblioteci de obiecte, şi sunt definite de clasele de obiecte din aplicaţiile server (create de utilizator sau existente deja).

Microsoft Access este o componentă ActiveX, care are implementată tehnologia Automation. Aceasta face posibilă folosirea obiectelor sale compo-nente (sau a întregii aplicaţii) şi din alte aplicaţii (Microsoft Visual Basic, Microsoft Excel, Microsoft Word etc.) care suportă de asemenea tehnologia Automation. De asemenea şi inversa acestei afirmaţii e adevărată.

Accesarea componentelor dintr-o aplicaţie Microsoft Access se face, aşa cum am mai arătat, prin obiectul Application.

De exemplu din Microsoft Visual Basic (care este un ActiveX) sau dintr-o aplicaţie Access, se poate deschide o bază de date Microsoft Access şi se pot folosi obiectele acesteia.

Pentru aceasta trebuie: 1) să se efectueze o referinţă către biblioteca Microsoft Access;

2) să se creeze o nouă instanţă a clasei Access-Application, care să fie asignată la o variabilă obiect:

Dim appAccess As New Access.Application

� Pentru aplicaţiile care nu suportă clauza NEW, se poate crea o nouă instanţă a clasei Access-Application folosind funcţiile CreateObject sau GetObject. Deci în MS Access există două funcţii prin care se pot folosi în VBA obiecte ActiveX şi anume:

− CreateObject, prin care se pot crea noi instanţe ale unui ActiveX. Dim appAccess As Object Set appAccess = CreateObject("Access.Application.8")

− GetObject, prin care se poate utiliza un obiect ActiveX, creat deja şi aflat într-un fişier.

3) După crearea unei noi instanţe a clasei Access-Application, se poate deschide sau crea în aceasta o bază de date (cu metodele: OpenCurrentDatabase sau NewCurrentDatabase) sau seta proprietăţi şi executa metode.

Exemplu. Utilizarea dintr-o aplicaţie Access a unei alte aplicaţii Access. Private Sub AccessExtern() ' ---- Se va lucra cu fişierul Access introdus OpenMdb InputBox("Introduceti numele unui _ fişier de tip MDB(creat sau nou)") End Sub '-------------------- Private Function OpenMdb(ByVal NumeBd As String) As Boolean ' Folosirea funcţiei CreateObject, într-o nouă instanţă Access

Page 181: 2.VBA_SC4

II-181

Const ErDejaCreat = 7865 Dim appAccess As Object ' --- Se poate înlocui această declaraţie cu: _ Dim appAccess As New Access.Application _ --- (deoarece este admisă în Access folosirea clauzei New) _ --- caz în care se va renunţa la funcţia CreateObject Dim Bd As Database Dim frm As Form Dim Ultim As Integer On Error GoTo Er ' Face o instanţă nouă pentru Access Set appAccess = CreateObject("Access.Application.8") ' Creeaza o nouă BD "NumeBd" în instanţa creată ' Daca există deja BD se va genera eroarea: ErDejaCreat = 7865, _ şi se va deschide BD respectivă appAccess.NewCurrentDatabase NumeBd Reia: ' …… Se efectuează prelucrări în baza de date ' Crează un formular nou, "FormTest" Set frm = appAccess.Application.CreateForm ' Setează câteva proprietăţi ale formularului With frm .Caption = "FormTest" .ScrollBars = 0 .NavigationButtons = True End With appAccess.DoCmd.Restore ' Închide formularul creat / Se salvează cu numele FormTest appAccess.DoCmd.Close appAccess.DoCmd.OpenForm "FormTest" ' Se redeschide în View ' Calculează Numărul din colectia Forms a ultimului formular deschis Ultim = appAccess.Application.Forms.Count - 1 MsgBox "S-a deschis în Baza de date: " & NumeBd & vbCr & _ "- Formularul:" & appAccess.Application.Forms(Ultim).NAME ' În var BD se va introduce din structura DAO, _ baza de date locală, ce se găseşte în instanţa Access nou creată Set Bd = _ appAccess.Application.DBEngine.Workspaces(0).Databases(0)

Page 182: 2.VBA_SC4

II-182

MsgBox "Nr de tabele din: " & NumeBd & " este " & Bd.TableDefs.Count Bd.Close '----------------------------- appAccess.CloseCurrentDatabase ' Close Database appAccess.Quit ' Close instanţa Access OpenMdb = True ' Prelucrarea s-a efectuat corect SF: Exit Function Er: If err.Number = ErDejaCreat Then ' Baza de date există deja ' Deschide BD "NumeBD" în instanţa creată appAccess.OpenCurrentDatabase NumeBd Resume Reia ' reia prelucrarea după ce se poate accesa BD Else MsgBox "Eroare la deschiderea fisierului MDB '" & _ NumeBd & "'" & vbCr & vbCr & err.Number & _ " -ExpAccess- " & err.Description, vbCritical Resume SF End If End Function

------------------

Din exemplul prezentat se observă că prin obiectul Application se pot utiliza toate obiectele unei aplicaţii MS Access.

Astfel prin proprietatea obiectului Application, DBEngine, care întoarce referinţa obiectului DBEngine, s-au accesat toate obiectele şi colecţiile modelului DAO.

De asemenea, se pot lansa comenzi utilizând metodele obiectului DoCmd, ca în exemplul de mai jos în care s-a deschis formularul "FormTest" al aplicaţiei:

appAccess.DoCmd.OpenForm "FormTest" ------------------

Majoritatea produselor create de firma Microsoft au implementat standardul Automation (ca şi standardul OLE).

Aplicaţiile MS Office: Access, Excel, Word etc. oferă sub formă de ActiveX obiectele din bibliotecile standard. Deci o aplicaţie Excel sau Word poate fi considerată ca un obiect ActiveX, şi utilizată într-o aplicaţie Access.

Page 183: 2.VBA_SC4

II-183

� În Anexa 1 şi Anexa 2 sunt prezentate structurile arborescent-ierarhice ale obiectelor din modelele MS Word şi MS Excel. Cunoaşterea acestor structuri va permite folosirea în aplicaţiile Access a tuturor facilităţilor oferite de cele două aplicaţii Microsoft.

Evident, pentru utilizarea unui obiect extern, este necesară cunoaşterea structurii acestuia, a proprietăţilor, metodelor şi evenimentelor sale. În Access, structura unei biblioteci de obiecte se poate afla prin comanda din meniul View | Object Browser.

Totuşi nu toate aplicaţiile MS Office pot crea clase noi de obiecte care să furnizeze în exterior obiectele sub forma unor ActiveX. De exemplu în Access, se pot crea clase noi de obiecte, dar utilizarea obiectelor provenite din acestea este numai internă aplicaţiei. Exemplu. În aplicaţia DAO.mdb, în formularul F_OLE, la acţionarea evenimentului click al butonului de comandă, este lansată procedura eveniment de mai jos, prin care se creează o instanţă nouă a unei aplicaţii Excel, în care se deschide o foaie de calcul ce se găseşte într-un fişier aflat în acelaşi director cu aplicaţia Access.

Private Sub ButonExcel_Click() Dim DirectorAplicatie As String Dim AplicatiaMdb As String Dim BD As Database Dim i As Integer, j As Integer Dim App As Object Set BD = CurrentDb ' Se preia numele complet al fişierului cu aplicaţia curentă AplicatiaMdb = BD.NAME Do' În i -poziţia ultimului "\" care delimitează directorul unde este fişierul i = InStr(j + 1, AplicatiaMdb, "\") If i = 0 Then Exit Do j = i Loop ' Directorul unde este fişierul cu aplicaţia curentă DirectorAplicatie = Left(AplicatiaMdb, j) ' Se creează un obiect ActiveX, Excel Set App = CreateObject("Excel.Application") App.Visible = True ' Se face vizibil obiectul ActiveX – Aplicaţia Excel ' Se deschide aplicaţia Excel "Foaie.xls" _ ce se găseşte în acelaşi director cu aplicaţia curentă App.Workbooks.Open DirectorAplicatie & "Foaie.xls" End Sub

Page 184: 2.VBA_SC4

II-184

Microsoft Visual Basic, este un produs care permite şi crearea de clase noi de obiecte, care să-şi ofere obiectele sub forma unor ActiveX (controale, biblioteci) aplicaţiilor client.

În cele ce urmează ne vom referi la utilizarea în aplicaţiile client (Access) a obiectelor create din clase de obiecte externe, prin folosirea standardului Automation.

II.4.2. Crearea referinţei către un obiect extern

La proiectarea unui formular (sau raport) Access, implicit, pe bara cu instrumente sunt plasate cele mai utilizate controale folosite, Text Box, Combo Box, Label, Option Button, Command Button etc, care sunt livrate în pachetul Access.

� Referinţa către controalele externe ActiveX

Realizarea standardizată a controalelor de tip ActiveX, prin tehnologia Automation permite utilizarea într-o aplicaţie client, a tuturor controalelor provenite din clase de obiecte, indiferent de firma producătoare sau de aplicaţia server în care au fost realizate.

Controalele ActiveX se găsesc de obicei într-un fişier cu extensia .OCX, în directorul C:\Windows\System. Simpla plasare a acestora pe discul calculato-rului nu permite însă folosirea lor de către aplicaţia client.

Pentru utilizarea unui control ActiveX, este necesar ca pentru acesta să se creeze o referinţă în aplicaţia Access (sau altă aplicaţie client).

Operaţia de creare într-o aplicaţie client a unei referinţe către un obiect extern, în vederea utilizării acestuia se mai numeşte înregistrarea obiectului.

În Access, înregistrarea unui ActiveX se face prin comanda: Tools | ActiveX Controls, prezentată în figura de mai jos.

Page 185: 2.VBA_SC4

II-185

Cele două butoane ale comenzii, Register şi Unregister, permit atât crearea cât şi anularea referinţelor la controale ActiveX.

• După acţionarea butonului: Register, sistemul solicită utilizatorului să introducă numele complet al fişierului care conţine un ActiveX, pentru a-l înregistra.

• Operaţia inversă, de anulare a înregistrării unui ActiveX, se face prin selecţia unui control după care se apasă pe butonul Unregister.

� Referinţa către bibliotecile externe ActiveX

Aşa cum am mai arătat, Access foloseşte în principal 3 biblioteci, DAO, ACCESS, VBA. Totuşi se pot folosi (cu aceeaşi tehnologie, Automation, ca şi la controalele ActiveX) şi alte biblioteci create de aplicaţii server.

Pentru utilizarea acestora, după copierea fişierului cu biblioteca (de obicei cu extensia .OLB sau .DLL) în acelaşi director, C:\Windows\System, trebuie creată referinţa printr-o comandă similară, Tools | References.

� Atât controalele cât şi bibliotecile ActiveX, sunt considerate nişte aplicaţii independente. Utilizarea lor impune aceleaşi restricţii privind drepturile de folosire (licenţa) ca şi la orice alt produs.

II.4.3. Folosirea unui control ActiveX, într-un formular sau raport

După înregistrare, introducerea într-un formular (raport) a unui control ActiveX se poate face în două feluri:

� Prin comanda "Insert ActiveX Controls", lansată ori de pe bara cu instrumente ori din meniul Access.

� Prin plasarea controlului direct pe bara de instrumente (în cazul utilizării frecvente a unui control ActiveX). Pentru aceasta se va proceda astfel:

Page 186: 2.VBA_SC4

II-186

− Se lansează comanda Customize, prin meniul contextual al oricărui taskbar. − Se poziţionează comanda Customize în pagina a doua, Commands. − În fereastra stângă, Categories, se selectează "ActiveX Controls". − Din fereastra din dreapta, Commands, se trage (Drag and Drop) cu mouse-ul controlul respectiv, pe bara de instrumente.

II.4.4. Controlul ProgressBar

Controlul ProgressBar este folosit pentru a prezenta vizual cum evoluează în timp execuţia unei operaţii al cărei nivel de realizare poate fi cuantificat numeric în codul de program, printr-o valoare care aparţine unui anumit interval.

Controlul ProgressBar este definit prin setarea a două condiţii: � Rangul controlului. Reprezintă intervalul care stabileşte valorile

extreme, minimă şi maximă, ale evoluţiei procesului respectiv. Deci el defineşte întreaga durată a operaţiei.

� Poziţia curentă a controlului. Este o valoare numerică aflată în intervalul definit de rangul controlului, care stabileşte poziţia relativă pe care o are "clepsidra" în control, adică cât din suprafaţa acestuia este umplută (zona albastră din figură).

------------------

Aceste valori sunt introduse prin proprietăţile cele mai semnificative ale controlului ProgressBar:

− Min – defineşte valoarea minimă a rangului (intervalului) controlului ProgressBar. − Max – defineşte valoarea maximă a rangului (intervalului) controlului ProgressBar. − Value – defineşte valoarea poziţiei curente a controlului ProgressBar. Dacă valoarea introdusă depăşeşte rangul, atunci se va produce o eroare de execuţie.

Restul proprietăţilor controlului ProgressBar sunt cele obişnuite de confi-gurare a marginilor, de vizibilitate etc.

Două proprietăţi specifice se referă la forma de afişare a controlului şi anume: − Orientation – pentru direcţia controlului, orizontal sau vertical. − Scrolling – pentru felul în care se deplasează clepsidra, în scroll (continuu ca în exemplu) sau în trepte (standard).

Exemplu. Mai jos se prezintă codul aflat în formularul F_ ProgressBar, din fişierul DAO.Mdb.

Acesta simulează printr-un control ProgressBar, PBar, funcţionarea unui cronometru, care va fi iniţializat cu o valoare introdusă în caseta de text, CTimp şi va porni automat după introducerea acesteia.

Page 187: 2.VBA_SC4

II-187

Figura prezentată este cea a formularului în timpul execuţiei sale.

Option Compare Database Option Explicit '---------------------------------- Private Sub Form_Open(Cancel As Integer) ' La desc. form Me!PBar.Visible = False ' Iniţial ProgressBar nu va fi vizibil. End Sub '------------------------------------ Private Sub CTimp_AfterUpdate() ' Valoarea din CTimp reprezintă secunde de cronometrat – clepsidra plină Dim Timp As Variant Timp = Me!CTimp If IsNumeric(Timp) And Timp >= 1 Then ' Se stabileşte domeniul de valori pentru controlul Progress Bar. Me!PBar.Max = Timp ' Valoarea maximă – pt. clepsidra plină ' Valoarea maximă – clepsidra plină Me!PBar.Min = 0 ' Valoarea minimă – pt. clepsidra goală Me!PBar.Value = Me!PBar.Max ' Val. la început a clepsidrei – plin Me!PBar.Visible = True ' Se face vizibil controlul Me.TimerInterval = 1000 ' Se setează evenimentul Timer la 1 sec. Else MsgBox "Introduceţi un număr de secunde!!", vbCritical End If End Sub '------------------------------------ Private Sub Form_Timer() ' Se execută o dată la fiecare secundă Me!CTimp = Me!CTimp - 1 ' Se scade 1 din contorul de secunde ' Se stabileşte valoarea clepsidrei la nivelul actual al timpului rămas Me!PBar.Value = Me!CTimp If Me!PBar.Value = 0 Then ' Clepsidra s-a golit – timpul a expirat Me.TimerInterval = 0 ' Se anulează evenimentul TIMER Me!PBar.Visible = False ' Se face invizibil controlul Progress Bar End If End Sub

� Controlul ProgressBar, face parte din grupul de controale ActiveX, care se găsesc în fişierul COMCTL32.OCX, din pachetul de distribuţie Visual Basic.

Page 188: 2.VBA_SC4

II-188

II.4.5. Controlul Common Dialog

Controlul Common Dialog este utilizat foarte des în aplicaţiile Windows în special pentru introducerea unui nume complet de fişier (cu extensie şi cale) în modulele de salvare sau deschidere de fişiere.

Controlul este invizibil, fereastra specifică acestuia (vezi figura de mai jos) devenind activă numai din momentul lansării metodei Action şi până când se închide fereastra acestuia prin 'apăsarea' pe butoanele Open sau Cancel (echivalent cu butonul X al ferestrei).

Configurarea controlului se face prin setarea unor proprietăţi ale acestuia, dar evident înainte de lansarea metodei Action.

� Proprietăţile cele mai utilizate în folosirea controlului la operaţiile de salvare/ deschidere de fişiere sunt:

• Title – se introduce un text care se va afişa în partea de sus a controlului (zona albastră de titlu a ferestrei);

• InitDir – reprezintă calea care va indica directorul al cărui conţinut se vizualizează. Aceasta va fi afişată în zona Look in;

• DefaultExt – este o extensie care va fi întoarsă dacă nu se specifică în mod explicit tipul fişierului;

• Filter – prin acesta se configurează caseta Files of Type, care va controla ce fişiere vor fi afişate din directorul selectat.

Ea reprezintă un string, în care se introduc mai multe informaţii (multiplu de 2) separate prin caracterul ( | ).

O pereche de 2 informaţii reprezintă: 1) Textul afişat în căsuţă (în exemplu Fişier Access) 2) Un nume de fişier (cu extensie) în care sunt permise caracterele

generice (*,?) şi care va genera o mulţime de nume care vor constitui un filtru pentru fişierele care se afişează.

Page 189: 2.VBA_SC4

II-189

De exemplu perechea: " Toate tipurile Access | *.md? ", va determina afişarea tuturor fişierelor care au extensia din 3 caractere dintre care primele două sunt "MD".

• FileName – corespunde numelui introdus în caseta File Name a controlului. Este folosit atât ca parametru de intrare (dacă se doreşte o iniţializare a casetei) dar în special ca parametru de ieşire, deoarece această proprietate va conţine la ieşire numele complet (cu cale şi extensie) ales de utilizator prin folosirea controlului.

� Aşa cum am mai arătat, metoda controlului este Action. Există 5 forme ale controlului specific pentru anumite operaţii şi anume:

− Action = 1; Open – se foloseşte de obicei pentru preluarea din fereastra Windows Explorer, a unui nume complet de obiect, de obicei fişier, asupra căruia se vor efectua anumite prelucrări în citire;

− Action = 2; Save – se foloseşte de obicei pentru introducerea unui nume complet de fişier (nou sau existent) care va fi creat (sau eventual rescris dacă există deja);

− Action = 3; Color – se foloseşte pentru aflarea codului unei anumite culori selecţionate dintr-o listă (de exemplu cu care se pot configura dinamic culorile unui control);

− Action = 4; Font – se foloseşte pentru selecţionarea dintr-o listă a unei fonte (de exemplu cu care se poate configura dinamic fonta folosită într-un control Text Box);

− Action = 5; Print. Ieşirea din metodă se face prin apăsarea butonului: • Open (Save) – care face ca proprietatea FileName să se configureze

corespunzător, adică calea afişată + numele introdus + extensia implicită (dacă numele nu o conţine explicit) sau

• Cancel – care face ca proprietatea FileName, să nu se modifice. Acelaşi lucru se produce dacă se închide fereastra prin comanda Close de închidere a ferestrei – butonul (X) din colţul dreapta sus. Explicaţie. Action, aşa cum se vede şi din utilizarea ei, este o proprietate. Totuşi ea având o acţiune în momentul setării ei (vizualizarea controlului în una din cele 5 forme specificate), practic se comportă ca o metodă.

Versiunile mai noi ale controlului au introdus 5 metode, care se pot folosi în locul lui Action. Aceste metode sunt: ShowOpen, ShowSave, ShowColor, ShowFont, ShowPrinter. Explicaţie. Dacă se iese din controlul Common Dialog, prin butonul Cancel, se poate provoca apariţia unei erori de execuţie specifice, cu codul 32755, dacă în prealabil se setează proprietatea acestuia CancelError cu True.

Page 190: 2.VBA_SC4

II-190

Exemplu. Funcţia CitireCD se găseşte în formularul F_CdialogContainer al aplicaţiei DAO.Mdb

Private Function CitireCD() As Variant ' - Întoarce numele complet introdus prin controlul Common Dialog _ - Dacă funcţia întoarce NULL atunci s-a ieşit prin _ butonul Cancel din Common Dialog '------------------------------------------- ' Parametrii de iniţializare pt. configurarea controlului Common Dialog ' Intrare – Titlul pus în caseta Common Dialog Me!CD.DialogTitle = "Selectati fisierul cu Baza de date" ' Intrare – Extensia implicită a numelui de fişier introdus _ Se foloseşte de obicei la Comanda de salvare Me!CD.DefaultExt = "Mdb" ' Intrare – Directorul implicit pentru poziţionarea iniţială _ a casetei Common Dialog Me!CD.InitDir = "" ' Intrare – Filtrul de selecţie pentru fişierele afişate _ Se introduc câte două informaţii (separatorul este caracterul (|) _ pentru fiecare rând afişat în caseta de selecţie: _ 1- Numele afişat pentru precizarea selecţiei ce se efectuează _ 2- Mulţimea numelor care se vor selecţiona _ prin folosirea caracterelor generice (*) şi (?) Me!CD.Filter = "Fisier Access|*.Mdb|All|*.*" ' Comenzile posibile ce se pot efectua: _ Action: = 1-Open / = 2-Save / = 3-Color / = 4-Font / = 5-Print Me!CD.FileName = "" 'Initializare nume fisier Me!CD.Action = 1 ' Open – Se dă controlul casetei Common Dialog _ ' La Iesire – Numele complet (cu cale şi extensie) a fişierului selecţionat _ Dacă se întoarce un string gol("") atunci s-a ieşit prin Cancel If Me!CD.FileName = "" Then CitireCD = Null ' ieşire prin apăsarea butonului Cancel Else CitireCD = Me!CD.FileName End If End Function

� Controlul Common Dialog se găseşte în fişierul COMDLG32.OCX, care face parte din pachetul de distribuţie al pachetului Visual Basic.

Page 191: 2.VBA_SC4

II-191

II.5. Module de clase de obiecte

II.5.1. Programarea prin clase de module

În Microsoft Access, în modulul general de cod, există posibilitatea creării a două tipuri de module:

1) Modulele standard – prezentate deja; 2) Modulele de clase – care permit configurarea unor obiecte noi, numite

obiecte programabile (customize object). Crearea unui modul de clasă se face prin comanda Insert | Class Module. Numele cu care este salvată clasa devine numele tipului de date al

obiectelor ce se vor crea din aceasta. Din punct de vedere structural modulele de clase sunt la fel cu cele

standard. De asemenea toate declaraţiile şi instrucţiunile folosite în modulele standard se pot folosi şi în cele de clasă, având aceeaşi semnificaţie.

II.5.2. Crearea prin clasele de module a obiectelor programabile

Prin clasele de module se crează definiţiile pentru obiectele programabile. Acestea sunt:

• Metodele obiectului vor fi definite de toate rutinele publice (proceduri sau funcţii) ce se găsesc în clasa de module.

• Proprietăţile obiectului. Există două posibilităţi de definire a acestora şi anume:

− prin nişte tipuri noi de rutine: Property Let, Property Get şi Property Set, declarate public în clasa de module; − prin orice variabilă public definită în partea de declaraţii a clasei de module.

• Evenimentele obiectului. Într-un modul de clasă există definite două evenimente şi anume:

− Evenimentul Initialize – care se produce înainte de execuţia primei accesări a unei proprietăţi sau metode a obiectului programabil (similar evenimentului Open de la formulare); − Evenimentul Terminate – care se produce în momentul ştergerii obiectului programabil (similar evenimentului Close de la formulare);

Crearea unui obiect programabil se va realiza prin crearea unei noi instanţe a clasei de module, care va referi obiectul respectiv. Există două posibilităţi de creare a unei instanţe şi anume:

• declararea unei variabile cu clauza New, de tipul clasei de module; • declararea unei variabile obiect generale, după care în prima instruc-

ţiune Set a acesteia se introduce clauza New;

Page 192: 2.VBA_SC4

II-192

Exemplu. Dacă există în modulul general de cod o clasă de module cu numele C_Amestec, atunci se va crea o nouă instanţă a acestei clase (un nou obiect programabil) prin instrucţiunea:

Dim vCls As New C_Amestec După această declaraţie, se pot folosi metodele şi proprietăţile definite

pentru clasa C_Amestec, prin intermediul variabilei vCls, care reprezintă o instanţă nouă a clasei.

Dacă există definită o metodă cu numele Culoare şi o proprietate cu numele Verde, atunci acestea se pot folosi în instanţa nou creată astfel:

vCls.Culoare MsgBox vCls.Verde

� Utilizarea proprietăţilor sau metodelor unui obiect programabil se va face în modul obişnuit, adică prin calificarea numelui acestora cu numele obiectului programabil.

� După declararea unui obiect programabil (instanţă a unei clase de module), sistemul va "cunoaşte" structura acestuia. Atunci când se va utiliza obiectul, după ce se va tasta semnul de calificare (.) se va deschide o listă ascunsă care va conţine toate proprietăţile şi metodele sale.

II.5.3. Instanţe implicite ş i instanţe neimplicite

� Instanţele implicite şi neimplicite ale clasei de module

Atunci când se creează o nouă instanţă a unei clase de module (prin declararea unei variabile de tipul respectiv, cu clauza New), se rezervă practic o zonă de memorie în care se va forma noul obiect programabil, care va avea o existenţă separată pe întreaga sa durată de viaţă. Durata de viaţă a unei instanţe este la fel ca la orice variabilă şi anume între momentul declarării ei şi până în momentul în care se închide modulul în care a fost declarată (se poate şterge o instanţă forţat şi prin intermediul clauzei Nothing). De asemenea setările care se fac în instanţa respectivă se vor pierde o dată cu ştergerea ei (anulare, închidere).

Definirea unei astfel de instanţe reprezintă ceea ce se numeşte instanţă neimplicită. Numărul instanţelor neimplicite poate fi oricât de mare.

Sistemul oferă definirea şi a unei singure instanţe implicite, care este chiar aceea în care se defineşte clasa de module. Numele obiectului din instanţa implicită este chiar numele clasei de module. Evident că dacă această instanţă este în modulul general de cod, ea va exista atât timp cât aplicaţia Access funcţionează, modificările proprietăţilor menţinându-se pe întreaga sa durată. Exemplu. Dacă în clasa de module C_Test există o proprietate pCul (definită prin declaraţia: Public clTest as Integer), atunci:

Sub Test ExClasa

Page 193: 2.VBA_SC4

II-193

' Se va afişa: ' Instanţa C1=10 ' Instanţa Implicită=10 ' Instanţa C2=20 ExClasa 'Se va afişa: ' Instanţa C1=10 – instanţă nouă ' Instanţa Implicită=20 – instanţa implicită a rămas activă ' Instanţa C2=30 – instanţă nouă ExClasa ' Se va afişa: ' Instanţa C1=10 – instanţă nouă ' Instanţa Implicită=30 – instanţa implicită a rămas activă ' Instanţa C2=40 – instanţă nouă End Sub

Sub ExClasa Dim C1 as New C_Test ' Instanţă neimplicită a clasei clTest Dim C2 as New C_Test ' Instanţă neimplicită a clasei clTest C1.pCul = C1.pCul + 10 ' se lucrează cu instanţa neimplicită C1 MsgBox "Instanţa C1=" & C1.pCul C_Test.pCul = C_Test.pCul + 10 ' se lucrează cu instanţa implicită MsgBox "Instanţa Implicită=" & C_Test.pCul Set C2 = C_Test ' Se introduce în ea instanţa implicită C2.pCul = C2.pCul + 10 ' se lucrează cu instanţa neimplicită C2 MsgBox "Instanţa C2=" & C2.pCul End Sub

� Instanţele implicite şi neimplicite ale clasei form de module

În Access, crearea unui formular este de fapt crearea unei clase form de modul, care va avea numele formularului respectiv la care se adaugă prefixul (Form_). Din această clasă de module, conform celor prezentate anterior, se pot crea mai multe instanţe neimplicite şi o instanţă implicită.

Instanţa implicită a respectivului formular se creează atunci când se deschide formularul printr-una din următoarele 4 posibilităţi:

• Interfaţa utilizator din fereastra Database; • Funcţia CreateForm. Deoarece aceasta creează formularul în Design,

este necesară trecerea lui ulterioară în View; • Metoda OpenForm a obiectului DoCmd; • Declararea în VBA a unei variabile de tip Form, care va referi instanţa

implicită, prin execuţia unei instrucţiuni Set.

Page 194: 2.VBA_SC4

II-194

Dim Vf As Form DoCmd.OpenForm "NumeFormular" Set Vf = Forms("NumeFormular")

� În VBA, există o facilitate deosebită privind deschiderea rapidă a unui formular şi anume: dacă se foloseşte o proprietate sau o metodă a unui formular (nu este permisă eventuala deschidere a acestuia în Design), atunci automat formularul se deschide, dar nu este vizbil. Deci se poate înlocui ultima secvenţă de deschidere a unei instanţe implicite cu:

Dim Vf As Form Form_NumeFormular.Visible=True

' Se deschide formularul în instanţa implicită (Form_NumeFormular) _ şi se face vizibil

Set Vf = Forms("NumeFormular") Instanţele neimplicite ale formularului se pot crea (aşa cum am mai

arătat) prin: • Declararea, folosind clauza New, a unei variabile de tipul clasei de

modul a formularului respectiv. • Trecerea pe True a proprietăţii Visible a formularului.

Dim Vf As New Form_ NumeFormular Vf.Visible=True

� Un formular deschis într-o instanţă neimplicită se poate închide ori prin buto-nul de închidere al formularului ori prin ştergerea variabilei form care îl referă. Exemplu.

Option Compare Database Option Explicit Dim Vf3 As New Form_F_FormOpen '------------------------------------------------ Sub Test_InstanteFormulare() Dim Vf1 As New Form_F_FormOpen Dim Vf2 As New Form_F_FormOpen Dim Vf As Form ' Cât timp rutina se execută _ evenimentele formularelor deschise sunt blocate Dim NF As Integer ' Se deschide instanţa implicită DoCmd.OpenForm "F_FormOpen" ' Se poate înlocui cu: ' Form_F_FormOpen.Visible = True NF = Forms.Count - 1

Page 195: 2.VBA_SC4

II-195

MsgBox "Numar:" & NF & " -Nume:" & Forms(NF).NAME ' va afişa: Numar:0 -Nume:F_FormOpen Set Vf = Forms(NF) ' Se asignează instanţa implicită la Vf Vf.Caption = Vf.Caption & " - Instanţa implicită" '------------ ' Se deschide prima instanţa neimplicită Vf1.Visible = True ' Vor fi 2 formulare F_FormOpen pe ecran NF = Forms.Count - 1 MsgBox "Numar:" & NF & " -Nume:" & Forms(NF).NAME ' va afişa: Numar:1 -Nume:F_FormOpen Vf1.Caption = Vf1.Caption & " - Instanţa neimplicită Nr.1" '------------ ' Se deschide a doua instanţa neimplicită Vf2.Visible = True ' Vor fi 3 formulare F_FormOpen pe ecran NF = Forms.Count - 1 MsgBox "Numar:" & NF & " -Nume:" & Forms(NF).NAME ' va afişa: Numar:2 -Nume:F_FormOpen Vf2.Caption = Vf2.Caption & " - Instanţa neimplicită Nr.2" '------------- ' Se deschide a treia instanţă neimplicită Vf3.Visible = True ' Vor fi 4 formulare F_FormOpen pe ecran NF = Forms.Count - 1 MsgBox "Numar:" & NF & " -Nume:" & Forms(NF).NAME ' va afişa: Numar:3 -Nume:F_FormOpen Vf3.Caption = Vf3.Caption & " - Instanţa neimplicită Nr.3" '------------- Stop Set Vf2 = Nothing ' Form – Instanţa neimplicită 2 se închide Stop End Sub ' La sfârşitul rutinei, toate variabilele acesteia se sterg ' Vf1 – se şterge | Form – Instanţa neimplicită 1 se închide ' Vf3 – este modală deci nu se şterge _ Form – Instanţa neimplicită 3 rămâne deschisă ' Rămâne deschis şi – Form – Instanţa implicită '=================================

Page 196: 2.VBA_SC4

II-196

� Dacă există mai multe instanţe ale unui formular, deoarece toate vor avea acelaşi nume, referirea acestora se va putea face numai prin indexarea colecţiei Forms.

� Eventualele modificări făcute prin VBA asupra proprietăţilor unui formular deschis într-o instanţă implicită sau neimplicită, se vor pierde o dată cu închiderea instanţei.

� Toate consideraţiile făcute asupra formularelor sunt valabile şi pentru rapoarte.

II.5.4. Proprietăţile unei instanţe a clasei de module

Proprietăţile unui obiect provenit din clasa de module reprezintă datele pe care le vor folosi metodele obiectului respectiv.

Aceste proprietăţi (date) trebuie să permită accesul, în citire (get) şi/ sau în scriere (let), din orice alt modul VBA.

Proprietatea obiectului programabil se va exprima prin numele proprietăţii calificat cu numele obiectului (instanţei).

Utilizarea unei proprietăţi în scriere se va face prin plasarea ei în partea din stânga a unei instrucţiuni de atribuire, iar utilizarea acesteia în citire se va face prin folosirea ei în orice expresie (de cele mai multe ori în partea din dreapta a unei instrucţiuni de atribuire).

II.5.4.1. Definirea proprietăţilor prin variabile publice

O variabilă publică declarată la nivelul clasei de module reprezintă o proprietate a acesteia, deoarece pe de o parte poate fi accesată din orice modul de cod, iar pe de altă parte poate fi folosită de rutinele interne ale clasei de module respective – dintre care unele şi anume cele publice constituie metodele obiectului.

Astfel proprietatea reprezintă practic un canal de transfer pentru date, între obiectul programabil provenit din clasa de module şi aplicaţia Access.

Pentru aceasta este necesar ca mai întâi să se creeze o nouă instanţă a clasei de module respective (ceea ce este echivalent cu crearea unui obiect programabil al clasei de module), prin care practic, se va delimita un spaţiu propriu de memorare al obiectului programabil, pentru toate declaraţiile din clasa de module, care se vor păstra pe toată durata de viaţă a obiectului. Astfel obiectul va folosi în mod exclusiv proprietăţile definite în propiul spaţiu de memorare.

De exemplu, dacă se defineşte în clasa de module C_Test, o variabilă publică pCul, aceasta va reprezenta o proprietate a acestei clase. Dacă la un moment dat, sunt definite 3 instanţe (obiecte programabile) ale clasei C_Test, atunci practic vor exista 3 variabile pCul, câte una pentru fiecare obiect.

� O variabilă permite atât memorarea datelor (scriere) cât şi citirea lor. Deci proprietăţile definite prin variabile publice se pot folosi atât în scriere cât şi în citire.

Page 197: 2.VBA_SC4

II-197

II.5.4.2. Definirea proprietăţilor prin rutine Property

Rutinele Property, în număr de trei, permit definirea unor proprietăţi şi ataşarea acestora modulului în care au fost create. Deci ele se pot ataşa nu numai unei clase de module (ceea ce face obiectul actualului paragraf), dar şi modulelor standard, formularelor sau rapoartelor.

Aşa cum am mai arătat, o proprietate are rolul de memorare (scriere) sau citire a unei date aparţinând unui obiect programabil. Rutinele Property, fiind de fapt nişte proceduri sau funcţii, vor permite ca pe lângă funcţia sus amintită, să permită şi prelucrări de orice complexitate asupra datelor respective, înainte de memorarea sau citirea lor.

Deoarece în programarea în VBA se lucrează cu tipuri de date obiect sau non-obiect (integer, string, etc.) şi proprietăţile vor fi de aceste două tipuri:

• Pentru proprietăţile non-obiect, se folosesc rutinele: − Property Let – care permite memorarea (scrierea, setarea) valorii proprietăţii; − Property Get – care permite citirea valorii proprietăţii;

• Pentru proprietăţile obiect, se folosesc rutinele: − Property Set – care permite setarea referinţei către un obiect; − Property Get – care permite citirea valorii proprietăţii.

� Într-un modul de clasă, există posibilitatea de a declara variabile modale private. Aşa cum am arătat, la crearea unei instanţe ele se vor plasa în spaţiul de memorie exclusiv al acesteia. De obicei, rutinele Property Let(Set), vor folosi aceste variabile private modale pentru memorarea rezultatelor prelucrărilor efectuate, iar rutinele Property Get vor avea ca valori iniţiale pentru prelucrarea efectuată înainte de a întoarce valoarea proprietăţii, valorile memorate în variabile private modale.

� Deoarece o proprietate e definită de obicei de două rutine, Property Let(Set) şi Property Get, acestea vor avea acelaşi nume, care va reprezenta şi numele proprietăţii.

� Deoarece un variant poate conţine atât date de tip obiect cât şi date de tip non-obiect, o proprietate de tip variant se poate defini prin toate cele trei rutine.

� O proprietate se poate defini şi numai printr-o rutină Property. În acest caz ea va fi:

− read only, dacă există numai Property Get; − write only, dacă există numai Property Let(Set);

Page 198: 2.VBA_SC4

II-198

Sintaxa de declarare a unei rutine Property este: [Public | Private] [Static] Property Get NumeProp _ ([ListaParam]) [As TipDate] [instrucţiuni] [NumeProp = expresie] [Exit Property] [instrucţiuni] [NumeProp = expresie] End Property

------------------

[Public | Private] [Static] Property {Let | Set} NumeProp_ ([ListaParam] ParamValoare) [instrucţiuni] [Exit Property] [instrucţiuni] End Property

------------------

În continuare prezentăm câteva consideraţii asupra rutinelor Property: • Rutinele Property folosesc acelaşi tip de reguli de definire ca rutinele

Sub sau Function. • La rutinele Property se folosesc în loc de Exit Sub(Function) şi End

Sub(Function), Exit Property şi End Property • Parametrii rutinelor Property, respectă aceleaşi reguli de formare ca ale

variabilelor. Ei sunt introduşi între paranteze şi sunt separaţi prin virgulă dacă sunt mai mulţi.

• Property Get funcţionează ca o funcţie. Ea va întoarce valoarea care se introduce printr-o instrucţiune din interiorul procedurii în parametrul de ieşire care este chiar numele proprietăţii. Ea se foloseşte într-o expresie, ca orice fel de rutină de tip funcţie.

• Property Let(Set) funcţionează ca o rutină de tip Sub (procedură). Ea va avea obligatoriu definit între parametrii ei un parametru formal de intrare, ParamValoare, care este întotdeauna ultimul parametru al rutinei în caz că există mai mulţi. Property Let(Set) se utilizează prin plasarea ei în partea din stânga a unei instrucţiuni de atribuire, urmând ca valoarea cu care se încarcă parametrul formal de intrare ParamValoare, să fie plasată după semnul egal al instrucţiuni de atribuire.

• Tipul de date al parametrului formal de intrare, ParamValoare, al rutinei Property Let(Set), trebuie obligatoriu să fie identic cu tipul de date al

Page 199: 2.VBA_SC4

II-199

numelui rutinei Property Get corespunzătoare (care reprezintă, aşa cum am văzut, parametrul formal de ieşire al acesteia).

• Parametrii specificaţi în sintaxa prezentată mai sus, prin ListaParam, sunt opţionali. Dacă ei sunt definiţi, atunci ei trebuie să fie obligatoriu în acelaşi număr, tip şi ordine, în toate rutinele Property cu acelaşi nume, deci care se referă la o anumită proprietate.

• Property Let(Set) are întotdeauna un parametru în plus şi anume ultimul, ParamValoare, decât Property Get referitoare evident la aceeaşi proprietate. Exemplu.

Property Let Prop1(P1 As Integer, P2 As String, pVal As Variant) ….=pVal instrucţiuni End Property

------------------

Property Get Prop1(A1 As Integer, A2 As String) As Variant Instrucţiuni Prop1=…… End Property

Exemplu. În clasa de module C_Test se defineşte o proprietate Color, care va conţine codul culorii active.

' Modulul clasei C_Test Option Compare Database Option Explicit ' în această variabilă privată se va memora valoarea proprietăţii Color Private CurrentColor As Integer Const BLACK = 1, RED = 2, GREEN = 3, BLUE = 4 '--------------------- Property Get Color () As String ' Întoarce culoarea activă Select Case CurrentColor Case BLACK Color = "Negru" Case RED Color = "Rosu" Case GREEN Color = "Verde" Case BLUE

Page 200: 2.VBA_SC4

II-200

Color = "Albastru" Case Else Color = "Nedefinit" End Select End Property '----------------------- Property Let Color(Culoarea As String) ' Setează proprietatea Color, prin valoarea introdusă în _ parametrul formal de intrare, Culoare Select Case Culoarea Case "Rosu" CurrentColor = RED Case "Verde" CurrentColor = GREEN Case "Albastru" CurrentColor = BLUE Case Else CurrentColor = BLACK ' Culoarea implicită este negru End Select End Property '------------------------- ' Utilizare proprietate a clasei de modul C_Test Sub TestProp Dim V As New C_Test MsgBox V.Color ' Afişează Nedefinit V.Color="Verde" V.Color="Rosu" MsgBox V.Color ' Afişează Roşu End Sub

II.5.5. Metodele unei instanţe a clasei de module

Orice rutină declarată public, în clasa de module, va constitui o metodă a obiectelor programabile ce se obţin din clasa respectivă.

Dacă rutina ce defineşte metoda este o funcţie, atunci această metodă poate să şi întoarcă o valoare. Exemplu. Definim metoda UpCuloare a clasei de module C_Test

Public Sub UpCuloare() ' Metoda prin care se măreşte cu 1 codul culorii active _

Page 201: 2.VBA_SC4

II-201

Acesta e memorat în variabila modală privată CurrentColor _ Dacă acesta este 4 (Blue), atunci se face 1 (Black). CurrentColor = CurrentColor + 1 If CurrentColor > BLUE Then CurrentColor = BLACK End Sub ' Utilizare metodă a clasei de modul C_Test Sub TestMetoda() Dim V As New C_Test V.Color = "Rosu" MsgBox V.Color ' Afişează Roşu Do V.UpCuloare MsgBox V.Color ' Afişează pe rând toate culorile definite, verde, albastru, negru, roşu Loop Until V.Color = "Rosu" End Sub

II.5.6. Asignarea de metode la evenimentele unei instanţe a clasei de module

Aşa cum s-a mai arătat, există două evenimente predefinite pentru o clasă de module:

− Initialize – ce se produce la crearea unei instanţe noi a unei clase; − Terminate – ce se produce la anularea instanţei respective. Când se produc aceste evenimente se pot efectua automat anumite prelu-

crări (metode).

II.5.6.1. Evenimentul Initialize

Evenimentul Initialize se produce atunci când se creează efectiv o instanţă a unei clase de module. De obicei acest lucru se petrece atunci când este utilizată pentru prima oară o proprietate sau o metodă a instanţei.

La producerea evenimentului Initialize al unei instanţe, se poate executa automat o procedură, dacă aceasta este definită în clasa de module din care provine instanţa.

Numele acestei proceduri este prestabilit: Class_ Initialize. De obicei această facilitate este folosită atunci când se doreşte efectuarea

anumitor iniţializări la crearea instanţelor.

Page 202: 2.VBA_SC4

II-202

II.5.6.2. Evenimentul Terminate

Evenimentul Terminate se produce atunci când se şterge din memorie o instanţă a unei clase de modul, adică când se termină durata de viaţă a variabilei care a creat instanţa. Aceasta se poate face pe două căi:

− Setarea variabilei ce defineşte instanţa cu clauza Nothing; − Terminarea modulului în care a fost declarată variabila;

La producerea evenimentului Terminate al unei instanţe, se poate executa automat o procedură, dacă aceasta este definită în clasa de module din care provine instanţa.

Numele acestei proceduri este prestabilit: Class_Terminate. De obicei această facilitate este folosită atunci când se doreşte refacerea

anumitor setări la anularea unei instanţe. Exemplu. Definim pentru clasa de module C_Test, metode pentru cele două evenimente prezentate.

Private Sub Class_Initialize() ' Se introduce o valoare care va seta var. modală privată CurrentColor Dim tC As Variant tC = InputBox("Introduceti un număr din {1…4} pentru iniţializare") If IsNumeric(tC) Then If tC >= 1 And tC <= 4 Then CurrentColor = tC End If End If End Sub Private Sub Class_Terminate() MsgBox "Anulare instanţă-Ultima culoare folosită: " & CurrentColor End Sub ' ----------utilizarea evenimentelor clasei C_Test Sub TestEveniment() Dim V As New C_Test MsgBox V.Color'La prima utilizare a instanţei V se lansează procedura _ eveniment Class_Initialize, care setează o culoare ce va fi afişată de MsgBox V.Color = "Rosu" MsgBox V.Color ' Afişează Roşu V.UpCuloare End Sub ' Se execută procedura eveniment Class_Terminate care afişează ' ultima culoare setată, prin metoda UpColor (adică verde care e după roşu)

Page 203: 2.VBA_SC4

II-203

ANEXA I - Structura ierarhică a obiectelor din MS Word

Application

AutoCorrect

AddIn

Pane

Window

*

AutoCorrectEntry

FirstLetterException

TwoInitialCaspExceptio

Assistant

AutoCaption

Browser

CaptionLabel

CommandBar *

Dialog

Dictionary

FileConverter

FileSearch

FontNames

KeyBinding

KeysBoundTo

Language

VBE

*

Dictionary

**

MailMessage

Options

MailingLabel

CustomLabel

RecentFile

Selection

Range

Document

HeaderFooter

SpellingSuggestion

SynonymInfo

Sistem

Task

Template

Template

VBProject **

DocumentProperty

ListGallery

ListTemplate

ListLevel

Document

Zoom

Selection

View

Zoom

ListTemplate

1

Page 204: 2.VBA_SC4

II-204

Microsoft Word (continuare 1)

1

ListParagraphs

Mailer

PageSetup

InlineShape

LinkFormat

RoutingSlip

StoryRanges

DocumentProperty

Index

LetterContent

Envelope

List

MailMerge

MailMergeDataSource

MailMergeField

TextColumn

LineNumbering

Field

Hyperlink

FillFormat

LineFormat

PictureFormat

OLEFormat

Document

Shape

*

+

+

++

Adjustments

Shape

Mailer

CalloutFormat

FillFormat

GroupShape

Hyperlink

LinkFormat

ShapeNode

OLEFormat

PictureFormat

ShadowFormat

TextEffectFormat

TextFrame

WrapFormat

ThreeDFormat

FreeformBuilder

Frame

ListTemplate

Paragraph Format

+ P

+ P

+ P

+ P

Border

Shading

TableOfAuthorities

TableOfAuthorities Category

TableOfContents

TableOfFigures

Template

Variable

VBProject **

Version

Window

2

Page 205: 2.VBA_SC4

II-205

Microsoft Word (continuare 2)

2

Bookmark Frame

++

Paragraph

Range

Border

Character

Comment

Endnote

Field

Find

Replacement

Font

Shading

Border

Footnote

ShapeRange

Style

FormField

CheckBox

DropDown

ListEntry

TextInput

Hyperlink

Shape

Table

Cell

Collumn

Cell

Row

Cell

ListFormat

ListParagraphs

ParagrahpFormat

DropCap

Paragraph Format

TabStop

TextRetrievalMode

Proofreading Errors

SubDocument

ReadabilityStatistics

Revision

Sentences

Words

Shading

Section

PageSetup

HeaderFooter

PageNumber

Shape

Page 206: 2.VBA_SC4

II-206

Anexa II - Structura ierarhică a obiectelor din MS Excel

Application

AutoCorrect

DocumentProperty Addin

RecentFile Window

Pane

DocumentProperty

VBProject

Mailer

Worksheet

Name

CustomView

Window

CommandBar

PivotCache

RoutingSlip

Pane

Shape

LinkFormat

OLEFormat

ShadowForm

Hyperlink

FillFormat

ControlFormat

ConnectorFormat

Comment

HPageBreak

VPageBreak

Hyperlink

Name

Adjustments

CalloutFormat

FreeformBuilder

LineFormat

PictureFormat

ThreeDFormat

GroupShapes

TextEffectFormat

TextFrame

ShapeNode

Characters

ChartObject

Scenario

OLEObject

Outline

Page Setup

QueryTable

PivotTable

Parameter

Chart

PivotCache

PivotFormula

PivotField

PivotItem

++

+

+

+

+

*

1

2

3

Page 207: 2.VBA_SC4

II-207

Microsoft Excel (continuare 1)

WorksheetFunction

CommandBar

ODBCError

Chart

Areas

Font

Interior

Name

Hyperlink

FormatCondition

1

2

*

FileSearch

FileFind

VBE

Assintat

*

* *

*

Names

Style

Axis

AxisTitle

Gridlines TickLabels

Range

Border

SoundNote

Style

Shape

Range

Validation

Comment

Characters

Comers

ChartGroup

DownBars

Border

PageSetup

Shape ++

Floor

Walls

ChartTitle

Series

ChartArea

ChartFillFormat

PlotArea

DataTable

Legend

Border

Font

LegendEntry

LegendKey

UpBars

SeriesLines

HiLoLines

TickLabels

Series

DropLines

ErrorBars

Border

DataLabel

Point

DataLabel

Interior

LeaderLine

Font

Interior

3

Page 208: 2.VBA_SC4

II-208

Bibliografie

• Microsoft Office 97-Visual Basic, Programmer's Guide, MS Corp. 96

• Building Applications with MS Access 97, MS Corporation 1996

• Microsoft Office 97 - Object Model Guide, MS Corporation 1996

• Brown A., Balter A., Bazele ACCESS 95, Ed. TEORA, 1997

• John Clark Craig, Jeff Webb, Visual Basic 5.0, Ed. TEORA, 1998

• Microsoft, Visual Basic 6 - ghidul programatorului, Ed. TEORA, 1998

• Jennings R., Utilizare ACCESS 95, Ed. TEORA, 1997

• Microsoft - SQL Server, MS Corporation 1995