Sei sulla pagina 1di 291

CUPRINS

• VBA - Bazele programarii Determinarea tipului de selecţie


Obiectele Find şi Replacement
• Instructiunile VBA Find
ClearFormatting
• Operatiuni de intrare-iesire Execute
Selection.Find
• Visual Basic Editor Range.Find
Replacement
• Modele de obiecte Obiectele Table, Column, Row şi Cell
Colecţia Tables
• Obiecte Microsoft Word Obiectul Table
Obiectul Application Colecţia Columns
Proprietăţi (obiectul Application) Obiectul Column
DisplayScrollBars Colecţia Rows, obiectul Row
DisplayStatusBar Colecţia Cells
Height Obiectul Cell
Width Exemple cu obiectele Table,
WindowState Column, Row şi Cell
ActiveDocument Utilizarea obiectului HeaderFooter
ActivePrinter Colecţia Styles
ActiveWindow Obiectul Style
Documents Colecţia CommandBars
Selection Colecţia Dialogs
Windows Câmpuri – adăugare, editare
Metode (obiectul Application) Verificarea unui obiect
Quit Modificarea comenzilor Word
Obiectul Document Lucrul cu evenimente
Referirea unui Document Evenimente pentru Document
Deschiderea documentelor Evenimente pentru Application
Crearea/salvarea documentelor Evenimente pentru ActiveX
Activarea unui document Auto Macro
Tipărirea unui document Automatizarea aplicaţiilor
Închiderea documentelor Automatizarea Word din altă aplicaţie
Accesarea obiectelor din Document Automatizarea altei aplicaţii din Word
Obiectul Range Comunicarea cu obiectele scufundate
Obiect Range sau obiect Selection
Referinţa prin metoda Range • Controale ActiveX si Dialoguri
Referinţa prin proprietatea Range Proiectarea casetelor de dialog
Modificarea unui document utilizator
Lucrul cu textul din Range Crearea unui nou dialog
Redefinirea unui obiect Range Scrierea procedurilor de răspuns la
Atribuirea obiectelor Range evenimente
Obiectul Selection Controale
Deplasarea şi extinderea selecţiei Label
Metoda GoTo TextBox
Metodele GoToNext, GoToPrevious ListBox
Obiecte accesibile din Selection ComboBox
Selection – proprietăţi şi metode CheckBox
uzuale OptionButton
Proprietatea Text ToggleButton
Formatarea textului selectat CommandButton
Returnarea obiectului Range TabStrip
Proprietatea Information MultiPage
Frame
1
Image • Obiecte Microsoft Access
Utilizarea dialogurilor utilizator Obiectele accesibile în Microsoft
Afişarea unui dialog Access
Obţinerea/editarea proprietăţilor în Obiectele Microsoft Access
execuţie Obiectul Application
Utilizarea controalelor în documente Utilizarea obiectului Application în
Word, Excel, PowerPoint automatizare
Controale ActiveX în documente Colecţia Forms
Word Referirea la un obiect Form
Controale ActiveX în foi de calcul Proprietăţile obiectului Form
Excel Proprietatea Me (obiectul Form)
Controale ActiveX în diapozitive Proprietatea Section (obiectul
PowerPoint Form)
Controlarea programatică a Proprietatea Properties (obiectul
controalelor din documentele aplicaţiilor Form)
Proprietatea Module (obiectul
• Obiecte Microsoft Excel Form)
Obiectul Application Proprietatea RecordSource
Obiectul Workbook (obiectul Form)
Deschiderea unui Workbook Module ataşate formelor
Metoda GetOpenFilename Crearea formelor în timpul execuţiei
Crearea/salvarea unui Workbook Colecţia Reports
Metoda Add (colecţia Workbooks) Referirea obiectelor Report
Metoda SaveAs Module asociate rapoartelor
Metoda Save Crearea rapoartelor în timpul
Metoda GetSaveAsFilename execuţiei
Închiderea unui Workbook Funcţiile CreateForm,
Metoda Close CreateReport
Obiectul Range Funcţiile CreateControl,
Referinţe de tip A1 sau nume de CreateReportControl
domeniu Exemplu de creare a unui raport
Utilizarea indicilor de linii şi coloane Colecţia Controls
Utilizarea proprietăţii Offset Controale Microsoft Access
Utilizarea proprietăţilor CurrentRegion Controale ActiveX
şi UsedRegion Referirea obiectelor Control
Parcurgerea unui domeniu de celule Proprietăţile obiectului Control
Utilizarea instrucţiunii For Proprietatea Hyperlink (obiectul
Each…Next Control)
Utilizarea instrucţiunii Do…Loop Proprietatea ControlType (obiectul
Utilizarea proprietăţii Address Control)
Evenimentele din Excel 97 Controale legate de date (Data-
Permiterea şi inhibarea Bound Controls)
evenimentelor Controale care au o colecţie
Utilizarea evenimentelor Controls
Evenimentele obiectului Worksheet Colecţia Modules
Exemplu Referirea la obiecte Module
Evenimentele obiectului Chart Module standard şi module clasă
Exemplu Proprietăţile obiectului Module
Evenimentele obiectului Workbook Determinarea numărului de linii
Exemplu Lucrul cu procedurile
Evenimentele obiectului Application Metodele obiectului Module
Utilizarea modulelor clasă cu Adăugarea de text la un modul
evenimente Evenimentele unui modul clasă
Colecţia References
Referirea obiectelor Reference
2
Proprietăţile obiectului Reference Înregistrarea unei surse de date
Metodele colecţiei References ODBC
Stabilirea unei referinţe în Visual Utilizarea DAO cu ODBCDirect
Basic Obiectul DBEngine
Obiectul DoCmd Colecţia Workspace
Metoda OpenForm Colecţia Connections
Metoda RunCommand Deschiderea conectărilor
Obiectul Screen asincrone
Proprietăţile obiectului Screen Colecţia Databases
Comutarea între Connection şi
• DAO (Data Access Objects) Database
Lucrul cu obiectele DAO Colecţia QueryDefs
Proiectarea bazelor de date în Executarea interogărilor
Microsoft Access asincrone
Stabilire unei referinţe la biblioteca de Colecţia Parameters
obiecte DAO Colecţia Recordsets
Referirea obiectelor DAO în Visual Obiecte Recordset de tip
Basic dinamic
Adăugarea de noi obiecte DAO la o Deschiderea asincronă a
colecţie obiectelor Recordset
Lucrul cu date externe Colecţia Fields
Utilizare DAO cu surse de date Utilizare ODBCDirect
ODBC Utilizarea actualizării optimiste
Utilizare Dao cu Microsoft Jet în lot
Obiectul DBEngine Tratarea coliziunilor
Colecţia Workspaces Utilizarea cursoarelor în spaţiile
Metoda CreateWorkspace ODBCDirect
Colecţia Errors Caracteristicile cursoarelor
Colecţia Databases Cursoare client-side sau
Colecţia TableDefs server-side
Colecţia Fields Alegerea tipului de cursor
Colecţia Indexes Blocarea înregistrărilor
Colecţia QueryDefs Limitări ale cursoarelor
Colecţia Parameters (obiectul Regăsirea mulţimilor multiple
QueryDef) de rezultate
Colecţia Relations (obiectul Lucrul cu proceduri memorate
Database)
Colecţia Recordsets • Obiecte Microsoft PowerPoint
Obiecte Recordset de tip Obiectul Application
tabelă Returnarea unui obiect
Obiecte Recordset de tip Application
dynaset Controlul aspectului ferestrei
Obiecte Recordset de tip aplicaţiei
snapshot Controlarea atributelor şi
Obiecte Recordset de tip comportării globale
forward-only Accesarea principalelor obiecte
Metodele obiectelor Recordset Accesarea obiectelor partajate
Securitatea datelor de Ms Office
Colecţia Properties Obiectul Presentation
Accesarea datelor ODBC Returnarea obiectului
Utilizarea Microsoft Jet pentru Presentation
date ODBC Deschiderea unei prezentări
Utilizarea ODBCDirect pentru Crearea unei prezentări
date ODBC Importul dintr-un outline Word
Activarea unei prezentări
3
Numerotarea şi dimensiunile Mutarea unui element din
slide-urilor spaţiul de lucru în caiet
Stabilirea unui aspect unitar Eliminarea unui
Tipărirea unei prezentări meniu/toolbar salvat în caiet
Salvarea unei prezentări Microsoft Word
Închiderea unei prezentări Microsoft PowerPoint
Configurarea şi executarea unei Componente ale interfeţei
prezentări utilizator
Accesul la diapozitivele Sistemul de meniuri
prezentării Adaptarea sistemului de meniuri
Obiectele Slides, Slide şi Componente personale şi
SlideRange componente built-in
Returnarea colecţiei Slides Utilizarea submeniurilro
Returnarea unui obiect Slide Utilizarea meniurilor contextuale
Returnarea unui obiect Text box, List box, Combo box
SlideRange Modificarea în design-time
Adăugarea unei diapozitiv Adăugarea de bare de meniu
Stabilirea fundalului şi schemei proprii
de culori Adăugarea meniurilor
Alegerea unui layout Adăugarea submeniurilor
Adăugarea de obiecte Adăugarea şi gruparea
Ordinea diapozitivelor comenzilor
Stabilirea efectelor tranziţiei Adăugarea şi modificarea
Referirea notelor meniurilor contextuale
Obiectul Selection Ştergerea componentelor de
Crearea unei selecţii meniu
Returnarea unei selecţii Restaurarea componentelor
Returnarea unui obiect din built-in
selecţie Modificarea în run-time
Obiectele View şi SlideShowView Afişarea unei bare de meniu
Prezentări, ferestre, viziuni Afişarea dinamică a
Returnarea obeictelor View şi componentelor de meniu
SlideShowView Permiterea şi inhibarea
Navigarea printre diapozitive componentelor de meniu
Alipirea la un obiect View Indicarea stării unei intrări de
Controlul viziunii din fereastra meniu
documentului Redenumirea unei intrări
Returnarea diapozitivului curent Bare de unelte
Controlul obiectelor în slide Adaptarea barelor de unelte
show Utilizarea meniurilor
Controlul animaţiei Text box, List box, Combo box
Răspunsul la acţiunea mouse- Modificarea barelor de unelte în
ului design-time
Controlul unui clip Adăugarea unei bare de
unelte
• Meniuri si bare de unelte Adăugarea şi gruparea
Modificarea interfeţei cu controalelor
utilizatorul Adaugarea şi iniţializarea
Dialogul Customize controalelor text box, list box,
Visual Basic combo box
Domeniul schimbărilor asupra Eliminarea unui control
interfeţei utilizator Restaurarea barelor de
Microsoft Access unelte built-in
Microsoft Excel Modificarea barelor de unelte în
run-time

4
Afişarea/ascunderea Tratarea erorilor în procedura
controalelor şi barelor de unelte apelantă
Mutarea şi redimensionarea Utilizarea datelor de tip Variant
barelor de unelte Tratarea centralizată a erorilor
Restaurarea barelor de Inhibarea tratării erorilor
unelte built-in Depanarea programelor care au
Permiterea şi interzicerea rutine de tratare a erorilor
accesului la controale Tratarea erorilor din obiectele
Indicarea stării activ/inactiv a referite
unui buton Tratarea erorilor transmise din
Modificarea controalelor Text obiectele referite
box, List box şi Combo box Depanarea tratării erorilor din
ID-uri de controale şi intrări de obiecte referite
meniu Depanarea programelor
Tipuri de erori
• Forme grafice Unelte de depanare
Obiectele Shape, ShapeRange şi Bara de unelte Debug
Shapes Evitarea "bug"-urilor
Returnarea colecţiei Shapes Design Time, Run Time şi Break
Returnarea obiectului Shape Mode
Returnarea colecţiei Utilizarea ferestrelor de depanare
ShapeRange Utilizarea modului break
Desenarea unei forme grafice Intrarea în modul break la o
Editarea unei forme grafice instrucţiune cu probleme
Determinarea Fixarea unei erori run-time şi
proprietăţilor/metodelor adecvate continuare
Lucrul cu obiecte OLE Monitorizarea datelor prin
Lucrul cu mai multe forme expresii de urmărire
Construirea unui obiect Adăugarea, editarea sau
ShapeRange eliminarea unei expresii urmărite
Lucrul cu colecţia ShapeRange Utilizarea urmăririi rapide
Utilizarea unui punct de oprire
• Tratarea erorilor. Depanarea programelor Utilizarea instrucţiunii Stop
Cum se gestionează erorile Executarea unor secvenţe de cod
Proiectarea unei rutine de tratare selectate
a erorilor Utilizarea comenzii Step Into
Stabilirea capcanei de erori Utilizarea comenzii Step Over
Scrierea unei rutine de tratare a Utilizarea comenzii Step Out
erorilor Trecerea peste secţiuni de cod
Ieşirea din rutina de tratare a Stabilirea instrucţiunii următoare
erorilor Indicarea instrucţiunii următoare
Diferenţa dintre Resume şi Monitorizarea listei de apeluri
Resume Next (Call Stack)
Reluarea execuţiei la o linie Testarea datelor şi procedurilor
specificată cu fereastra Immediate
Ierarhia de tratare a erorilor Tipărirea informaţiilor în fereastra
Căutarea în lista de apeluri Immediate
Indicaţii pentru o tratare Tipărirea din codul aplicaţiei
complexă a erorilor Tipărirea din fereastra
Testarea tratării erorilor prin Immediate
generarea de erori Atribuirea de valori
Definirea codurilor proprii de Testarea procedurilor cu
eroare fereastra Immediate
Tratarea inline a erorilor Verificarea numerelor de eroare
Returnarea numerelor de eroare
5
Trucuri utile în fereastra Încărcarea la cerere din Word
Immediate Codul executat la
Consideraţii speciale încărcare/descărcare
Oprirea execuţiei în procedurile Excel – evenimentele
evenimentelor MouseDown sau AddinInstall şi AddinUninstall
KeyDown PowerPoint – procedurile
Oprirea execuţiei în procedurile Auto_Open şi Auto_Close
evenimentelor GotFocus sau Word – procedurile AutoExec
LostFocus şi AutoExit
Verificarea finală a codului
• Distribuirea solutiilor VBA pentru aplicatiile Referinţe la ActiveWorkbook
Microsoft Office sau ActiveDocument
Pregătirea soluţiei pentru Apelul procedurilor din alte
distribuire proiecte
Alegerea modului de Evitarea referinţelor
împachetare a soluţiei nerezolvate
Controlul încărcării PowerPoint – apelul unei
Încărcarea la start rutine fără referinţă
Încărcarea automată în Excel Referinţe legate târziu
Încărcarea automată în Protejarea codului
PowerPoint Salvarea soluţiei ca un Add-in
Încărcarea add-in-urilor din sau Global Template
sesiunea precedentă Crearea unui Add-in în Excel
Încărcarea programatică Crearea unui Add-in în
Încărcarea ca răspuns la un PowerPoint
eveniment Crearea unui template global
Încărcarea unui template prin în Word
linia de comandă Depanarea unui Add-in sau
Descărcarea programatică Global Template
Încărcarea la cerere Depanarea unui add-in în
Utilizarea referinţelor explicite Excel
în Excel Depanarea unui add-in în
Încărcare unei biblioteci în PowerPoint
Excel Depanarea unui template
Adăugarea meniurilor Excel global în Word
fără add-in Distribuirea soluţiilor prin Setup
Încărcarea la cerere în Wizard
PowerPoint

6
1. BAZELE PROGRAMĂRII Visual Basic for Application (VBA)

Tipuri de date

Variabilele şi constantele utilizate într-un program VBA pot avea diverse tipuri, specifice datelor memorate. Spre
deosebire de alte limbaje de programare, există un tip universal — tipul Variant —, care poate conţine aproape orice alt
tip de date. Acest tip este asignat în mod implicit tuturor variabilelor nedeclarate altfel, încât declararea explicită poate fi
utilizată atunci când se doreşte economisirea memoriei (tipul Variant alocă mai multă memorie), viteză în execuţie sau
atunci când se scriu date într-un fişier în acces direct.

Boolean
Domeniu de valori: True sau False (valorile logice)
Memorie: 2 bytes
Declarator de tip:
Observaţii. Convertirea valorilor numerice la tipul Boolean: 0 produce False, valorile nenule produc True.
Convertirea valorilor de tip Boolean la alte tipuri numerice: False devine 0, True devine -1.
Byte
Domeniu de valori: 0–255 (numere întregi, fără semn)
Memorie: 1 byte
Declarator de tip:
Observaţii.
Currency
Domeniu de valori: -922 337 203 685 477.5808 — 922 337 203 685 477.5807
Memorie: 8 bytes
Declarator de tip: @
Observaţii. Utilizate pentru calcule băneşti (sau alte situaţii în care precizia este foarte importantă).
Valorile sunt memorate în format întreg, scalate prin 10 000, pentru a obţine 15 cifre la partea întreagă şi
4 cifre la partea zecimală (reprezentare în virgulă fixă).
Date Domeniu de valori: 1 ianuarie 100 — 31 decembrie 9999, 0:00:00 — 23:59:59
Memorie: 8 bytes
Declarator de tip:
Observaţii. Informaţiile de tip dată calendaristică şi/sau timp orar sunt memorate drept numere flotante,
partea întreagă reprezentând data calendaristică, partea fracţionară reprezentând timpul.
La convertiri, miezul nopţii este 0, miezul zilei este .5, numerele negative reprezintă date înainte de 30
decembrie 1899.
Poate fi atribuit ca valoare de tip date orice literal care reprezintă o dată calendaristică recunoscută ca
atare, literalul trebuind să fie cuprins între simboluri #, de exemplu #1 Jan 99#.
Decimal
Domeniu de valori: (vezi observaţiile)
Memorie: 12 bytes
Declarator de tip:
Observaţii. Valorile de tip Decimal sunt memorate ca întregi fără semn însoţiţi de un factor de scală, între
0 şi 28, specificând numărul de zecimale. Pentru scala=0 (fără parte zecimală), cea mai mare valoare
posibilă este +/-79,228,162,514,264,337,593,543,950,335. Cu scala=28 cea mai mare valoare este +/-
7.9228162514264337593543950335 iar cea mai mică valoare nenulă este +/-
0.0000000000000000000000000001.
Notă: Deocamdată, tipul Decimal poate fi utilizat doar ca subtip în Variant, adică nu se pot declara
variabile ca fiind de tip Decimal. Acestea pot fi create ca Variant cu subtipul Decimal prin funcţia Cdec
(funcţia forţează o expresie să fie de un tip specificat, din aceeaşi categorie de funcţii fiind şi CBool,
CByte etc.).
Double
Domeniu de valori: numere negative de la -1.79769313486232E308 până la -4.94065645841247E-324;
numere pozitive de la 4.94065645841247E-324 până la 1.79769313486232E308 (numere flotante în
dublă precizie).
Memorie: 8 bytes
7
Declarator de tip: #
Observaţii.
Integer
Domeniu de valori: -32 768 — 32 767.
Memorie: 2 bytes
Declarator de tip: %
Observaţii.
Long
Domeniu de valori: -2 147 483 648 — 2 147 483 647.
Memorie: 4 bytes
Declarator de tip: &
Observaţii.
Object
Domeniu de valori: (vezi observaţiile)
Memorie: 4 bytes
Declarator de tip:
Observaţii. Adrese pe 32 de biţi care se referă la obiecte. Prin instrucţiunea Set se atribuie unei variabile
declarate de tip Object referinţa la obiectul dorit.
Notă. Prin declararea unei variabile de tip Object, referirea la un obiect prin Set produce o ataşare târzie
(la timpul execuţiei – run-time binding). Pentru o ataşare timpurie (la timpul compilării – compile-time
binding) se va utiliza o variabilă declarată cu numele clasei respective.
Single
Domeniu de valori: numere negative de la -3.402823E38 până la -1.401298E-45; numere pozitive de la
1.401298E-45 până la 3.402823E38.
Memorie: 4 bytes
Declarator de tip: !
Observaţii.
String
Domeniu de valori: şir de lungime variabilă: până la 2^31 caractere; şir de lungime fixă: până la 2^16
caractere.
Memorie: 2 bytes
Declarator de tip: $
Observaţii. Un şir de lungime fixă declarat Public nu poate fi utilizat într-un modul de clasă.
Variant (default)
Domeniu de valori: aceleaşi cu domeniile specificate la tipurile precedente şi care pot fi subtipuri ale
tipului Variant, cu menţiunea că toate subtipurile numerice au domeniul de la Double.
Memorie: în funcţie de subtipul valorii: valorile numerice ocupă 16 bytes, valorile de tip String necesită 22
bytes plus câte un byte pentru fiecare caracter.
Declarator de tip:
Observaţii. Este tipul specificat implicit (în lipsa unei declaraţii explicite) pentru o constantă, variabilă, sau
argument (caz care, deşi nerecomandat, poate elimina erorile provocate de diferenţele de tip ale
argumentelor la apelul procedurilor).
Cu excepţia datelor de tip String cu lungime fixă şi a datelor cu tipuri definite de utilizator, tipul Variant
poate conţine orice alt tip de dată. În plus poate să conţină valorile speciale Empty, Error, Nothing şi Null.
Tipul considerat pentru o dată conţinută într-un Variant poate fi determinat cu funcţia VarType sau
TypeName.
Valorile unei variabile Variant pot să-şi convertească valorile automat. În general, datele numerice sunt
memorate în tipul de origine, dar este posibil ca ele să fie promovate la tipul superior dacă rezultatul unei
operaţii necesită acest fapt. De exemplu o valoare declarată iniţial drept Integer şi atribuită unui Variant
va fi memorată ca un întreg până când, ridicând-o de exemplu la o putere, valoarea ei excede domeniul
tipului Integer. În acest caz are loc promovarea (ca mod de reprezentare) la tipul superior adecvat (Long
sau Double). Dacă depăşirea domeniului are loc pentru subtipurile Currency, Decimal sau Double, atunci
se va semnala eroare.
Utilizarea tipului Variant permite o tratare mai diferenţiată a şirurilor de cifre: în operaţii numerice vor fi
considerate numere iar în operaţii cu şiruri vor fi considerate şiruri.
Accesul la valorile Variant este mai lent decât accesul la valorile definite prin tipuri explicite.
8
Valorile speciale au semnificaţia:

o Empty este valoarea unui Variant care nu a fost iniţializat. În calcule numerice este considerat 0 iar în
operaţii cu şiruri este şirul de lungime zero.
o Null este valoarea unui Variant care, în mod programatic, nu conţine date.
o Error este valoarea utilizată pentru a arăta îndeplinirea unei condiţii de eroare (prin convertirea unui real
cu funcţia CVErr). Procesarea se va efectua de către utilizator, tratarea automată a erorilor nu este
activată la setarea acestor valori.
o Nothing este utilizată pentru disocierea unei variabile de tip Object de un obiect efectiv.

Tipuri definite de utilizator

Un tip de dată definit de utilizator reprezintă echivalentul unei înregistrări dintr-un fişier (bază de date), adică o grupare de
entităţi de tipuri diferite. Definirea are loc la nivel de modul, prin instrucţiuni Type. Pentru clauzele care apar se va vedea
discuţia de la domeniul variabilelor.

[Private | Public] Type varname

elementname [([subscripts])] As type

[elementname [([subscripts])] As type]

...

End Type

unde varname este numele dat tipului definit, iar prin elementname se definesc componentele tipului. Se pot utiliza şi
componente de tipuri utilizator deja definite. Componentele pot fi şi tablouri, caz în care apar definiţiile specifice (vezi
declararea variabilelor).

Declararea constantelor, variabilelor şi tablourilor

Nume

La denumirea procedurilor, constantelor, variabilelor şi argumentelor într-un modul Visual Basic

se cere respectarea următoarelor reguli:

• primul caracter trebuie să fie o literă;


• nu se utilizează spaţiu, punct (.), semnul exclamării(!), sau caracterele @, &, $, #
• lungimea denumirii nu poate depăşi 255 de caractere;
• la acelaşi nivel de existenţă nu pot să existe denumiri identice. Pot să existe totuşi, în acelaşi modul, o variabilă
privată şi o variabilă la nivel de procedură care să poarte acelaşi nume.

În general, nu se recomandă definirea unor denumiri identice cu nume de funcţii, instrucţiuni sau metode existente în
Visual Basic. Dacă s-a ajuns totuşi la această situaţie, atunci utilizarea funcţiei intrinseci limbajului, a instrucţiunii sau
metodei care intră în conflict cu un nume asignat necesită calificarea ei în raport de biblioteca asociată. De exemplu,
VBA.Left este apelul la funcţia Left atunci când este definită de utilizator şi o variabilă Left. Notă. Visual Basic nu este
case-sensitive, deci denumirea unei entităţi nu are ca atribut distinctiv capitalizarea literelor, dar mediul de programare
VBA păstrează capitalizarea din instrucţiunea unde este definit un nume.

Declararea constantelor
9
Definirea unei constante se realizează prin instrucţiunea Const, în care se poate specifica tipul, domeniul şi valoarea
constantei. Valoarea unei constante nu se poate schimba programatic.

[Public | Private] Const constname [As type] = expression

Public — cuvânt cheie, opţional, utilizat la nivel de modul pentru a declara constante recunoscute în toate procedurile din
toate modulele. Nu este permis în proceduri.

Private — cuvânt cheie, opţional, utilizat la nivel de modul pentru a declara constante recunoscute în toate procedurile din
modulul în care apare declaraţia. Nu este permis în proceduri.

constname — numele constantei (obligatoriu).

type — tipul constantei: Byte, Boolean, Integer, Long, Currency, Single, Double, Decimal (încă nu este suportat), Date,
String, sau Variant. Fiecare constantă presupune o clauză As type proprie; în lipsa clauzei se va ataşa automat tipul cel
mai apropiat expresiei.

expression — combinaţie de identificatori, constante, operatori (cu excepţia Is) care produce un sir, număr sau obiect. Nu
se pot utiliza variabile, funcţii utilizator sau funcţii VBA predefinite.

În mod implicit, constantele sunt private. La nivel de procedură, sau de modul clasă, domeniul lor nu poate fi modificat
prin utilizarea clauzei Public. La nivel de modul standard vizibilitatea poate fi modificată prin Public.

Constantele declarate în proceduri Sub, Function sau Property sunt locale procedurii, constantele declarate în afara unei
proceduri este definită în modulul respectiv.

Mai multe declaraţii de constante pot fi scrise pe o aceeaşi linie, separate prin virgule la nivel de atribuiri de expresii. În
acest caz, cuvintele Public sau Private care apar se aplică întregii linii.

Exemple

Const NrLinii = 15

Public Const MesajInitial = "Tastati numarul de linii"

Private Const NrLinii as Integer = 15

Public Const NrLinii = 15, Pondere as Single = 1.21

Este de remarcat că, în ultima linie, doar Pondere este de tip Single, în timp ce NrLinii este de tip Integer (în lipsa clauzei
As type se atribuie tipul expresiei).

Declararea variabilelor

Variabilele, simple sau tablou, se definesc prin instrucţiunile Dim, Private, Public, ReDim sau Static. Numele unei variabile
trebuie să respecte regulile generale de formare a identificatorilor, tipul variabilei poate fi definit explicit (prin clauza As
type) sau implicit (ca Variant).

În cazul în care modulul conţine instrucţiunea Option Explicit cu sintaxa

Option Explicit

10
şi care trebuie să apară înaintea oricărei proceduri din modul, toate variabilele trebuie să fie declarate prin instrucţiunile
menţionate. Lipsa instrucţiunii Option Explicit permite ca variabilele să fie definite acolo unde este nevoie de ele prin
simpla menţionare a unui nou identificator, tipul lor fiind stabilit implicit. Această ultimă posibilitate poate produce erori
greu detectabile.

Sintaxa instrucţiunilor de declarare a variabilelor este următoarea şi se observă asemănarea clauzelor.

Dim [WithEvents] varname[([subscripts])] [As [New] type]

Private [WithEvents] varname[([subscripts])] [As [New] type]

Public [WithEvents] varname[([subscripts])] [As [New] type]

Static varname[([subscripts])] [As [New] type]

ReDim [Preserve] varname(subscripts) [As type]

varname — numele variabilei (obligatoriu).

subscripts — dimensiunile tabloului de date (dacă se declară o variabilă tablou). Pot exista până la 60 de indici, separaţi
prin virgule, declararea dimensiunilor pentru un indice fiind de forma

[lower To] upper

Limita inferioară este, implicit, 0, dar poate fi controlată prin instrucţiunea Option Base.

Dacă nu se indică limitele indicilor (dar parantezele sunt prezente), se defineşte o variabilă tablou
dinamică (nu şi prin Static) ale cărei dimensiuni pot fi precizate/redefinite prin instrucţiunea ReDim.

New — permite crearea implicită a unui obiect (atunci când se declară o variabilă de tip obiect). O nouă instanţă a
obiectului este creată la prima referinţă a variabilei definite. Clauza nu poate să apară la declararea variabilelor de tipuri
intrinseci şi nici la declararea instanţelor obiectelor dependente.

type — tipul variabilei definite: Byte, Boolean, Integer, Long, Currency, Single, Double, Decimal (nesuportat încă), Date,
String (pentru şiruri cu lungime variabilă), String * length (pentru şiruri cu lungime fixă), Object, Variant, tip utilizator sau
tip de obiect.

Dacă se definesc mai multe variabile într-o instrucţiune, definiţiile se separă prin virgulă iar clauza de tip nu este extinsă şi
la variabilele definite ulterior.

Deşi toate instrucţiunile permit declararea unor variabile (simple sau tablou), fiecare instrucţiune are un efect distinct în
ceea ce priveşte vizibilitatea variabilelor şi persistenţa valorilor.

• Dim defineşte variabile atât la nivel de modul cât şi la nivel de procedură. Variabilele definite la nivel de modul
sunt accesibile în procedurile acelui modul, iar variabilele de la nivel de procedură sunt vizibile doar în procedura
respectivă.
• Private este utilizată la nivel de modul pentru a declara variabile accesibile doar în procedurile acelui modul.
• Public este utilizată pentru a declara variabile accesibile în toate procedurile din toate modulele şi din toate
aplicaţiile. Prin includerea instrucţiunii Option Private Module este posibil ca variabilele publice să fie vizibile doar
în proiectul în care sunt definite.
• Static este utilizată la nivel de procedură nestatică pentru a declara variabile care îşi păstrează valoarea de la o
execuţie a procedurii la alta, atât timp cât modulul în care apare procedura nu este resetat sau repornit.
11
Variabilele definite prin Static sunt vizibile doar în procedura respectivă. Este de remarcat că se poate defini o
întreagă procedură utilizând clauza Static (vezi definirea procedurilor), caz în care toate variabilele sunt statice.
• ReDim este utilizată la nivel de procedură pentru realocarea memoriei variabilelor tablou dinamice. Utilizarea
clauzei Preserve permite doar modificarea ultimei dimensiuni şi păstrează valorile deja existente. (Pentru detalii
vezi şi VBA Help).

Exemple

Dim x As Double, ColtStanga As Integer

Private I, J As Long

Static Venit As Currency, NumPren As String

Dim Retineri(5) As Currency

Public indicatori(10) As Byte

Dim matrice(1 To 3, 100 To 200) As String

Public fntScris As Font

Dim appWD As Word.Application

Proceduri

Printr-o procedură se înţelege, similar altor limbaje de programare, o mulţime de instrucţiuni care este identificată printr-
un nume şi care se execută unitar printr-un singur apel. Ar trebui, pentru claritatea programului, ca o procedură să
efectueze o prelucrare unitară identificabilă în logica programului.

Există trei tipuri principale de proceduri: Sub, Function şi Property. Ultimul tip este caracteristic definirii unui obiect şi va fi
prezentat ulterior. O procedură de tip Sub poate primi şi transmite informaţii prin intermediul unor variabile publice sau/şi
a unor parametri. Numele procedurii nu are ataşată nici o valoare. O procedură de tip Function se deosebeşte prin aceea
că numele procedurii are ataşată o valoare (valoarea funcţiei) şi poate fi utilizat ca orice altă variabilă din proiect.

Observaţie. Orice instrucţiune executabilă trebuie să aparţină unei proceduri. Declaraţiile pot să apară şi în afara
procedurilor, la nivel de modul.

Proceduri Sub

Organizarea generală a unei proceduri de tip Sub este

[Private | Public] [Static] Sub name ([arglist])

[instrucţiuni]

[Exit Sub]

[instrucţiuni]

End Sub

12
Public, Private, Static — determină vizibilitatea procedurii. Public = vizibilă pentru toate procedurile şi toate modulele (în
funcţie de Option Private se defineşte vizibilitatea pentru alte proiecte). Private = vizibilă doar pentru procedurile din
modulul unde procedura este declarată. Static = arată că toate variabilele locale îşi păstrează valorile între apeluri.

name — numele procedurii.

arglist — lista de argumente, separate prin virgule.

Prin instrucţiunea Exit Sub se poate ieşi din procedură şi altminteri decât prin linia finală.

Argumentele se definesc după sintaxa:

[Optional] [ByVal | ByRef] [ParamArray] varname[( )] [As type] [= defaultvalue]

Optional — arată că parametrul nu este obligatoriu. Parametrii opţionali trebuie să fie grupaţi la sfârşitul listei (apariţia
clauzei Optional cere ca toţi parametrii care urmează să aibă aceeaşi clauză).

ByVal — arată că apelul paramatrului se face prin valoare (orice modificare a valorii transmise nu este regăsită după
părăsirea procedurii, calculele efectuându-se pe o copie a parametrului).

ByRef — arată că apelul paramatrului se face prin referinţă (orice modificare a valorii transmise este regăsită după
părăsirea procedurii). Acesta este modul implicit de transmitere a parametrilor.

ParamArray — folosit doar ca ultim argument în listă, denotă un tablou Optional de elemente de tip Variant. Clauza
ParamArray permite definirea unui număr arbitrar de parametri. ParamArray nu poate fi utilizat împreună cu ByVal,
ByRef, sau Optional.

varname — numele argumentului. Dacă este tablou se vor indica parantezele.

type — tipul parametrului transmis: Byte, Boolean, Integer, Long, Currency, Single, Double, Decimal, Date, String (doar
lungime variabilă), Object, Variant. Pentru parametrii obligatorii (fără Optional) poate fi şi un tip definit sau de obiect.

defaultvalue — defineşte valoarea implicită pentru argumentele opţionale. Poate fi orice expresie, dar pentru tipul Object
se admite doar Nothing.

Apelul unei proceduri Sub

Pentru a executa o procedură de tip Sub din altă procedură (vezi şi discuţia privind vizibilitatea) se menţionează, pe o
linie separată, numele procedurii urmat sau nu de parametri. Dacă este necesar, datorită apelării unui alt proiect sau
modul, atunci apelul este după modelul:

Nume_proiect.Nume_modul.Nume_procedură listă de argumente

unde lista de argumente poate sau nu să fie inclusă între paranteze. Argumentele efective sunt separate în listă prin
virgule şi trebuie să respecte ordinea (şi tipul) argumentelor din definiţia procedurii. În cazul procedurilor cu multe
argumente, dintre care multe opţionale, transferul poate provoca erori de scriere a codului (un argument opţional necesită
totuşi virgula sa, de unde o numărare atentă a virgulelor etc.). Pentru asemenea situaţii (în special) se permite şi
transferul valorilor prin intermediul tehnicii de argumente denumite. Aceasta se realizează alcătuind lista de argumente, la
apelul procedurii, din intrări de forma

nume_argument:=valoare_argument

13
separate prin virgule şi la care nu mai contează ordinea iniţială a argumentelor. Se vor specifica doar parametrii care se
transmit efectiv (adică valorile opţionale dorite şi toate valorile neopţionale).

Pentru apelul unei proceduri se va studia şi instrucţiunea Call.

Proceduri Function

O procedură de tip Function este similară, ca definiţie, unei proceduri Sub, dar are particularitatea că returnează o
valoare prin numele său (care se comportă deci ca o variabilă).

[Public | Private] [Static] Function name [(arglist)] [As type]

[statements]

[name = expression]

[Exit Function]

[statements]

[name = expression]

End Function

Este de remarcat că se poate ataşa un tip numelui funcţiei (adică valorii funcţiei) şi se va remarca existenţa instrucţiunilor
prin care se atribuie funcţiei valorile calculate.

Valoarea returnată de o funcţie poate fi utilizată într-o altă expresie prin includerea numelui funcţiei urmat, între
paranteze, de valorile efective ale parametrilor.

Dacă apelul se face prin intermediul instrucţiunii Call, valoarea funcţiei nu poate fi utilizată. În asemenea situaţii se
activează de fapt doar prelucrările colaterale (care, pentru claritatea codului, nici nu sunt recomandate).

Exemple de proceduri

Public Function AriaCilindru (raza, inaltime) As Double

Const Pi = 3.14159

cilBaza = Pi*raza^2

cilLaterala = 2*Pi*raza*inaltime

AriaCilindru = 2*cilBaza + cilLaterala

End Function

Sub AriaCilindru (ByVal raza As Single, ByVal inaltime As Single, ByRef cilAria As Double)

Const Pi As Single = 3.14159

14
Dim cilBaza As Single, cilLaterala As Single

cilBaza = Pi*raza^2

cilLaterala = 2*Pi*raza*inaltime

cilAria = 2*cilBaza + cilLaterala

End

Apelul funcţiei poate fi într-o instrucţiune de genul

CostTotalPiesa = AriaCilindru (r1, h1) * CostUnitar

în timp ce apelul subrutinei poate fi

AriaCilindru inaltime:=h1, raza:=r1, cilAria:=AriePiesa

Organizarea generală a unui proiect VBA

Obiectele şi prelucrările necesare realizării unei aplicaţii VBA (presupunând că se doreşte atingerea unui ansamblu
coerent de scopuri) sunt gestionate sub forma unui proiect, care are un nume implicit sau dat de utilizator. La un anumit
moment pot fi deschise mai multe proiecte, identificabile prin denumirile lor.

Deoarece prelucrările proiectate în VBA sunt ataşate documentelor (acţiunilor) unor aplicaţii particulare (Word, Excel
etc.), proiectele sunt salvate o dată cu documentele pe care le însoţesc. Acest fapt nu reduce aria de probleme
abordabile întrucât prelucrările propriu-zise nu sunt limitate la documentul însoţit (se poate deschide astfel un document
Word alb şi să se efectueze orice prelucrare dorită, fără a avea obligaţia de a scrie ceva în documentul deschis).

Într-un proiect VBA sunt identificabile următoarele componente:

• Module standard (denumite iniţial module de cod). Conţin declaraţii şi proceduri generale. Există de asemenea şi
module care conţin tratarea evenimentelor specifice documentului de care este ataşat proiectul.
• Module de clasă. Conţin definirea obiectelor create de utilizator.
• Forme. Conţin definiţiile dialogurilor din interfaţa proiectată de utilizator ca şi codul program necesar controlării
dialogurilor.
• Referinţe. Într-un proiect este menţinută lista altor proiecte, care sunt referite în proiectul curent.

Un modul de cod poate începe cu o secţiune de declaraţii. Prin declaraţii înţelegem instrucţiuni neexecutabile prin care se
definesc constante, variabile şi proceduri externe. Utilizând Public, Static, Private se precizează şi domeniul de vizibilitate
a entităţilor definite.

Gestionarea (crearea, editarea, ştergerea etc.) obiectelor dintr-un proiect se face prin comenzi ale mediului VBA, care
este prezentat într-o secţiune separată.

Domeniul unei variabile, constante sau proceduri

Domeniul unei entităţi reprezintă mulţimea instrucţiunilor unde poate fi referită acea entitate. Se poate vorbi astfel de
vizibilitatea unei entităţi. Domeniul este dependent de locul definirii entităţii, de clauzele care apar la definire şi de
parametrii globali ai proiectului.

15
Notă. Este de remarcat că utilizarea unei denumiri în afara domeniului iniţial prefigurat produce, în lipsa
instrucţiunii Option Explicit, crearea unei noi entităţi, fără nici o legătură cu cea precedentă, sursă de erori
greu detectabile. Acesta este motivul pentru care se recomandă declararea explicită a tuturor variabilelor.

Există trei tipuri de domenii:

o la nivel de procedură;
o la nivel de modul, privat;
o la nivel de modul, public.

Nivelul procedură

O variabilă sau constantă definită într-o procedură este vizibilă doar în procedură respectivă. Dacă o asemenea entitate
trebuie referită şi în alte proceduri, atunci declararea ei se va efectua la nivel de modul, sau se va transmite procedurii
prin intermediul argumentelor.

Nivel de modul, privat

Variabilele şi constantele definite la nivel de modul (în secţiunea Declarations) sunt Private în mod implicit, adică sunt
vizibile doar în modulul respectiv. Utilizarea clauzei Private nu este deci necesară, dar este recomandată.

Notă. Dacă se utilizează instrucţiunea Option Private Module (în secţiunea Declarations a modulului) atunci variabilele şi
procedurile publice vor fi vizibile doar în proiectul curent. În lipsa acestei declaraţii, procedurile publice (din toate modulele
standard sau clasă) sunt vizibile în toate proiectele care se referă la proiectul curent. Procedurile, variabilele şi
constantele publice din alte module (cum ar fi modulele ataşate formelor) sunt Private pentru proiectul de definiţie, deci
ele nu sunt accesibile proiectelor care se referă la proiectul unde sunt declarate.

Nivel de modul, public

Variabilele declarate la nivel de modul drept Public sunt vizibile în toate procedurile din proiect. Procedurile sunt publice
în mod implicit, cu excepţie procedurilor de tratare a evenimentelor, care sunt Private în mod implicit. A se vedea şi nota
anterioară.

Viata unei variabile

Prin viaţa unei variabile se înţelege timpul cât variabila are o valoare. Este evident că valoarea unei variabile se poate
modifica pe durata vieţii sale, dar definitoriu este faptul că variabila are o anumită valoare pe întreaga durată a vieţii sale.
La părăsirea domeniului, variabila "moare" şi nu mai are ataşată o valoare.

La începutul execuţiei unei proceduri, toate variabilele sunt iniţializate:

Variabilă numerică 0 (zero)

Şir de lungime variabilă "" (şir de lungime zero)

Şir de lungime fixă Completat cu caracterul Chr(0) (având codul ASCII 0)

Variabilă Variant Empty

Variabile de tip utilizator fiecare element este iniţializat separat, potrivit tipului primar

Variabilă Object Nothing (până la asignarea unei referinţe prin Set)

16
Variabilele care nu sunt modificate îşi păstrează valoarea iniţială.

Variabilele declarate prin Dim la nivel de procedură au valoare până la terminarea execuţiei procedurii (chiar dacă se
trece prin apel în alte proceduri).

Variabilele declarate prin Static, la nivel de procedură, au aceeaşi viaţă ca şi variabilele declarate la nivel de modul şi îşi
păstrează valoarea până la terminarea execuţiei codului (inclusiv de la un apel la altul). Includerea clauzei Static în
instrucţiunea Sub sau Function are ca efect declararea tuturor variabilelor definite în procedura respectivă drept variabile
statice (deci care îşi păstrează valorile între apeluri).

Variabilele declarate la nivel de modul standard îşi păstrează valoarea pe tot timpul execuţiei. Variabilele declarate la
nivel de modul clasă îşi păstrează valoarea atât timp cât există o instanţă a clasei. Diferenţa faţă de variabilele Static este
aceea că memoria este utilizată permanent (nu se eliberează la părăsirea domeniului).

Variabile Object

Declararea unei variabile de tip obiect se poate efectua prin declararea tipului generic Object

Dim myDoc As Object

sau specificând exact numele de clasă dintr-o bibliotecă de obiecte referită

Dim myDoc As Word.Document

În primul mod de definire (ca Object) nu se poate efectua la momentul compilării existenţa obiectului, nu se poate verifica
utilizarea corectă a proprietătilor şi metodelor obiectului şi nu se poate lega această informaţie de variabila obiect definită.
Ataşarea unui obiect este, în acest caz, o legare târzie (late binding) la momentul execuţiei şi se efectuează prin
instrucţiunea Set.

Specificarea unei clase la definirea variabilei obiect produce o legare timpurie (early binding) care este mai rapidă, se
face la momentul compilării şi poate înlătura mai rapid erori posibile în utilizarea metodelor şi proprietăţilor obiectului.

Instrucţiunea Set are sintaxa:

Set objectvar = {[New] objectexpression | Nothing}

unde
o objectvar este numele variabilei (sau proprietăţii)
o New permite crearea unei noi instanţe a clasei
o Objectexpression este o expresie constând în numele unui obiect, altă variabilă declarată de acelaşi tip
obiect, sau funcţie ori metodă care returnează un obiect de acelaşi tip obiect
o Nothing permite deconectarea asocierii cu un obiect specific, eliberând resursele sistem şi de memorie
utilizate.

În general, atunci când se utilizează Set pentru a asigna o referinţă de obiect la o variabilă, nu se creează o copie a
obiectului pentru acea variabilă. Este creată doar o referinţă la obiect. Astfel, mai multe variabile de tip obiect pot să se
refere la acelaşi obiect: orice schimbare a obiectului se va reflecta în toate variabilele care referă obiectul. Utilizând
clauza New se va crea efectiv o copie (instanţă) a obiectului.

Exemple

Prin următoarele două instrucţiuni se defineşte variabila objWord care este legată târziu de o aplicaţie Word:

17
Dim objWord As Object

Set obhWord = CreateObject("Word.Application")

Legarea timpurie se poate efectua prin

Dim objWord As Word.Application

Este de remarcat că instrucţiunea Set apelează o funcţie care creează şi returnează o referinţă la un obiect ActiveX.

Constante predefinite (built–in)

Bibliotecile de obiecte din fiecare aplicaţie Office furnizează o mulţime de constante predefinite, care pot fi utilizate pentru
a stabili proprietăti sau pentru a transmite argumente către proprietăţi sau metode. Constantele sunt, de regulă, grupate
în tipuri enumerate care reprezintă valorile posibile pentru o proprietate specifică. Deşi este posibilă să se utilizeze
valoarea numerică a constantei este recomandat să se utilizeze constanta numită întrucât dezvoltări ulterioare ale
mediului Microsoft Office (ca şi ale aplicaţiilor din Visual Studio) tind să păstreze compatibilitatea între denumirile
constantelor şi nu între valorile efective.

De exemplu se preferă

Application.DisplayAlerts = wdAlertAll

în loc de

Application.DisplayAlerts = -1

pentru a fixa ca Word să afişeze toate mesajele de alertă la execuţia unei proceduri. Codul scris astfel este şi mai explicit.

INSTRUCŢIUNILE VBA

Generalităţi

Există trei categorii de instrucţiuni Visual Basic:


• instrucţiuni de declarare (prezentate la declararea variabilelor) prin care se denumesc şi se declară tipul pentru
variabile, constante şi proceduri;
• instrucţiuni de atribuire (prezentate în continuare) prin care se atribuie valori variabilelor sau constantelor;
• instrucţiuni executabile (prezentate în continuare) care iniţiază acţiuni: execută metode sau proceduri,
controlează fluxul execuţiei codului.
În mediul de dezvoltare VBA, sintaxa instrucţiunilor este verificată automat după ce se trece la instrucţiunea următoare
(prin Enter).

Continuarea instrucţiunilor

O instrucţiune poate să fie scrisă pe mai multe linii prin utilizarea caracterului de continuare a liniei "_" precedat de un
spaţiu. De exemplu, crearea prin program a unui tabel într-un document Word:

ActiveDocument.Tables.Add Range:=Selection.Range, _

NumRows:=3, _

18
NumColumns:= 3

unde, pe lângă continuarea liniilor se va remarca utilizarea argumentelor numite la apelul metodei de adăugare a unui
nou tabel la colecţia de tabele a documentului.

Două instrucţiuni pot fi scrise pe o aceeaşi linie dacă sunt separate cu caracterul ":".

Etichetarea liniilor

O linie poate fi identificată:


• printr-o etichetă: orice nume, care respectă regulile generale, care începe în prima coloană a liniei şi se termină
cu caracterul ":"
• printr-un număr: orice combinaţie de cifre, care începe în prima coloană a liniei şi este unic în modulul respectiv.
Identificatorii de linii pot fi utilizaţi în instrucţiuni de control, desi codul astfel construit nu respectă regulile programării
structurate..

Comentarii

Textele explicative (necesare documentării codului) pot fi introduse pe linii separate sau în continuarea liniei de cod.
O linie de comentariu începe cu un apostrof (') sau cu cuvântul Rem urmat de un spaţiu.
Comentariul de pe aceeaşi linie cu o instrucţiune se introduce printr-un apostrof urmat de comentariu.

Operatori

În formarea expresiilor de diverse tipuri, operatorii sunt cei utilizaţi aproape general în limbajele de programare de nivel
înalt. Pentru fixarea termenilor şi notaţiilor sunt totuşi prezentaţi, pe categorii, însoţiţi, acolo unde este cazul de scurte
explicaţii.

Operatori aritmetici

Operator Semnificaţie Observaţii

^ Ridicarea la putere rezultatul este Double sau Variant(Double) cu excepţia: dacă un operand este Null,
rezultatul este tot Null

* Înmulţirea rezultatul este dat de cel "mai precis" factor, ordinea crescătoare a "preciziei" fiind,
pentru înmulţire, Byte, Integer, Long, Single, Currency, Double şi Decimal. Dacă o
expresie este Null, rezultatul este Null. O expresie Empty este considerată ca 0. Pentru
excepţii se va studia Help – *(operator).

/ Împărţirea rezultatul este, în general, Double sau Variant(Double). Dacă o expresie este Null,
rezultatul este Null. O expresie Empty este considerată ca 0. Pentru excepţii se va
studia Help – /(operator).

\ Împărţirea întreagă înainte de împărţire, operanzii sunt rotunjiţi la Byte, Integer sau Long. Rezultatul este
Byte, Variant(Byte), Integer, Variant (Integer), Long, sau Variant(Long). Dacă o
expresie este Null, rezultatul este Null. O expresie Empty este considerată ca 0.

Mod Restul împărţirii operanzii sunt rotunjiţi la întregi şi se obţine restul împărţirii. Rezultatul este Byte,
Variant(Byte), Integer, Variant (Integer), Long, sau Variant(Long). Dacă o expresie este

19
Null, rezultatul este Null. O expresie Empty este considerată ca 0.

+ Adunarea numerică în general, operanzi numerici produc adunarea, iar operanzi şiruri produc
sau concatenarea concatenarea. În cazul numeric, rezultatul este de tipul cel "mai precis" al operanzilor,
şirurilor ordinea de "precizie" fiind pentru adunare şi scădere: Byte, Integer, Long, Single,
Double, Currency şi Decimal. Deoarece operanzii pot fi orice expresie, pentru o
informare completă (de exemplu operanzi Variant) se va studia Help – +(operator).

- Scăderea sau operanzii pot fi doar numerici. Rezultatul este de tipul cel "mai precis" al operanzilor,
inversarea semnului ordinea de "precizie" fiind pentru adunare şi scădere: Byte, Integer, Long, Single,
Double, Currency şi Decimal. Dacă o expresie este Null, rezultatul este Null. O
expresie Empty este considerată ca 0. Pentru excepţii se va studia Help – -(operator).

Operatori de comparare

Relaţiile care există între diferite tipuri de entităţi se pot evidenţia prin comparaţii având una dintre formele următoare:

result = expression1 comparisonoperator expression2

result = object1 Is object2

result = string Like pattern

unde

result este o variabilă numerică

expression este o expresie oarecare

comparisonoperator este un operator relaţional

object este un nume de obiect

string este o expresie şir oarecare

pattern este o expresie String sau un domeniu de caractere.

Operatorii de comparare sunt cei uzuali: < (mai mic), <= (mai mic sau egal), > (mai mare), >= (mai mare sau egal), =
(egal), <> (diferit, neegal).

Rezultatul este True (dacă este adevărată relaţia), False (dacă relaţia este neadevărată), Null (dacă cel puţin un operand
este Null).

Operatorul Is produce True dacă variabilele se referă la acelaşi obiect şi False în caz contrar.

Operatorul Like compară două şiruri cu observaţia că al doilea tremen este un şablon. Prin urmare rezultatul este True
dacă primul şir operand este format după şablon, False în caz contrar. Atunci când un operand este Null, rezultatul este
tot Null.

Comportarea operatorului Like depinde de instrucţiunea Option Compare, care poate fi:

20
• Option Compare Binary, ordinea este cea a reprezentării interne binare, determinată în Windows de codul de
pagină.
• Option Compare Text, compararea este insenzitivă la capitalizarea textului, ordinea este determinată de setările
locale ale sistemului.

Construcţia şablonului poate cuprinde caractere wildcard, liste de caractere, domenii de caractere:

? un caracter oarecare

* oricâte caractere (chiar nici unul)

# o cifră oarecare (0–9).

[charlist] oricare dintre caracterele enumerate în listă, un domeniu de litere poate fi dat prin utilizarea cratimei.

[!charlist] orice caracter care nu este în listă

Observaţie. Pentru a utiliza în şablon caracterele speciale cu valoare de wildcard se vor utiliza construcţii de tip listă: [[],
[?] etc. Paranteza dreapta va fi indicată singură: ].

Pentru alte observaţii utile se va studia Help – Like operator.

Operatori de concatenare

Pentru combinarea şirurilor de caractere se pot utiliza operatorii & şi +.

În sintaxa

expression1 & expression2

unde operanzii sunt expresii oarecare, rezultatul este

• de tip String, dacă ambii operanzi sunt String


• de tip Variant(String) în celelalte cazuri
• Null, dacă ambii operanzi sunt Null.

Înainte de concatenare, operanzii care nu sunt şiruri se convertesc la Variant(String). Expresiile Null sau Empty sunt
tratate ca şiruri de lungime zero ("").

Operatori logici

Pentru operaţiile logice sunt utilizaţi următorii operatori, uzuali în programare.

Operator Semnificaţie Observaţii

And conjuncţia logică Null cu False dă False, Null cu True sau cu Null dă Null. Operatorul And realizează
şi operaţia de conjuncţie bit cu bit pentru expresii numerice.

21
Eqv echivalenţa logică Dacă o expresie este Null, rezultatul este Null. Eqv realizează şi compararea bit cu
bit a două expresii numerice, poziţionând cifrele binare ale rezultatului după regulile
de calcul ale echivalenţei logice: 0 Eqv 0 este 1 etc.

Imp implicaţia logică True Imp Null este Null, False Imp * este True, Null Imp True este True, Null Imp
False (sau Null) este Null. Operatorul Imp realizează şi compararea bit cu bit a două
expresii numerice, poziţionând cifrele binare ale rezultatului după regulile de calcul
ale implicaţiei logice: 1 Imp 0 este 0, în rest rezultatul este 1.

Not negaţia logică Not Null este Null. Prin operatorul Not se poate inversa bit cu bit valorile unei
variabile, poziţionându-se corespunzător un rezultat numeric.

Or disjuncţia logică Null Or True este True, Null cu False (sau Null) este Null. Operatorul Or realizează
şi o comparaţie bit cu bit a două expresii numerice poziţionând biţii corespunzători ai
rezultatului după regulile lui Or logic.

Xor disjuncţia exclusivă Dacă un operand este Null, atunci rezultatul este Null. Se poate efectua operaţia de
sau exclusiv şi bit cu bit pentru două expresii numerice [b1+b2(mod 2)].

Instrucţiuni de atribuire

Atribuirea se poate efectua prin instrucţiunea Let (pentru valori atribuite variabilelor şi proprietăţilor), Set (pentru atribuirea
de obiecte la o variabilă de tip obiect), Lset şi Rset (pentru atribuiri speciale de şiruri sau tipuri definite de utilizator).

Instrucţiunea Let

Atribuie valoarea unei expresii la o variabilă sau proprietate.

[Let] varname = expression

unde varname este nume de variabilă sau de proprietate.

Este de remarcat forma posibilă (şi de fapt general utilizată) fără cuvântul Let.

Observaţii. Valoarea expresiei trebuie să fie compatibilă ca tip cu variabila (sau proprietatea): valori numerice nu pot fi
atribuite variabilelor de tip String şi nici reciproc.

Variabilele Variant pot primi valori numerice sau String, reciproc nu este valabil decât dacă valoarea expresiei Variant
poate fi interpretată compatibilă cu tipul variabilei: orice Variant poate fi atribuit unei variabile de tip String (cu excepţia
Null), doar Variant care poate fi interpretat nuric poate fi atribuit unei variabile de tip numeric.

La atribuirea valorilor numerice pot avea loc conversii la tipul numeric al variabilei.

Atribuirea valorilor de tip utilizator poate fi efectuată doar dacă ambii termeni au acelaşi tip definit. Pentru alte situaţii se
va utiliza instrucţiunea Lset.

Nu se poate utiliza Let (cu sau fără cuvântul Let) pentru legarea de obiecte la variabile obiect. Se va utiliza în această
situaţie instrucţiunea Set.

22
Instrucţiunea LSet

Copie, cu aliniere la stânga, un şir de caractere (valoarea expresiei din dreapta) într-o variabila de tip String. Deoarece
copierea este binară, poate fi utilizată pentru atribuiri între tipuri utilizator diferite (rezultatul este impredictibil deoarece nu
se face nici o verificare de tipuri/componente ale valorilor de tip record). Sintaxa este

LSet stringvar = string

LSet varname1 = varname2

unde

stringvar, string reprezintă variabila de tip String şi expresia de acelaşi tip implicate într-o atribuire de şiruri.

varname1, varname2 sunt denumiri de variabile, de tipuri definite de utilizator (vezi instrucţiunea Type) diferite. Zona de
memorie alocată celei de a doua variabile este copiată (aliniată la stânga) în zona de memorie a primei variabile.

Caracterele care rămân neocupate se completează cu spaţii, iar dacă zona de unde se copie este mai mare, caracterele
din dreapta se pierd (sunt trunchiate).

Instrucţiunea LSet

Copie, cu aliniere la dreapta, un şir de caractere (valoarea expresiei din dreapta) într-o variabila de tip String. Sintaxa
este

RSet stringvar = string

Caracterele rămase neocupate în variabilă sunt completate ccu spaţii. Instrucţiunea RSet nu se poate utiliza (analog lui
LSet) pentru tipuri definite de utilizator.

Instrucţiuni executabile

Execuţia unui program are loc, în lipsa oricărui control, instrucţiune cu instrucţiune, de la stânga la dreapta şi de sus în
jos. Acest sens poate fi modificat, într-o oarecare măsură, prin ordinea de precedenţă a operaţiilor în evaluarea
expresiilor. Este evident că o asemenea structură simplă nu poate cuprinde toate aspectele programării şi din acest motiv
necesitatea structurilor de control a fluxului execuţiei. Unele instrucţiuni au fost păstrate doar din motive de compatibilitate
cu versiunile iniţiale ale limbajului, în locul lor fiind preferate structuri mai evoluate sau similare altor limbaje de
programare.

Instrucţiuni de transfer (GoSub…Return, GoTo, OnError, On…GoSub, On…GoTo)

Această categorie cuprinde instrucţiunile prin care controlul execuţiei este transferat la o altă instrucţiune din procedură.
În general, utilizarea acestor comenzi nu produce programe foarte structurate (în sensul programării structurate) şi prin
urmare, pentru o mai mare claritate a codului, pot fi înlocuite cu alte structuri de programare.

GoSub…Return

În cadrul unei proceduri un grup de instrucţiuni poate fi organizat ca o subrutină (similar unei proceduri on-line, nenumite)
identificată prin linia de început. Transferul controlului la acest grup de instrucţiuni şi revenirea la locul apelului se poate
efectua prin GoSub…Return cu sintaxa

GoSub line
23
...

line

...

Return

unde line este o etichetă de linie sau un număr de linie din aceeaşi procedură.

Pot exista mai multe instrucţiuni Return, prima executată produce saltul la instrucţiunea care urmează celei mai recente
instrucţiuni GoSub executate.

GoTo

Realizează tranferul controlului execuţiei la o linie din aceeaşi procedură.

GoTo line

unde line este o etichetă de linie sau un număr de linie din aceeaşi procedură.

On Error

Permite controlul erorilor prin transferul controlului la rutine de tratare.

Observaţie. Este prezentată în secţiunea dedicată controlului erorilor.

On…GoSub, On…GoTo

Permit o ramificare multiplă, după valoarea unei expresii. Se recomandă, pentru claritatea codului, utilizarea structurii
Select Case în locul acestor structuri.

On expression GoSub destinationlist

On expression GoTo destinationlist

unde

expression este o expresie numerică având valoare întreagă (după o eventuală rotunjire) între 0 şi 255 inclusiv.

destinationlist este o listă de etichete de linii sau numere de linii, separate prin virgule (elementele pot fi de ambele
categorii), din aceeaşi procedură cu instrucţiunea.

Dacă valoarea expresiei este negativă sau mai mare decât 255 se produce o eroare.

Dacă valoarea expresiei, fie ea k, este în domeniul rangurilor listei, atunci se transferă controlul la linia identificată de al k-
lea element al listei.

Dacă valoarea expresiei este 0 sau mai mare decât numărul de elemente din listă, transferul se efectuează la linia care
urmează instrucţiunea On...GoSub sau On...GoTo.

24
Instrucţiuni de terminare sau oprire a programului (DoEvents, End, Exit, Stop)

Terminarea execuţiei programului sau oprirea temporară (pauza) se pot realiza prin instrucţiunile enumerate aici.

DoEvents

Deşi nu este o instrucţiune VBA ci este o funcţie, includerea ei este naturală prin aceea că permite cedarea controlului
către sistemul de operare, care poate astfel să funcţioneze în regim de multitasking. Acţiunea poate fi realizată şi prin alte
tehnici (de exemplu utilizarea unui Timer etc.). Sintaxa este

DoEvents( )

Funcţia returnează, în general, valoarea 0.

Controlul este redat programului după ce sistemul de operare a terminat procesarea evenimentelor din coada de
evenimente, ca şi procesarea tuturor caracterelor din coada SendKeys.

Observaţie. Pentru alte observaţii se va studia documentaţia comenzii DoEvents.

End

Termină execuţia unei proceduri (sub forma prezentată aici) sau indică sfârşitul codului unei structuri de tip bloc (cum ar fi
End Function, End If etc., prezentate la structurile respective).

Sintaxa, în ipostaza opririi execuţiei, este:

End

Prin această instrucţiune, care poate fi plasată oriunde în program, execuţia este terminată imediat, fără a se mai executa
eventualele instrucţiuni scrise pentru tratarea unor evenimente specifice sfârşitului de program (Unload, Terminate etc.).

Fişierele deschise prin Open sunt închise şi toate variabilele sunt eliberate. Obiectele create din modulele clasă sunt
distruse, iar referinţele din alte aplicaţii la asemenea obiecte sunt invalidate. Memoria este eliberată.

Exit

Prin instrucţiunea Exit, sub una din multiplele ei forme, se întrerupe o ramură de execuţie (cum ar fi o procedură, o
structură iterativă etc.) pentru a se continua nivelul apelant. Sintaxa este

Exit Do

Exit For

Exit Function

Exit Property

Exit Sub

şi efectele sunt prezentate la structurile respective. Nu trebuie confundată cu instrucţiunea End.

25
Stop

Efectul instrucţiunii este dependent de modul de execuţiei a programului. Dacă se execută varianta compilată a
programului (fişierul .exe) atunci instrucţiunea este similară instrucţiunii End (suspendă execuţia şi închide fişierele
deschise). Dacă execuţia este din mediul VBA, atunci se suspendă execuţia programului, dar nu se închid fişierele
deschise şi nu se şterge valoarea variabilelor. Execuţia poate fi reluată din punctul de suspendare.

Stop

Instrucţiunea este similară introducerii unui punct de oprire (Breakpoint) în codul sursă.

Structuri iterative (Do...Loop, For...Next, For Each...Next,


While...Wend, With)

Prin intermediul construcţiilor de tip bloc prezentate în această secţiune se poate repeta, în mod controlat, un grup de
instrucţiuni. În cazul unui număr nedefinit de repetiţii, condiţia de oprire poate fi testată la începutul sau la sfârşitul unui
ciclu, prin alegerea structurii adecvate.

Do…Loop

Se vor utiliza structuri Do…Loop pentru a executa un grup de instrucţiuni de un număr de ori nedefinit aprioric. Dacă se
cunoaşte numărul de cicluri, se va utiliza structura For…Next.

Înainte de continuare se va testa o condiţie (despre care se presupune că poate fi modificată în instrucţiunile executate).
Diferitele variante posibile pentru Do…Loop diferă după momentul evaluării condiţiei şi decizia luată.

Do [{While | Until} condition]

[statements]

[Exit Do]

[statements]

Loop

sau

Do

[statements]

[Exit Do]

[statements]

Loop [{While | Until} condition]

unde

condition este o expresie care valoare de adevăr True sau False. O condiţie care este Null se consideră False.
26
statements sunt instrucţiounile care se repetă atâta timp (while) sau până când (until) condiţia devine True.

Dacă decizia este de a nu continua ciclarea, atunci se va executa prima instrucţiune care urmează întregii structuri (deci
de după linia care începe cu Loop).

Se poate abandona ciclarea oriunde în corpul structurii prin utilizarea comenzii Exit Do (cu această sintaxă). Dacă apare
o comandă Exit Do se poate omite chiar şi condiţia din enunţ întrucât execuţia se va termina prin această decizie.

Structurile Do pot fi inserate (dar complet) unele în altele. O terminare (prin orice metodă) a unei bucle transferă controlul
la nivelul Do imediat superior.

Execuţia structurilor este explicată în tabelul următor

Do While…Loop Testează condiţia la începutul buclei, execută bucla numai dacă rezultatul este True şi
continuă astfel până când o nouă evaluare produce False.

Do Until…Loop Testează condiţia la începutul buclei, execută bucla numai dacă rezultatul este False şi
continuă astfel până când o nouă evaluare produce True.

Do…Loop While Se execută întotdeauna bucla o dată, se testează condiţia la sfârşitul buclei şi se
repetă bucla atât timp cât condiţia este True. Oprirea este pe condiţie falsă.

Do…Loop Until Se execută întotdeauna bucla o dată, se testează condiţia la sfârşitul buclei şi se
repetă bucla atât timp cât condiţia este False. Oprirea este pe condiţie adevărată.

For…Next

Atunci când se cunoaşte numărul de repetări ale unui bloc de instrucţiuni, se va folosi structura For…Next. Structura
utilizează o variabilă contor, a cărei valoare se modifică la fiecare ciclu, oprirea fiind atunci când se atinge o valoare
specificată. Sintaxa este:

For counter = start To end [Step step]

[statements]

[Exit For]

[statements]

Next [counter]

unde

counter este variabila contor (numără repetările), de tip numeric. Nu poate fi de tip Boolean sau element de tablou.

start este valoarea iniţială a contorului.

end este valoarea finală a contorului.

step este cantitatea care se adună la contor la fiecare pas. În cazul în care nu se specifică este implicit 1. Poate fi şi
negativă.
27
statements sunt instrucţiunile care se repetă. Dacă nu se specifică, atunci singura acţiune este cea de modificare a
contorului de un număr specificat de ori.

Acţiunea este dictată de pasul de incrementare şi relaţia dintre valoarea iniţială şi cea finală.

Instrucţiunile din corpul structurii se execută dacă

o counter <= end pentru step >= 0 sau


o counter >= end pentru step < 0.

După ce toate instrucţiunile s-au executat, valoarea step este adăugată la valoarea contorului şi instrucţiunile se execută
din nou după acelaşi test ca şi prima dată, sau bucla For…Next este terminată şi se execută prima instrucţiune de după
linia Next.

Specificarea numelui contorului în linia Next poate clarifica textul sursă, mai ales în cazul când există structuri For…Next
îmbricate.

Corpul unei bucle For…Next poate include (complet) o altă structură For…Next. În asemenea situaţii, structurile îmbricate
trebuie să aibă variabile contor diferite.

Instrucţiunile Exit For pot fi plasate oriunde în corpul unei bucle şi provoacă abandonarea ciclării. Controlul execuţiei se
transferă la prima instrucţiune de după linia Next.

For Each…Next

Similară structurii For…Next, structura For Each…Next repetă un grup de instrucţiuni pentru fiecare element dintr-o
colecţie de obiecte sau dintr-un tablou (cu excepţia celor de un tip utilizator). Este utilă atunci când nu se cunoaşte
numărul de elemente sau dacă se modifică, în timpul execuţiei, conţinutul colecţiei.

Sintaxa este:

For Each element In group

[statements]

[Exit For]

[statements]

Next [element]

unde

element este variabila utilizată pentru parcurgerea elementelor. Dacă se parcurge o colecţie de obiecte,
atunci element poate fi Variant, o variabilă generică de tip Object, sau o variabilă obiect specifică pentru
biblioteca de obiecte referită. Pentru parcurgerea unui tablou, element poate fi doar o variabilă de tip
Variant.

group este numele colecţiei de obiecte sau al tabloului.

statements este grupul de istrucţiuni executate pentru fiecare element.

28
Execuţia unei structuri For Each…Next este

1. Se defineşte element ca numind primul element din grup (dacă nu există nici un element, se transferă controlul la
prima instrucţiune de după Next – se părăseşte bucla fără executarea instrucţiunilor).
2. Se execută instrucţiunile din corpul buclei For.
3. Se testează dacă element este ultimul element din grup. Dacă răspunsul este afirmatif, se părăseşte bucla.
4. Se defineşte element ca numind următorul element din grup.
5. Se repetă paşii 2 până la 4.

Instrucţiunile Exit For sunt explicate la For…Next.

Buclele ForEach...Next pot fi îmbricate cu condiţia ca elementele utilizate la iterare să fie diferite.

Observaţie. Pentru ştergerea tuturor obiectelor dintr-o colecţie se va utiliza For…Next şi nu For Each…Next. Se va utiliza
ca număr de obiecte colecţie.Count.

While…Wend

Execută un grup de instrucţiuni atât timp cât este adevărată o condiţie. Sintaxa

While condition

[statements]

Wend

Este recomandat să se utilizeze o structură Do…Loop în locul acestei structuri.

With

Programarea orientată pe obiecte produce, datorită calificărilor succesive, construcţii foarte complexe atunci când se
numesc proprietăţile unui obiect. În cazul modificărilor succesive ale mai multor proprietăţi ale aceluiaşi obiect, repetarea
zonei de calificare poate produce erori de scriere şi conduce la un text greu de citit. Codul este simplificat prin utilizarea
structurii With…End With. O asemenea structură execută o serie de instrucţiuni pentru un obiect sau pentru o variabilă de
tip utilizator. Sintaxa este:

With object

[statements]

End With

unde

object este numele unui obiect sau a unui tip definit de utilizator

statements sunt instrucţiunile care se execută pentru entitatea precizată.

Permiţând omiterea recalificărilor din referinţele la obiectul precizat, orice construcţie de tipul

".nume" este interpretată în instrucţiunile structurii drept "object.nume".

29
Într-un bloc With nu se poate schimba obiectul procesat.

La plasarea unui bloc With în interiorul altui bloc With, obiectul extern este mascat complet, deci calificările eventuale la
acest obiect vor fi efectuate.

Nu se recomandă saltul în şi dintr-un bloc With.

Structuri de decizie (If…Then…Else, Select Case)

Ramificarea firului execuţiei după rezultatul verificării unei condiţii este o necesitate frecventă în orice implementare.

Pe lângă structurile prezentate, se pot utiliza trei funcţii care realizează alegeri în mod liniarizat (pe o linie de cod):
Choose(), Iif(), Switch().

If…Then…Else

O asemenea structură, întâlnită de altfel în toate limbajele de programare, execută un grup de instrucţiuni ca răspuns la
îndeplinirea unei condiţii (compusă sau nu din mai multe condiţii testate secvenţial). Sintaxa permite o mare varietate de
forme:

If condition Then [statements] [Else elsestatements]

sau

If condition Then

[statements]

[ElseIf condition-n Then

[elseifstatements] ...

[Else

[elsestatements]]

End If

unde

condition are una din formele: expresie numerică sau şir care se poate evalua True sau False (Null este interpretat
False);
expresie de forma TypeOf objectname Is objecttype, evaluată True dacă objectname este de tipul obiect specificat în
objecttype.

statements, elsestatements, elseifstatements sunt blocurile de instrucţiuni executate atunci când condiţiile
corespunzătoare sunt True.

La utilizarea primei forme, fără clauza Else, este posibil să se scrie mai multe instrucţiuni, separate de ":", pe aceeaşi
linie.

30
Verificarea condiţiilor implică evaluarea tuturor subexpresiilor, chiar dacă prin jocul operanzilor şi operatorilor rezultatul
poate fi precizat mai înainte (de exemplu OR cu primul operand True).

Select Case

Instrucţiunea Select Case se poate utiliza în locul unor instrucţiuni ElseIf multiple (dintr-o structură If…Then…ElseIf)
atunci când se compară aceeaşi expresie cu mai multe valori, diferite între ele. Instrucţiunea Select Case furnizează, prin
urmare, un sistem de luare a deciziilor similar instrucţiunii If…Then…ElseIf. Totuşi, Select Case produce un un cod mai
eficient şi mai inteligibil. Sintaxa este:

Select Case testexpression

[Case expressionlist-n

[statements-n]] ...

[Case Else

[elsestatements]]

End Select

unde

testexpression este o expresie numerică sau şir.

expressionlist-n este lista, separată prin virgule, a uneia sau mai multe expresii de forma:

• expression.
• expression To expression. Cuvântul To introduce un interval de valori, valoarea minimă fiind prima specificată.
• Is comparisonoperator expression. Se va utiliza Is cu operatori de comparare (exceptând Is şi Like) pentru a
specifica un domeniu de valori.

statements-n reprezintă una sau mai multe instrucţiuni care se vor executa dacă testexpression este egală cu un element
din expressionlist-n.

elsestatements reprezintă una sau mai multe instrucţiuni care se vor executa dacă testexpression nu este egală cu nici
un element din listele liniilor Case.

Dacă testexpression se potriveşte cu un element dintr-o listă Case, se vor executa instrucţiunile care urmează această
clauză Case până la următoarea clauză Case, sau până la End Select. Control execuţiei trece apoi la instrucţiunea care
urmează liniei finale End Select. Rezultă că dacă testexpression se regăseşte în mai multe liste, doar prima potrivire este
considerată.

Clauza Case Else are semnificaţia uzuală "altfel, în rest, în caz contrar etc.", adică introduce instrucţiunile care se
execută atunci când expresia de test nu se potriveşte nici unui element din listele clauzelor Else. Dacă aceasta este
situaţia şi nu este specificată o clauză Case Else, atunci execuţia urmează cu prima instrucţiune de după End Select.

Instrucţiunile Select Case pot fi scufundate unele în altele, structurile interioare fiind complete (fiecare structură are End
Select propriu, includerea este completă).

Apeluri de proceduri şi programe


31
În această secţiune se prezintă doar funcţia Shell(), deoarece despre proceduri şi apelul lor s-a discutat în capitolul 1.

Funcţia Shell()

Execută un program executabil şi returnează un Variant(Double) reprezentând ID-ul de task al programului în caz de
succes; în caz contrar returnează zero. Sintaxa este

Shell(pathname[,windowstyle])

unde

pathname este Variant (String). Conţine numele programului care se execută, argumentele necesare şi
poate da calea completă (dacă este nevoie).

windowstyle este Variant (Integer) şi precizează stilul ferestrei în care se va executa programul (implicit
este minimizat, cu focus).

Valorile posibile pentru argumentul windowstyle sunt

Constanta numită Valoarea Semnificaţia

VbHide 0 Fereastra este ascunsă iar focus-ul este pe fereastra ascunsă.

VbNormalFocus 1 Fereastra are focus-ul şi este dimensionată şi poziţionată normal.

VbMinimizedFocus 2 Fereastra este afişată ca o icoană (minimizată) dar are focus-ul.

VbMaximizedFocus 3 Fereastră maximizată, cu focus.

VbNormalNoFocus 4 Fereastra este normală (restaurată la mărimea şi poziţia cea mai recentă) dar nu
are focus-ul. Fereastra activă curentă îşi păstrează focus-ul.

VbMinimizedNoFocus 6 Fereastră minimizată, fără focus. Fereastra activă curentă îşi păstrează focus-ul.

Dacă funcţia Shell nu poate porni programul specificat se va semnala eroare. Programul pornit prin Shell se execută
asincron, deci nu există certitudinea că acest program se termină înainte de execuţia instrucţiunilor care urmează liniei
Shell.

Operaţiuni de intrare-ieşire

În categoria operaţiunilor de I/O se pot deosebi

• schimbul de informaţii cu utilizatorul: acesta se poate desfăşura prin intermediul unor formulare (forms)
predefinite (InputBox, MsgBox) sau prin intermediul unor formulare definite de dezvoltatorul proiectului VBA.
• schimbul de informaţii cu fişiere şi/sau baze de date: acesta se realizează prin intermediul unor instrucţiuni
dedicate acestor operaţii.

32
Dialogul standard cu utilizatorul

În general, utilizatorul răspunde la apariţia unei boxe de dialog prin acţionarea butonului adecvat răspunsului său şi/sau
prin înscrierea unei informaţii într-o zonă dedicată acestui scop. Informaţia înscrisă este transferată programului ca
valoare a funcţiei care iniţiază dialogul grafic.

Funcţia InputBox

Apelul funcţiei InputBox afişează o boxă de dialog care conţine un mesaj, două butoane (OK şi Cancel) şi o zonă text în
care se poate tasta un răspuns (de tip String, chiar dacă se transmite o valoare numerică). Se aşteaptă ca utilizatorul să
introducă un text în zona rezervată sau să acţioneze un buton. Textul introdus este transmis ca valoare a funcţiei la
acţionarea butonului OK (sau Enter), iar acţionarea butonului Cancel (ca şi închiderea dialogului ca fereastră) transmite
un şir de lungime zero (indiferent de valoarea zonei text. Sintaxa este

InputBox(prompt[, title] [, default] [, xpos] [, ypos] [, helpfile, context])

unde

prompt este expresia String cu mesajul afişat în dialog (max. 1024 caractere). Mesajul poate fi aranjat pe mai multe linii
prin combinaţii de caractere Chr(13) – carriage return, Chr(10) – linefeed, Chr(13)&Chr(10) – CR+LF.

title este expresia de tip String cu titlul ferestrei dialogului. Dacă este omis se va folosi titlul aplicaţiei.

default este expresia de tip String, opţională, conţinând textul afişat iniţial în zona text rezervată utilizatorului. Textul este,
în lipsa modificării lui, retransmis ca răspuns (acţionând butonul OK).

xpos este expresia numerică specificând poziţia orizontală a dialogului (în twips, de la latura stânga a ecranului). În lipsa
argumentului, boxa de dialog este centrată orizontal.

ypos este expresia numerică specificând poziţia verticală a dialogului (în twips, de la latura de sus a ecranului). În lipsa
argumentului, boxa de dialog este poziţionată la aproximativ o treime de ecran.

helpfile este expresia de tip String care identifică fişierul Help utilizat.Dacă este indicat helpfile, trebuie să fie precizat şi
context. Textul de ajutor poate fi văzut prin tasta F1, anumite aplicaţii afişează şi un buton Help.

context Expresie numerică cu numărul de context Help al intrării corespunzătoare dialogului afişat. Apare obligatoriu
împreună cu helpfile.

Dacă valoarea funcţiei nu este atribuită (sau utilizată într-o altă expresie), este evident că se pierde, fără semnalarea
vreunei erori.

Funcţia MsgBox

Un dialog mai simplu decât InputBox este realizat prin forma predefinită afişată de funcţia MsgBox. Se afişează un mesaj
într-o boxă de dialog şi se aşteaptă ca utilizatorul să acţioneze unul dintre butoanele existente (numărul şi tipul lor lor este
fixat la proiectarea aplicaţiei). Funcţia returnează un întreg indicând care buton a fost acţionat. Sintaxa este

[intvariable=]MsgBox(prompt[, buttons] [, title] [, helpfile, context])

unde

prompt este textul mesajului (Vezi InputBox)


33
buttons este o expresie numerică egalăcu suma valorilor care specifică numărul, tipul şi atributele butoanelor. Aici se
fixează şi modalitatea ferestrei (Vezi constantele predefinite din tabelul care urmează). Valoarea implicită este 0.

title,helpfile, context identice cu argumentele similare descrise la InputBox.

Constantele recomandate pentru formarea argumentului buttons sunt

Constanta Valoare Descriere

VbOKOnly 0 Numai butonul OK

VbOKCancel 1 OK şi Cancel

VbAbortRetryIgnore 2 Abort, Retry şi Ignore

VbYesNoCancel 3 Yes, No şi Cancel

VbYesNo 4 Yes şi No

VbRetryCancel 5 Retry şi Cancel

VbCritical 16 Icoana de Critical Message

VbQuestion 32 Icoana de Warning Query

VbExclamation 48 Icoana Warning Message

VbInformation 64 Icoana de Information Message

VbDefaultButton1 0 Primul buton este cel implicit (echivalent cu Enter)

VbDefaultButton2 256 Al doilea buton este cel implicit

VbDefaultButton3 512 Al treilea buton este cel implicit

VbDefaultButton4 768 Al patrulea buton este cel implicit

VbApplicationModal 0 Application modal: aplicatia curentă este oprită până când răspunde utilizatorul

VbSystemModal 4096 System modal: toate aplicaţiile sunt oprite până când utilizatorul răspunde la dialog

Valorile 0-5 descriu butoanele, 16,32,48 şi 64 descriu stilul icoanei afişate, 0, 256 şi 512 determină butonul implicit, iar
ultimul grup (0 şi 4096) determină modalitatea boxei de dialog. La formarea argumentului Buttons se va adună doar câte
un număr din fiecare grup.

Pentru a utiliza valoarea returnată de funcţie, aceasta trebuie inclusă într-o expresie (eventual atribuită unei variabile
întregi).

Valorile returnate de funcţie şi care pot fi testate, în expresii logice, pentru a alege ramura de prelucrare dorită de
utilizator sunt

34
Constanta Valoare Descriere

VbOK 1 OK

VbCancel 2 Cancel

VbAbort 3 Abort

VbRetry 4 Retry

VbIgnore 5 Ignore

VbYes 6 Yes

VbNo 7 No

Acţionarea tastei Esc este echivalentă cu acţionarea butonului Cancel (dacă acesta este prezent). Dacă în dialog este
prezent butonul Help, acţionarea lui nu termină dialogul.

Utilizarea fişierelor

Procesările tipice programate în VBA prelucrează informaţii din două mari categorii de fişiere:

• fişiere ale aplicaţiilor server (.doc în Word, .xls în Excel etc.)


• fişiere utilizator (create şi/sau gestionate de proiect pentru date de intrare, temporare sau de ieşire).

Accesarea directă a fişierelor din prima categorie (fără apelul aplicaţiei server specifice) poate produce coruperea
fişierului, astfel încât nu mai este recunoscut de aplicaţia mamă. Prelucrarea acestor fişiere trebuie să fie
executată în aplicaţiile care le-au creat.

Pentru lucrul cu un fişier utilizator (în continuare prin fişier se va înţelege, fără alte precizări, un fişier utilizator) acesta
trebuie mai întâi deschis (instrucţiunea Open), operaţiunea producând şi crearea fişierului în cazul unui fişier inexistent
(nou). După utilizare fişierul trebuie să fie închis (operaţiune efectuată, la terminarea normală a programului, în mod
automat).

Un fişier are ataşat un număr de identificare, unic pentru un proces. Identificare fişierului se poate efectua, în program,
prin numele său sau prin numărul ataşat. Numărul poate fi în domeniul 1–255 pentru fişierele proprii aplicaţiei şi în
domeniul 256–511 pentru fişiere accesibile din alte aplicaţii. Un număr neutilizat (liber) poate fi furnizat de apelul la funcţia
FreeFile().

Există trei moduri de acces la înregistrările unui fişier, acces definit la deschiderea acestuia.

• acces secvenţial (modurile Input, Output şi Append), utilizat de regulă pentru scrierea fişierelor text (rapoarte,
jurnale etc.);
• acces raandom (aleator) (modul Random), în cazul când este necesar să se scrie şi să se citească înregistrările
într-o ordine nedefinită, operaţiunile de intrare/ieşire fiind amalgamate între ele;
• acces binar (modul Binary), utilizat la citirea/scrierea fişierelor byte cu byte (de exemplu fişiere bitmap).

Un fişier deschis cu un mod de acces trebuie exploatat în acest mod până când este închis şi deschis în alt mod (dacă
structura lui permite aşa ceva).

Instrucţiunile tipice pentru accesul la informaţiile dintr-un fişier sunt

35
Modul de acces Scriere Citire

Secvenţial Print #, Write # Input #

Random Put Get

Binar Put Get

Deoarece gestionarea fişierelor nu se rezumă doar la scriere/citire, în tabelul următor este un rezumat al principalelor
operaţiuni pe care le suportă fişierele, cu instrucţiunile care facilitează respectiva acţiune.

Acţiune Instrucţiuni

Citire Get, Input, Input #, Line Input #

Controlul ieşirilor Format, Print, Print #, Spc, Tab, Width #

Copierea unui fişier FileCopy

Creare, acces Open

Fixarea atributelor FileAttr, GetAttr, SetAttr

Fixarea poziţiei active de citire/scriere Seek

Inchidere Close, Reset

Informaţii despre un fişier EOF, FileAttr, FileDateTime, FileLen, FreeFile,


GetAttr, Loc, LOF, Seek

Lungimea unui fişier FileLen

Operaţii asupra fişierelor Dir, Kill, Lock, Unlock, Name

Scriere Print #, Put, Write #

Doar instrucţiunile şi funcţiile des utilizate sunt prezentate în continuare, pentru celelalte se va studia intrarea
corespunzătoare din Help (în mediul VBA).

Open

Deschide un fişier în sensul că rezervă o zonă tampon (buffer) pentru fişier şi determină modul de acces utilizat. Nu se
pot efectua instrucţiuni de I/O pe un fişier dacă acesta nu este deschis în prealabil. Sintaxa:

Open pathname For mode [Access access] [lock] As [#]filenumber [Len=reclength]

unde

pathname expresie String care specifică numele fişierului (poate include întreaga cale unitate, directoare etc., după
regulile uzuale);

36
mode cuvânt cheie care specifică modul de acces la fişier: Append, Binary, Input, Output sau Random; dacă nu se
specifică nimic se va considera acces Random;

access clauză opţională specificând operaţiunile I/O permise pentru fişier: Read, Write sau Read Write;

lock clauză opţională specificând operaţiile asupra fişierului permise altor procese care se execută (când fişierul este
deschis): Shared, Lock Read, Lock Write şi Lock Read Write.

filenumber numărul de fişier pentru fişierul deschis (între 1 şi 511, vezi observaţia din partea introductivă); funcţia FreeFile
furnizează următorul număr disponibil;

reclength număr (<=32,767) exprimând, în octeţi, lungimea înregistrării (la aceesul Random) sau lungimea bufferului (la
accesul secvenţial); la accesul Binary, clauza este ignorată.

Dacă fişierul indicat nu există, atunci este creat un fişier cu acest nume în cazurile care presupun o ieşire în fişier:
modurile Append, Binary, Output sau Random.

Un fişier poate fi deschis în mai multe moduri simultan (prin instrucţiuni Open distincte pentru fiecare mod, cu numere
diferite) dacă există compatibilitate între moduri: Binary, Input şi Random permit acest lucru, Append, Output nu permit
(fişierul trebuie mai întâi închis şi abia apoi deschis într-un asemenea mod).

FreeFile

Funcţia returnează un întreg reprezentând următorul număr de fişier disponibil.

FreeFile[(rangenumber)]

rangenumber este un Variant care specifică domeniul din care se solicită un număr liber de fişier: 0 (valoarea implicită)
returnează un număr în 1–255 (pentru fişiere proprii, 1 returnează un număr în 256–511 (pentru fişiere accesate din alte
aplicaţii).

Get

Citeşte date dintr-un fişier deschis şi le transferă într-o variabilă. Datele citite cu Get sunt, în general, scrise în fişier cu
comanda Put.

Get [#]filenumber, [recnumber], varname

unde

filenumber este numărul fişierului de unde se citesc date (fişierul trebuie să fie deschis)

recnumber număr opţional în format Variant (Long), reprezintă numărul înregistrării (modul Random) sau numărul
octetului (modul Binary) de unde începe citirea. Prima poziţie este 1.

varname numele variabilei unde se transferă informaţia.

Dacă nu se specifică numărul înregistrării se va citi din poziţia activă de după ultima instrucţiune Get, Put sau Seek.
Argumentul lipsă este indicat prin virgule: Get #4,,FileBuffer.

37
Pentru observaţiile privind acţiunea instrucţiunii Get, separat pentru modul Random şi Binary, se va studia Help - Get.
Observaţiile sunt utile atunci când se operează, în special, cu tipurile Variant şi cu tablouri.

Put

Scrie valoarea unei variabile date într-un fişier deschis în prealabil. Datele scrise cu Put sunt, în general, citite din fişier cu
Get.

Put [#]filenumber, [recnumber], varname

unde

filenumber este numărul fişierului unde se scriu datele (fişierul trebuie să fie deschis);

recnumber număr opţional în format Variant (Long), reprezintă numărul înregistrării (modul Random) sau numărul
octetului (modul Binary) unde începe scrierea. Prima poziţie este 1.

varname numele variabilei a cărei valoare se scrie în fişier.

Dacă nu se specifică numărul înregistrării se va scrie în poziţia activă de după ultima instrucţiune Get, Put sau Seek.
Argumentul lipsă este indicat prin virgule: Put #4,,FileBuffer.

Pentru observaţiile privind acţiunea instrucţiunii Put, separat pentru modul Random şi Binary, se va studia Help - Put.
Observaţiile sunt utile atunci când se operează, în special, cu tipurile Variant şi cu tablouri.

Input #

Citeşte date dintr-un fişier secvenţial şi le transferă în variabilele specificate.

Instrucţiunea se va utiliza doar cu fişierele deschise în modul Input sau Binary, datele citite cu Input # sunt scrise, de
regulă, cu Write #.

Input #filenumber, varlist

unde

filenumber numărul fişierului (deschis în prealabil);

varlist listă de variabile, delimitate de virgule, pentru care se citesc valorile din fişier. Nu se pot include nume de tablouri
sau variabile Object, dar se acceptă elemente de tablou şi variabiel de tipuri utilizator.

Pentru situaţiile uzuale (tipuri numerice sau String standarde) asignarea valorilor se efectuează fără modificări. Pentru
alte situaţii:

Informaţia citită Valoarea asignată

Virgulă sau linie goală Empty

#NULL# Null

#TRUE# sau #FALSE# True sau False

38
#yyyy-mm-dd hh:mm:ss# Data şi/sau timpul reprezentat de expresie

#ERROR errornumber# errornumber (variabila este un Variant considerat drept eroare)

Ghilimelele duble (" ") sunt ignorate în şirul de intrare.

Pentru o citire corectă, datele din fişier trebuie să apară în aceeaşi ordine şi de acelaşi tip cu variabilele din listă. O
variabilă numerică primeşte valoarea 0 dacă intrarea corespunzătoare nu este numerică. Atingerea sfârşitului de fişier
când operaţiunea de citire nu este încheiată, provoacă eroare.

Întrucât utilizarea fişierelor este, în mod uzual, aceea de memorare controlată a unor informaţii (şi nu aceea de a descifra
informaţii scrise într-o structură necunoscută), se recomandă scrierea cu Write # în cazul utilizării ulterioare a comenzii
Input #.

Funcţia Input()

Citeşte şi returnează un şir de caractere citite dintr-un fişier deschis în mod Input sau Binary. Datele citite prin această
funcţie sunt scrise, de regulă, prin Print # sau Put.

Input(number, [#]filenumber)

unde

number orice expresie numerică specificând numărul de caractere care se citesc.

filenumber număr de fişier (deschis).

Spre deosebire de instrucţiunea Input #, funcţia Input returnează toate caracterele citite (inclusiv virgule, CR, LF,
ghilimele şi spaţii de început).

Pentru fişierele deschise pentru acces Binary, încercarea de a citi prin funcţia Input până când EOF returnează True
generează eroare (procedeul este valid pentru citirea din fişiere binare cu Get). Se vor utiliza funcţiile LOF and Loc pentru
detectarea sfârşitului de fişier.

Observaţie. Pentru date pe octeţi din fişiere text se va utiliza funcţia InputB, cu o sintaxă similară, unde number specifică
numărul de octeţi de returnat (în loc de numărul de caractere). A se vedea şi Help – Returning Strings from Functions.

Line Input #

Citeşte o singură linie dintr-un fişier secvenţial (deschis) şi asignează şirul obţinut unei variabile de tip String. O linie este
considerată terminată la întâlnirea caracterului CR (Chr(13)) sau a combinaţiei CR+LF (Chr(13)&Chr(10)). Caracterele
CR şi/sau LF nu sunt adăugate şirului asignat (se poate considera că secvenţa lor a fost sărită).

Line Input #filenumber, varname

unde

filenumber numărul ataşat fişierului (deschis),

varname nume de variabilă String sau Variant.

39
Datele citite cu Line Input # sunt, de regulă, scrise cu Print #.

Write #

Scrie o înregistrare într-un fişier secvenţial. Datele scrise prin Write # sunt citite, de regulă, cu Input #. Utilizarea scrierii cu
Write # asigură o delimitare corectă a fiecărui câmp scris, ceea ce permite regăsirea corectă (fără alte artificii) a
informaţiilor la citirea cu Input #. În acelaşi timp, informaţiile sunt regăsite corect indiferent de configurările locale.

Sintaxa este

Write #filenumber, [outputlist]

unde

filenumber numărul ataşat fişierului (deschis în prealabil),

outputlist o listă de expresii numerice sau şir, separate prin virgule, spaţii sau punct-virgulă, ale căror
valori se scriu în fişier.

Specificarea unei virgule după filenumber fără outputlist produce o linie goala în fişier.

Sunt respectate urtmătoarele reguli de scriere:

• datele numerice sunt scrise cu punct ca separator zecimal (indiferent de setările locale);
• datele Boolean sunt scrise ca #TRUE# sau #FALSE#, nefiind traduse după setările locale;
• datele calendaristice şi timpul sunt scrise potrivit formatului de dată universală; dacă o componentă este omisă
(sau este zero), se scrie doar partea indicată;
• Null se scrie drept #NULL#, iar Empty nu produce nimic în ieşire;
• Date de tip Error apare #ERROR errorcode#.

Instrucţiunea Write # inserează între virgule între elementele scrise în fişier, ca şi ghilimele în jurul şirurilor de caractere
(nu este prin urmare nevoie ca utilizatorul să introducă separatori pentru claritate). După ce toate valorile au fost scrise,
se inserează automat o combinaţie CR+LF, astfel încât următoarea scriere va fi pe un rând nou.

Print #

Scrie într-un fişier secvenţial date formatate ca pe ecran (display-formatted). Prin urmare, cu excepţiile specificate în
continuare, setările locale sunt respectate. Datele scrise cu Print # sunt, de regulă, citite cu Line Input # sau cu Input.

Sintaxa este

Print #filenumber, [outputlist]

unde

filenumber numărul ataşat fişierului (deschis în prealabil),

outputlist listă de expresii formatate ale căror valori sunt tipărite. Elementele se separă prin virgule, spaţii sau punct şi
virgulă.

Un element al listei de ieşire este de forma

40
[{Spc(n) | Tab[(n)]}] [expression] [charpos]

unde

Spc(n) inserează n spaţii în ieşire

Tab(n) poziţionează punctul de inserţie (începutul zonei de scriere) la o coloană indicată absolut de n. Utilizând doar Tab
se trece la următoarea zonă de ieşire.

expression expresia a cărei valoare se tipăreşte (numerică sau String).

charpos Specifică poziţia punctului de inserţie pentru următorul caracter care va fi tipărit, potrivit tabelului care urmează.
Dacă nu se specifică, următoarea tipărire va fi pe rândul următor.

charpos Locul punctului de inserţie

; Imediat după ultimul caracter tipărit

Tab(n) Coloana cu numărul n

Tab Începutul următoarei zone de tipărire

Dacă se omite outputlist dar se include un separator după filenumber, se va insera o linie goală în fişier.

Datele logice sunt scrise drept True, False (fără traduceri locale).

Datele calendaristice sunt scrise potrivit setării locale pentru format scurt.

Empty nu produce nimic, Null este scris Null, iar Error este scris ca Error errcode (fără traduceri locale).

Informaţiile numerice scrise sunt după configurările locale (separator zecimal).

Pentru o interpretare corectă, utilizatorul trebuie să separe valorile afişate prin formatări adecvate.

Pentru afişari în fereastra Immediate a mediului VBA, se va vedea şi metoda Print (vezi Help – Print Method).

Close

Închide unul sau mai multe fisiere deschise prin Open pentru instrucţiuni de I/O. Prin acestă operaţiune se rupe legătura
între fişiere şi numerele ataşate şi se eliberează zonele tampon rezervate. Pentru un fişier închis nu se mai pot executa
operaţiuni I/O (până la o nouă deschidere).

Sintaxa este

Close [filenumberlist]

unde

filenumberlist este lista de numere ataşate fişierelor care se închid, de forma


[[#]filenumber] [, [#]filenumber] …; dacă lista nu este prezentă, atunci se vor închide toate fişierele care sunt deschise.

41
Înainte de închidere, în fişierele deschise pentru Output sau Append se scriu zonele buffer nescrise încă.

Reset

Închide toate fişierele deschise prin instrucţiuni Open. Sintaxa este

Reset

Înaine de închidere se scriu în fişiere toate bufferele nescrise încă.

Seek

Stabileşte poziţia (înregistrării sau octetului) într-un fişier unde se va efectua următoarea operaţiune de intrare/ieşire,
fişierul fiind deschis prin Open (vezi şi funcţia Seek). Sintaxa

Seek [#]filenumber, position

unde

filenumber numărul ataşat fişierului.

position număr între 1 şi 2,147,483,647, inclusiv, care indică locul următoarei


operaţii I/O.

Numerele înregistrărilor specificate în instrucţiunile Get şi Put au priorirtate în raport cu poziţia fixată prin Seek (are loc o
repoziţionare).

Dacă operaţiunea Seek indică o poziţie după sfârşitul fişierului, următoarea operaţiune de scriere (fără repoziţionare)
extinde fişierul.

Poziţia indicată nu poate fi zero sau negativă.

Funcţia Seek

Returnează, ca un întreg Long, poziţia curentă I/O dintr-un fişier specificat. Fişierul trebuie să fie în prealabil deschis.

Seek(filenumber)

filenumber este un număr de fişier.

Valoarea returnată este între 1 şi 2,147,483,647 (echivalent cu 2^31 – 1), inclusiv (vezi şi setarea poziţiei prin
instrucţiunea Seek) şi are semnificaţia din următorul tabel.

Modul de acces Valoarea returnată

Random Numărul următoarei înregistrări (care va fi citită sau scrisă)

Binary, Output, Poziţia octetului (numerotat de la 1) la care va avea loc următoarea operaţiune I/O
Append, Input

42
EOF

Returnează un întreg cu valoarea logică True (-1) atunci când se atinge sfârşitul unui fişier deschis pentru citire (Random,
Binary sau Input). Pentru fişierele dschise în ieşire funcţia generează mereu True.

EOF(filenumber)

filenumber este un întreg conţinând numărul fişierului testat.

Utilizarea uzuală este

Do While Not EOF(filenum)

… (instrucţiuni, inclusiv citire din fişierul filenum)

Loop

Pentru acces secvenţial (Input) se întoarce False până când se atinge sfârşitul de fişier, pentru fişierele Random sau
Binary se returnează False până când ultima instrucţiune Get executată nu a putut citi o înregistrare întreagă.

Citirea cu Input dintr-un fişier deschis Binary produce eroare la utilizarea mecanismului general (până când EOF () este
true): se va utiliza citirea cu Get sau citirea cu Input împreună cu funcţiile LOF sau Loc.

Loc

Returnează, ca Long, poziţia curentă de citire/scriere într-un fişier deschis.

Loc(filenumber)

filenumber este numărul ataşat fişierului.

Valoarea funcţiei depinde de modul de acces

Mod Valoarea returnată

Random Numărul ultimei înregistrări scrise sau citite

Sequential Poziţia curentă împărţită la 128. (Se spune că această informaţie nu este niciodată utilă sau utilizată)

Binary Poziţia ultimului octet citit sau scris.

Funcţia Loc este utilizată, împreună cu funcţia LOF, la testarea sfârşitului de fişier la citiri Binary (schema generală este
dată la LOF).

LOF

Returnează un Long care reprezintă, în octeţi, mărimea unui fişier deschis prin Open. Pentru fişierele nedeschise se
poate utiliza, în acelaşi scop, funcţia FileLen().

LOF(filenumber)

43
filenumber este numărul ataşat fişierului.

Utilizarea acestei funcţii, împreună cu funcţia Loc, pentru determinarea sfârşitului de fişier (similar cu EOF) accesat
Binary este după schema generală:

Open filename For Binary As filenum

Do While CurrentLocation < LOF(filenumber)

… (citire din fişierul filenum )

CurrentLocation = Loc(filenumber)

Loop

Visual Basic Editor

În această secţiune se prezintă mediul de dezvoltare Visual Basic for Applications integrat în Microsoft Office 97.
Informaţiile sunt, în general, valabile pentru Microsoft Excel 97, Word 97 şi PowerPoint 97 care sunt prevăzute cu un
mediu complet de dezvoltare VBA, numit Visual Basic Editor. Atunci când vor fi necesare, se vor da explicaţii
suplimentare pentru Access 97.

Utilizând Visual Basic Editor, numit în continuare VBE, se poate crea, edita, depana şi executa cod program asociat cu
documente Microsoft Office.

Proiectele dezvoltate în VBE, deşi sunt asociate aplicaţiilor din Office, nu pot fi reduse, ca problematică, la procesarea de
texte (Word), calcul tabelar (Excel), prezentări electronice (PowerPoint) sau baze de date (Access). Este corect să se
considere aceste proiecte drept aplicaţii similare celor dezvoltate în alte medii de programare, având însă la dispoziţie
componentele aplicaţiilor din Office. Cu alte cuvinte, nu este vorba de o limitare a posibilităţilor de prelucrare, ci o
potenţare a acestora prin apelul posibil la obiectele din Office.

O obiecţie la utilizarea VBA este aceea că proiectul se poate executa doar dintr-o aplicaţie Office (deci deschizând, chiar
formal, un document Word, sau o foaie Excel etc.), dar multitudinea de componente disponibile în dezvoltarea proiectului
compensează acest neajuns. În plus nu trebuie uitat că orice aplicaţie necesită o interfaţă utilizator (puternică în Microsoft
Office) şi că aplicaţiile de bază sunt întreţinute şi completate de Microsoft, astfel încât proiectele noastre se vor actualiza
şi ele o dată cu componentele Office.

Un ultim argument este acela că mediul VBE este identic cu mediul de dezvoltare din Microsoft Visual Studio (Visual
Basic, C++ etc.) astfel că practica în VBA poate fi considerată introductivă către alte aplicaţii RAD.

Interfaţa grafică VBE

Pentru a deschide editorul VB, mai întâi se va porni o aplicaţie din Microsoft Office, apoi se poate acţiona

• combinaţia Alt+F11 (dacă nu a fost atribuită altei operaţiuni), sau


• butonul Visual Basic Editor de pe bara de unelte Visual Basic (meniul View, Toolbars etc.) vizualizată într-o
aplicaţie Office, sau
• Meniul Tools, Macro, Visual Basic Editor.

În Access se va activa fişa Modules a proiectului.


44
Interfaţa grafică VBE este suficient de complexă, asemănătoare mediilor de programare din Visual Studio. Pe lângă
obiectele grafice uzuale (Menu Bar, bare de unelte) sunt disponibile ferestre specializate pentru lucrul cu anumite
categorii de obiecte:

• Properties Window pentru vizualizarea şi fixarea proprietăţilor în momentul proiectării (design-time);


• Project Explorer care permite navigarea, vizualizarea şi modificarea proiectelor deschise la un moment dat;
• Code Window unde este se scrie şi este vizibil codul sursă al proiectului activ;
• Locals Window care permite vizualizarea variabilelor locale cu valorile lor;
• Immediate Window care permite executarea imediată a unei linii de cod;
• Watch Window unde se afişează valorile unor expresii specificate (utile în depanarea programelor).

Properties Window

Prin proprietate a unui obiect se înţelege o caracteristică a respectivului obiect (cum ar


fi culoarea sau vizibilitatea etc.). Fixarea valorii proprietăţii se reflectă în aparenţa
obiectului sau în comportamentul lui (de exemplu, fixarea proprietăţii
ShowSpellingErrors la valoarea True arată în document erorile de scriere).

Fereastra Properties poate fi utilizată, în momentul proiectării, pentru a vizualiza toate


proprietăţile obiectului activ şi a modifica valorile dorite.

În partea superioară este cutia de obiecte în care se poate selecta un obiect (sau mai
multe) dintre cele vizibile.

În fişa Alphabetic se listează proprietăţile modificabile ale obiectului selectat, în ordine


alfabetică. Se poate modifica valoarea unui atribut prin selectarea numelui proprietăţii şi
tastarea sau selectarea noii valori.

În fişa Categorized sunt listate proprietăţile după categorii, într-un control de tip Explorer, in care ramurile pot fi expandate
sau.

Fereastra Properties poate fi arătată (când nu este vizibilă), prin comanda Properties Window din meniul View.

Project Explorer

Codul sursă asociat cu un workbook, document, template sau prezentare este asociat
într-un proiect, care este memorat şi salvat în mod automat o dată cu caietul Excel,
documentul Word, şablonul sau prezentarea respectivă. În fereastra Project Explorer se
pot vedea, modifica şi naviga printre toate proiectele asociate oricărui document, caiet,
şablon sau prezentare deschise.

Pentru un proiect se listează, într-un control de tip Explorer, obiectele care recunosc
evenimente, formele, modulele, referinţele. Pentru a vedea codul dintr-un modul sau
codul asociat unui obiect, se selectează respectivul modul sau obiect şi se apasă
butonul View Code (primul din stânga). Pentru a vedea interfaţa utilizator pentru un
obiect sau formă se selectează şi se apasă butonul View Object (cel din mijloc). Pentru a
vedea organizarea în foldere a elementelor listate în Project Explorer se va apăsa butonul Toggle Folders.

Fiecare element este însoţit, în arborele de structură, de icoana specifică elementului: proiect, folder, referinţă, obiect etc.

45
Code Window

Fereastra principală a Editorului Visual Basic este cea în care se poate scrie
codul sursă. Deoarece procedurile sunt asociate unor obiecte de interfaţă, sau
aparţin unui modul, mai întâi se va selecta, din Project Explorer, modulul sau
forma vizată şi apoi se va apăsa butonul View Code.

Pentru a vedea mai mult de o procedură în fereastra de cod, se va selecta


boxa de control Default to Full Module View în fişa Editor din Options
(meniul Tools) (în caz contrar se va vedea doar câte o procedură).

În partea de sus a ferestrei se găsesc două boxe:

• Object Box unde se poate selecta obiectul pentru care se afişează procedurile asociate;
• Procedures/Events Box unde se poate selecta procedura pentru care se vizualizează/editează codul. Procedurile
pot fi de tip eveniment, dacă obiectul selectat este o formă utilizator. Selectarea unei proceduri produce o defilare
a textului astfel încât pointerul să fie la prima linie a procedurii.

Pot fi deschise mai multe ferestre de editare, textul poate fi mutat/copiat între ferestre, ferestrele se pot diviza utilizând
bara de divizare etc.

Acţionarea butonului Procedure View Icon (primul din stânga, pe bara de jos a ferestrei) sau a butonului Full Module View
Icon produce alegerea între vizualizarea unei singure proceduri sau a tuturor procedurilor din modul.

Locals Window

Utilă în procesul de punere la punct a programului, fereastra Locals serveşte la afişarea automată a tuturor variabilelor
declarate în procedura curentă. Conţinutul ferestrei este actualizat de fiecare dată când se trece din modul Run în modul
Break sau atunci când se navighează în stiva de apeluri.

Pentru o descriere a ferestrei se va vedea secţiunea dedicată depanării programelor.

Immediate Window

Permite scrierea şi execuţia imediată a unei linii de cod. Linia poate fi copiată în şi dintr-o fereastră de cod.

În modul de execuţie Break, instrucţiunea din fereastra Immediate este executată în contextul procedurii afişate în
Procedure Box.

Pentru acţiunile posibile în fereastra Immediate, se va studia Help – Immediate Window Keyboard Shortcuts.

Watch Window

Este fereastra unse sunt afişate automat valorile expresiilor urmărite în etapa de depanare a proiectului.

Pentru o descriere a ferestrei Watch se va vedea secţiunea dedicată depanării programelor.

Scrierea procedurilor

Instrucţiunile unui proiect se pot înscrie, după modul lor de creare, în două mari categorii:

46
• scrise de aplicaţia de bază (Word, Excel etc.) prin traducerea acţiunilor interfeţei utilizator (meniuri, comenzi etc.)
în cod VBA. Această operaţiune este cea de înregistrare a unui macro.
• scrise într-o fereastră de cod de către utilizator (proiectant), cu asistenţa mediului VBE.

Înregistrarea unui macro

Acţiunea este utilă atât prin aceea că operaţiuni simple pot fi traduse uşor în instrucţiuni VBA, procedurile pot fi editate din
VBE, iar pentru proceduri mai complexe (cum ar fi operatiuni de căutare/înlocuire sau formatări de obiecte grafice) codul
generat automat oferă un bun model de utilizare a obiectelor, proprietăţilor şi metodelor aplicaţiei.

Pentru a înregistra un macro:

• Se afişează bara de unelte Visual Basic (meniul View - Toolbars şi selectarea barei dorite).
• Pe bara Visual Basic se acţionează butonul Record Macro.
• În dialogul Record Macro se înlocuieşte numele dat implicit în boxa Macro Name şi apoi OK.

Se poate utiliza boxa Store macro pentru a alege locul de memorare a codului.

• Se execută acţiunile menite să fie înregistrate/traduse în VB, în succesiunea dorită.


• Pe bara Stop Recording (apărută la iniţierea procesului de înregistrare) se apasă butonul Stop Recording.

Pentru a vedea liniile de cod generate, se deschide în aplicaţia de bază meniul Tools, comanda Macro, apoi Macros, se
selectează după denumire şi se apasă butonul Edit.

Codul sursă poate fi văzut şi prin navigarea în VBE prin Project Explorer, ferestre de cod etc.

Din punctul de vedere al programării se poate spune că un macro este o procedură publică fără argumente, deci poate fi
scrisă şi direct în fereastra de cod a unui document. Din punct de vedere formal, toate procedurile care pot fi executate
din dialogul Macros (Tools - Macro - Macros) sunt macro-uri.

Scrierea unei proceduri

Dacă se doreşte scrierea unor proceduri generale, care nu sunt asociate unui obiect sau eveniment specific, se ca crea o
procedură într-un modul standard.

Pentru a crea un modul standard nou (gol), se merge în Project Explorer în proiectul unde se adaugă modulul nou creat
şi se dă comanda Module din meniul Insert.

Pentru a deschide un modul standard existent, se va selecta modulul din Project Explorer şi se apasă butonul View
Code (sau dublu click).

Pentru a adăuga o procedură la un modul, se selectează modulul în Project Explorer, se deschide meniul Insert şi se dă
comanda Procedure. Se deschide dialogul Add Procedure unde se vor selecta opţiunile definitorii (subrutină sau funcţie,
publică sau nu etc.) şi se dă OK. După aceasta se pot adăuga liniile de cod ale procedurii.

Scrierea unei proceduri de eveniment (event procedure)

Dacă se doreşte scrierea de cod sursă care să se execute automat atunci când are loc un anumit eveniment (cum ar fi
deschiderea unui document, acţionarea unui buton etc.), trebuie să se scrie o procedură asociată evenimentului
respectiv. O asemenea procedură se va numi procedura evenimentului.

47
Anumite obiecte din aplicaţiile Microsoft Office recunosc un set predefinit de evenimente, care pot fi declanşate de către
sistem sau de către utilizator. Evenimentele specifice fiecărui obiect trebuie să fie studiate separat (se va studia secţiunea
din Help pentru fiecare aplicaţie), doa principalele obiecte, cu proprietăţile, metodele si evenimentele lor, sunt prezentate
şi în acest curs, în capitole separate.

Modul cum aplicaţia răspunde la evenimentele recunoscute poate fi controlat prin scrierea procedurilor de eveniment. O
asemenea procedură se va scrie în fereastra Code asociată obiectului. De fiecare dată când apare evenimentul se
execută procedura evenimentului respectiv. De exemplu, dacă se scrie o procedură asociată cu evenimentul Open al
unui document Word, procedura se va executa automat la fiecare deschidere a acelui documentului.

O procedură de eveniment este memorată în documentul, caietul, foaia de calcul, diapozitivul, forma utilizator etc. unde
poate fi declanşat evenimentul. Pentru a vedea codul sursă al procedurii, se va selecta obiectul în Project Explorer şi click
pe butonul View Code pentru a deschide fereastra de cod asociată. Dintr-o fereastră de cod deschisă, asociată, se va
selecta obiectul vizat, din boxa de obiecte, şi în boxa de proceduri vor fi listate atunci toate procedurile evenimentelor,
chiar dacă ele nu sunt efectiv scrise. Selectarea unui eveniment va scrie (dacă nu există) liniile obligatorii ale procedurii şi
va fixa cursorul de editare în procedura respectivă.

Numele unei proceduri de eveniment este format din numele obiectului, care recunoaşte evenimentul, urmat de caracterul
"_" şi de numele evenimentului asociat. De exemplu, Document_Open este numele procedurii care se execută la
deschiderea unui document.

Pentru controale ActiveX, numele este legat de numele codului controlului. Schimbarea numelui codului după ce s-au
scris procedurile evenimentelor impune modificarea denumirilor acestora. La cele mai multe obiecte (Document,
Worksheet, UserForm) denumirile sunt legate de numele clasei, deci nu mai trebuiesc redenumite.

Observaţie. Dacă se doreşte ca o procedură să fie asociată cu un document specific, dar nu cu un eveniment specific,
atunci procedura se va scrie în secţiunea (General) a documentului respectiv (de exemplu o rutină care să poată fi
apelată din mai multe proceduri de eveniment).

Unelte VBE pentru scrierea instrucţiunilor

Deoarece multe dintre denumirile obiectelor, proprietăţilor sau metodelor care apar în codul VBA sunt complexe, mediul
de dezvoltare oferă o serie de unelte pentru completarea automată a cuvintelor cheie, pentru oferirea de ajutor în
reamintirea denumirilor etc.

Dacă s-au tastat suficient de multe caractere încât VB poate recunoaşte un cuvânt, atunci prin CTRL+SPACE, sau click
pe butonul Complete Word de pe bara de unelte Edit, completează cuvântul.

În dialogul Options (meniul Tools) se pot activa următoarele acţiuni, executate automat la completarea unei linii de cod:

• verificarea automată a sintaxei — Auto Syntax Check;


• obligativitatea declarării tuturor variabilelor, adăugarea automată a instrucţiunii Option Explicit la orice nou modul
— Require Variable Declaration;
• afişarea unei liste cu informaţii utile (logice la poziţia curentă a cursorului) la completarea instrucţiunii — Auto List
Member;
• afişarea informaţiei despre proceduri şi parametrii lor — Auto Quick Info;
• afişează, doar în modul Break, valoarea unei variabile peste care este plasat cursorul — Auto Data Tips;
• alinierea automată a liniilor noi la începutul liniei precedente — Auto Indent;
• fixarea lăţimii între poziţiile tabulatorului, 1 la 32 de spaţii (implicit fiind 4) —Tab Width.

Pe bara de unelte Edit există câteva butoane, care ajută la completarea cuvintelor şi expresiilor în timpul scrierii
instrucţiunilor:

48
• List Properties/Methods — deschide o cutie în fereastra Code cu proprietăţile şi metodele permise pentru obiectul
care precede caracterul punct ("."), utilă atunci când se operează cu obiecte.
• List Constants — deschide în fereastra de cod, la punctul de inserţie, o cutie cu constantele permise pentru
proprietatea care precede semnul egal ("=") în instrucţiunea curentă.
• Quick Info — oferă, ca ajutor, sintaxa pentru o variabilă, funcţie etc. prin analiza locului punctului de inserţie pe
linia curentă.
• Parameter Info — arată o cutie, la punctul de inserţie, cu informaţia despre parametrii funcţiei în care este
pointerul.
• Complete Word — acceptă caracterele pa care le propune VBE drept completare la cuvântul tastat.
• Comment Block — care transformă în comentarii liniile selectate.
• Uncomment Block — înlătură semnul de comentarii la liniile selectate.

Executarea unei proceduri Sub

O procedură poate să se execute:

• automat, ca răspuns la declanşarea unui eveniment (procedura evenimentului);


• din VBE, dacă punctul de inserţie este în procedură şi se acţionează butonul Run Sub/UserForm de pe bara de
unelte Standard sau Debug;
• ca un macro, Run din dialogul Macros (Tools - Macro) al aplicaţiei de bază;
• apelată din altă procedură.

La apelul unei proceduri din altă procedură se va ţine seama de interacţiunea declaraţiilor Public, Private, ca şi de
referinţele la alte proiecte (meniul Tools - References).

Modele de obiecte

Aproape toate acţiunile programate în VB implică manevrarea programatică a unor obiecte. Toate aplicaţiile din Microsoft
Office sunt alcătuite din componente formate din obiecte sau care gestionează obiecte.

În această secţiune se prezintă principalele concepte din programarea orientată pe obiecte, ca şi uneltele şi tehnicile
disponibile pentru a explora şi utiliza obiectele specifice din Office 97.

Deoarece fiecare aplicaţie din Office are un model propriu de obiecte, va fi dedicat câte un capitol pentru Word, Excel
etc., în care se vor prezenta particularităţile de operare şi obiectele specifice aplicaţiei.

Privire generală

Orice aplicaţie poate fi gândită ca ansamblul a două lucruri: conţinut şi funcţionalitate. Conţinutul se referă la documentele
pe care le conţine aplicaţia, la elementele care compun documentele, la informaţiile privind atributele elementelor.
Funcţionalitatea se referă la modurile, căile în care se poate lucra cu conţinutul aplicaţiei, de exemplu: deschiderea,
închiderea documentelor, adăugarea, copierea, formatarea elementelor etc.

Conţinutul şi funcţionalitatea unei aplicaţii sunt divizate în unităţi discrete de conţinut şi funcţionalitate specifică, numite
obiecte. Exemplele uzuale sunt date de foile de calcul Excel, celule ale unei foi de calcul, secţiuni ale unui document
Word etc., fiecare având evident un conţinut şi o funcţionalitate specifică, cele două componente fiind unitar legate între
ele. Obiectele unei aplicaţii sunt ierarhizate în structuri, modelul de obiecte al aplicaţiei..

Obiectul de nivel maxim al unei aplicaţii este, uzual, obiectul Application, care este aplicaţia însăşi. Obiectul Application
conţine alte obiecte care pot fi accesate numai când obiectul Application există (deci când aplicaţia se execută). De
exemplu, obiectul Application Excel conţine obiecte Workbook, după cum obiectul Application Word conţine obiecte

49
Document. Deoarece obiectul Document depinde de existenţa obiectului Application Word, se spune că obiectul
Document este copilul obiectului Application; invers, obiectul Application se zice părintele obiectului Document.

Este uzual ca un obiect, care este copil al altui obiect, să aibă, la rândul său, alte obiecte copii. De asemenea, este
posibil ca un copil să aibă mai mulţi părinţi.

Modul în care obiectele, care alcătuiesc o aplicaţie, sunt aranjate relativ unele faţă de altele, împreună cu modul în care
conţinutul şi funcţionalitatea sunt divizate prin obiecte este numit ierarhia de obiecte sau modelul de obiecte. Fiecare
aplicaţie are un model de obiecte propriu, reprezentarea grafică a ierarhiei de obiecte pentru aplicaţie poate fi văzută în
Visual Basic Help din aplicaţie.

Fiecare obiect din ierarhie are un conţinut şi o funcţionalitate care se aplică, ambele, atât obiectului însuşi, cât şi tuturor
obiectelor descendente din ierarhie. Cu cât obiectul este situat mai sus în ierarhie, cu atât este mai vast domeniul
conţinutului şi funcţionalităţii sale. Locul unui obiect în model este gândit astfel încât conţinutul şi funcţionalitatea lui sunt
adecvate domeniului său. Se poate gândi şi faptul că, dacă aplicaţia este divizată în obiecte, fiecare obiect oferă acces la
arii specifice de conţinut şi funcţionalitate.

Afirmaţiile care implică obiecte utilizează şi termenii de "conţinut în" pentru copil şi "conţine" pentru părinte. Astfel,
obiectul Application Word conţine obiecte Document, dar obiectul Selection este conţinut în obiectul Windows etc.

Proprietăţi şi metode

Pentru a avea acces la conţinutul şi funcţionalitatea unui obiect, pentru început trebuie să se identifice obiectul (subiect
discutat în continuare). După identificare, obiectul este accesibil prin intermediul proprietăţilor şi metodelor sale.

În general, prin proprietate se înţelege un atribut numit al obiectului. Valoarea atributului (proprietăţii) poate fi modificată
(de cele mai multe ori) sau poate fi obţinută (ştiută) programatic.

Prin metodă se înţelege o procedură care acţionează asupra unui obiect. Pentru a distinge o metodă de o procedură
obişnuită (care poate de asemenea să acţioneze asupra unui obiect, în general vorbind), trebuie precizat că metodele
implementează funcţionalitatea obiectului, sunt specifice obiectului căruia i se aplică şi sunt definite o dată cu obiectul
(deci la proiectarea aplicaţiei de bază, în cazul obiectelor Office). Orice procedură utilizator acţionează asupra obiectului
prin intermediul metodelor specifice (aplicabile) acelui obiect.

În general, se utilizează proprietăţile pentru a accesa conţinutul şi se apelează metodele pentru a realiza funcţionalitatea
obiectului. Totuşi, această distincţie este relativă: există proprietăţi care se apropie de metode şi metode care seamănă a
fi proprietăţi. Atunci când vom discuta despre obiecte definite de utilizator se va vedea că este uşor să se treacă graniţa
dintre metode si proprietăţi în proiectarea obiectelor.

Legătura dintre modelul obiectelor şi interfaţa utilizator

Există două căi prin care utilizatorul poate interacţiona cu obiectele aplicaţiei:

o manual (utilizând interfaţa utilizator a aplicaţiei);


o programatic (utilizând un limbaj de programare).

În accesul manual se utilizează tastatura, mouse-ul sau cheile directe pentru a naviga către acea parte şi funcţie a
aplicaţiei care execută ceea ce se doreşte (formatarea unui paragraf, ştergerea unor formule dintr-o celulă, modificarea
unui slide etc.).

În accesul programatic, de exemplu în instrucţiuni Visual Basic, se navighează în ierarhia de obiecte pentru a identifica
obiectul vizat şi apoi se utilizează proprietatea sau metoda care produce efectul urmărit. De exemplu, prin linia următoare,
scrisă într-o procedură,
50
Workbook("Activitate.xls").Worksheets("Vanzari").Range("A5").Value = 100

se navighează în caietul Activitate la foaia Vanzari şi se înscrie valoarea 100 în celula A5. Este evident că înscrierea are
loc efectiv doar în momentul execuţiei procedurii.

Deoarece ambele moduri de acces, interfaţa utilizator a aplicaţiei de bază şi Visual Basic, ajung la acelaşi conţinut şi
funcţionalitate, multe dintre obiectele, proprietăţile şi metodele existente în modelele de obiecte Office au aceleaşi
denumiri cu elementele din interfaţa utilizator (denumiri de meniuri, comenzi, acţiuni etc.). Se poate observa, explicabil din
punctul de vedere al evoluţiei către modelele obiectuale, o asemănare globală a modelului de obiecte cu interfaţa
utilizator. Această asemănare este întărită şi de faptul că pentru orice acţiune posibilă prin interfaţa utilizator există
posibilitatea de a scrie cod Visual Basic echivalent (vezi şi discuţia cu înregistrarea macro-urilor).

Din exemplul prezentat la accesul din VB, este de reţinut importanţa cunoaşterii locului ocupat de obiectul procesat în
ierarhia de obiecte: pentru a utiliza proprietăţile sau metodele lui trebuie identificat corect prin navigarea (calificarea) de la
nivelul cel mai de sus până la el. Întregul traseu (cu excepţia nivelului Application, care este uneori subînţeles) trebuie
specificat ca în exemplul arătat.

Colecţii de obiecte

O colecţie este un obiect care include obiecte similare (dar nu neapărat), astfel încât se poate opera cu ansamblul lor.
Acest lucru nu înseamnă că metodele sau proprietăţile obiectelor (dacă sunt toate de acelaşi tip) se aplică tuturor
elementelor colecţiei. Ca obiect separat, o colecţie are proprietăţi şi metode specifice (numărul de elemente, adăugarea
unui nou element etc.).

De regulă, colecţiile definite în Office (există posibilitatea de a defini noi colecţii) se remarcă prin aceea că au forma de
plural a denumirii elementelor lor: Workbooks este colecţia de obiecte Workbook, Documents este colecţia de obiecte
Document etc.

Elementele (membrii) colecţiei se pot identifica prin numărul de ordine (începând cu 1) sau prin nume (rezultă că
ansamblul elementelor este ordonat). Astfel instrucţiunea

Presentations.Item("Perspective").Close

utilizată în PowerPoint produce activarea prezentării cu numele Perspective şi apoi o închide. Exemplul utilizează metoda
Item pentru a returna elementul colecţiei de prezentări cu numele specificat. De regulă, această metodă este implicită,
deci

Presentations("Perspective").Close

este o formă echivalentă.

Numărul de elemente ale colecţiei se pot afla prin proprietatea Count, se pot adăuga noi elemente prin metoda Add etc.

O utilizare frecventă a colecţiilor este parcurgerea tuturor elementelor într-o structură For Each…Next sau For…Next:

Public Sub DocScris()

For Each doc In Documents

If doc.Words.Count > 1 Then

MsgBox doc.Name + Str(doc.Words.Count)


51
End If

Next

End Sub

care, într-o aplicaţie Word, afişează numele tuturor documentelor deschise cu mai mult de un cuvânt scris.

Automatizarea acţiunilor prin folosirea obiectelor

Prin automatizarea unei acţiuni se înţelege scrierea unei proceduri care să producă, la executarea ei, acţiunea dorită.
Execuţia poate fi comandată direct sau ca răspuns la declaşarea unui eveniment.

Pentru a automatiza o acţiune în Microsoft Office, se va obţine o referinţă la obiectul care dispune de conţinutul şi
funcţionalitatea pe care le urmărim şi se vor aplica proprietăţile şi metodele adecvate. Procesul poate necesita o
succesiune de asemenea operaţii.

Obţinerea unei referinţe la un obiect

Pentru a obţine o referinţă la un obiect trebuie să se construiască o expresie care ajunge să acceseze un obiect din
modelul de obiecte şi apoi, utilizând proprietăţi şi/sau metode, să se navigheze în sus sau în jos prin ierarhia de obiecte
până când ajungem la obiectul dorit.

Proprietăţile şi metodele utilizate pentru a returna punctul de start şi pentru a parcurge ierarhia de obiecte se numesc
accesori de obiecte (object accessors) sau accesori.

Câteva idei utile pentru construirea expresiei care returnează referinţa la un obiect sunt următoarele:

- un loc obişnuit pentru a accesa modelul de obiecte este obiectul cu nivelul cel mai înalt, uzual obiectul Application. Se
va utiliza proprietatea Application pentru a returna o referinţă la obiectul Application. Următoarea expresie returnează o
referinţă la obiectul Application (pentru orice bibliotecă de obiecte care conţine un obiect Application).

Application

- pentru a ajunge din vârful ierarhiei până la un obiect, se vor parcurge obiectele de pe toate nivelele, utilizând accesori
care returnează un obiect din altul. De exemplu, proprietatea Documents a obiectului Word Application returnează
obiectul colecţie Documents, care reprezintă toate documentele deschise. Prin urmare următoarea expresie întoarce o
referinţă la obiectul colecţie Documents:

Application.Documents

- Există accesori direcţi (shortcut accessors) care dau acces direct la obiecte din model fără să fie necesar un acces prin
vârful ierarhiei. Asemenea accesori sunt Documents, Workbooks, Presentations care dau acces imediat la colecţia de
documente din Word, Excel şi PowerPoint. Există şi alte proprietăţi cu rol de accesori direcţi: ActiveWindow,
ActiveDocument, ActiveWorksheet, ActiveCell. De exemplu, următoarea instrucţiune închide documentul Word activ:

ActiveDocument.Close

Observaţie. Se poate utiliza drept shortcut orice accesor care apare în zona Members of din Object Browser atunci când
este selectat <globals> în zona Classes; adică nu trebuie să se returneze obiectul căruia i se aplică proprietatea sau
metoda înaintea utilizării proprietăţii sau metodei, întrucât Visual Basic poate să determine din contextul în care se
execută codul cărui obiect i se aplică proprietatea sau metoda respectivă.
52
- Pentru a returna un singur element al unei colecţii se va utiliza proprietatea sau metoda Item cu numele sau numărul de
ordine al elementului. Pentru cele mai multe colecţii, Item este implicit, deci poate lipsi

Workbooks.Item("Vanzari")

Workbooks("Vanzari")

- Pentru a "urca" în ierarhia de obiecte, se utilizează, de obicei, proprietatea Parent a obiectului curent. De notat că
proprietatea Parent poate returna uneori, în special dacă obiectul este membru al unei colecţii, "bunicul" obiectului în
locul părintelui (adică părintele colecţiei în locul colecţiei). De exemplu

Document.Parent

- returnează obiectul Application şi nu Documents.

- Prin funcţia TypeName (executată eventual în Immediate Window) se poate găsi ce tip de obiect întoarce proprietatea
Parent (funcţia nu este limitată la această proprietate, vezi VB Help).

Aplicarea proprietăţilor şi metodelor

După obţinerea unei referinţe la obiectul urmărit, acestuia i se pot aplica proprietăţi şi metode pentru a modifica valoarea
unui atribut sau pentru a-l procesa. Se utilizează operatorul punct (".") pentru a separa expresia care returnează o
referinţă la obiect de proprietatea sau metoda care se aplică obiectului. De exemplu

ActiveWindow.Left = 200

fixează poziţia din stânga a ferestrei active utilizând proprietatea Left a obiectului Window, referinţa la acest obiect fiind
returnată de accesorul direct ActiveWindow.

ActiveDocument.Close

închide documentul activ (în Word) utilizând metoda Close a obiectului Document la care returnează o referinţă
accesorul ActiveDocument.

Proprietăţile şi metodele pot avea argumente care să precizeze valorile sau acţiunile. Următorul exemplu Word utilizează
metoda PrintOut cu specificarea paginilor care se tipăresc:

ActiveDocument.PrintOut From:=" 3", To:=" 7"

Este uneori necesar să se navigheze prin mai multe nivele în modelul de obiecte pentru a ajunge la ceea ce se consideră
date reale în aplicaţie, cum ar fi valorile din celulele foii de calcul sau textul dintr-un document Word. Următoarele
exemple Word arată cum se poate ajunge la text din vârful ierarhiei de obiecte:

o Proprietatea Application returnează o referinţă la obiectul Application.


o Proprietatea Documents a obiectului Application returnează o referinţă la colecţia Documents.
o Metoda Item a colecţiei Documents returnează o referinţă la un songur obiect Document.
o Proprietatea Words a obiectului Document returnează o referinţă la colecţia Words.
o Metoda Item a colecţiei Words returnează o referinţă la un singur obiect Range.
o Proprietatea Text a obiectului Range stabileşte textul itemului referit.

Astfel, următorul exemplu completează primul cuvânt din document

53
Application.Documents.Item(1).Words.Item(1).Text = "Primul "

Deoarece proprietatea Documents este o proprietate globală, poate fi utilizat fără calificativul Application; deoarece
Item este proprietate sau metodă implicită pentru colecţia de obiecte, nu trebuie enunţată explicit. Din aceste
considerente, exemplul următor realizează exact aceeaşi acţiune ca şi exemplul precedent:

Documents(1).Words(1).Text = :Primul "

Pentru alte exemple de referinţe şi de utilizare a metodelor şi proprietăţilor se vor urmări exemplificările de la capitolele
următoare.

Ajutor în scrierea programelor

Pentru o imagine completă a uneltelor şi mecanismelor prin care mediul de programare VB susţine activitatea de scriere
a instrucţiunilor sursă se va citi şi capitolul dedicată mediului VBE.

Utilizarea Macro Recorder

Înregistrarea unui macro oferă un ajutor important atunci când se cunoaşte realizarea unei acţiuni în interfaţa utilizator a
aplicaţiei de bază şi se doreşte cunoaşterea obiectelor, proprietăţilor şi metodelor care pot să realizeze acea acţiune (sau
ceva asemănător).

În general, codul generat de înregistrarea macro nu este foarte eficient şi robust, deoarece înregistrarea pleacă de la
obiectul selectat în momentul startului şi realizează doar navigarea în restul modelului de obiecte. Orice utilizare
ulterioară va necesita o selectare sau activare similară pentru a îndeplini acţiunea aşteptată. Trebuie să se considere
codul înregistrat doar o primă schiţă a procedurii, modificări ulterioare trebuind să producă o variantă mai clară şi mai
robustă.

Codul generat este mai robust şi mai flexibil dacă va conţine expresii care navighează prin ierarhia de obiecte fără să
înceapă cu un obiect selectat sau activat. Idei în acest sens pot fi obţinute din studierea exemplelor date în Visual Basic
Help: poziţionarea punctului de inserţie pe o denumire de proprietate sau metodă şi acţionarea tastei F1 afişează
subiectul respectiv din Help.

O cale directă de accesare a fişierului de ajutor pentru un obiect este poziţionarea în graficul care prezintă ierarhia de
obiecte (specifică fiecărei aplicaţii) şi dublu click pe un obiect afişează subiectul dedicat obiectului în VB Help.

Exemplele prezentate în Help pot fi copiate, în mod uzual, utilizând Clipboard, în fereastra de cod.

Object Browser

Fiecare aplicaţie din Microsoft Office are o bibliotecă de obiecte (object library sau
type library), care conţine informaţii despre obiectele, proprietăţile, metodele,
evenimentele şi constantele predefinite ale aplicaţiei. Pentru accesul la informaţia
respectivă se poate utiliza Object Browser, unealtă din VBE.

Pentru a deschide Object Browser din VBE (în Excel, Word sau PowerPoint) sau
dintr-un modul (Access), se alege Object Browser din meniul View.

În boxa Project/Library se alege numele bibliotecii care se consultă, sau <All


libraries> pentru a vedea o listă completă. Dacă biblioteca dorită nu este în lista celor
disponibile, se va crea o referinţă la această bibliotecă prin alegerile corespunzătoare în dialogul References (meniul
Tools) al proiectului curent.

54
În boxa Classes se afişează numele tuturor obiectelor şi tipurilor enumerate (constantele predefinite) în bibliotecile
referite.

Notă. O clasă este un tip, o descriere a unui obiect. Un obiect este o instanţă efectivă a unei clase. Deseori aceşti
termeni sunt utilizaţi unul în locul celuilalt, dacă nu se produc confuzii (uneori chiar şi atunci).

În boxa Members of se afişează toate proprietăţile, metodele şi evenimentele proprii (asociate) clasei selectate în boxa
Classes.

Selectarea unei intrări în listă poate fi completată cu F1 pentru a vedea textul ajutător, iar în zona inferioară (Detail pane)
se afişează infromaţii privind sintaxa, starea read-only sau read-write, biblioteca unde aparţine, tipul rezultatului returnat
(dată sau obiect). Dacă o informaţie este de tip legătură, activarea acesteia produce informaţii suplimentare, lucru util
pentru a deduce modul de navigare către obiect. În figura prezentată se vede proprietatea Count a clasei AddIns,
proprietatea returnând o valoare de tip Long. Textul din zona Detail poate fi copiat (prin Clipboard) sau dus prin drag-
and-drop într-o fereastră cod.

Legarea timpurie şi uneltele de construire a instrucţiunilor

Atunci când se creează într-o aplicaţie o variabilă obiect care se referă la un obiect furnizat de altă aplicaţie, Visual Basic
trebuie să verifice că obiectul există şi că proprietăţile şi metodele utilizate pentru obiect sunt specificate corect. Acest
proces de verificare se numeşte legare (binding). Legarea poate să apară în timpul execuţiei proiectului (legare târzie)
sau în timpul compilării (legare timpurie). Codul legat târziu este mai încet decât codul legat timpuriu. În plus, uneltele de
ajutor în scrierea codului pot să lucreze corect doar în cazul legării timpurii.

Pentru a lega timpuriu codul se vor parcurge etapele:

• Se stabileşte o referinţă la biblioteca de tipuri care conţine obiectele referite (Tools - References).
• Se declară variabila obiect de un tip specific (de exemplu As Document şi nu As Object).
• Dacă se scrie cod care utilizează obiecte din mai multe biblioteci, se va specifica numele aplicaţiei unde sunt
declarate obiectele, mai ales dacă obiecte cu acelaşi nume există în mai multe biblioteci. (de exemplu As
Excel.Window).

Dacă o proprietate sau o metodă utilizată returnează un tip generic Object şi nu un tip specific, atunci pentru legarea
timpurie se va declara mai întâi o variabilă de tipul specific şi apoi se va atribui rezultatul generic returnat acestei
variabile, după modelul

Dim testWs As Worksheet

Set testWs = Workbooks(1).Worksheets(1)

necesar deoarece metoda Item a obiectului Worksheets returnează un tip Object şi nu Worksheet (chiar dacă se referă
la o foaie de calcul).

Programarea obiectelor altei aplicaţii

Se poate executa, într-o aplicaţie din Office, cod care să lucreze cu obiecte din altă aplicaţie. Pentru a realiza acest lucru,
se va urmări schema următoare:

1. Se stabileşte o referinţă la biblioteca de tipuri a celeilate aplicaţii (meniul Tools - References).


2. Se declară variabile obiect care vor referi obiecte din altă aplicaţie cu tipuri specifice. Se va urmări calificarea
fiecărui tip cu numele aplicaţiei care expune obiectul. Exemplul următor declară o variabilă care se referă la un
document Word şi o variabilă care se referă la un caiet Exce:

55
Dim appWD As Word.Application, wbXL As Excel.Workbook

3. Se utilizează funcţia CreateObject cu identificatorul programatic OLE al obiectului cu care se doreşte să se


lucreze în cealaltă aplicaţie, după modelul

Dim appWD As Word.Application

Set appWD = CreateObject("Word.Application.8")

appWD.Visible = True

4. Pentru informaţii asupra identificatorilor OLE se va vedea VB Help - "OLE Programmatic Identifiers".
5. Se aplică obiectului, conţinut în variabilă, proprietăţile şi metodele după modelul următor, care creează un nou
document Word:

Dim appWD As Word.Application

Set appWD = CreateObject("Word.Application.8")

appWD.Documents.Add

6. La sfârşitul lucrului cu cealaltă aplicaţie, se va utiliza metoda Quit pentru a o închide, după modelul

appWD.Quit

Obiecte Microsoft Word

Visual Basic suportă un set de obiecte care corespund direct elementelor din Microsoft Word 97, cele mai multe familiare
celor care cunosc interfaţa utilizator din Word: obiectul Document reprezintă un document deschis, obiectul Bookmark
reprezintă un bookmark (semn de carte, punct de referinţă) într-un document etc. Orice element din Word — documente,
tabele, paragrafe, câmpuri etc. — poate fi reprezentat printr-un obiect din Visual Basic. Pentru automatizarea lucrului în
Word se utilizează metodele şi proprietăţile acestor obiecte.

Modelul de obiecte din Word 97 cuprinde aproximativ 180 de obiecte. O reprezentare grafică a structurii ierarhice se
poate vedea în Help – "Microsoft Word Objects". O descriere detaliată a unui obiect se obţine prin dublu click pe numele
obiectului (în diagramă) sau, uzual, prin indexul din Help. La instalarea aplicaţiei trebuie să se meargă pe Custom şi să
se selecteze Online Help for Visual Basic.

Dintr-un document Word, pentru a ajunge la modelul de obiecte se deschide dialogul Help şi se merge pe succesiunea
Contents and Index – Microsoft Word Visual Basic Reference – Visual Basic Reference – Getting Started with
Visual Basic – Microsoft Word Objects.

Din editorul VB se ajunge la conţinutul şi indexul VB Help for Word prin succesiunea Help – Contents and Index –
Microsoft Word Visual Basic Reference (din fişa Contents) – Shortcut to Microsoft Word Visual Basic Reference.

În cele ce urmează se vor prezenta doar principalele obiecte (mai sus în ierarhie, cele mai des utilizate, pentru
operaţiunile curente etc.) cu principalele metode şi proprietăţi şi pentru scopurile uzuale.

Obiectul Application

La pornirea unei sesiuni Word se creează automat un obiect Application. Se utilizează proprietăţile şi metodele
obiectului Application pentru a controla sau returna (afla) atributele întregii aplicaţii, a controla aspectul ferestrei Word şi
56
pentru a accesa restul modelului de obiecte. Se utilizează proprietatea Application pentru a returna obiectul Application
Word.

Proprietăţi (Application)

Dintre proprietăţile care controlează aspectul vizibil al aplicaţiei menţionăm câteva în continuare.

DisplayScrolllBars

Exprimă faptul dacă sunt sau nu afişate barele de defilare. Read/write.

La citire, returnează o valoare Boolean:

• True, dacă un document, cel puţin, are o bară de defilare


• False, dacă în nici o fereastră de document nu există bare de defilare.

Valoarea proprietăţii se poate modifica:

• Atribuirea valorii True afişează barele de defilare în toate ferestrele


• Atribuirea valorii False elimină barele de defilare din toate ferestrele.

Application.DisplayScrollBars = True
Application.DisplayScrollBars = False

Pentru barele orizontale sau verticale, individual, se utilizează proprietăţile DisplayHorizontalScrollBar şi


DisplayVerticalScrollBar pentru o fereastră sppecificată.

DisplayStatusBar

Exprimă faptul dacă este afişată bara de stare a aplicaţiei. Read/write. Boolean.

La citire, returnează o valoare Boolean: True dacă bara este afişată, False în caz contrar.

La scriere atribuirea unei valori logice produce efectul evident.

Height

Read/write. Long.

Înălţimea ferestrei aplicaţiei Word. Pentru a vedea dimensiunea maximă admisă se va utiliza proprietatea UsableHeight.

Width

Read/write. Long.

Returnează sau fixează lăţimea obiectului, în puncte.

With Application
.Height = 450
57
.Width = 600
End With

WindowState

Read/write. Long.

Returnează sau stabileşte starea ferestrei aplicaţiei. Poate fi una dintre valorile wdWindowStateMaximize,
wdWindowStateMinimize sau wdWindowStateNormal, cu interpretări evidente. Valoarea wdWindowStateNormal arată o
fereastră care nu este minimizată sau maximizată.

Pentru a putea seta starea ferestrei, aceasta trebuie să fie activă (se va utiliza metoda Activate în acest scop).
Următoarea instrucţiune maximizează fereastra aplicaţiei Word

Application.WindowState = wdWindowStateMaximize

Alte proprietăţi care controlează comportarea globală a aplicaţiei Word, cum ar fi cele care corespund atributelor accesate
prin comanda Options din meniul Tools, se găsesc la obiectul Options.

Utilizând proprietatea Options a obiectului Applications, se returnează un obiect Options care poate fi apoi configurat,
după exemplul

With Application.Options
.AllowDragAndDrop = True
.ConfirmConversions = False
.MeasurementUnit = wdPoints
End With

Pentru informaţii complete se va studia obiectul Options.

Dintre proprietăţile obiectului Application care oferă acces la obiecte situate mai jos în ierarhie (accesori) sunt
enumerate cele mai des utilizate.

ActiveDocument

Read-only.

Returnează un obiect Document care reprezintă documentul activ (cel care are focusul). Dacă nu există nici un
document deschis, atunci apare o eroare.

ActivePrinter

Read/write. String.

Returnează sau stabileşte numele imprimantei active. Exemplul următor alege imprimanta activă:

ActivePrinter = "HP LaserJet 4 local on LPT1:"

Se observă utilizarea denumirii din mediul Windows.

ActiveWindow

58
Read-only.

Returnează un obiect Window care reprezintă fereastra activă. Dacă nu există nici o fereastră deschisă, apare o eroare.

MsgBox Application.ActiveWindow
ActiveWindow = "Fereastra activa"

Primul exemplu afişează numele ferestrei active, al doilea atribuie un nou nume ferestrei active. Este de remarcat că
numele ferestrei nu este obligatoriu identic cu numele documentului şi că exemplele funcţionează corect pentru că
proprietatea implicită a obiectului returnat este numele (Name).

Documents

Read-only.

Întoarce colecţia Documents a tuturor documentelor deschise.

Selection

Read-only.

Întoarce obiectul Selection, care reprezintă un domeniu selectat (redus eventual la punctul de inserţie). Este de remarcat
că există o singură selecţie pe fereastră (sau ochi de fereastră) şi doar una este activă – cea returnată.

Pentru exemple se va vedea prezentarea obiectului Selection.

Windows

Read-only.

Returnează colecţia Windows a tuturor ferestrelor document. Colecţia corespunde ferestrelor cu denumirile (şi numerele
de ordine) listate la meniul Window din Word.

MsgBox Windows.Count

afişează numărul ferestrelor deschise în Word (ataşate unor documente).

Metode (Application)

Dintre metodele obiectului Application enumerăm doar Quit, celelalte sunt sau mai rar utilizate, sau se mai aplică şi altor
obiecte şi vor fi prezentate ulterior.

Quit

Apelul procedurii duce la închiderea aplicaţiei Word şi, opţional, salvează sau rutează documentele deschise. Sintaxa:

expression.Quit(SaveChanges, Format, RouteDocument)

unde

expression este o expresie care returnează un obiect Application.


59
SaveChanges este de tip Variant, opţional, şi specifică dacă Word salvează documentele înaintea închiderii. Poate fi o
constantă (de tipul enumerat WdSaveOptions) wdDoNotSaveChanges, wdPromptToSaveChanges sau wdSaveChanges,
interpretările fiind evidente.

OriginalFormat este de tip Variant, opţional, şi specifică modul în care Word salvează documentele al căror format
original nu a fost acela de document Word. Poate fi o constantă (de tipul enumerat WdOriginalFormat) dintre
wdOriginalDocumentFormat, wdPromptUser sau wdWordDocument.

RouteDocument este de tip Variant, opţional. Este True dacă se doreşte directarea documentului către următorul
recipient. Dacă documentul nu are ataşată o fişă de rutare (routing slip), argumentul este ignorat (vezi obiectul
RoutingSlip).

În exemplul următor

Application.Quit SaveChanges:=wdPromptToSaveChanges, OriginalFormat:=wdWordDocument

se părăseşte Word, se întreabă utilizatorul dacă se salvează documentele care au fost modificate de la ultima salvare şi
toate documentele se salvează în format Word (indiferent de formatul iniţial).

Obiectul Document

Deschiderea sau crearea unui fişier în Word produce crearea unui obiect Document. Se utilizează proprietăţile şi
metodele obiectului Document sau ale colecţiei Documents pentru a deschide, crea, salva, activa şi închide fişiere.

În prezentarea obiectului Document alegem calea acţiunilor uzuale asupra unui document şi nu listarea proprietăţilor şi
metodelor (decât acolo unde este absolut necesar).

Returnarea unui obiect Document

Se poate obţine orice document deschis ca un obiect Document prin

Documents(index)

unde index este numele documentului (ca şir) sau numărul de ordine al documentului în colecţie. Deoarece numărul de
ordine se poate schimba, prin modificarea colecţiei, se recomandă utilizarea numelor documentelor. În exemplul

Set wdRaport = Documents("Raport.doc")

variabila wdRaport, definită de tip obiect, conţine un obiect Document care se referă la documentul deschis "Raport.doc".
Orice transformare a variabilei se va reflecta în documentul Raport.doc.

Se poate utiliza şi proprietatea ActiveDocument (vezi Application) pentru a returna obiectul Document care se referă la
documentul activ:

If Documents.Count >= 1 Then


MsgBox ActiveDocument.Name
Else
MsgBox "Nici un document nu este deschis"
End If

60
Deschiderea documentelor

Pentru a deschide un document existent, se va utiliza metoda Open a colecţiei Documents, metodă care deschide
documentul specificat şi îl adaugă la colecţia Documents. Returnează un obiect Document. Sintaxa, în versiunea
aplicabilă aici, este

expression.Open(FileName, ConfirmConversions, ReadOnly, AddToRecentFiles, PasswordDocument,


PasswordTemplate, Revert, WritePasswordDocument, WritePasswordTemplate, Format)

unde

expression este o expresie care returnează un obiect Documents.

FileName este de tip Variant şi conţine numele documentului (inclusiv calea, dacă este necesar). În Windows se pot
specifica mai multe fişiere separate prin spaţii. Este semnalată eroare dacă fişierul specificat nu există.

ConfirmConversions este de tip Variant, opţional. Are valoarea True pentru a afişa dialogul Convert File dacă fişierul nu
este în format Word.

ReadOnly este de tip Variant, opţional. Are valoarea True dacă documentul se deschide ca read-only.

AddToRecentFiles este de tip Variant, opţional. Are valoarea True dacă numele fişierului se adaugă listei fişierelor recent
utilizate (de la baza meniului File).

PasswordDocument este de tip Variant, opţional şi reprezintă parola necesară la deschiderea documentului.

PasswordTemplate este de tip Variant, opţional şi reprezintă parola necesară la deschiderea şablonului (template).

Revert este de tip Variant, opţional. Controlează ce se întâmplă dacă FileName este numele unui fişier deja deschis: True
pentru a neglija orice schimbări nesalvate şi redeschiderea documentului; False pentru a activa documentul deschis.

WritePasswordDocument este de tip Variant, opţional. Este parola necesară pentru salvarea schimbărilor aduse
documentului.

WritePasswordTemplate este de tip Variant, opţional. Este parola necesară pentru salvarea modificărilor aduse şablonilui.

Format este de tip Variant, opţional. Indică tipul de conversie utilizat la deschiderea documentului. Poate fi o constantă
(din tipul enumerat wdOpenFormat) dintre:

wdOpenFormatAuto, wdOpenFormatDocument, WdOpenFormatRTF,

wdOpenFormatTemplate, wdOpenFormatText, WdOpenFormatUnicodeText.

Valoarea implicită este wdOpenFormatAuto.

Pentru o mai bună informare asupra ultimului argument, se va studia obiectul FileConverter.

În exemplul următor se deschide fişierul Test.doc din folderul curent:

Set wdTestDoc = Documents.Open(FileName:="test.doc")

61
Este de remarcat, în exemplu, că fişierul este în directorul curent, ceea ce poate produce erori la executarea codului: este
suficent ca utilizatorul să schimbe folderul pentru ca documentul test.doc să nu mai fie găsit. Din acest motiv este de
preferat ca numele să con de remarcat, în exemplu, că fişierul este în directorul curent, ceea ce poate produce erori la
executarea codului: este suficent ca utilizatorul să schimbe folderul pentru ca documentul test.doc să nu mai fie găsit. Din
acest motiv este de preferat ca numele să conţină calea completă, ceea ce contribuie la robusteţea codului. În acelaşi
scop se vor utiliza proprietăţile PathSeparator (a obiectului Application), care returnează caracterul separator utilizat de
sistemul de fişiere, diferit în DOS/Windows şi Macintosh şi DefaultFilePath (a obiectului Options), care
returnează/setează căi ale folderelor specificate.

În exemplul următor se utilizează obiectul FileSearch pentru a determina dacă există fişierul care trebuie deschis:

defaultDir = Options.DefaultFilePath(wdDocumentsPath)
With Application.FileSearch
.FileName = "test.doc"
.LookIn = defaultDir
.Execute
If .FoundFiles.Count = 1 Then
Documents.Open FileName:=defaultDir & _
Application.PathSeparator & "test.doc"
Else
MsgBox "Fisierul test.doc nu este gasit"
End If
End With

Se va observa utilizarea structurii With…End With şi a modului cum se formează argumentul FileName din cale şi
denumire.

O altă modalitate de deschidere a unui document este prin afişarea dialogului Open uzual în Office (ca şi în alte aplicaţii
Windows). Acest mod se realizează prin

Dialogs(wdDialogFileOpen).Show

care returnează un obiect Dialog ce se referă la dialogul Open (din meniul File) iar metoda Show afişează şi execută
acţiunile executate în boxa de dialog Open.

Utilizarea metodei Display (în locul metodei Show) produce doar afişarea dialogului fără nici o altă acţiune. Dacă
utilizatorul apasă butonul OK al boxei, atunci este returnată valoarea -1 şi se poate şti numele fişierului selectat în boxă
după modelul următor:

Set dlg = Dialogs(wdDialogFileOpen)


aButton = dlg.Display
fSelected = dlg.Name
If aButton = -1 Then
Documents.Open FileName:=fSelected
End If

Observaţie. Pentru o discuţie mai amplă asupra utilizării cutiilor de dialog definite în Word se va vedea Word VB Help –
"Displaying built-in Word dialog boxes".

Pentru a determina dacă un anumit document este deschis se poate enumera colecţia Documents şi testa numele
documentelor deschise. În următorul exemplu se activează documentul "cautat.doc" dacă este deschis şi se deschide
dacă nu este deja deschis.

62
docFound = True
For Each aDoc In Documents
If InStr(1,aDoc.Name,"cautat.doc",1) Then
aDoc.Activate
Exit For
Else
docFound = False
End If
Next aDoc
If docFound = False Then Documents.Open FileName:="cautat.doc"

Pentru a determina câte documente sunt deschise se utilizează proprietatea Count a colecţiei Documents:

If Documents.Count = 0 Then MsgBox "Nu este deschis nici un document"

Crearea şi salvarea documentelor

Pentru a crea un nou document se utilizează metoda Add aplicată colecţiei Documents. Metoda returnează documentul
creat ca un obiect Document, astfel încât valoarea returnată poate fi atribuită unei variabile de tip obiect pentru a putea
referi direct noul document în program:

Dim myDoc As Document


Set myDoc = Documents.Add
myDoc.PageSetup.TopMargin = InchesToPoints(1.25)

ultima instrucţiune fixează marginea de sus la 1.25".

Documentul nou devine documentul activ.

Pentru a salva un document nou pentru prima dată, se utilizează metoda SaveAs a obiectului Document. Exemplul
următor este de acest fel:

ActiveDocument.SaveAs FileName:="salvat.doc"

Documentul activ este salvat cu numele "salvat.doc" şi poate fi identificat cu acest nume în colecţia Documents.

Exemplul următor construieşte o expresie mai complicată, exploatând cele spuse mai sus: se creează un nou document
care este salvat imediat cu un nume şi apoi se inserează în document un tabel cu două linii şi trei coloane.

Documents.Add.SaveAs FileName:="vanzari.doc"
Documents("vanzari.doc").Tables.Add _
Range:=Selection.Range, NumRows:=2, NumColumns:=3

Pentru salvarea modificărilor efectuate într-un document, se utilizează metoda Save a colecţiei Documents:

Documents("vanzari.doc").Save

Utilizarea metodei Save cu un document nou deschide dialogul Save As pentru a întreba utilizatorul despre numele dat
fişierului.

Pentru salvarea tuturor fişierelor deschise se va utiliza metoda Save aplicată colecţiei Documents.

63
Metoda Save are sintaxa dependentă de obiectul căruia i se aplică:

expression.Save

unde expression este orice expresie care returnează un obiect Document sau Template, este aplicabilă unui document
sau template.

expression.Save(NoPrompt, OriginalFormat)

este aplicabilă colecţiei Documents. Argumentele sunt

expression este orice expresie care returnează un obiect Documents.

NoPrompt este de tip Variant, opţional. Are valoarea True pentru ca Word să salveze automat toate documentele, False
pentru ca Word să întrebe utilizatorul înaintea de salvarea fiecărui document care a fost modificat.

OriginalFormat este de tip Variant, opţional. Specifică modul în care sunt salvate documentele.

Poate fi o constantă (de tipul enumerat WdOriginalFormat) dintre wdOriginalDocumentFormat, wdPromptUser sau
wdWordDocument.

Activarea unui document

Pentru activarea unui alt document se aplică metoda Activate obiectului Document respectiv. Reamintim că la crearea
unui nou document, acesta rămâne activ. Documentul activat trebuie să fie deschis (inclus în colecţia Documents):

Documents("raport.doc").Activate
Doc1.Activate

dacă variabila Doc1 a primit ca valoare un document deschis.

Metoda Activate, aplicabilă mai multor obiecte (vezi Word VB Help – Activate Method), are sintaxa

expression.Activate

unde expression este orice expresie care returnează un obiect căruia i se poate aplica metoda.

Tipărirea unui document

Întrucât tipărirea unui document este gestionată de mai multe comenzi şi parametri, din dialoguri diferite în mediul Word,
controlul tipăririi din Visual Basic necesită eventuale intervenţii asupra obiectului Options (pentru a fixa parametrii
accesaţi uzual prin Tools – Options – fişa Print) şi utilizarea metodei PrintOut, aplicabilă obiectului Document.

Proprietăţile obiectului Options, care privesc tipărirea, sunt identificate uşor prin aceea că numele lor începe cu Print:
PrintComments, PrintHiddenText, PrintDrawingObjects, PrintFieldCodes etc., atribuirea valorii True fiind echivalentă
cu marcarea boxei de control din dialogul Word corespunzător.

Metoda PrintOut este aplicabilă obiectelor Application, Document sau Window şi are parametri corespunzători
opţiunilor din dialogul Print (meniul File din mediul Word). Sintaxa, cu specificarea şi explicarea principalelor argumente,
este

64
expression.PrintOut(Background, Append, Range, OutputFileName, From, To, Item, Copies, Pages, PageType,
PrintToFile, Collate, FileName)

unde

expression este orice expresie care returnează un obiect Application, Document sau Window. Background este de tip
Variant, opţional. Are valoarea True dacă tipărirea are loc în fundal (macro-ul continuă în timpul tipăririi documentului).

Append este de tip Variant, opţional. Are valoarea True atunci când, la tipărirea în fişier, documentul este adăugat
fişierului specificat în argumentul OutputFileName; are valoarea False pentru rescrierea fişierului OutputFileName.

Range este de tip Variant, opţional şi specifică tipul de domeniu tipărit. Poate fi una din constantele (de tip
WdPrintOutRange): wdPrintAllDocument, wdPrintCurrentPage, wdPrintFromTo, wdPrintRangeOfPages sau
wdPrintSelection.

OutputFileName este de tip Variant, opţional. Dacă PrintToFile este True, atunci argumentul dă numele (eventual cu cale)
pentru fişierul unde are loc tipărirea.

From este de tip Variant, opţional. Specifică numărul paginii de unde începe tipărirea, dacă Range este wdPrintFromTo.

To este de tip Variant, opţional. Specifică numărul paginii până unde se tipăreşte, dacă Range este wdPrintFromTo.

Item este de tip Variant, opţional. Specifică elementul care se tipăreşte. Poate fi o constantă (de tipul enumerat
WdPrintOutItem): wdPrintAutoTextEntries, wdPrintComments, wdPrintDocumentContent, wdPrintKeyAssignments,
wdPrintProperties sau wdPrintStyles.

Copies este de tip Variant, opţional. Specifică numărul de copii tipărite.

Pages este de tip Variant, opţional. Specifică numerele paginilor şi secvenţele de pagini care se tipăresc, separate prin
virgule, dacă Range este wdPrintRangeOfPages. De exemplu, "2, 6-10" înseamnă pagina 2 şi paginile de la 6 la 10.

PageType este de tip Variant, opţional. Specifică tipul de pagini tipărite. Poate fi o constantă (de tipul WdPrintOutPages):
wdPrintAllPages, wdPrintEvenPagesOnly sau wdPrintOddPagesOnly.

PrintToFile este de tip Variant, opţional. Are valoarea True pentru a trimite comenzile de tipărire către un fişier. Numele
fişierului este dat în argumentul OutputFileName.

Collate este de tip Variant, opţional. Are valoarea True pentru a tipări toate paginile documentului înaintea tipăririi
următoarei copii (argument valabil în cazul tipăririi mai multor copii ale documentului – argumentul Copies).

FileName este de tip Variant, opţional. Numele fişierului (inclusiv calea, dacă este în alt folder decât cel curent) care
conţine documentul care se tipăreşte. Dacă argumentul este omis, atunci se tipăreşte documentul activ. Argumentul este
admis doar pentru obiectul Application.

Exemplul următor fixează pentru documentul activ tipărirea textului ascuns şi tipăreşte primele trei pagini:

Options.PrintHiddenText = True
ActiveDocument.PrintOut Range:=wdPrintFromTo, From:=" 1", To:=" 3"

Dacă tipărirea se efectuează cu valorile curente (implicite) ale parametrilor, atunci este suficientă comanda:

ActiveDocument.PrintOut
65
Se observă că operaţiunea de tipărire necesită, pentru o procesare mai fină, specificarea documentului, specificarea
paginilor, a tipului de tipărire (toate, pagini pare sau impare), specificarea destinaţiei (imprimantă sau fişier).

Se va vedea şi proprietatea PageSetup care controlează atributele paginii pentru document, secţiune etc.

Închiderea documentelor

Pentru închidere se aplică metoda Close obiectului Document sau colecţiei Documents.

Documents("raport.doc").Close

Dacă s-au efectuat modificări în document, de la ultima salvare, se afişează dialogul de salvare. Închiderea tuturor
documentelor deschise se efectuează aplicând metoda Close pentru întreaga colecţie:

Documents.Close

Metoda Close este aplicabilă mai multor obiecte. Sintaxa pentru Documents sau Document este

expression.Close(SaveChanges, OriginalFormat, RouteDocument)

unde

expression este o expresie care returnează un obiect Document sau Documents.

SaveChanges este de tip Variant, opţional. Specifică tipul de acţiune privind salvarea documentului înainte de închidere.
Poate fi o constantă (de tip WdSaveOptions): wdDoNotSaveChanges, wdPromptToSaveChanges sau wdSaveChanges,
cu interpretări evidente.

OriginalFormat este de tip Variant, opţional. Specifică formatul documentului la salvare (poate fi o constantă (de tip
WdOriginalFormat): wdOriginalDocumentFormat, wdPromptUser sau wdWordDocument.

RouteDocument este de tip Variant, opţional. Are valoarea True dacă documentul este rutat către următorul recipient.
Dacă documentul nu are ataşată o fişă de rutare (routing slip), argumentul este ignorat (vezi obiectul RoutingSlip).

Următorul exemplu închide, fără salvare, toate documentele:

Documents.Close SaveChanges:=wdDoNotSaveChanges

Accesarea obiectelor dintr-un document

Din obiectul Document se pot accesa, prin proprietăţi sau metode, obiecte care corespund entităţilor care formează
documentul scris în Word. Dintre obiectele accesibile menţionăm (nu toate): Bookmarks, Characters, CommandBars,
Comments, DocumentProperties, Endnotes, Fields, Footnotes, FormFields, Frames, HyperLinks, Indexes, Lists,
ListTemplates, PageSetup, Paragraphs, Range, Revisions, Sections, Sentences, Shapes, StoryRanges, Styles,
Subdocuments, Tables, TablesOfContents, TablesOfFigures, Template, Variables, Windows, Words.

De exemplu, prin

MsgBox "Sunt " & ActiveDocuments.Tables.Count & " tabele în document"

afişează un mesaj cu numărul tabelelor existente în documentul activ.

66
Este evident că utilizând proprietăţile şi metodele obiectelor astfel returnate se pot modifica programatic obiectele referite:
se pot adăuga şi formata tabele, câmpuri, paragrafe, cuvinte etc.

ActiveDocument.Footnotes.Add Range:=myRange, Text:="Textul notei de subsol adaugate"

adaugă o notă de subsol la locul din document specificat de variabila myRange.

Obiectul Range

Un obiect Range reprezintă o zonă continua dintr-un document. Fiecare obiect Range este definit de o poziţie (de
caracter) de început şi de o poziţie (de caracter) de sfârşit. Utilizat pentru identificarea unor porţiuni din document,
obiectul Range este similar obiectului Bookmark, diferenţa fiind totuşi importantă: un obiect Range există doar atât timp
cât se execută procedura care l-a definit.

Atunci când poziţia de început este identică cu poziţia de sfârşit, obiectul Range identifică punctul de inserţie. Nu există
limitări asupra întinderii unui obiect Range.

Obiectele Range sunt independente de selecţia din document: se poate defini şi modifica un domeniu fără să se schimbe
selecţia. Se pot defini, de asemenea, domenii multiple într-un document, în timp ce selecţia este unică într-un ochi de
fereastră..

Pentru a înţelege toate proprietăţile obiectului Range (şi ale altor obiecte, de altfel), trebuie ştiut că zonele unui document
se presupun structurate în episoade (stories). Un episod (story) este o zonă de text diferită de celelalte zone din acel
document. Astfel, dacă un document conţine text principal (body text), note de subsol şi anteturi, atunci documentul
conţine un episod cu textul principal, un episod cu note de subsol şi un episod cu anteturi. Există 11 tipuri diferite de
episoade posibile într-un document, corespunzând următoarelor constante (din WdStoryType):

WdEndnotesStory wdEvenPagesFooterStory wdEvenPagesHeaderStory

WdFirstPageFooterStory wdFirstPageHeaderStory wdFootnotesStory

WdMainTextStory wdPrimaryFooterStory wdPrimaryHeaderStory

WdTextFrameStory

Tipul episodului pentru un obiect de gen domeniu (Range), selecţie (Selection) sau semn de carte (Bookmark) este
returnat de proprietatea StoryType. Cunoaşterea acestei proprietăţi este importantă prin aceea că mediul Word deschide
ferestre sau ochiuri diferite după episodul în care este punctul de inserţie (selecţia), Pentru navigarea programatică între
aceste ochiuri trebuie să se cunoască valoarea proprietăţii StoryType.

Proprietăţile Start, End şi StoryType identifică un obiect Range în mod unic. Start şi End specifică sau returnează
poziţiile de început şi, respectiv, de sfârşit ale obiectului Range. Poziţia de caracter de la începutul fiecărui episod este 0,
poziţia de după primul caracter este 1 ş.a.m.d.

Proprietăţile Start şi End sunt de tip Long, read/write. Poziţiile returnate sunt relative la începutul episodului. Dacă fixarea
unei proprietăţi strică ordinea naturală dintre start şi end, atunci cealaltă valoare este fixată automat la valoarea atribuită.

Prin atribuirea de valori proprietăţilor Start şi End se poate modifica dimensiunea domeniului referit.

Obiect Range vs. obiect Selection

În general, este de preferat să se opereze cu obiecte Range în loc de obiecte Selection, deoarece:
67
• se pot defini şi utiliza mai multe obiecte Range (doar un obiect Selection pe fereastră);
• procesarea obiectelor Range nu modifică textul selectat;
• procesarea obiectelor Range este mai rapidă decât a selecţiei.

La înregistrarea unui macro creează, de obicei, referinţe la obiectul Selection. Utilizarea obiectului Range poate
simplifica totuşi codul creat. Următorul exemplu aplică stilul bold primelor două cuvinte din document şi inserează un
paragraf după cele două cuvinte:

Set myRange = ActiveDocument.Range(Start:=0, End:=ActiveDocument.Words(2).End)


myRange.Bold = True
myRange.InsertParagraphAfter

Este interesant de comparat acest cod cu secvenţa obţinută la înregistrarea unui macro care efectuează aceeaşi sarcină.

Returnarea unui obiect Range prin metoda Range

Aplicată unui obiect Document, metoda Range returmează un obiect Range situat în episodul principal. Sintaxa este

expression.Range(Start, End)

unde

expression este orice expresie care returnează un obiect Document.

Start este de tip Long, opţional. Specifică punctul de început (în poziţii de caracter).

End este de tip Long, opţional. Specifică punctul de sfârşit (în poziţii de caracter).

Poziţiile de caracter încep cu 0 la începutul documentului. Sunt numărate toate caracterele, inclusiv caracterele
netipăribile. Caracterele ascunse se numără chiar dacă nu sunt afişate. Dacă nu se specifică poziţiile de început şi/sau
sfârşit, se consideră, implicit, începutul şi sfârşitul documentului.

Exemplul următor scrie în bold primele 10 caractere ale documentului:

ActiveDocument.Range(Start:=0, End:=10).Bold = True

Dacă este necesar ca obiectul Range returnat să fie referit de mai multe ori, se va utiliza instrucţiunea Set prin care se
atribuie obiectul returnat unei variabile obiect:

Dim myRange As Range


Set myRange = ActiveDocument.Range
myRange.InsertAfter Text:="Final"

Se observă definirea unei variabile obiect de tip specificat Range, obţinerea unui obiect Range egal cu tot documnetul
(prin nespecificarea valorilor de start şi end), atribuirea acestui obiect variabilei definite şi utilizarea variabilei pentru a
referi obiectul. Efectul este inserarea cuvântului "Final" după ultimul caracter din document.

În exemplul următor se observă utilizarea unui obiect Range doar ca punct de referinţă în document (asemenea unui
Bookmark):

Set inceputDoc = ActiveDocument.Range(Start:=0, End:=0)

68
Poziţiile de start şi end pot fi specificate direct sau prin intermediul proprietăţilor Start şi End ale altor obiecte cum ar fi
Selection, Bookmark sau Range, ca în exemplul următor în care se defineşte un domeniu care se referă la a două şi a
treia propoziţie din document:

Set myRange=ActiveDocument.Range( _
Start:=ActiveDocument.Sentences(2).Start, _
End:=ActiveDocument.Sentences(3).End)

Deoarece obiectul Range nu are un corespondent visual în document, se poate utiliza metoda Select a obiectului pentru
a produce selectarea textului din domeniu şi a verifica, astfel, definirea corectă a obiectului Range:

myRange.Select

selectează porţiunea de text conţinută în variabila myRange, căreia în prealabil i s-a atribuit un Range.

Returnarea unui obiect Range prin proprietatea Range

Proprietatea Range este disponibilă pentru multiple obiecte — de exemplu Paragraph, Bookmark, Endnote, Cell — şi
este utilizată pentru întoarcerea unui obiect Range.

Exemplele următoare sunt uşor interpretabile. Pentru explicaţii complete se vor studia obiectele respective.

Active.Document.Paragraphs(1).Range
ActiveDocument.Tables(1).Rows(1).Range
ActiveDocument.Bookmarks(1).Range

Nu trebuie uitată structura With…End With pentru procesări multiple ale aceluiaşi obiect Range.

Modificarea unei porţiuni a unui document

Visual Basic include obiecte care pot fi utilizate pentru a modifica următoarele tipuri de elemente ale documnetului:
caractere, cuvinte, propoziţii, paragrafe şi secţiuni. Tabelul următor arată proprietăţile (aplicabile unor diverse obiecte)
care corespund acestor elemente şi obiectele returnate:

expresia obiect returnat

Words(index) Range

Characters(index) Range

Sentences(index) Range

Paragraphs(index) Paragraph

Sections(index) Section

Pentru ultimele două colecţii din tabel este de notat că pentru a junge la obiectul Range corespunzător se va apela la
proprietatea Range. Prin urmare

Paragraphs(index).Range
Sections(index).Range
69
dau acces la obiectele Range respective.

Pentru modificarea unui domeniu de text din document, se poate crea un obiect Range cu acele elemente (caractere,
propoziţii, paragrafe etc.). Aplicarea proprietăţilor şi metodelor obiectului Range astfel creat va produce modificarea
textului referit de obiect:

ActiveDocument.Words(1).Case = wdUpperCase

trece primul cuvânt din document în majuscule. De remarcat că proprietatea Case este aplicată obiectului Range returnat
de ActiveDocument.Words(1).

În formarea obiectelor Range sunt importante proprietăţile Start şi End care dau începutul şi sfârşitul.

Proprietăţile elementelor documentului, specificate în tabelul anterior în prima coloană, sunt admise pentru obiectele
Document, Selection şi Range.

Lucrul cu textul dintr-un obiect Range

Accesul la conţinutul unui obiect Range este realizat prin proprietatea Text. Proprietatea Text returnează textul
neformatat (plain text) al domeniului referit. Atunci când se setează această proprietate, textul domeniului referit este
înlocuit de valoarea atribuită proprietăţii.

primCuvant = ActiveDocument.Words(1).Text
ActiveDocument.Words(1).Text = "Capitol"

returnează sau modifică primul cuvânt din documentul activ.

Pentru inserarea unui text înaintea sau după un obiect Range se utilizează, respectiv, metodele InsertBefore sau
InsertAfter. După inserarea unui text, domeniul este extins automat pentru a include şi textul inserat (înainte sau după).

Sintaxa metodelor este

expression.InsertBefore(Text)

expression.InsertAfter(Text)

unde

expression este o expresie care returnează un obiect Selection sau Range.

Text este de tip String şi reprezintă textul care se inserează.

Pentru inserarea caracterelor speciale se va utiliza funcţia Chr, sau constantele Visual Basic cum ar fi vbCr, vbLf, vbCrLf
sau vbTab.

Inserarea unui text după un domeniu care se referă la un întreg paragraf are loc după marca de paragraf. Drept urmare
textul este inserat la începutul paragrafului următor. Pentru a anula acest lucru se va identifica sfârşitul de domeniu
(Range sau Selection) şi se va scădea cu 1 poziţia finală (deci se va trece în faţa caracterului marcă de paragraf).
Exemplul următor arată mecanismul utilizat:

Set Doc = ActiveDocument

70
Set myRange = Doc.Range( _
Start:=Doc.Paragraphs(1).Range.End - 1, _
End:=Doc.Paragraphs(1).Range.End - 1)
myRange.InsertAfter " sfărşit de paragraf."

Un domeniu poate fi redus la punctul de început sau de sfârşit (proprietăţile Start şi End devin egale cu poziţia de
caracter respectivă) prin metoda Collapse. Sintaxa este

expression.Collapse(Direction)

unde

expression este o expresie care returnează un obiect Range sau Selection.

Direction este de tip Variant, opţional şi indică direcţia în care are loc implozia domeniului. Poate fi o constantă (de tip
WdCollapseDirection) dintre: wdCollapseEnd sau wdCollapseStart. Valoarea implicită este wdCollapseStart.

Utilizarea metodei cu wdCollapseEnd, atunci când domeniul se referă la un întreg paragraf, produce un domeniu situat
după marca de paragraf.

Pentru formatarea textului dintr-un obiect Range, se utilizează

• proprietatea Font pentru formatarea caracterelor


• proprietatea ParagraphFormat pentru formatarea paragrafelor.

Proprietatea Font returnează un obiect Font care dispune de toate metodele şi proprietăţile necesare pentru aplicarea
formatărilor admise pentru caractere în Word.

Proprietatea ParagraphFormat returnează un obiect ParagraphFormat care permite efectuarea tuturor formatărilor
admise pentru un paragraf în Word.

Deoarece ambele obiecte, Font şi ParagraphFormat sunt foarte complexe dar reprezintă acţiuni de rutină pentru un
utilizator Word nu vor fi prezentate aici. Exemplul următor constituie un model suficient pentru orice altă acţiune care
implică aceste obiecte:

With ActiveDocument.Paragraphs(1).Range.Font
.Name = "Times New Roman"
.Size = 14
.AllCaps = True
End With
With ActiveDocument.Paragraphs(1).Range.ParagraphFormat
.LeftIndent = InchesToPoints(0.5)
.Space1
End With

Textul sursă precedent realizează pentru primul paragraf din documentul activ setarea fontului ca "Times New Roman",
de mărime 14 şi scris cu majuscule. În formatarea paragrafului se realizează indentarea din stânga cu 1.5" şi spaţierea la
un rând.

Redefinirea unui obiect Range

Pentru modificarea limitelor unui obiect Range se pot utiliza, în mod uzual, proprietăţile Start şi End:

71
myRange.End = myRange.End + 10

Metodele MoveStart şi MoveEnd produc o acţiune similară, dar se pot utiliza unităţi diverse, predefinite, pentru
extinderea domeniului. Ambele metode returnează un inţreg care arată numărul de unităţi cu care s-a modificat Start sau
End, sau 0 dacă operaţiunea nu s-a putut realiza. Sintaxa este

expression.MoveStart(Unit, Count)

expression.MoveEnd(Unit, Count)

unde

expression este o expresie care returnează un obiect Range sau Selection.

Unit este de tip Variant, opţional. Reprezintă unitatea cu care se deplasează punctul de start/end al obiectului. Poate fi
una dintre constantele (de tip WdUnits): wdCharacter, wdWord, wdSentence, wdParagraph, wdSection, wdStory, wdCell,
wdColumn, wdRow sau wdTable. Pentru obiectul Selection poate fi şi wdLine. Valoarea implicită este wdCharacter.

Count este de tip Variant, opţional. Numărul maxim de unităţi cu care se mută punctul de start/end. Poate fi negativ sau
pozitiv, cu interpretările curente. În cazul când operaţiunea produce inversarea fizică a poziţiilor de Start şi End, cele două
poziţii devin egale (Range suferă un colaps). Valoarea implicită este 1.

În exemplul următor

myRange.MoveEnd Unit:=wdParagraph, Count:=1

se extinde domeniul încât să cuprindă şi următorul paragraf.

Observaţie. Există şi metode mai fine cum ar fi MoveUntil, MoveWhile, MoveStartUntil, MoveEndWhile etc. Se va
vedea intrarea respectivă din Word VB - Help.

Metoda SetRange poate fi utilizată pentru modificarea simultană a limitelor unui obiect Range existent. Nu trebuie să se
confunde cu metoda Range, care defineşte obiectul.

expression.SetRange(Start, End)

unde

expression este o expresie care returneazăun obiect Range sau Selection.

Start este de tip Long, poziţia nouă de start.

End este de tip Long, poziţia nouă de sfârşit (end).

De exemplu:

myRange.SetRange Start:=myRange.Start, End:=myRange.End+10

care extinde domeniul cu 10 caractere.

72
Pentru deplasarea obiectului Range cu un număr de unităţi se va studia metoda Next. Acest procedeu se poate folosi la
parcurgerea secevenţială a unei secvenţe de cuvinte, paragrafe. Este de reamintit că o asemenea parcurgere poate fi
efectuată şi prin structura For Each…Next.

Atribuirea obiectelor Range

O primă procedură este cea, exemplificată mai sus, în care se utilizează instrucţiunea Set pentru atribuirea unui Range la
o variabilă obiect, instrucţiune care poate opera şi în ipostaza

Set Range2 = Range1

La modificarea unui obiect, schimbarea se va reflecta automat şi în celălalt obiect.

Este de observat că printr-o instrucţiune de atribuire directă

Range2 = Range1

se atribuie proprietatea implicită a obiectului Range1 (adică proprietatea Text) proprietăţii implicite a obiectului Range2.
Prin urmare codul este echivalent cu

Range2.Text = Range1.Text

care nu modifică obiectele Range respective (doar conţinutul lui Range2). Cele două obiecte pot fi la locaţii diferite, doar
conţinutul este acelaşi şi legătura dintre ele nu se stabileşte permanent.

Prin proprietatea Duplicate se creează un nou obiect Range, duplicat, cu aceleaşi limite şi text:

Set Range2 = Range1.Duplicate

Modificarea limitelor unui obiect nu influenţează limitele celuilalt, dar modificarea textului poate produce modificarea
celuilalt în cazul suprapunerii domeniilor.

Obiectul Selection

Atunci când se procesează un document în Microsoft Word, este uzual să se selecteze o porţiune de text şi să se
formateze/modifice/etc. porţiunea selectată. În Visual Basic, operaţiunea de selectare prealabilă nu este necesară,
obiectul Range permite toate acţiunile pentru domenii determinate ale documentului. Totuşi, atunci când se doreşte ca,
programatic, să se răspundă unei selecţii efectuate de utilizator, sau să se modifice selecţia etc., se poate opera cu
obiectul Selection.

Există un singur obiect Selection pe ochi de fereastră şi doar un obiect este activ la un moment dat (corespunzând
locului unde este puctul de inserţie, cu toată zona selectată adiacentă). Este evident, din lucrul în Word, că o selecţie
poate să se refere la un întreg domeniu sau poate fi redusă la punctul de inserţie.

Obiectul Selection este returnat de proprietatea Selection a obiectelor Application, Window sau Pane. Utilizată cu
Application, proprietatea returnează obiectul Selection care se referă la selecţia activă. Prin urmare

Selection.InsertAfter Text:=" Text adăugat după selecţie"

utilizează proprietatea Selection a obiectului Application (fiind globală nu trebuie specificat obiectul), este returnată
selecţia activă şi se inserează un text, similar metodei InsertAfter de la Range.

73
Dacă se lucrează cu selecţia dintr-o fereastră particulară, obiectul respectiv se specifică:

Windows("Document2").Selection.Paragraphs(1).SpaceBefore = InchesToPoints(0.15)

măreşte la 0.15" spaţiul dinaintea primului paragraf din selecţie (dacă selecţia este punctul de inserţie, se modifică
paragraful curent).

Următorul exemplu inserează text în antetul primei pagini

With ActiveWindow
.View.Type = wdPageView
.View.SeekVCiew = wdSeekPrimaryHeader
.ActivePane.Selection.InsertAfter Text:="Capitolul I"
End With

În general, metodele şi proprietăţile uzuale ale obiectului Selection sunt similare celor de la obiectul Range. Este totuşi
de amintit că obiectul Selection are corespondent grafic în document: zona selectată. Orice extindere sau implozie se
vede imediat.

Deplasarea şi extinderea selecţiei

Deoarece nu există decât o selecţie pe ochi de fereastră, selectarea unei noi zone mută implicit şi obiectul Selection.
Această selectare se efectuează aplicând metoda Select unui element din document:

ActiveDocument.Words(1).Select

permite mutarea selecţiei la primul cuvânt, astfel încât se poate utiliza după aceea metoda Selection:

Selection.Text = "Primul"

pentru modificarea textului selectat.

Există un număr de metode care deplasează selecţia în document (prin modificarea corespunzătoare a obiectului
Selection).

Move(Unit, Count) – reduce selecţia la punctul de sfârşit (Count > 0) sau de început (Count < 0) şi deplasează apoi
punctul de inserţie astfel obţinut Count unităţi (in sensul pozitiv sau negativ).

MoveEnd, MoveStart – similare descrierilor de la obiectul Range

MoveLeft(Unit,Count,Extend) – unde Unit poate fi wdCell, wdCharacter, wdWord sau wdSentence, Count este numărul
de unităţi, Extend arată tipul acţiunii: wdMove pentru colaps la stânga şi mutarea selecţiei, wdExtend pentru extensie spre
stânga.

MoveRight(Unit,Count,Extend) – este similară metodei MoveLeft, dar acţiunea este spre dreapta.

MoveDown(Unit,Count,Extend), MoveUp(Unit,Count,Extend) – cu acţiune similară metodelor precedente, dar direcţia de


acţiune este sus-jos. Unit poate fi wdLine, wdParagraph, wdWindow sau wdScreen. Extend poate fi wdMove sau
wdExtend, cu sensul explicat anterior.

Exemple:

74
Selection.MoveDown Unit:=wdParagraph, Count:=1, Extend:=wdMove

mută punctul de inserţie la începutul paragrafului următor.

Selection.MoveEnd Unit:=wdParagraph, Count:=1

extinde selecţia prin mutarea poziţiei finale la sfârşitul paragrafului.

Selection.MoveRight Unit:=wdCharacter, Count:=1, Extend:=wdExtend

extinde selecţia activă cu un cuvânt spre dreapta.

Utilizarea metodelor GoToNext, GoToPrevious sau GoTo permite mutarea selecţiei prin alegerea tipului de element
ţintă din document, a direcţiei etc.

Metoda GoTo

Aplicată obiectului Selection, mută punctul de inserţie în poziţia de caracter imediat precedentă elementului specificat şi
returnează un obiect Range (cu excepţia specificării elementelor wdGoToGrammaticalError, wdGoToProofreadingError
sau wdGoToSpellingError, caz în care Obiectul Range include şi textul eronat). Sintaxa este

expression.GoTo(What, Which, Count, Name)

unde

expression este o expresie care returnează un obiect Document, Range sau Selection.

What este de tip Variant, opţional şi precizează tipul elementului unde se mută punctul de inserţie (selecţia). Poate fi una
dintre constantele (de tipul enumerat WdGoToItem):

wdGoToBookmark wdGoToComment wdGoToEndnote

wdGoToEquation wdGoToField wdGoToFootnote

wdGoToGrammaticalError wdGoToGraphic wdGoToHeading

wdGoToLine wdGoToObject wdGoToPage

wdGoToPercent wdGoToProofreadingError wdGoToSection

wdGoToSpellingError wdGoToTable

Which este de tip Variant, opţiomal şi specifică modul de mutare a selecţiei. Poate fi una dintre constantele (de tip
WdGoToDirection): wdGoToAbsolute, wdGoToFirst, wdGoToLast, wdGoToNext, wdGoToPrevious sau wdGoToRelative.

Count este de tip Variant, opţional şi indică numărul utilizat la determinarea elementului (în funcţie de tipul de acţiune dat
de Which). Este doar pozitiv şi pentru găsirea unui element anterior se va utiliza wdGoToPrevious cu un Count > 0.

Name este Variant, opţional şi dă numele elementului ţintă, dacă What este wdGoToBookmark, wdGoToComment,
wdGoToField sau wdGoToObject.

75
Exemple:

Selection.GoTo What:=wdGoToHeading, Which:=wdGoToFirst


Selection.GoTo What:=wdGoToHeading, Which:=wdGoToAbsolute, Count:=1
Selection.GoTo What:=wdGoToLine, Which:=wdGoToAbsolute, Count:=4
Selection.GoTo What:=wdGoToLine, Which:=wdGoToPrevious, Count:=2
Selection.GoTo What:=wdGoToField, Name:="Date"

Metodele GoToNext, GoToPrevious

Pentru acţiuni limitate doar la deplasarea cu un singur element, metodele cu sintaxa (pentru obiectele Range sau
Selection):

GoToNext(What)

GoToPrevious(What)

unde

What este una dintre constantele de tip WdGoToItem (vezi metoda GoTo).

Metodele returnează un obiect Range (vezi discuţia de la GoTo).

Obiecte accesibile din Selection

Cele mai multe obiecte accesibile din obiectele Range şi Document sunt disponibile şi din obiectul Selection. Se pot astfel
procesa obiectele din interiorul selecţiei. Lista obiectelor care sunt referite din Selection este

Bookmarks, Borders, Cells, Characters, Columns, Comments, Document, Endnotes, Fields, Find, Font, Footnotes,
FormFields, Frames, HeaderFooter, Hyperlinks, InlineShapes, PageSetup, ParagraphFormat, Paragraphs, Revision,
Range, Rows, Sections, Sentences, Shading, ShapeRange, Tables, Words.

Aceste obiecte (colecţii de obiecte) sunt returnate prin proprietăţile cu aceleaşi denumiri ale obiectului Selection. De
exemplu

Selection.Paragraphs.LeftIndent = InchesToPoints(0.5)
Selection.Words(1).Italic = True
MsgBox Selection.Footnotes(1).Range.Text

Pentru parcurgerea tuturor obiectelor dintr-o colecţie returnată se va folosi structuraFor Each…Next:

For Each aBook In Selection.Bookmarks


MsgBox aBook.Name
Next aBook

Proprietăţi şi metode uzuale ale obiectului Selection

Proprietatea Text

Se va utiliza proprietatea Text pentru a returna sau stabili conţinutul obiectului Selection:

76
strText = Selection.Text
Selection.Text = "Hello World"

Se va utiliza metoda InsertBefore sau InsertAfter pentru inserarea unui text înainte sau după selecţie (cu extinderea
corespunzătoare a selecţiei).

Formatarea textului selectat

Se vor utiliza proprietăţile Font şi ParagraphFormat pentru accesul la proprietăţile şi metodele proprii caracterelor şi,
respectiv, paragrafelor:

With Selection.Font
.Name = "Times New Roman"
.Size = 14
End With
Selection.ParagraphFormat.LeftIndent = InchesToPoints(0.5)

Returnarea obiectului Range

O importanţă deosebită o are proprietatea Range, care returnează un obiect Range ce se referă la selecţia curentă. În
acest mod se poate exploata faptul că pot exista mai multe obiecte Range şi memora selecţii succesive:

Set myRange = Selection.Range

O altă utilizare este aceea când anumite metode sau proprietăţi se pot aplica doar unui obiect Range:

Selection.Range.CheckSpelling

Proprietatea Information

Returnarea informaţiilor despre selecţie, cum ar fi numărul paginii curente, numărul total de pagini, faptul că selecţia este
în antet sau picior de pagină etc. Sintaxa este

expression.Information(Type)

unde

expression este o expresie care returnează un obiect Range sau Selection.

Type este de tip Long şi precizează tipul informaţiei care se returnează. Poate fi una dintre cele 35 de
constante de tip WdInformation, dintre care menţionăm (doar pentru a exemplifica tipuri de informaţii
obţinute):

o wdActiveEndAdjustedPageNumber – numărul paginii care conţine sfârşitul activ al selecţiei sau


domeniului. Numărul este ajustat pentru a considera personalizările efectuate de utilizator (număr de
început etc.).
o wdActiveEndPageNumber – numărul paginii care conţine sfârşitul activ al selecţiei sau domeniului.
Numărul este dat relativ la începutul documnetului, şi nu este modificat de personalizările efectuate de
utilizator (număr de început etc.).
o wdHorizontalPositionRelativeToPage – poziţia orizontală a selecţiei sau domeniului; distanţa de la
marginea stângă a selecţiei la latura stângă a paginii. Distanţa este dată în twips (20 twips = 1 point, 72
points = 1 inch). Dacă selecţia sau domeniul nu este în zona ecran, atunci se întoarce – 1.

77
o wdInHeaderFooter – întoarce True dacă selecţia/domeniul este în ochiul de fereastră antet sau footer,
sau în header sau footer (în page layout view).
o wdWithInTable – întoarce True dacă selecţia este într-un tabel.
o wdZoomPercentage – întoarce procentajul curent de mărire a documentului, după cum este fixat de
proprietatea Percentage.

Exemplul următor afişează, dacă selecţia este într-un tabel, numărul de coloane şi de linii ale tabelului:

If Selection.Information(wdWithInTable) = True Then


MsgBox "Coloane = " & Selection.Information(wdMaximumNumberOfColumns) _
& vbCR & "Linii = " & Selection.Information(wdMaximumNumberOfRows)
End If

Determinarea tipului de selecţie (text sau punct de inserţie)

Prin proprietatea Type se poate obţine informaţia privind tipul selecţiei. Valoarea returnată, Long, este una dintre
constantele tipului enumerat WdSelectionType:

wdNoSelection, wdSelectionBlock, wdSelectionColumn,

wdSelectionFrame, wdSelectionInlineShape, wdSelectionIP,

wdSelectionNormal, wdSelectionRow, wdSelectionShape

Dintre aceste constante, wdSelectionNormal reprezintă selecţia uzuală a unei porţiuni de text, wdSelectionBlock
reprezintă selecţia sub formă de bloc dreptunghiular, wdSelectionIP este selecţia redusă la punctul de inserţie.

Exemplul următor selectează paragraful care conţine punctul de inserţie, dacă selecţia este redusă la punctul de inserţie:

If Selection.Type = wdSelectionIP Then


Selection.Paragraphs(1).Range.Select
End If

Obiectele Find şi Replacement

Găsirea şi înlocuirea unor domenii specificate de text dintr-un document este o operaţiune frecventă în procesarea
textelor. Pentru realizarea programatică, în Visual Basic, dispunem de obiectele Find (pentru găsirea textului specificat) şi
Replacement (pentru înlocuire).

Obiectul Find este permis fie din Selection, fie din Range. Există mici deosebiri între cele două moduri de acces, legate
îndeosebi de transformarea obiectelor dacă procesul de căutare se termină cu succes.

Obiectul Replacement este accesibil din obiectul Find şi permite toate acţiunile disponibile în boxa de dialog Find and
Replace (meniul Edit din Word).

Schema generală pentru realizarea unei căutări urmată, sau nu, de o înlocuire este

o stabilirea parametrilor căutării/înlocuirii, prin proprietăţile obiectului Find/ Replacement. In proprietatea


Text se precizează textul căutat sau înlocuitor.
o executarea căutării/înlocuirii prin aplicarea metodei Execute.

78
Find

Dintre proprietăţile obiectului Find menţionăm

• Font, returnează un obiect Font pentru care se pot stabili atributele căutate.
• Format, este setat pe True dacă în căutare se consideră formatul textului. Read-write, Boolean.
• Forward, direcţia căutării: True pentru înainte, False pentru înapoi. Read/wtite, Boolean.
• Found este True dacă s-a găsit o potrivire. Read, Boolean.
• MatchCase este True pentru o căutare care diferenţiază majusculele de minuscule. Read-write, Boolean.
• MatchWildcards este True dacă textul căutat conţine caractere şablon de căutare. Read/write, Boolean.
• ParagraphFormat, returnează un obiect ParagraphFormat prin care se pot stabili atribute de paragraf căutate.
• Style permite stabilirea stilului căutat (predefinit sau utilizator). Pentru lista constantelor ce denumesc stilurile
predefinite se va vedea Word VB Help – Style Property.
• Text, conţine textul căutat. Read-write, String.
• Wrap precizează modul de continuare în cazul atingerii sfârşitului (sau începutului) fişierului sau negăsirii textului
în domeniul căutat. Poate fi o constantă (de tip WdFindWrap): wdFindAsk – consultarea utilizatorului,
wdFindContinue – continuarea în restul documentului, wdFindStop – oprirea la epuizarea domeniului de căutare.
Read/write, Long.

Obiectul Find are două metode:

o ClearFormatting pentru înlăturarea oricărei formatări a textului căutat, necesară pentru a iniţia o nouă
căutare de formate;
o Execute pentru a efectua căutarea pe baza atributelor fixate.

ClearFormatting

Anulează orice formatare specificată pentru o operaţiune de căutare sau înlocuire. Corespunde butonului No Formatting
din dialogul Find and Replace (meniul Edit).

expression.ClearFormatting

unde

expression este o expresie care returnează un obiect Find sau Replacement.

Execute

Execută operaţiunea Find specificată. Returnează True dacă operaţiunea de căutare se termină cu succes (este găsită o
potrivire cu textul căutat). Unele dintre argumentele metodei acoperă valori ale proprietăţilor obiectului Find.

expression.Execute(FindText, MatchCase, MatchWholeWord, MatchWildcards, MatchSoundsLike, MatchAllWordForms,


Forward, Wrap, Format, ReplaceWith, Replace)

unde

expression este o expresie care returnează un obiect Find.

FindText este de tip Variant, opţional. Reprezintă textul căutat. Pentru căutarea unui format anume se va specifica un şir
vid (""). Se pot utiliza caracterele speciale, similar celor disponibile în căutările Word uzuale.

MatchCase este de tip Variant, opţional. True sau False după cum în căutare are importanţă capitalizarea caracterelor.
79
MatchWholeWord este de tip Variant, opţional. Este True dacă în căutare se vor potrivi doar cuvinte întregi.

MatchWildcards este de tip Variant, opţional. True dacă textul căutat utilizează şabloane de căutare (wildcards).

MatchSoundsLike este de tip Variant, opţional. True dacă operaţiunea de căutare acceptă şi cuvinte care "sună" la fel cu
textul căutat.

MatchAllWordForms este de tip Variant, opţional. True dacă operaţiunea de căutare acceptă ca succes toate formele
textului căutat.

Forward este de tip Variant, opţional. True pentru o căutare înainte (spre sfârşitul documentului).

Wrap este de tip Variant, opţional. Controlează continuarea operaţiunii la epuizarea domeniului cercetat. Valorile posibile
sunt date la proprietatea Wrap: wdFindContinue, wdFindStop sau wdFindAsk.

Format este de tip Variant, opţional. True dacă în căutare este specificată o formatare (de caracter sau paragraf).

ReplaceWith este de tip Variant, opţional. Textul înlocuitor. Pentru a specifica un obiect grafic sau nontext, elementul se
trece în Clipboard şi se specifică "^c" în ReplaceWith.

Replace este de tip Variant, opţional. Specifică numărul de înlocuiri. Poate fi o constantă (de tip WdReplace):
wdReplaceAll, wdReplaceNone sau wdReplaceOne.

Selection.Find

Returnarea unui obiect Find din obiectul Selection produce schimbarea selecţiei la îndeplinirea criteriilor de căutare.
Textul care corespunde proprietăţilor căutării devine noua selecţie. Următorul exemplu selectează următoarea apariţie a
cuvântului "Hello", căutarea oprindu-se la atingerea sfârşitului documentului:

With Selection.Find
.Forward = True
.Wrap = wdFindStop
.Text = "Hello"
.Execute
End With

Acelaşi efect se putea obţine folosind argumentele metodei Execute:

Selection.Find.Execute FindText:="Hello", Forward:=True, Wrap:=wdFindStop

Range.Find

Utilizarea proprietăţii Find a obiectului Range nu produce modificarea selecţiei curente, dar obiectul Range respectiv
este redefinit la găsirea textului care îndeplineşte condiţiile:

With ActiveDocument.Content.Find
.Text = "blue"
.Forward = True
.Execute
If .Found = True Then .Parent.Bold = True
End With

80
De remarcat că proprietatea Content returnează obiectul Range care conţine episodul principal al documentului (textul
principal). Codul din exemplu execută o căutare a primei apariţii a cuvântului "blue" în documentul activ. Dacă
operaţiunea se termină cu succes, atunci obiectul Range este redefinit la cuvântul găsit, astfel încât prin .Parent se face
referinţă la obiectul Range redefinit şi cuvântul "blue" este trecut în stilul bold. Acelaşi efect se obţinea prin

Set myRange = ActiveDocument.Content


myRange.Find.Execute FindText:="blue", Forward:=True
If myRamge.Find.Found = True Then myRange.Bold = True

atributele căutării fiind definite prin argumentele metodei Execute.

Obiectul Replacement

Referinţa la obiectul Replacement se obţine prin proprietatea Replacement a obiectului Find:

expression.Find.Replacement

Obiectul Replacement reprezintă atributele textului nou (înlocuitor) într-o operaţiune de căutare cu înlocuire.

Dintre proprietăţile obiectului Replacement amintim:

• Font, returnează un obiect Font prin care se pot stabili atributele caracterelor noului text.
• ParagraphFormat, returnează un obiect ParagraphFormat prin care se pot stabili atribute de paragraf pentru
noul text.
• Style permite stabilirea stilului pentru textul nou (predefinit sau utilizator). Pentru lista constantelor ce denumesc
stilurile predefinite se va vedea Word VB Help – Style Property.
• Text, conţine textul înlocuitor (nou). Read-write, String.

Obiectul Replacement are doar metoda ClearFormatting, prin care se anulează toate atributele de format asociate
noului text. Este util să se aplice metoda înaintea definirii unei noi formatări pentru textul înlocuitor. Sintaxa este similară
metodei de la obiectul Find.

Executarea unei operaţiuni de înlocuire necesită, de obicei, precizarea argumentului Replace al metodei Execute (pentru
Find):

With Selection.Find
.ClearFormatting
.Text = "hi"
.Replacement.ClearFormatting
.Replacement.Text = "hello"
.Execute Replace:=wdReplaceAll, Forward:=True, Wrap:=wdFindContinue
End With

execută o căutare a cuvântului "hi", neformatat, şi înlocuirea tuturor apariţiilor cu cuvântul "hello", de asemenea
neformatat. Căutarea şi înlocuirea are loc în tot documentul, indiferent de unde se începe. Selecţia se modifică la fiecare
întâlnire a cuvântului "hi", deoarece se pleacă din obiectul Selection.

With ActiveDocument.Content.Find
.ClearFormatting
.Font.Bold = True
With .Replacement
.ClearFormatting
.Font.Bold = False
81
End With
.Execute FindText:="", ReplaceWith:="", Format:=True, Replace:=wdReplaceAll
End With

În acest exemplu se utilizează atât pentru căutare, cât şi pentru înlocuire textul vid, ceea ce produce doar o înlocuire a
formatului bold cu formatul normal. Este de remarcat, pentru înlocuirea formatelor, combinaţia de valori ale argumentelor
FindText, ReplaceWith, Format. Selecţia nu se modifică, deoarece s-a plecat din obiectul Range (returnat de
proprietatea Content).

Obiectele Table, Column, Row şi Cell

Prelucrarea tabelelor, un subiect foarte important în procesarea textelor, este posibilă programatic prin utilizarea
obiectelor

• Table, care referă un tabel din document,


• Column, care referă o coloană dintr-un tabel,
• Row, care referă o linie dintr-un tabel şi
• Cell, care referă o celulă dintr-un tabel.

Datorită complexităţii lucrului cu tabele (trasare liberă, uniri de celule, divizări de celule etc.), metodele şi proprietăţile
obiectelor amintite pot uneori să se producă rezultate neaşteptate (ca şi în procesarea uzuală din Word) dacă nu sunt
înţelese exact.

În general obiectele sunt accesate ca elemente din colecţiile respective, dar există şi posibilitatea accesării individuale.

Colecţia Tables

Reprezintă mulţimea tuturor tabelelor dintr-o selecţie, domeniu sau document. Serveşte pentru returnarea unui tabel:

expression.Tables(index)

sau pentru adăugarea, programatică, a unui nou tabel la colecţie utilizând metoda Add:

expression.Add(Range, NumRows, NumColumns)

unde

expression este o expresie care returnează un obiect Tables.

Range este obiectul Range care referă domeniul unde se inserează tabelul în document. Dacă domeniul nu este redus la
punctul de inserţie, atunci tabelul adăugat înlocuieşte tot domeniul conţinut.

NumRows, de tip Long, este numărul iniţial de linii ale tabelului.

NumColumns, de tip Long, este numărul iniţial de coloane ale tabelului.

Obiectul Table

Este returnat prin numărul de ordine dintr-o colecţie Tables.

82
Proprietăţile obiectului se referă la formatarea globală a tabelului sau la obiectele componente ale unui tabel. Din prima
categorie fac parte:

o AutoFormatType, de tip Long, read only, este o constantă de tip WdTableFormat (vezi intrarea din Help
corespunzătoare) care arată dacă tabelul este formatat prin AutoFormat. De exemplu,
wdTableFormatNone reprezintă un tabel neformatat, pe când wdTableFormatProfessional arată
selectarea formatului automat Professional. Vezi şi metoda AutoFormat.
o Shading returnează un obiect Shading prin care se stabilesc atributele de umbrire.
o Uniform, de tip Boolean, read only, are valoarea True dacă toate liniile au acelaşi număr de coloane.

Accesul la obiectele componente se realizează prin proprietăţile

o Borders, colecţia de chenare a tabelului,


o Columns, colecţia de coloane,
o Rows, colecţia de linii.

Metodele obiectului Table permit atât operaţiuni asupra întregului tabel (autoformat, ştergere, selectare, sortare, divizare
etc.), cât şi accesul la celulele tabelului. Menţionăm:

o Cell(Row,Column) returnează un obiect Cell care referă celula de pe linia Row şi coloana Column din
tabel. Row şi Column sunt de tip Long şi au valori de la 1 la numărul maxim de linii, respectiv coloane.
o Delete produce eliminarea obiectului, deci ştergerea din document a tabelului.
o Select realizează selectarea tabelului, astfel încât se poate opera apoi cu proprietatea Selection.
o Sort(ExcludeHeader, FieldNumber, SortFieldType, SortOrder, FieldNumber2, SortFieldType2,
SortOrder2, FieldNumber3, SortFieldType3, SortOrder3, CaseSensitive, LanguageID) produce sortarea
tabelului. Datorită sintaxei complexe, argumentele vor fi studiate în Word VB Help.
o Split(BeforeRow) duce la divizarea tabelului înainte de linia indicată în BeforeRow (de tip Variant, poate
fi un număr de linie sau un obiect Row).

Colecţia Columns

Reprezintă colecţia coloanelor unui tabel şi este returnată prin proprietatea Columns a unui obiect Table.

Dintre proprietăţi enumerăm

o Borders, returnează colecţia de chenare,


o Shading, returnează un obiect Shading prin care se stabilesc atributele de umbrire,
o Width returnează sau stabileşte lăţimea coloanelor, în puncte. Read/write, de tip Long.
o First returnează prima coloană din colecţie. Read only.
o Last returnează ultima coloană din colecţie. Read only.

Metodele permit operaţiuni specifice tuturor colecţiilor (Count, Add) sau specifice obiectului coloane de tabel:

o Add(BeforeColumn) prin care se adaugă o nouă coloană în faţa coloanei referite de BeforeColumn (care
este de tip Variant, opţional, returnează un obiect Column).
o AutoFit care ajustează lăţimea coloanei, dacă este posibil, pentru a cuprinde textul interior.
o DistributeWidth care produce o redistribuire a lăţimilor încât toate coloanele să fie egale.
o SetWidth(ColumnWidth, RulerStyle) care stabileşte lăţimea coloanelor: ColumnWidth, de tip Single, este
lăţimea în puncte; RulerStyle, de tip Long, controlează modul în care este ajustata lăţimea. RulerStyle
poate fi una dintre constantele WdRulerStyle: wdAdjustFirstColumn – modifică doar prima coloană,
wdAdjustNone – nu modifică celelalte coloane, wdAdjustProportional – ajustează toate coloanele din
dreapta, wdAdjustSameWidth – aceeaşi lăţime tuturor coloanelor specificate. Ultimul argument este mai

83
important pentru stabilirea lăţimii unor celule sau unei singure coloane (aplicând metoda obiectelor
respective şi nu colecţiei).

Obiectul Column

Reprezintă o singură coloană dintr-un tabel. Este referită ca element al colecţiei Columns:

expression.Tables(index tabel).Columns(index)

Dintre proprietăţile obiectului menţionăm:

o Borders, Shading, Width sunt similare celor enumerate la colecţia Columns.


o Cells returnează colecţia de celule din coloana referită.
o Index, read only, Long, returnează numărul de ordine al coloanei în colecţia Columns.
o IsFirst, IsLast sunt True dacă este referită prima, respectiv ultima coloană din colecţie.
o Next, Previous returnează următorul element, respectiv precedentul element din colecţia Columns.

Metodele obiectului Column sunt

o AutoFit, Delete, Select, SetWidth cu explicaţii evidente sau similare metodelor sinonime prezentate
anterior.
o Sort(ExcludeHeader, SortFieldType, SortOrder, CaseSensitive, LanguageID) care ordonează celulele
coloanei. Argumentele sunt
o ExcludeHeader, opţională, este True dacă se omite din ordonare prima linie.
o SortFieldType, opţional, Variant, arată tipul de sortare – poate fi una dintre constantele WdSortFieldType:
wdSortFieldAlphanumeric (valoarea implicită), wdSortFieldDate sau wdSortFieldNumeric.
o SortOrder, opţional, Variant, specifică ordinea. Poate fi o constantă de tip WdSortOrder:
wdSortOrderAscending (implicită) sau wdSortOrderDescending.
o CaseSensitive, opţional, Variant, este True dacă se ia în considerare capitalizarea literelor. Implicit este
False.
o LanguageID, opţional, Variant, specifică limbajul de sortare. Poate fi una dintre constantele
WdLanguageID (vezi WdLanguageID Property în Word VB Help).

Colecţia Rows, Obiectul Row

Reprezintă colecţia liniilor dintr-un tabel şi, respectiv, o linie a tabelului. Utilizarea acestor obiecte este similară operării cu
obiectele Columns şi Column. Există o serie de proprietăţi specifice, linie antet, împărţirea între pagini etc, dar
corespund direct atributelor din Word şi au semnificaţii evidente.

Colecţia Cells

Reprezintă celulele dintr-o coloană, linie, selecţie sau domeniu.

Pe lângă proprietăţile similare celor prezentate la coloane (Borders, Shading, Width, Height etc.) este utilă proprietatea

o VerticalAlignment care returnează sau stabileşte alinierea verticală a textului în celule. Poate fi o
constantă de tip WdVerticalAlignment: wdAlignVerticalBottom, wdAlignVerticalCenter,
wdAlignVerticalJustify sau wdAlignVerticalTop. Read/write Long.

Metodele mai des întrebuinţate sunt

84
o Add(BeforeCell) care adaugă o nouă celulă înaintea celulei referite de BeforeCell (de tip Variant,
opţională, returnează un obiect Cell).
o Merge care produce fuzionarea tuturor celulelor din colecţie. Rezultatul este o singură celulă în tabel.
o Split(NumRows, NumColumns, MergeBeforeSplit) care produce divizarea celuleor din colecţie potrivit
valorilor argumentelor:
o NumRows, NumColumns reprezintă numărul liniilor, coloanelor după divizare. Opţionale, de tip Variant.
o MergeBeforeSplit este de tip Variant, opţional şi are valoarea True dacă se doreşte fuzionarea celulelor
înainte de divizare.
o SetHeight(RowHeight, HeightRule) stabileşte înălţimea pentru toată linia unei celule implicate.
o RowHeight este Single şi dă înălţimea în puncte.
o HeightRule este Variant, opţională şi dă regula de ajustare a celorlalte linii; poate fi una dintre constantele
de tip WdRowHeightRule wdRowHeightAtLeast (valoarea implicită), wdRowHeightAuto sau
wdRowHeightExactly.
o SetWidth(ColumnWidth, RulerStyle), cu explicaţia de la Columns.
o DistributeHeight, DistributeWidth care distribuie înălţimea, respectiv lăţimea, în mod egal.

Obiectul Cell

Reprezintă o celulă dintr-un tabel. Poate fi returnată prin metoda Cell dintr-un obiect Table sau ca element al colecţiei
Cells.

Proprietăţi de identificare sunt cele care returnează, ca obiecte sau ca index, coloana şi linia celulei:

o Column, ColumnIndex returnează ca obiect sau ca index coloana celulei.


o Row, RowIndex returnează ca obiect sau ca index linia celulei.

Proprietăţi navigare în colecţia Cells sunt

o Next, Previous cu semnificatia imediată.

Proprietăţile de aspect şi dimensiuni sunt cele prezentate la Columns/Column.

Proprietatea care dă acces la conţinutul celulei şi permite deci adăugarea de text etc. este:

o Range care returnează un obiect Range.

Metodele aplicabile unui obiect Cell sunt

o AutoSum inserează un câmp formulă care calculează suma valorilor din tabel situate deasupra sau la
stânga celulei.
o Delete(ShiftCells) elimină celula referită, ShiftCells arată cum are loc acţiunea. ShiftCells este Variant,
opţional şi poate avea o valoare dintre constantele de tip WdDeleteCells: wdDeleteCellsEntireColumn,
wdDeleteCellsEntireRow, wdDeleteCellsShiftLeft sau wdDeleteCellsShiftUp (potrivit opţiunilor uzuale de
la operarea în Word).
o Formula(Formula, NumFormat) inserează în celulă o formulă specificată şi formatează rezultatul.
Argumentele
o Formula este şirul care conţine o formulă admisă în Word De exemplu "=SUM(ABOVE)". Dacă mai sus
sau la stânga celulei sunt valori numerice, formula este opţională şi se completează potrivit alegerilor
implicite Word.
o NumFormat este de tip Variant, opţional şi specifică formatul pentru rezultat într-o formă admisă (vezi
Word VB Help –Numeric Picture (\#) field switch).
o Merge(MergeTo) produce unirea celulei curente cu celula referită, ca obiect, de MergeTo.
o Select produce selectarea celulei, deci se poate apela apoi proprietatea globală Selection.

85
o SetHeight, SetWidth stabilesc înălţimea şi lăţimea celulei potrivit descrierii de la Cells.
o Split(NumRows, NumColumns) divizează celula în numărul indicat de linii şi coloane. Valorile
neprecizate sunt considerate 1.

Exemple cu obiecte Table, Column, Row, Cell

Subiectul este foarte amplu şi pentru mai multe exemple se vor studia subiectele corespunzătoare din Word Visual Basic
Help.

If Selection.Tables.Count >=1 Then


Selection.Tables(1).ConvertToText Separator:=wdSeparateByTabs
End If

converteşte în text primul tabel din selecţie, dacă selecţia conţine tabele, separând conţinutul celulelor de pe o linie prin
caractere tab.

Set myCell = ActiveDocument.Tables(1).Cell(Row:=1, Column:=1)


Set myCell = ActiveDocument.Tables(1).Columns(1).Cells(1)

stabilesc referinţe la celula din prima linie şi prima coloană a primului tabel din documentul activ. Ambele linii se referă la
aceeaşi celulă.

i=1
For Each celula In ActiveDocument.Tables(1).Range.Cells
celula.Range.InsertBefore Text:="Celula " & i
i = i+1
Next celula

produce numerotarea celulelor din primul tabel al documentului. Este de remarcat utilizarea proprietătii Range a obiectului
Table (pentru a returna un obiect Range pentru care se returnează colecţia Cells), ca şi utilizarea proprietăţii Range a
obiectului Cell pentru inserarea de text.

ActiveDocument.Tables(1).Columns(1).Select

selectează prima coloană a primului tabel.

ActiveDocument.Tables(1).Rows(1).Shading.Texture = wdTexture10Percent

aplică o umbrire de 10% primei linii din tabel.

În continuare sunt prezentate doar unele aspecte, considerate mai des utilizate, ale operării cu alte obiecte (decât cele
prezentate în precedentele două fişiere) din modelul de obiecte al aplicaţiei Microsoft Word. Pentru informaţii mai ample
se va studia Word VB Help sau alte materiale bibliografice.

Utilizarea Obiectului HeaderFooter

Obiectul HeaderFooter poate să reprezinte fie un antet, fie un picior de pagină. Obiectul HeaderFooter este un membru
al colecţiei HeaderFooters, care este accesibilă din obiectul Section. Este important de ştiut că nu se pot adăuga
elemente la colecţia HeadersFooters. Un document Word poate să aibă anteturi/picioare de pagină pentru prima pagină,
pentru pagini pare şi pentru pagini impare şi toate acestea sunt reprezentate.

86
Se utilizează proprietăţile Headers(index) sau Footers(index), ale obiectului Section, pentru a returna un obiect
individual HeaderFooter, unde index este o constantă din tipul enumerat WdHeaderFooterIndex:
wdHeaderFooterEvenPages, wdHeaderFooterFirstPage sau wdHeaderFooterPrimary. Este însă evident, după denumiri,
că Headers se referă la anteturi iar Footers la picioare de pagină.

Următorul exemplu arată cum se poate modifica prin program un picior de pagină (de pe pagina impară):

Set oRange = ActiveDocument.Sections(1).Footers(wdHeaderFooterPrimary).Range


With oRange
.Delete
.Fields.Add Range:=oRange, Type:=wdFieldFileName, Text:="\p"
.InsertAfter Text:=vbTab
.InsertAfter Text:=vbTab
.Collapse Direction:=wdCollapseStart
.Fields.Add Range:=oRange, Type:=wdFieldAuthor
End With

Se observă definirea unui Range pentru a referi conţinutul piciorului de pagină, ştergerea vechiului conţinut, adăugarea
unui câmp cu numele fişierului (în Text se dă switch-ul \p de inserare a căii fisierului), inserarea a două caractere TAB
(pentru poziţionarea în dreapta a denumirii fişierului), comprimarea domeniului la punctul de start şi inserarea unui câmp
cu numele autorului (din informaţia adiacentă documentului).

Un obiect HeaderFooter poate fi returnat şi prin proprietatea HeaderFooter a obiectului Selection, cu menţiunea că
selecţia trebuie să fie într-un antet sau picior de pagină. Această condiţie se realizează, de exemplu, prin utilizarea
proprietăţii View, aplicată ferestrei active, care returnează un obiect View.

Proprietatea Type a obiectului View permite returnarea/stabilirea tipului de viziune (constante WdViewType, read/write,
Long): wdMasterView, wdNormalView, wdOnlineView, wdOutlineView, wdPageView sau wdPrintPreview. În modul page
layout (wdPageView), proprietatea SeekView returnează sau stabileşte care element din document este afişat (constante
WdSeekView, Read/write, Long): wdSeekCurrentPageFooter, wdSeekCurrentPageHeader, wdSeekEndnotes,
wdSeekEvenPagesFooter, wdSeekEvenPagesHeader, wdSeekFirstPageFooter, wdSeekFirstPageHeader,
wdSeekFootnotes, wdSeekMainDocument, wdSeekPrimaryFooter sau wdSeekPrimaryHeader.

Următorul exemplu inserează un număr de pagină centrat, în piciorul de pagină al paginii curente:

With ActiveWindow.View
.Type = wdPageView
.SeekView = wdSeekCurrentPageFooter
End With
Selection.HeaderFooter.PageNumbers.Add _
PageNumberAlignment:=wdAlignPageNumberCenter

Exemplul mai arată şi modul de inserare a numerelor de pagină: prin proprietatea PageNumbers se returnează colecţia
câmpurilor cu numerele de pagină incluse în respectivul antet sau picior de pagină. Proprietatea Add a colecţiei adaugă
un nou câmp număr de pagină (în mod uzual singurul element al colecţiei), referit printr-un obiect PageNumber pentru
care se pot stabili o serie de atribute, după cum altele (reînceperea numerotării, tipul de numerotare) se stabilesc la nivel
de colecţie.

În sfârşit, o serie de atribute importante pentru un document, cum ar fi tipurile de anteturi şi picioare de pagină existente,
se stabilesc din proprietăţile obiectului PageSetup, care reprezintă comanda uzuală Page Setup (Word – meniul File).

Se utilizează proprietatea DifferentFirstPageHeaderFooter a obiectului PageSetup pentru a specifica o primă pagină


diferită, proprietatea OddAndEvenPagesHeaderFooter pentru anteturi/picioare de pagină diferite pentru pagini

87
pare/impare. Dacă proprietatea OddAndEvenPagesHeaderFooter este True, atunci se returnează antetul/piciorul
paginii impare prin wdHeaderFooterPrimary şi antetul/piciorul paginii pare prin wdHeaderFooterEvenPages.

Colecţia Styles

Accesibilă din obiectul Document, prin proprietatea Styles, colecţia Styles reprezintă toate stilurile din documentul
respectiv. Identificarea unui stil particular se efectuează uzual prin

expression.Styles(index)

unde

expression returnează un obiect Document

index este nume de stil (definit de utilizator), constantă WdBuiltinStyle (nume de stil predefinit, cum ar fi
wdStyleHeading1) sau număr (indicele în colecţie). Numele trebuie dat exact, cu spaţieri dacă aşa a fost definit, cu
excepţia capitalizării.

Adăugarea unui nou stil definit de utilizator se realizează prin metoda Add, având sintaxa

expression.Add(Name, Type)

unde

expression este o expresie care returnează un obiect Styles.

Name este String şi reprezintă numele noului stil.

Type este Variant, opţional şi stabileşte tipul stilului. Poate fi una dintre constantele WdStyleType:
wdStyleTypeParagraph sau wdStyleTypeCharacter.

Obiectul Style

Reprezintă un singur stil predefinit sau definit de utilizator. Obiectul Style include atributele stilului ca proprietăţi, dintre
care enumerăm:

o Font dă acces la obiectul Font care permite formatarea caracterelor


o ParagraphFormat dă acces către formatarea paragrafului
o NextParagraphStyle stabileşte stilul pentru următorul paragraf
o BuiltIn care este True dacă stilul este un stil predefinit (built-in).

De exemplu, prin

Set aDoc = ActiveDocument.AttachedTemplate.OpenAsDocument


With aDoc
.Styles(wdStyleHeading1).Font.Name = "Arial"
.Close SaveChanges:=wdSaveChanges
End With

se deschide şablonul ataşat documentului activ ca un document Word (singurul mod în care se pot schimba stiluri într-un
template) şi se modifică proprietatea Font a stilului "Heading 1", după care se închide template-ul.

88
Colecţia CommandBars

Ansamblul meniurilor şi barelor de unelte sunt reprezentate de colecţia CommandBars. După cum se ştie din operarea
Word, la personalizarea mediului trebuie să se precizeze domeniul de valabilitate al personalizărilor: şablon, document
etc. În mod analog, înainte de a modifica programatic mediul de utilizare se va apela proprietatea globală
CustomizationContext pentru a preciza locul de memorare al modificărilor mediului.

Pentru salvarea modificărilor de comenzi în şablonul Normal se va utiliza

CustomizationContext = NormalTemplate

iar pentru salvarea în şablonul ataşat documentului

CustomizationContext = ActiveDocument.AtttachedTemplate

Exemplul următor adaugă comanda Double Underline la bara de unelte Formatting:

CustomizationContext = NormalTemplate
CommandBars ("Formatting").Controls.Add Type:=msoControlButton, ID:=60, Before:=7

Pentru o discuţie mai amplă se va citi capitolul dedicat meniurilor şi barelor de unelte.

Colecţia Dialogs

Dialogurile mediului Word (cum ar fi Open, Save As etc.) sunt activate în Visual Basic prin apelul colecţiei Dialogs. La
această colecţie nu se pot adăuga alte elemente. Există totuşi posibilitatea, discutată într-un capitol separat, de a proiecta
dialoguri utilizator.

Pentru accesarea unui dialog, se utilizează Dialogs(index), unde index este o constantă de tip WdWordDialog, care
identifică boxa de dialog necesară. Se returnează astfel un obiect Dialog care poate fi exploatat prin proprietăţile şi
metodele sale. Exemplul următor afişează dialogul Open:

dlgAnswer = Dialogs(wdDialogFileOpen).Show

Denumirile sunt construite, în general, prin "wdDialog" & "nume meniu" & "nume comandă", de exemplu wdDialog & File
& PageSetup => wdDialogFilePageSetup. O parcurgere a elementelor tipului enumerat WdWordDialog, prin intermediul
Object Browser-ului, este edificatoare.

Pentru informaţii mai ample se vor studia articolele din Word Visual Basic Help – "Displaying built-in Word dialog boxes",
"Built-in dialog box argument lists".

Dintre proprietăţile şi metodele unui obiect Dialog menţionăm:

o Type, proprietatea care returnează tipul boxei built-in. Poate fi una dintre constantele WdWordDialog.
Read-only, Long.
o DefaultTab, proprietatea care returnează sau stabileşte fişa activă la afişarea dialogului. Poate fi o
constantă de tip WdWordDialogTab. Read/write, Long.
o Display, metoda care afişează dialogul, fără a transmite acţiunile efectuate de utilizator asupra
dialogului.
o Show, metoda care afişează dialogul, acţiunile utilizator fiind transmise sau executate.
o Execute, metoda care aplică configurarea curentă a opţiunilor dintr-un dialog.

89
Adăugarea şi editarea câmpurilor dintr-un document

Se pot adăuga câmpuri la un document prin aplicarea metodei Add colecţiei Fields.

expression.Add(Range, Type, Text, PreserveFormatting)

unde

expression este o expresie care returnează un obiect Fields.

Range este o expresie care returnează un Range. Este domeniul unde se adaugă câmpul. Dacă
domeniul nu este redus la punctul de inserţie, câmpul înlocuieşte domeniul.

Type este de tip Variant, opţional. Stabileşte câmpul care se inserează. Poate fi o constantă de tip
WdFieldType (vezi Help).

Text este de tip Variant, opţional. Text adiţional necesar specificării câmpului (de exemplu informaţii de
gen switch).

PreserveFormatting este de tip Variant, opţional. Are valoarea True pentru a păstra formatarea câmpului
şi la actualizări.

Dintre proprietăţile obiectului Field, membru al colecţiei Fields, menţionăm

o Result, care returnează un obiect Range reprezentând rezultatul câmpului.


o Code, care returnează un obiect Range reprezentând codul câmpului.
o Next, care returnează următorul câmp în colecţie.
o Previous, care returnează câmpul precedent din colecţie.

Dintre metode amintim

o DoClick, echivalent cu acţionarea câmpului de către mouse.


o Update, care produce actualizarea rezultatului (recalcularea).

Exemplul următor schimbă codul primului câmp din selecţie, actualizează câmpul şi afişează rezultatul:

If Selection.Fields.Count >=1 Then


With Selection.Fields(1)
.Code.Text = "CREATEDATE \*MERGEFORMAT"
.Update
MsgBox .Result.Text
End With
End If

Observaţie. Pentru alte obiecte, cum ar fi Shapes, care reprezintă obiectele dintr-un strat de desen
(drawing layer), se vor vedea capitolele dedicate obiectelor comune tuturor aplicaţiilor Office.

Verificarea dacă un obiect este valid

În această secţiune se discută câteva tehnici pentru verificarea validităţii unei valori returnate de o expresie sau care este
memorată într-o variabilă. Aceste verificări pot elimina erori în execuţia codului proiectat.

90
Se poate utiliza funcţia TypeName pentru a determina un tip de obiect. Sintaxa este

TypeName(varname)

unde varname este un Variant care conţine orice variabilă cu excepţia variabilelor de un tip definit de utilizator.

În exemplul următor se afişează un mesaj în bara de stare a aplicaţiei în cazul cănd Selection.NextField returnează un
obiect Field (informaţie utilă în prelucrarea formularelor):

If TypeName(Selection.NextField) = "Field" Then StatusBar = "Mai există un câmp"

O formă echivalentă este

Set myField = Selection.NextField


If TypeName(myField) = "Field" Then StatusBar = "Mai există un câmp"

În cazul când nu s-ar fi returnat un obiect, valoarea funcţiei era Nothing:

If Not (myField Is Nothing) Then myField.Update

Este disponibilă proprietatea globală IsObjectValid prin care se determină dacă obiectul referit de o variabilă este un
obiect valid. Această proprietate returnează False dacă obiectul referit a fost şters (nu există). Utilizarea este

expression.IsObjectValid(Object)

unde

expression este o expresie care returnează un obiect Application, opţională.

Object este de tip Object, o variabilă care se referă la un obiect.

Exemplul următor efectuează o trecere prin toate paragrafele, le numără şi compară cu proprietatea Count (o verificare
de dragul exemplificării):

Dim i As Integer
i=1
Do While IsObjectValid(ActiveDocument.Paragraphs(i).Next)
i=i+1
Loop
MsgBox Str(i) & " paragrafe = (?) " & Str(ActiveDocument.Paragraphs.Count)

Modificarea comenzilor Word

Majoritatea comenzilor Word pot fi modificate prin transformarea lor în macro-uri.

Pentru afişarea listei cu toate comenzile Word disponibile, se urmează secvenţa de comenzi, iniţiată din Word:

o Tools
o Macro
o selecteaza Word commands în lista Macro in

91
o în boxa Macro name se afişează toate comenzile, denumirile având ca primă aprte numele meniului
utilizat implicit pentru comandă (de genul FileOpen).

Se poate înlocui o comandă Word printr-un macro, dacă se scrie o procedură macro (reamintim că o procedură fără
argumente este recunoscută ca un macro) cu acelaşi nume ca şi comanda. Dacă se creează o procedură cu numele
FileSave, aceasta este executată de către Word atunci când se dă comanda Save (meniul File), sau se click-ează
butonul Save (de pe bara Standard) sau se tastează combinaţia directă asociată cu FileSave.

Pentru scrierea unei proceduri de acest gen se poate urma

o Tools => Macro => Macros => Word commands în Macro in


o selectarea comenzii care se înlocuieşte
o selectarea locului de memorare în boxa Macro in. De exemplu Normal.dot pentru valabilitate generală
(obţinerea unui macro global).
o Create

Editorul Visual Basic deschide un modul care conţine un şablon al noii proceduri, cum ar fi

Sub FileSaveHtml()
'
' FileSaveHtml Macro
' Save file as HTML document
'
WordBasic.FileSaveHtml

End Sub

în care se pot completa/şterge orice instrucţiuni.

Pentru a reveni la comanda Word iniţială este suficient să se elimine sau să se redenumească procedura cu numele
comenzii.

Se poate înlocui, de asemenea, o comandă Word dacă se creează un modul de cod având acelaşi nume cu comanda
(de exemplu FileSave) şi care conţine o procedură denumită "Main".

Lucrul cu evenimente

Un eveniment este o acţiune recunoscută de un obiect şi pentru care se poate scrie cod care să se execute, ca răspuns
la producerea evenimentului. Evenimentele pot să se producă atât ca rezultat al acţiunii utilizatorului sau prin program,
cât şi prin declanşarea de către sistem.

În Microsoft Word sunt recunoscute mai multe categorii de evenimente: asociate unui document, asociate aplicaţiei şi
asociate controalelor ActiveX.

Evenimente ale obiectului Document

Trei evenimente sunt recunoscute de obiectul Document: Close, New şi Open.

o Close se produce atunci când se închide documentul. Dacă procedura de răspuns este memorată într-un
template, se execută atât la închiderea oricărui document bazat pe şablon, cât şi la închiderea şablonului
dacă este deschis pentru editare.

92
o New se produce la crearea unui nou document bazat pe şablon (codul de răspuns este memorat în
şablon, nu în document). O procedură de răspuns la New, memorată în document, nu se va executa
niciodată.
o Open se produce la deschiderea documentului. Vezi şi observaţia legată de şablon de la Close.

Procedurile de răspuns la aceste evenimente se scriu în modulul clasă intitulat "ThisDocument". Pentru a crea o
procedură se urmează etapele:

1. În Project Explorer, sub proiectul Normal sau document, se dublu clickează ThisDocument. (În viziunea Folder,
ThisDocument este localizat în folderul Microsoft Word Objects.)
2. În lista Object se selectează Document.
3. În lista Procedure se selectează evenimentul dorit (Close, New sau Open). Ca rezultat se adaugă în modul o
procedură vidă, denumită standard.
4. Se completează procedura cu instrucţiunile necesare scopului urmărit.

Următorul exemplu maximizează fereastra aplicaţiei Word atunci când documentul este deschis:

Private Sub Document_Open()


Application.WindowState = wdWindowStateMaximize
End Sub

Domeniul de valabilitate (vizibilitate) a unei proceduri eveniment depinde de locul memorării (de revăzut completările date
la enumerarea evenimentelor).

Procedurile eveniment din template-ul Normal nu au un domeniu global. Ele se vor executa doar dacă şablonul Normal
este şi şablonul ataşat documnetului.

Procedurile care există şi în document şi în template-ul ataşat se vor executa amândouă.

Evenimente ale obiectului Application

Evenimentele aplicaţiei apar atunci când utilizatorul părăseşte aplicaţia sau atunci când focalizarea este mutată pe alt
document. Totuşi, diferit faţă de obiectul Document sau de controalele ActiveX, obiectul Application nu recunoaşte
evenimentele în mod implicit (nu răspunde în mod standard la producerea lor). Din acest motiv, înainte de a utiliza
evenimentele obiectului Application, se va crea un modul clasă nou şi se declară un obiect de tip Application cu
evenimente. Se utilizează, în acest scop, comanda Class Module din meniul Insert al mediului VBE.

Observaţie. Denumirile utilizate în continuarea acestei secţiuni nu sunt standard, cu excepţiile evidente.

Pentru a permite evenimentele obiectului Application, se va adăuga modulului clasă definit o declaraţie de tipul

Public WithEvents App As Application

După ce noul obiect a fost declarat cu evenimente, el apare în lista Object a modulului clasă şi se pot scrie procedurile
eveniment pentru noul obiect (selectabile din lista Procedure).

Înainte ca procedurile să se execute, trebuie să se conecteze obiectul declarat în modulul clasă cu obiectul Application.
Acest lucru se poate efectua din orice modul utilizând, de exemplu, declaraţia

Public apl As New EventClass

93
unde EventClass este numele modulului clasă creat.

După crearea variabilei obiect apl (o instanţă a clasei EventClass), se poate stabili egalitatea între obiectul App al clasei
EventClass şi obiectul Application Word prin

Sub InitializeApp()
Set apl.App = Application
End Sub

După executarea procedurii InitializeApp, obiectul App din clasa EventClass punctează către obiectul Application Word
şi procedurile evenimentelor din clasă se vor executa la apariţia evenimentelor corespunzătoare.

Există două evenimente recunoscute de obiectul Application (după permiterea lor, ca mai sus):

o DocumentChange, care se produce la crearea unui nou document, la deschiderea unui document, sau
la activarea unui alt document (mutarea focalizării).
o Quit, care are loc la părăsirea aplicaţiei Word de către utilizator.

Următorul exemplu asigură că barele de unelte Standard şi Formatting sunt vizibile înainte de părăsirea aplicaţiei (încât
următoarea activare a aplicaţiei le afişează):

Private Sub App_Quit ()


CommandBars("Standard").Visible = True
CommandBars("Formatting").Visible = True
End Sub

Evenimentele controalelor ActiveX

Un document Word poate să includă controale ActiveX cum ar fi boxe de control, liste ascunse, butoane de comandă.
Pentru a scufunda un asemenea obiect într-un document, cel mai simplu este să se vizualizeze cutia de unelte pentru
controale prin

o acţionare buton dreapta mouse pe o bară de unelte


o selectare Control Toolbox

sau

o meniul View => Toolbars => selectare Control Toolbox.

Din cutia de controale se apasă categoria de controale dorită şi la punctul de inserţie se inserează o instanţă a obiectului.
Dublu click pe obiectul inserat dă acces la rutinele de procesare a evenimentelor asociate controlului. Pentru a vedea
execuţia procedurilor se va acţiona unealta Exit Design Mode din Control Toolbox.

Word implementează, pentru controalele ActiveX dintr-un document, evenimentele

o LostFocus, care apare atunci când focalizarea este mutată de la control la alt obiect,
o GotFocus, care apare atunci când focalizarea este mutată pe controlul ActiveX scufundat.

Fiecare control ActiveX recunoaşte, totuşi, evenimente adiţionale, explicate la obiectele respective. În acest curs mai
multe explicaţii şi exemple sunt date în capitolul "Controale ActiveX şi dialoguri".

Utilizarea macro-urilor automate (Auto Macro)


94
Anumite proceduri macro, identificate prin denumirile speciale recunoscute ca atare de aplicaţie, sunt executate în mod
automat la efectuarea unei operaţii specifice. Word recunoaşte următoarele denumiri drept macro-uri automate:

AutoExec care se execută la pornirea aplicaţiei Word sau se încarcă un template global.

AutoNew care se execută la fiecare creare a unui document nou.

AutoOpen care se execută la deschiderea unui document existent.

AutoClose care se execută la închiderea unui document.

AutoExit care se execută la închiderea aplicaţiei Word sau la descărcarea unui şablon global.

Macrourile automate sunt recunoscute dacă

o Modulul este bnumit cu numele macro-ului şi conţine o procedură denumită "Main."


o O procedură, în orice modul, are o denumire rezervată.

Macrourile automate pot fi memorate oriunde, template-ul Normal, alt şablon sau în document, cu excepţia procedurii
AutoExec care nu se execută dacă nu este memorată în Normal template sau un template global memorat în folderul
Startup.

În cazuri de conflict de denumiri, se execută macro-ul automat memorat în contextul cel mai apropiat, adică în ordinea:
document…attached template…Normal template.

Observaţie. Apăsarea tastei Shift simultan cu comanda previne executarea unui macro automat. De exemplu, la crearea
unui nou document pe baza unui template care are o procedură AutoNew, apăsarea tastei Shift în momentul acţionării
butonului OK din dialogul New, previne executarea macr-ului (tasta trebuie păstrată apăsată până când se afişează noul
document).

Într-o procedură care poate declanşa un macro automat, prevenirea execuţiei se ia prin instrucţiunea

WordBasic.DisableAutoMacros

Automatizarea aplicaţiilor

Pentru a putea schimba date cu alte aplicaţii, cum ar fi Excel, Access etc., se utilizează tehnica de automatizare a
aplicaţiilor (cunoscută anterior drept OLE Automation). Automatizarea permite returnarea, editarea şi exportul datelor
prin referirea obiectelor, proprietăţilor, metodelor altor aplicaţii. Obiectele aplicaţii referite în altă aplicaţie sunt denumite
obiecte de automatizare.

Automatizarea aplicaţiei Word din altă aplicaţie

A. Primul pas pentru a face aplicaţia Word disponibilă în altă aplicaţie, pentru automatizare (deci pentru manevrarea
programatică sau nu a obiectelor Word), este crearea unei referinţe la biblioteca de tipuri Word (Word type library):

o Tools (din Visual Basic Editor)


o References
o selectarea boxei de control Microsoft Word 8.0 Object Library.

B. Se declară o variabilă obiect care va referi un obiect Application Word, după exemplul

95
Dim appWD As Word.Application.8

C. Se apelează funcţia CreateObject (pentru crearea unui obiect de automatizare) sau GetObject (pentru regăsirea unui
obiect de automatizare existent) cu Word OLE Programmatic Identifier (Word.Application.8 sau Word.Document.8), ca în
exemplul următor. Pentru a vedea sesiunea Word se utilizează proprietatea Visible:

Dim appWD As Word.Application.8


Set appWD = CreateObject("Word.Application.8")
appWD.Visible = True

Funcţia CreateObject returnează un obiect Application Word şi-l asignează variabilei appWD. Utilizând obiectele,
proprietăţile şi metodele obiectului Application Word se poate controla aplicaţia Word prin intermediul variabilei appWD.
De exemplu, crearea unui nou document

appWD.Documents.Add

D. Funcţia CreateObject porneşte o sesiune Word pe care automatizarea nu o închide atunci când expiră variabila obiect
care se referă la obiectul Application Word. Nici stabilirea referinţei obiectului la Nothing nu produce închiderea
aplicaţiei Word. Pentru aceasta se va utiliza metoda Quit a aplicaţiei Word.

Următorul exemplu, din Microsoft Excel, inserează datele din celulele A1:B10 din Sheet1 într-un document Word nou şi,
în acest document, le aranjează într-un tabel. Comentariile incluse explică etapele prelucrării.

'
'declararea variabilei obiect appWD
'
Dim appWD As Word.Application
Err.Number = 0
On Error GoTo notloaded
'
'obţinerea unui obiect Word Application, dacă este pornită o sesiune Word
'
Set appWd = GetObject(, "Word.Application.8")
notloaded:
If Err.Number = 429 Then
'
' se iniţiază o sesiune Word (nu este altă sesiune deschisă)
'
Set appWD = CreateObject("Word.Application.8")
theError = Err.Number
End If
'se vizualizează sesiunea Word
appWD.Visible = True
With appWD
'crearea unui nou document
Set myDoc = .Documents.Add
With .Selection
'
' transferul datelor din foaia Excel în documentul Word,
' pe două coloane separate prin TAB
'
For Each c In Worksheets ("Sheet1").Range("A1:B10")
.InsertAfter Text:=c.Value
Count = Count +1

96
If Count Mod 2 = 0 Then
.InsertAfter Text:=vbCr
Else
.InsertAfter Text:=vbTab
End If
Next c
'
' convertirea textului în tabel şi autoformatarea tabelului
'
.Range.ConvertToTable Separator:=wdSeparateByTabs
.Tables(1).AutoFormat Format:=wdTableFormatClassic1
End With
'
' salvarea documentului Word
'
myDoc.SaveAs FileName:="C:\Temp.doc"
End With
'
' închiderea sesiunii Word, dacă sesiunea este deschisă de acest cod
'
If theError = 429 Then appWD.Quit
'
' eliberarea variabilei appWD
'
Set appWD = Nothing

Automatizarea altei aplicaţii din Word

Pentru a controla alte aplicaţii dintr-un document Word, se va proceda în mod analog automatizării aplicaţiei Word din alte
aplicaţii (vezi secţiunea precedentă).

Cele două exemple, unul referitor la Excel, celălalt la PowerPoint, devin mai explicite după revederea exemplului anterior.

Textul selectat în documentul Word activ este trimis către o foaie de calcul Excel, în celula A1:

Dim xlObj As Excel.Application.8


If Tasks.Exists("Microsoft Excel") = True Then
Set xlObj = GetObject(, "Excel.Application.8")
Else
Set xlObj = CreateObject(, "Excel.Application.8")
End If
xl.Obj.Visible = True
If xlObj.Workbooks.Count = 0 Then xlObj.Workbooks.Add
xlObj.Worksheets("Sheet1").Range("A1").Value = Selection.Text
Set xlObj = Nothing

Exemplul următor creează o nuoă prezentare PowerPoint, completează prima boxă text cu numele documentului Word
activ şi a doua boxă text cu primul paragraf al documentului. La terminare se eliberează variabila obiect aplicaţie.

Dim pptObj As PowerPoint.Application.8


If Tasks.Exists("Microsoft PowerPoint") = True Then
Set pptObj = GetObject(, "PowerPoint.Application.8")
Else
Set pptObj = CreateObject(, "PowerPoint.Application.8")

97
End If
ppt.Obj.Visible = True
Set pptPres = pptObj.Presentations.Add
Set aSlide =pptPres.Slides.Add(ndex:=1, Layout:=ppLayoutText)
aSlide.Shapes(1).TextFrame.TextRange.Text = ActiveDocument.Name
aSlide.Shapes(2). TextFrame.TextRange.Text = _
ActiveDocument.Paragraphs(1).Range.Text
Set pptObj = Nothing

Comunicarea cu obiectele Word scufundate

Se poate utiliza proprietatea Application a oricărui obiect Word pentru a returna obiectul Word Application. Acest lucru
este util pentru returnarea obiectului Word Application dintr-un document Word scufundat în altă aplicaţie.

Următorul exemplu, executat din Excel, necesită ca Shapes(1) din foaia activă să fie un document Word scufundat
(obţinut prin Insert…Object…). Prin exemplu se modifică documentul Word.

Dim appWD As Word.Application


Set embeddedDoc = ActiveSheet.Shapes(1)
Set appWd = embeddedDoc.OLEFormat.Object.Object.Application
appWD.ActiveDocument.Range(Start:=0, End:=0).InsertBefore Text:="Textul nou"

În mod similar, exemplul următor, executat din PowerPoint, necesită ca Shapes(1) din primul slide să fie un document
Word embedded:

Dim appWD As Word.Application


Set embeddedDoc = Presentations(1).Slides(1).Shapes(1)
embeddedDoc.OLEFormat.Activate
Set appWD = embeddedDoc.OLEFormat.Object.Application
MsgBox appWd.ActiveDocument.Content.Text

Controale ActiveX şi Dialoguri

Proiectele create în Visual Basic for Applications pot fi completate cu o interfaţă utilizator evoluată, sub forma unor cutii
de dialog la nivelul celor existente deja în Microsoft Office. Performanţele şi aspectul dialogurilor utilizator sunt
îmbunătăţite prin posibilitatea de plasare a unor controale ActiveX (numite anterior controale OLE).

Un control ActiveX trebuie gândit ca un obiect căruia i se pot stabili atribute (prin proprietăţi) şi care recunoaşte
evenimente (este "viu").

Aceste controale, cu proprietăţi ajustabile, recunosc multiple evenimente. Astfel, prin scrierea procedurilor eveniment,
interfaţa cu utilizatorul proiectului poate fi personalizată şi diferenţiată corespunzător.

Controalele ActiveX pot fi plasate şi direct în documentele aplicaţiilor: documente Word, foi de calcul Excel, diapozitive
PowerPoint. Inserarea acestora este facilitată de cutia de unelte Control Toolbox, care poate fi afişată la fel cu orice altă
bară de unelte.

Aplicaţiile din Office 97 utilizează aceleaşi unelte pentru proiectarea dialogurilor, astfel încât prezentarea care urmează
este valabilă pentru toate proiectele VBA (din Word, Excel, PowerPoint şi, cu unele excepţii, pentru Access).

98
Proiectarea boxelor de dialog utilizator

Crearea unui dialog utilizator (termenul utilizator este adăugat pentru diferenţierea de dialogurile built-in, încorporate
mediului şi se referă la cel care scrie codul şi nu la cel care îl va utiliza, confuzia nefiind atât de mare încât să trebuiască
o denumire specială) necesită parcurgerea mai multor etape:

o crearea unei forme (form sau UserForm), care constituie suportul pe care sunt adăugate controalele;
o plasarea controalelor pe formă;
o stabilirea proprietăţilor pentru controale;
o scrierea procedurilor de răspuns la evenimentele formei şi controalelor plasate pe ea.

Atunci când se proiectează un dialog, în Visual Basic Editor, suntem în modul de proiectare (design mode). În acest
mod se pot edita controalele şi controalele nu reacţionează la evenimente. La execuţia boxei de dialog, deci la afişarea
dialogului exact cum va fi văzut de un utilizator, suntem în modul de execuţie (run mode). Controalele răspund
evenimentelor în modul execuţie.

Crearea unui nou dialog

Orice boxă de dialog utilizator din proiect este o formă (sau UserForm). O UserForm nouă conţine o bară de titlu şi o zonă
goală în care se pot plasa controale.

o Din meniul Insert, în Visual Basic Editor, se alege UserForm.

Este afişată o formă nouă ale cărei proprietăţi se stabilesc în fereastra Properties (vezi figurile ataşate, în figura cu forma
sunt plasate şi două controale).

Proprietăţile formei sunt clasificate în categoriile:

o aparenţă (Appearence);
o comportare (Behaviour);
o font (Font);
o Diverse (Misc);
o imagine (Picture);
o poziţie (Position);
o defilare (Scrolling).

după cum se vizualizează alegând fişa Categorized din fereastra Properties.

Proprietăţile de aparenţă se referă la culorile utilizate, la efectele vizuale de umplere etc.

Proprietăţile de comportare descriu modul de continuare a acţiunilor la părăsirea ultimului control


de pe formă (Cycle) sau accesul utilizatorului la obiect (Enabled).

Prin Font se specifică fontul utilizat implicit pe formă (poate fi modificat pentru fiecare control în parte).

În Misc se găsesc proprietăţile care stabilesc numele formei, memoria utilizată la afişare, imaginea mouse-ului etc.

În Picture se dau specificaţiile imaginii utilizate pentru pavarea formei.

În Position sunt specificaţiile de poziţie şi dimensiuni.

În Scrolling se fixează vizibilitatea şi poziţia barelor de defilare.


99
Concomitent cu afişarea formei, în Design Mode, devine vizibilă şi cutia cu controale, Toolbox, (vezi figura).

Pentru a adăuga un control pe formă, se trage controlul dorit pe formă şi se ajustează dimensiunile
în mod uzual, sau se click-ează controlul dorit, cursorul devine cursor cruce şi se întinde pe formă
cu dimensiunile dorite.

Operaţiunea de dragare din cutie pe formă poate fi efectuată şi în sens invers: tragerea unui
control, sau a unui grup de controale, de pe formă în cutie de unelte creează un template care
poate fi reutilizat.

După adăugarea controalelor pe formă, se utilizează comenzile din meniul Format sau butoanele
de pe bara de unelte UserForm din VBE pentru a ajusta alinierea şi spaţierea controalelor. Se utilizează dialogul Tab
Order (din meniul View) pentru a modifica ordinea de parcurgere a controalelor la tastări succesive de Tab (în execuţie –
run time).

VBE stabileşte proprietatea TabIndex a controloalelor pentru a determina ordinea la Tab-uri.. Dacă se doreşte ca
utilizatorul să nu aibă acces prin Tab la un control, se va stabili proprietatea TabStop la False. Pentru aceasta, se
acţionează butonul drept al mouse-ului pe control şi selectarea comenzii Properties din meniul contextual.

Scrierea procedurilor de răspuns la evenimente

Fiecare formă sau control recunoaşte un set predefinit de controale, care pot fi declanşate fie de utilizator, fie de sistem.
De exemplu, un buton de comandă recunoaşte evenimentul Click declanşat de acţionarea cu mouse-ul, iar forma
recunoaşte evenimentul Initialize care apare atunci când este iniţializată.

Pentru a scrie o procedură eveniment, se deschide fereastra Code prin dublu click pe UserForm sau pe controlul
respectiv, selectarea numelui evenimentului în boxa Procedure a ferestrei Code. Procedurile eveniment au denumiri
create într-un mod standard: numele formei sau controlului, liniuţa de subliniere şi numele evenimentului, de exemplu
Command1_Click, UserForm_Deactivate etc.

Evenimentele recunoscute de un obiect sunt listate în boxa Procedure a ferestrei Code asociate, cele care au deja
ataşate proceduri fiind scrise în bold.

La scrierea codului de răspuns la evenimente, controalele sunt numite cu denumirile existente la acel moment. Cum
aceste denumiri pot fi modificate oricând în dezvoltarea proiectului, procedurile eveniment ataşate nu se redenumesc în
mod automat. Se recomandă astfel ca denumirile să fie acordate înainte de scrierea procedurilor respective, în caz
contrar orice modificare a numelor trebuie să fie însoţită de modificările denumirilor procedurilor.

Controale

În această secţiune se explică, pe scurt, principalele controale disponibile în proiectarea dialogurilor.

Label Control

Un control Label este utilizat pentru afişarea unui text, descriptiv, cum ar fi titluri, captări, instrucţiuni de ajutor. Textul
afişat nu este şi nu poate fi legat de surse de date.

Proprietatea implicită este Caption, reprezentând textul afişat.

Evenimentul implicit este Click, declanşat la acţionarea butonului stâng mouse pe control.

100
TextBox Control

Afişează informaţie scrisă de utilizator sau primită dintr-o mulţime organizată de date.

Dacă TextBox este legată de o sursă de date, atunci modificarea informaţiei afişate produce şi modificarea informaţiei din
sursa de date (de exemplu un câmp dintr-o tabel). Informaţia afişată poate fi formatată doar unitar (acelaşi font, acelaşi
stil).

Proprietatea implicită este Value, reprezentând conţinutul boxei.

Evenimentul implicit este Change, declanşat la modificarea proprietăţii Value.

ListBox Control

Afişează o listă de valori şi permite selectarea unei sau mai multor intrări din listă.

Într-o ListBox cu o singură coloană se poate adăuga o intrare prin metoda AddItem.

Dacă ListBox este legată de o sursă de date, atunci este memorată valoarea selectată în sursă.

Controlul ListBox poate să apară ca o listă ori ca un grup de controale OptionButton sau CheckBox. Pentru această
din ultimă opţiune se va stabili proprietatea ListStyle la Option; proprietatea MultiSelect va determina atunci intrările:
Single – butoane radio, Multi sau Extended – boxe de control.

Proprietatea implicită este Value, reprezentând valoarea selectată curent (din coloana dată de proprietatea
BoundColumn).

Evenimentul implicit este Click.

ComboBox Control

Combină posibilităţile de la ListBox şi TextBox: utilizatorul poate introduce o valoare nouă (ca la TextBox), sau poate
selecta o valoare dintr-o listă (ca la ListBox). Grafic, un control ComboBox arată ca o listă ascunsă (doar o linie este
afişată).

Dacă se leagă controlul la o sursă de date (celule dintr-o foaie de calcul) va fi afişată valoarea selectată în sursă. Pentru
un control cu mai multe coloane, proprietatea BoundColumn determină unde se afişează sursa de date.

Proprietatea implicită este Value, reprezentând valoarea selectată.

Evenimentul implicit este Change.

CheckBox Control

Afişează starea selectat / neselectat a unui element. Este utilizat pentru alegeri între două alternative (Yes/No, True/False
sau On/Off.).

Selectarea este afişată prin prezenţa unui X în caseta corespunzătoare şi starea curentă este Da, Adevărat, Prezent etc.
Neselectarea este arătată printr-o casetă vidă şi indică starea Nu, Fals, Absent etc. În funcţie de valoarea proprietăţii
TripleState, controlul poate să aibă şi valoarea Null.

101
La legarea de o sursă de date, schimbarea stării se reflectă în modificarea valorii sursei. Un CheckBox suspendat
(disabled) afişează starea dar nu poate fi modificat.

Proprietatea implicită este Value, , adică Null – starea null (nici selectat nici deselectat), (–1) – True (selectat), 0 – False
(deselectat).

Evenimentul implicit este Click.

OptionButton Control

Permite afişarea elementului selectat dintr-un grup de opţiuni. Controlul este cunoscut şi ca
buton radio (apăsarea unui buton de selectare a unei game de lungimi de undă le
deselectează pe celelalte). Este de observat că butoanele de opţiune dintr-un frame sunt
mutual exclusive. Figura este capturată din modul Design.

Dacă un OptionButton este legat la o sursă de date, controlul poate să arate valori Yes/No,
True/False sau On/Off, corespondenţele între valori şi starea controlului fiind evidente. Schimbarea stării butonului
modifică şi sursa.

Un control inhibat este desenat şters şi nu arată nici o valoare. În funcţie de proprietatea TripleState, controlul poate
avea şi valoarea Null.

ToggleButton Control

Arată starea de selectare a unui element (similar unui checkbox) prin imaginea grafică a unui buton
apăsat sau nu.

Dacă un control ToggleButton este legat de o sursă de date, controlul arată valoarea curentă a sursei ca Yers/No,
True/False, On/Off sau ceva similar. Butonul apăsat reprezintă Yes, True sau On. Dacă ToggleButton este legat de o
sursă de date, schombarea stării controlului se reflectă şi în valoarea sursei.

Un control ToggleButton inhibat (disabled) este desenat neclar, arată totuşi valoarea dar nu poate fi modificat.

Proprietatea implicită este Value, adică Null – starea null (nici selectat nici deselectat), (–1) – True (selectat), 0 – False
(deselectat).

Evenimentul implicit este Click.

CommandButton Control

Este utilizat pentru indicarea începerii, terminării sau întreruperii unei acţiuni. Este reprezentat grafic precum butoanele
uzuale OK, Cancel etc. din dialogurile aplicaţiilor din Office (şi nu numai).

În general, pentru realizarea scopului este utilizată procedura (sau macro) asociat evenimentului Click. Pe un
CommandButton se poate afişa text (proprietatea Caption), imagine (proprietatea Picture) sau ambele.

Proprietatea implicită este Value, întotdeauna False. Stabilind proprietatea Value drept True (într-o procedură), iniţiază
evenimentul Click al butonului de comandă.

Evenimentul implicit este Click.

102
TabStrip Control

Este utilizat, de obicei, pentru prezentarea unor seturi de informaţii (ca valori ale unor controale
grafice), fiecare grup de informaţii aparţinând altei entităţi. Prin urmare structura informaţiei
afişate este întotdeauna aceeaşi, dar se referă la entităţi diferite (persoane, fapte etc.).

Din punct de vedere grafic, se poate confunda acest control cu MultiPage, diferenţa fiind
aceea că la TabStrip zona de afişare (client region) este comună tuturor fişelor (doar informaţia se modifică), pe când la
MultiPage fiecare fişă (pagină) are o zonă proprie, cu controale proprii.

Se poate spune că dacă se păstrează structura informaţiei, atunci se va utiliza un control TabStrip, un tab definind
purtătorul informaţiilor. Dacă informaţia este structurată în categorii, atunci se poate utiliza controlul MultiPage, fiecare
categorie având propria zonă client.

Observaţie. TabStrip este implementat ca un container a unei colecţii Tabs de obiecte Tab.

Proprietatea implicită pentru TabStrip este SelectedItem, care returnează obiectul Tab selectat şi este folosit la
controlarea programatică a obiectului.

Evenimentul implicit este Change, declanşat la selectarea altui Tab.

MultiPage Control

Prezintă mai multe pagini de informaţii distincte. Spre deosebire de controlul TabStrip, selectarea
altei pagini poate prezenta o altă structură de informaţii.

În acest mod se pot afişa seturi consistente (categorii) de informaţii, păstrând în acelaşi timp
unitatea întregii înregistrării.

Observaţie. MultiPage este implementat ca un container a unei colecţii Pages de obiecte Page.

Proprietatea implicită este Value, care returnează indexul paginii avtive curente (în colecţia Pages).

Evenimentul implicit este Change, declanşat la schimbarea paginii.

Frame Control

Reprezentat grafic ca un chenar cu o denumire, controlul serveşte la gruparea unor controale. Grupul poate fi unit doar
prin categoria de informaţii, permiţând utilizatorului o identificare rapidă a controalelor, dar, pentru anumite controale cum
ar fi OptionButton, gruparea are efect şi în comportarea controalelor din grup. Exemplul de la OptionButton arată un
Frame care include butoane radio: acestea sunt mutual exclusive. Exemplul de la ToggleButton arată un Frame similar,
dar butoanele pot fi acţionate în orice configuraţie.

Evenimentul implicit este Click.

Image Control

Permite afişarea unui imagini (poze) pe o formă, ca element al datelor reprezentate pe formă şi nu ca un simplu element
decorativ. De exemplu fotografia unui angajat în forma cu informaţiile personale ale angajatului. Cu alte cuvinte, nu se
controlează aspectul grafic al imaginii, ci modul cum ea apare în control (de unde, cât de mare etc.).

103
Controlul permite tăierea (retezarea) imaginii, dimensionare, măriri, dar nu permite editarea propriu-zisă (care va fi
efectuată printr-un program de grafică).

Dacă se dă controlului o dimensiune egală cu cea a formei, atunci Image poate furniza un fundal pe care se pot poziţiona
alte controale.

Sunt suportate formatele .bmp, .cur, .gif, .ico, .jpg, .wmf de fişiere grafice.

Evenimentul implicit este Click.

Utilizarea dialogurilor utilizator

Pentru a schimba informaţii cu utilizatorul proiectului printr-o cutie de dialog utilizator, trebuie ca

o dialogul să fie afişat,


o să se accepte acţiunile utilizatorului asupra controalelor din dialog şi, la închiderea dialogului,
o să se dispună de informaţia introdusă de utilizator (pentru a fi procesată, pentru a controla acţiunile
ulterioare etc.).

Afişarea unui dialog

Afişarea unui dialog pentru testare, deci în Design Mode, se realizează prin comanda Run Sub/UserForm (meniul Run
din VBE). Afişarea dialogului în mod programatic se realizează utilizând metoda Show după modelul

[object.]Show

dacă object nu este specificat, atunci se va considera implicit dialogul asociat modulului activ UserForm.

Dacă obiectul specificat nu este încărcat la apelarea metodei, atunci VB îl încarcă automat. O cutie de dialog utilizator
este întotdeauna modală, deci utilizatorul trebuie să răspundă (chiar dacă prin închidere) înainte de a utiliza altceva din
aplicaţie. Nu se execută alte instrucţiuni până când dialogul nu este ascuns sau închis (descărcat – unloaded). Este
posibil totuşi să se lucreze în alte aplicaţii.

Obţinerea şi stabilirea proprietăţilor în execuţie

Pentru modificări ale proprietăţilor unui control este necesar ca valorile acestora să fie citite şi redefinite în timpul
execuţiei (Run time sau Run Mode).

Asemenea acţiuni sunt, de exemplu, utile atunci când pentru un control se dau valori implicite (default), deci valori cu care
dialogul să se afişeze indiferent de acţiunile de la alte afişări anterioare. În acest caz, se va adăuga codul corespunzător
în procedura de eveniment Initialize a dialogului. Afişarea formei declanşează evenimentul Initialize şi astfel au loc şi
atribuirile de valori specificate.

Exemplul următor presupune existenţa unei forme UserForm, denumită frmPhoneOrders, care are

o un control TextBox, denumit txtCustomerName,


o un control ListBox, denumit lstRegions,
o un control CheckBox, denumit chkSendExpress.

Codul următor realizează iniţializarea valorilor de pe formă, încât orice arătare a formei se realizează în aceeaşi
configuraţie:

104
Private Sub UserForm_Initialize()
With frmPhoneOrders
.txtCustomerName.Text = "Mamma S.R.L." 'se iniţializează TextBox
.chkSendExpress.Value = True 'se iniţializează CheckBox
With .lstRegions
.AddItem "Iasi" 'se iniţializează ListBox
.AddItem "Suceava"
.AddItem "Botosani"
.ListIndex = 2 'se selectează ultima intrare
End With
End With
End Sub

Este de remarcat că deşi în modelele de obiecte Word, Excel şi PowerPoint colecţiile sunt indexate de la 1, în tablourile şi
colecţiile asociate formelor se foloseşte indexarea de la 0. De aici selectarea ultimei intrări (cu numărul de ordine 3) din
listă prin instrucţiunea ListIndex = 2.

Dacă se doreşte stabilirea valorilor iniţiale pentru un control, dar apelurile ulterioare să reţină modificările efectuate, se vor
da aceste valori înainte afişării dialogului. Următorul exemplu arată o procedură care afişează forma după atribuirea
valorilor implicite.

Private Sub GetUserName( )


With UserForm1
.lstRegions.AddItem "North"
.lstRegions.AddItem "South"
.lstRegions.AddItem "East"
.lstRegions.AddItem "West"
.txtSalesPersonID.Text = "0000"
.Show
End With
End Sub

Prin setarea proprietăţilor unui control şi aplicarea metodelor în timpul execuţiei, se pot efectua modificări într-un dialog
utilizator care se execută, modificări apărute ca răspuns la acţiunile şi alegerile utilizatorului. De exemplu, accesibilitatea
unor controale poate fi controlată prin modificarea proprietăţii Enabled. Dacă proprietatea este setată pe False, atunci
utilizatorul nu poate accesa controlul: cum ar fi interzicerea accesului la butonul OK până când o anumită informaţie nu
este completată în dialog.

Exemplul următor arată cum accesul la un grup de butoane radio nu este permis decât dacă o CheckBox este marcată:

Private Sub CheckBox1_Change()


With Me ' Me se referă la forma curentă
If .CheckBox1.Value = True Then
.OptionButton1.Enabled = False
.OptionButton2.Enabled = False
.OptionButton3.Enabled = False
Else
.OptionButton1.Enabled = True
.OptionButton2.Enabled = True
.OptionButton3.Enabled = True
End If
End With
End Sub

105
Prin intermediul metodei SetFocus se controlează focalizarea. Un control care are focusul este cel care răspunde la
intrările din tastatură. De exemplu

Private Sub Image1_Click ()


Me.CheckBox1.SetFocus
End Sub

realizează trecerea focusului la CheckBox1 atunci când imaginea din controlul Image1 (unde este scrisă procedura
eveniment) este click-ată.

În timpul execuţiei se pot manevra şi proprietăţile/metodele formei. În acest mod se modifică dinamic aspectul formei.

Astfel, o utilizare frecventă este aceea când se modifică porţiunea afişată a formei, vizualizând (deci dând acces)
controale suplimentare, sau ascunzându-le (nu mai pot fi accesate, deşi nu sunt inhibate). În acest scop se operează cu
proprietatea Height.

Presupunem că o formă, cu un buton radio, este dimensionată în proiectare cu Height = 120 şi se adaugă un control, de
exemplu un CheckBox, la baza formei, controlul fiind poziţionat prin proprietatea Top setată la mai mult de 120 (deci în
afara zonei afişate din formă). Se adaugă următoarele proceduri eveniment:

Private Sub UserForm_Initialize ()


Me.Height = 120 'Orice afişare a formei readuce înălţimea la 120
End Sub

Private Sub OptionButton1_Click ()

With Me
.Height = 300 – .Height
'Modificarea butonului radio basculează între cele două dimensiuni ale formei
End With
End Sub

Pentru ca exemplul să funcţioneze corect se presupune că forma extinsă la 180 afişează şi boxa de control.

În exemplul următor se arată cum putem parcurge informaţii printr-un obiect TabStrip. Valoarea afişată într-o boxă text
este modificată după indexul tab-ului selectat:

Private Sub TabStrip1_Click (ByVal Index As Long)


If Index = 0 Then
Me.TextBox1.Text = "7710 Park Lane"
ElseIf Index = 1 Then
Me.TextBox1.Text = "5520 5th Avenue"
End If
End Sub

De amintit că numerotarea începe de la 0 într-o colecţie de pe o formă.

Validarea informaţiilor introduse de un utilizator este un alt subiect important în procesarea unui dialog. Pentru efectuarea
verificărilor că utilizatorul a introdus tipul corect de informaţii printr-un control, se va testa valoarea atunci când controlul
pierde focusul sau când întregul dialog este închis. Evenimentele Enter şi Exit pot fi utilizate în acest scop.

106
Enter apare imediat înainte ca un control să primească efectiv focusul de la alt control de pe aceeaşi formă. Exit apare
imediat înainte ca un control să piardă focusul în favoarea altui control de pe aceeaşi formă. Sintaxa procedurilor
eveniment respective este

Private Sub object_Enter( )

Private Sub object_Exit( ByVal Cancel As MSForms.ReturnBoolean)

unde

object este un nume valid de control care recunoaşte evenimentul

Cancel este starea evenimentului: False arată procesarea evenimentului de către control (opţiunea implicită); True arată
că evenimentul este tratat de aplicaţie şi focusul rămâne pe controlul curent.

Deoarece evenimentul Enter se declanşează înainte ca focusul să fie dat unui control, poate fi utilizat pentru afişarea
unui text explicativ, de procesare a respectivului obiect.

În scrierea procedurii pentru Exit nu trebuie uitată atribuirea valorii True argumentului pentru ca focusul să rămână pe
controlul curent.

De studiat şi metoda SetFocus prin care un anumit control de pe formă primeşte focusul.

Următorul exemplu previne utilizatorul să părăsească o zonă text în care trebuie să introducă neapărat o valoare
numerică:

Private Sub txtCustAge_Exit (ByVal Cancel As MsForms.ReturnBoolean)


If Not IsNumeric(txtCustAge.Text) Then
MsgBox "Vârsta trebuie să fie numerică"
Cancel = True
End If
End Sub

Pentru verificarea datelor înainte de închiderea dialogului, se include codul corespunzător (prin care se pot verifica
valorile mai multor controale de pe formă) în aceeaşi procedură care descarcă (închide) dialogul. Dacă există erori de
completare se va părăsi procedura, prin Exit Sub, înainte de executarea instrucţiunii Unload şi se va da focusul primului
control eronat.

Exemplul următor se execută la acţionarea butonului de comandă, denumit cmdOK, şi previne părăsirea dialogului prin
acţionarea acestui buton dacă boxa text txtCustAge nu este numerică:

Private Sub cmdOK_Click ()


If Not IsNumeric (txtCustAge.Text) Then
MsgBox "Vârsta trebuie să fie numerică"
txtCustAge.SetFocus 'Controlul reprimeşte focusul
Exit Sub 'Se părăseşte procedura
End If
custAge = txtCustAge.Text 'Se salvează valoarea controlului
Unload Me 'Se descarcă forma
End Sub

Este de menţionat că pentru trecerea valorii în alt modul de cod, variabila custAge trebuie calificată, de exemplu
ThisDocument.custAge.
107
La închiderea unui dialog, toate datele introduse de utilizator se pierd. Returnarea valorilor controalelor dintr-o formă
după ce forma a fost descărcată conduce la valorile implicite în locul celor introduse/selectate de utilizator. Din acest
motiv, informaţia necesară trebuie să fie salvată în variabile de la nivelul modul, înaintea descărcării formei. Exemplul
precedent utilizează în acest scop variabila custAge, care trebuie să fie declarată la nivel de modul prin

Public custAge As Integer

de exemplu.

Cutiile de dialog utilizator sunt afişate întotdeauna drept modale. Prin urmare utilizatorul trebuie să închidă dialogul
înainte de a se întoarce în aplicaţia principală.

Închiderea (descărcarea) formei se realizează prin instrucţiunea Unload. În mod uzual se va include în formă cel puţin un
buton de comandă prin acţionarea căruia se închide forma.

Exemplul următor inserează în documentul Word textul introdus de utilizator în boxa txtUserName şi închide forma, la
acţionarea butonului de comandă denumit cmdOK:

Private Sub cmdOK_Click ()


ActiveDocument.Content.InsertAfter txtUserName.Text
Unload UserForm1
End Sub

Pentru a utiliza aceeaşi boxă de dialog în mai multe aplicaţii (Word, Excel, PowerPoint acceptă aceleaşi dialoguri). Dacă
dialogul conţine totuşi referiri la obiecte specifice unei aplicaţii, atunci utilizarea în altă aplicaţie nu este lipsită de erori.

Pentru reutilizarea dialogurilor proiectate se exportă ca un fişier .frm care poate fi importat în alte aplicaţii:

• În VBE unde s-a proiectat forma, right-click pe UserForm din Project Explorer, click Export File.
• Se alege un nume şi Save. Se obţine un fişier nume.frm.
• În VBE unde se doreşte reutilizarea formei, right-click pe proiectul respectiv din Project Explorer, click pe Import
File.
• Selectarea numelui formei şi Open.

Utilizarea controalelor în documente Word, foi de calcul Excel sau diapozitive PowerPoint

În acelaşi mod în care controalele se adaugă unei forme, acestea pot fi adăugate unui document, foi de calcul sau slide
pentru a le transforma în obiecte interactive. De exemplu, se pot adăuga boxe text, listă, butoane radio etc. unui
document, pentru a-l transforma într-un formular online. Se pot adăuga butoane de comandă pe o foaie de calcul pentru
a executa proceduri macro uzuale etc.

Deşi modul de operare este foarte asemănător, există deosebiri precum

o adăugarea controalelor se realizează cu ajutorul cutiei de unelte Control Toolbox (şi nu Toolbox ca în
VBE). Afişarea acestei cutii se realizează din View - Toolbars - Control Toolbox.
o bascularea între Design mode şi Run mode se efectuează în Word sau Excel prin acţionarea
butoanelor Exit Design Mode şi Design Mode de pe bara Visual Basic. În PowerPoint se trece în Slide
Show pentru a fi în Run Mode şi se revine într-o viziune de editare pentru Design Mode.
o un control poate avea mulţimi diferite de evenimente într-un document, foaie sau slide în raport cu
acelaşi control de pe o formă. De exemplu, un buton de comandă dintr-o formă are evenimentul Exit, în
timp ce un buton de comandă dintr-un document nu recunoaşte acest eveniment.

108
Controale ActiveX în documente Word

La adăugarea şi operarea cu controale într-un document Word sunt importante următoarele idei:

• Controalele ActiveX se pot adăuga fie stratului (layer-ului) de text fie stratului de desen. Pentru plasarea
controlului în text, se va acţiona simultan tasta SHIFT şi click-ul pe controlul din Control Toolbox. În acest caz,
controlul se va insera ca un caracter, pentru un aspect bun trebuie să se lucreze la atributele liniei şi paragrafului.
Pentru plasarea unui control în layer-ul de desen se acţionează unealta din Control Toolbox fără a acţiona şi
tasta SHIFT. În acest caz, controlul este similar unui obiect Picture din documentul Word.
• Un control adăugat pe stratul text este un obiect InlineShapes la care se obţine acces programatic prin colecţia
InlineShapes. Un control adăugat pe stratul de desen este un obiect Shape la care se ajunge programatic prin
colecţia Shapes.
• Controalele din stratul text sunt tratate precum caracterele şi sunt poziţionate în linia de text, se mută o dată cu
textul sau cu inserarea de caractere etc.
• Controalele din Control Toolbox nu pot fi aduse prin dragare în document. La click pe un control, acesta este
inserat la punctul de inserţie (pe stratul text) sau într-o poziţie bazată pe aceasta (pe startul de desen). Inserarea
consecutivă a mai multor obiecte în aceeaşi poziţie pe stratul de desen poate să producă o stivă din care vedem
doar ultimul control plasat, de aici controalele trebuiesc duse în locuri distincte din document.
• În Design Mode, controalele ActiveX sunt vizibile doar în viziunile Page Layout sau Online Layout.
• Controalele ActiveX din stratul de desen sunt întotdeauna în Run Mode în viziunile Page Layout sau Online
Layout.
• Dacă se intenţionează ca utilizatorul să fie capabil să se mute între controalele unui formular online prin
acţionarea tastei TAB, controalele se vor plasa pe stratul text şi se va proteja forma prin click pe butonul Protect
Form de pe bara de unelte Forms.
• Dacă, la crearea unui formular online, se doreşte adăugarea de câmpuri de formular în locul controalelor ActiveX,
se va utiliza bara de unelte Forms.

Controale ActiveX în foi de calcul Excel

Se pot adăuga controale, la caiete sau foi de calcul, lângă datele pe care le controlează, astfel încât operarea în foaia de
calcul să se efectueze cât mai cursiv şi mai pe înţeles.

Următoarele afirmaţii punctează principalele aspecte ale plasării controalelor ActiveX pe o foaie de calcul Excel.

• În plus faţă de proprietăţile standard ale controalelor, se pot utiliza pentru controalele dintr-o foaie Excel
proprietăţile: BottomRightCell, LinkedCell, ListFillRange, Placement, PrintObject, TopLeftCell şi ZOrder. La
aceste proprietăţi se ajunge în mod uzual. Următorul exemplu arată cum se poate realiza, prin program, o defilare
a ferestrei active până când controlul CommandButton1 ajunge în colţul din stânga sus:

Set t = Sheet1.CommandButton1.TopLeftCell
With ActiveWindow
.ScrollRow = t.Row
.ScrollColumn = t.Column
End With

• Anumite metode şi proprietăţi din Microsoft Excel Visual Basic sunt inhibate atunci când un control ActiveX este
activat. De exemplu, metoda Sort nu poate fi utilizată când un control este activ. În acest caz se va activa în
prealabil un alt element de pe foaie, după modelul:

Private Sub CommandButton1_Click


Range("a1").Activate
Range("a1:a10").Sort Key1:=Range("a1")
CommandButton1.Activate
109
End Sub

Se observă revenirea la activarea butonului de comandă după ce s-a efectuat sortarea.

• Controalele dintr-un workbook Excel scufundat într-un document al altei aplicaţii nu vor funcţiona dacă utilizatorul
va utiliza dublu click pentru editarea caietului. Controalele vor funcţiona dacă utilizatorul va deschide caietul prin
right-click şi Open din meniul direct.
• La salvarea unui workbook Excel 97 în format Microsoft Excel 5.0/95, toată informaţia asociată cu controalele
ActiveX se pierde.
• Cuvântul cheie Me dintr-o procedură eveniment a unui control ActiveX de pe o foaie de calcul se referă la foaia
de calcul şi nu la control.

Controale ActiveX în diapozitive PowerPoint

Adăugarea controalelor ActiveX la diapozitive PowerPoint pot produce un schimb de informaţii cu utilizatorul, de exemplu
personalizări ale prezentării după opţiunile privitorului.

Principalele aspecte care trebuie urmărite sunt:

• Un control de pe un slide este întotdeauna în Design Mode, cu excepţia viziunii Slide Show.
• Pentru ca un control particular să apară pe toate diapozitivele, se va plasa pe Slide Master.
• Cuvântul cheie Me dintr-o procedură eveniment a unui control dintr-un slide, se referă la slide. Dacă evenimentul
este a unui control de pe master, atunci Me se referă la master şi nu la slide-ul afişat în momentul când s-a
declanşat evenimentul.
• Scrierea codului eveniment pentru slide-uri este similară scrierii de cod pentru controalele de pe o formă.
Exemplul următor stabileşte culoarea de fundal a diapozitivului pe care se găseşte butonul de comandă:

Private Sub cmdChangeColor_Click()


With Me
.FollowMasterBackground = Not .FollowMasterBackground
.Background.Fill.PresetGradient msoGradientHorizontal, 1, msoGradientBrass
End With
End Sub

• Se pot dota diapozitivele cu unelte de navigaţie. Dacă acestea sunt poziţionate din Master, vor fi disponibile pe
toate diapozitivele. De exemplu, adăugând la Slide Master două butoane denumite, respectiv, cmdBack şi
cmdForward, şi scriind procedurile de eveniment următoare, demonstraţia poate fi condusă acţionând
respectivele butoane.

Private Sub cmdBack_Click ()


Me.Parent.SlideShowWindow.View.Previous
End Sub
Sub cmdForward_Click ()
Me.Parent.SlideShowWindow.View.Next
End Sub

• Pentru a lucra cu toate controalele ActiveX de pe un slide anume fără a afecta celelalte forme desenate (Shapes)
de pe slide, se poate construi o colecţie ShapeRange care conţine doar controalele. Se pot aplica apoi metode şi
proprietăţi întregii colecţii sau parcurge, în mod uzual, colecţia pentru a procesa fiecare control în parte. Exemplul
următor aliniază controalele de pe primul diapozitiv din prezentarea activă şi le aranjează vertical.

With ActivePresentation.Slides(1).Shapes
numShapes = Count
110
If numShapes > 1 Then
numControls = 0
ReDim ctrlArray(1 To numShapes)
For i = 1 To numShapes
If .Item(i).Type = msoOLEControlObject Then
numControls = numControls + 1
ctrlArray(numControls) = .Item(i).Name
End If
Next
If numControls > 1 Then
ReDim Preserve ctrlArray(1 To numControls)
Set ctrlRange = .Range(ctrlArray)
ctrlRange.Distribute msoDistributeVertically, True
ctrlRange.Align msoAlignLefts, True
End If
End If
End With

Lucrul, prin program, cu controale din documentele aplicaţiilor

Accesul programatic la un control se poate obţine prin numele controlului sau prin intermediul colecţiei căreia îi aparţine.
Denumirea unui obiect este cea specificată drept valoare a proprietăţii (Name) în fereastra Properties a controlului.

Următoarele exemple prezintă principalele acţiuni care implică controale şi documente.

Stabilirea titlului (caption) unui control:

CommandButton1.Caption = "Run"

Dacă numele controlului se utilizează în afara modulului clasă asociat documentului, foii de calcul sau diapozitivului care
conţine controlul, atunci numele controlului trebuie calificat cu numele documentului respectiv:

Sheet1.CommandButton1.Caption = "Run"

Se poate accesa un control ActiveX şi prin colecţia Shapes, OLEObjects sau InlineShapes, după caz.

o Controalele adăugate la stratul de desen al unui document, foaie sau slide sunt conţinute în obiectele
Shape şi pot fi gestionate programatic prin intermediul colecţiei Shapes.
o În Excel, controalele ActiveX sunt conţinute de asemenea în obiectele OLEObject şi pot fi programate
prin colecţia OLEObjects.
o În Word, controalele ActiveX adăugate în stratul text sunt conţinute în obiectele InlineShape şi pot fi
controlate prin colecţia InlineShapes.

Pentru accesul prin intermediul colecţiilor, se utilizează numele obiectului Shape care conţine un control particular şi nu
numele din cod al controlului. În Excel şi PowerPoint, numele obiectului care conţine un control este numele de cod
implicit al controlului (cum ar fi CommandButton1). În Word, numele obiectului (de forma implicită Control 1) care conţine
un control nu este legat de numele de cod al controlului. Pentru a schimba numele de cod al unui control se selectează
controlul şi se schimbă valoarea proprietăţii (Name). Pentru a schimba numele unui obiect Shape, OLEObject sau altui
obiect care conţine un control se va schimba valoarea proprietăţii Name.

o Adăugarea unui buton de comandă la prima foaie de calcul:

Worksheets(1).OLEObjects.Add "Forms.CommandButton.1" _
111
Left:=10, Top:=10, Height:=20, Width:=100

o Instrucţiunea următoare stabileşte proprietatea Left a controlului:

Worksheets(1).OLEObjects("CommandButton1").Left = 10

o Următorul exemplu stabileşte titlul obiectului:

Worksheets(1).OLEObjects("CommandButton1").Object.Caption = "Run"

o Adăugarea unei boxe de control la documentul activ, pe stratul text:

ActiveDocument.InlineShapes.AddOLEControl ClassType:="Forms.CheckBox.1"

o Stabilirea unor atribute ale controalelor dintr-un document Word:

ActiveDocument.InlineShapes(1).Width = 200
ActiveDocument.InlineShapes(1).OLEFormat.Object.Value = True

o Adăugarea unui control ComboBox la stratul de desen:

ActiveDocument.Shapes.AddOLEControl ClassType:="Forms.ComboBox.1"

o Fixarea unor proprietăţi ale unui ComboBox de pe stratul de desen

ActiveDocument.Shapes("Control 1").Left = 100


ActiveDocument.Shapes("Control 1").OLEFormat.Object.Text = "Reed"

o Adăugarea şi modificarea unui buton de comandă la un diapozitiv:

ActivePresentation.Slides(1).Shapes.AddOLEObject Left:=100, Top:=100, _


Width:=150, Height:=50, ClassName:="Forms.CommandButton.1"
ActivePresentation.Slides(1).Shapes("CommandButton1").Left = 100
ActivePresentation.Slides(1).Shapes("CommandButton1") _
.OLEFormat.Object.Caption = "Run"

Obiectele Microsoft Excel

Visual Basic suportă un set de obiecte care corespund direct elementelor din Microsoft Excel, cele mai multe identificabile
după denumirea uzuală din mediul Excel. Astfel, obiectul Workbook reprezintă un caiet, obiectul Worksheet reprezintă o
foaie de calcul iar obiectul Range reprezintă un domeniu de celule dintr-o foaie de calcul. Fiecare element din Microsoft
Excel – caiet, foaie, diagramă, celulă etc. – poate fi reprezentat printr-un obiect în Visual Basic. Prin scrierea unor
proceduri, care controlează aceste obiecte, se pot automatiza operaţiile efectuate în Excel.

Pentru a vedea modelul de obiecte pentru Microsoft Excel, se va căuta "Microsoft Excel Objects" în Help. Pentru a vedea
fişierele de Help necesare se va urma calea: Visual Basic Editor — Help — Contents and Index — (Contents tab) —
Microsoft Excel Visual Basic Reference — Shortcut to Microsoft Excel Visual Basic Reference. Fişierele sunt
disponibile dacă la instalarea aplicaţiei s-a marcat boxa Online Help for Visual Basic.

Dintre cele peste 100 de obiecte care alcătuiesc ierarhia de obiecte Excel, vom prezenta în acest capitol doar pe cele mai
importante. Prezentarea este simplificată şi din cauză că prezentarea obiectelor Word a conturat problematica modelelor
de obiecte Office şi a fixat anumite reguli de operare cu aceste obiecte.
112
Obiectul Application

Cele mai multe proprietăţi ale obiectului Application Excel controlează atributele de vizualizare ale ferestrei aplicaţiei sau
comporatrea globală a aplicaţiei. De exemplu, valoarea proprietăţii DisplayFormulaBar este True dacă bara de formule
este vizibilă, iar valoarea proprietăţii ScreenUpdating este False dacă actualizarea ecranului este inhibată.

În plus, proprietăţile obiectului Application oferă acces la obiectele situate mai jos în ierarhie de obiecte (constituie ceea
ce s-a numit accesori). Astfel, proprietatea Windows dă acces la colecţia Windows (reprezentând toate ferestrele
deschise în aplicaţie), proprietatea Workbooks dă colecţia Workbooks a tutror caietelor deschise etc. Din această
categorie enumerăm:

o Charts, colecţia tuturor foilor de tip chart,


o Dialogs, colecţia tuturor dialogurilor predefinite în mediul Excel,
o Names, colecţia tutror numelor create în caietul activ,
o RecentFiles, colecţia fişierelor utilizate recent (după lista din meniul File),
o Sheets, colecţia tutror foilor deschise în caietul activ,
o Windows,
o Workbooks,
o Worksheets, colecţia tuturor foilor de calcul din caietul activ.

Returnarea unui obiect particular din colecţie se efectuează după procedurile generale, explicate în capitolele
introductive.

În categoria accesorilor mai pot fi încadrate proprietăţile care returnează un obiect Range: ActiveCell, Cells, Rows,
Columns, Selection (dacă este selectat un domeniu de celule).

Proprietăţile ActiveWorkbook, ActiveSheet, ActiveChart şi ActiveWindow returnează obiectele care reprezintă


elementele active corespunzătoare din Excel.

Anumite metode şi proprietăţi care se aplică obiectului Application se aplică şi unor obiecte situate mai jos în ierarhie.
Utilizarea acestor proprietăţi şi metode la nivelul Application vor modifica toate caietele, foile deschise. De exemplu,
metoda Calculate aplicată la nivelul Application produce recalcularea tuturor foilor, din toate caietele, pe când utilizată la
nivel de Workbook sau de Worksheet produce recalcularea doar a foilor locale.

Obiectul Workbook

După cum se ştie, similarul unui document din Word este în Excel caietul (workbook). Deschiderea sau închiderea unui
fişier în Excel implică deci deschiderea sau închiderea unui caiet. In Visual Basic, metodele utilizate la lucrul cu fişiere
sunt metode ale obiectului Workbook sau ale colecţiei Workbooks.

Deschiderea unui Workbook

Pentru a deschide un caiet se utilizează metoda Open. Metoda este aplicată întotdeauna colecţiei Workbooks, returnată
prin proprietatea globală cu aceeaşi denumire. Exemplul următor deschide caietul "Book1.xls" din folderul curent şi
afişează apoi valoarea din prima celulă a primei foi:

Sub OpenBook1()
Set myBook = Workbooks.Open(Filename:="Book1.xls")
MsgBox myBook.Worksheets(1).Range("A1").Value
End Sub

Este de remarcat că obiectul Workbook returnat de metodă se referă la caietul deschis, care rămâne activ.

113
Asupra utilizării utilizării sau nu a căii pe care se găseşte fişierul se vor reciti cele spuse la deschiderea documentelor
Word.

Există două foldere remarcabile pentru care se poate obţine în mod automat calea: folderul cu fişierele Excel executabile
şi folderul Library (creat automat la instalarea aplicaţiei). Obţinerea acestor căi se realizează prin proprietăţile Path şi
LibraryPath ale obiectului Application). Astfel

EXEPath = Application.Path & Application.PathSeparator


LibPath = Application.LibraryPath & Application.PathSeparator

returnează, respectiv, calea către fişierele executabile Excel şi calea către fişierele de bibliotecă. O cale returnată se
termină cu separatorul adecvat sistemului pe care se execută aplicaţia, astfel încât codul este independent de platformă
Windows sau Macintosh). Instrucţiunile

fName = LibPath & "Book1.xls"


Set myBook = Workbooks.Open(Filename:=fName)

considerate împreună cu atribuirea variabilei LibPath de mai sus, realizează deschiderea fişierului Book1.xls din folderul
Library.

Se poate lăsa utilizatorului opţiunea de a decide aupra numelui fişierului care se deschide. Acest lucru se poate realiza
prin metoda GetOpenFilename a obiectului Application. Metoda afişează cutia de dialog standard Open, dar, în loc să
deschidă fişierul selectat, returnează un şir cu numele complet calificat al fişierului. Următorul exemplu demonstrează
metoda:

Sub DemoGEtOpenFilename()
Do
fName = Application.GetOpenFilename
Loop Until fName <> False
MsgBox "Opening " & fName
Set myBook = Workbook.Open (Filename:=fName)
End Sub

Metoda GetOpenFilename

Afişează dialogul Open şi returnează numele de fişier selectat fără a deschide efectiv fişierul.

expression.GetOpenFilename(FileFilter, FilterIndex, Title, ButtonText, MultiSelect)

unde

expression este o expresie care returnează un obiect Application.

FileFilter este de tip Variant, opţional. Este un şir specificând criteriile de filtrare a fişierelor listate în dialog. Şirul constă în
perechi formate din şirul de filtrare şi din specificarea filtrului în format MS-DOS, toate elementele fiind separate prin
virgule. În partea rezervată, două filtre MS-DOS sunt separate prin ";". Exemple: "Text Files (*.txt),*.txt,Add-In Files
(*.xla),*.xla", "Visual Basic Files (*.bas; *.txt),*.bas;*.txt", implicit se consideră "All Files (*.*),*.*".

FilterIndex este de tip Variant, opţional. Specifică indexul criteriului de filtrare implicit. de la 1 la numărul de filtre specificat
în FileFilter. Implicit se consideră 1.

Title este de tip Variant, opţional. Specifică titlul boxei de dialog. Implicit este "Open".

114
ButtonText este specific pentru Macintosh.

MultiSelect este de tip Variant, opţional. Este True atunci când se pot selecta mai multe nume de fişiere, False dacă este
permisă selectarea unui singur fişier. Implicit este False. În cazul selecţiei multiple se va returna un tablou de denumiri
(chiar dacă este selectat un singur fişier).

Metoda returnează numele fişierului selectat sau numele introdus de utilizator. În cazul când utilizatorul anulează boxa
(prin Cancel), se returnează False. Metoda poate schimba atât folderul curent cât şi unitatea.

Crearea şi salvarea unui Workbook

Se creează un nou caiet prin aplicarea metodei Add la colecţia Workbooks. Valoarea returnată se va atribui (prin Set)
unei variabile obiect pentru a putea referi noul caiet în program. Noul workbook devine activ.

Metoda Add (colecţia Workbooks)

Returnează un obiect Workbook. Sintaxa

expression.Add(Template)

unde

expression este o expresie care returnează un obiect Workbooks. (Metoda se poate aplica, cu parametri specifici, tuturor
colecţiilor.)

Template este de tip Variant, opţional. Determină modul de creare a noului caiet. Dacă argumentul este un şir cu numele
(posibil cu cale) unui fişier Excel, noul caiet este deschis după modelul fişierului specificat. Argumentul poate fi o
constantă (de tipul enumerat XlWBATemplate), caz în care se va crea un caiet cu o singură foaie de tipul determinat de
constantă. Valorile posibile sunt: xlWBATChart, xlWBATExcel4IntlMacroSheet, xlWBATExcel4MacroSheet sau
xlWBATWorksheet. Dacă argumentul este omis, atunci se creează un caiet cu un număr de foi egal cu proprietatea
SheetsInNewWorkbook a obiectului Application).

Salvarea unui caiet se efectuează prin metoda SaveAs (la prima salvare) sau prin metoda Save. Există, similar metodei
GetOpenFilename, metoda GetSaveAsFilename (pentru Application).

Metoda SaveAs

are sintaxa

expression.SaveAs(Filename, FileFormat, Password, WriteResPassword, ReadOnlyRecommended, CreateBackup,


AccessMode, ConflictResolution, AddToMru, TextCodePage, TextVisualLayout)

unde

expression returnează un obiect Workbook.

Filename, opţional, Variant. Conţine numele noului fişier, poate include o cale.

FileFormat, opţional, Variant. Specifică formatul de fişier utilizat la salvare. Lista formatelor admise (cele care se pot
selecta şi la salvarea din Excel) se găseşte în Help la proprietatea FileFormat.

115
Password, opţional, Variant. Un şir unde capitalizarea este considerată (cel mult 15 caractere) care conţine parola de
protejare a fisşierului.

WriteResPassword, opţional, Variant. Un şir care conţine parola necesară pentru scrierea fişierului. Dacă la deschidere
nu se dă parola exactă, fişierul este deschis doar în citire.

ReadOnlyRecommended, opţional, Variant. Este True pentru a afişa, la deschidere, un mesaj cu recomandarea de a
deschide fişierul doar în citire.

CreateBackup, opţional, Variant. Este True dacă se creează o copie backup.

AccessMode, opţional, Variant. Conţine modul de acces la workbook. Poate fi una dintre constantele (din tipul
XlSaveAsAccessMode): xlShared (shared list), xlExclusive (exclusive mode) sau xlNoChange (nu se modifică modul de
acces). Ultima valoare este cea implicită. Argumentul este ignorat dacă se salvează xlShared fără a schimba numele
fişierului. Pentru schimbarea modului de acces se utilizează metoda ExclusiveAccess.

ConflictResolution, opţional, Variant. Specifică modul de rezolvare a conflictelor de schimbare în cazul când fişierul este
shared. Poate fi una dintre constantele (de tip XlSaveConflictResolution): xlUserResolution (afişează un dialog privind
conflictul şi rezolvarea)), xlLocalSessionChanges (acceptă automat modificările locale) sau xlOtherSessionChanges
(acceptă celelalte schimbări în locul modificărilor locale). Prima constantă este valoarea implicită.

AddToMru, opţional, Variant. Este True dacă se adaugă numele fişierului la lista fişierelor utilizate recent. Implicit este
False.

TextCodePage, TextVisualLayout, opţionale, Variant. Neutilizate în versiunea U.S. English.

Metoda Save

Salvează modificările caietului specificat.

expression.Save

unde

expression returnează un obiect Workbook.

Pentru marcarea unui fişier drept salvat fără a-l scrie efectiv pe disc, se va atribui valoarea True proprietăţii Saved.

Metoda GetSaveAsFilename

Similar metodei GetOpenFilename, această metodă afişează dialogul standard Save As, returnează un nume de fişier,
dar nu salvează nici un fişier.

expression.GetSaveAsFilename(InitialFilename, FileFilter, FilterIndex, Title, ButtonText)

unde

expression este o expresie care returnează un obiect Application.

InitialFilename, opţional, Variant. Specifică numele de fişier propus. Dacă acest nume este omis, atunci se va utiliza
numele caietului activ.

116
FileFilter, opţional, Variant. Şirul care specifică criteriul de filtrare. Pentru structura şirului se va revedea metoda
GetOpenFilename de la deschiderea documentelor.

FilterIndex, opţional, Variant. Este indicele criteriului de filtrare, de la 1 la numărul de filtre dat la FileFilter. Implicit este 1.

Title, opţional, Variant. Titlul boxei de dialog.

ButtonText este specific Macintosh.

Metoda returnează numele de fişier selectat sau cel introdus de utilizator. Numele returnat poate include şi calea. Metoda
returnează False dacă dialogul este închis de utilizator prin Cancel. Metoda poate schimba folderul sau unitatea curentă.

Următorul exemplu crează un nou caiet şi-l salvează prin metoda GetSaveAsFilename:

Sub CreateAndSave()
Set newBook = Workbooks.Add
Do
fName = Application.GetSaveAsFilename
Loop Until fName <> False
newBook.SaveAs Filename:=fName
End Sub

Închiderea unui Workbook

Pentru a închide un workbook, se va aplica metoda Close a obiectului Workbook. Închiderea poate avea loc cu sau fără
salvarea modificărilor.

Metoda Close

Produce închiderea obiectului. Aplicată colecţiei Workbooks are sintaxa

expression.Close

unde

expression returnează un obiect Workbooks. Dacă există modificări ale caietelor, se va afişa dialogul de interogare
asupra eventualei salvări.

Aplicată obiectelor Window şi Workbook metoda are sintaxa

expression.Close(SaveChanges, FileName, RouteWorkbook)

unde

expression este o expresie care returnează un obiect Workbook sau Window.

SaveChanges este opţional, Variant. Dacă nu există modificări, argumentul este ignorat. Dacă există modificări în caiet
dar caietul mai apare şi în altă fereastră deschisă, atunci argumentul este de asemenea ignorat. Dacă există modificări şi
caietul nu mai apare în altă fereastră, atunci salvarea se efectuează după valorile: True – salvarea modificărilor sub
numele dat la FileName sau dialog Save As; False – nu se salvează modificările; argument omis – interogare utilizator.

117
FileName este opţional, Variant. Salvează modificările sub acest nume.

RouteWorkbook este opţional, Variant. Dacă nu este indicată nici o rutare (nu există nici un RoutingSlip ataşat),
argumentul este ignorat. Altfel, Excel efectueazărutarea documentului după valorile acestui argument: True – trimite
caietul la următorul recipient; False – caietul nu este transmis mai departe; omis – interogarea utilizatorului asupra
trimiterii.

Închiderea unui workbook din Visual Basic nu execută macrourile Auto_Close din workbook. Se va utiliza metoda
RunAutoMacros pentru executarea macrourilor automate de închidere. Aceste macrouri sunt menţinute în Excel din
motive de compatibilitate, deci se referă la foi automatizate în versiuni Excel mai vechi.

Exemplul următor arată deschiderea unui caiet, modificări temporare ale caietului şi închiderea fără salvarea modificărilor:

Sub OpenChangeClose()
Do
fName = Application.GetOpenFilename
Loop Until fName <> False
Set myBook = Workbooks.Open (Filename:=fName)
' Aici se modifică foile de calcul
myBook.Close SaveChanges:=False
End Sub

Obiectul Range

Prin intermediul unui obiect Range se poate referi o singură celulă, un domeniu de celule, o întreagă linie sau coloană, o
selecţie cu arii multiple sau un domeniu 3-D. Din acest motiv obiectul Range este oarecum neuzual prin aceea că poate
reprezenta atât o singură celulă cât şi o mulţime de celule. Nu există un obiect colecţie pentru Range, asă că un obiect
Range poate fi gândit fie ca un obiect, fie ca o colecţie, după situaţie.

Există foarte multe proprietăţi şi metode care returnează un obiect Range:

ActiveCell DirectDependents RowFields

BottomRightCell DirectPrecedents RowRange

Cells EntireColumn Rows

ChangingCells EntireRow Selection

CircularReference Next TableRange1

Columns Offset TableRange2

CurrentArray PageRange TopLeftCell

CurrentRegion Precedents UsedRange

Dependents Range VisibleRange

Pentru specificarea exactă a acestor proprietăţi şi metode se vor căuta subiectele respective în Help.

În continuare sunt menţionate, mai mult prin exemple, moduri de lucru cu obiecte Range.

118
Referinţe de tip A1 sau nume de domeniu

Unul dintre modurile uzuale de returnare a unui obiect Range este acela al utilizării unei referinţe de tip A1 sau al unui
nume definit.

• inserarea unei valori într-o celulă:

Worksheets("Sheet1").Range("A1").Value = 3

• inserarea unei formule într-o celulă:

Range("B1").Formula = "=5–10*RAND()"

• inserarea aceleeaşi valori într-un întreg domeniu de celule:

Range("C1:E3").Value = 6

• ştergerea conţinutului unor celule:

Range("A1","E3").ClearContents

• Stabilirea stilului bold pentru un domeniu numit (la nivel de workbook):

Range("myRange").Font.Bold = True

• Atribuirea aceleeaşi valori fiecărei celule dintr-un domeniu numit (la nivel de foaie):

Range("Sheet1!yourRange").Value = 3

• Setarea unei variabile obiect la un domeniu:

Set objRange = Range("myRange")

Este de menţionat că expresiile care nu sunt calificate se referă la foaia curentă, deci multe din exemplele de mai sus nu
ar opera dacă foaia curentă este o foaie de tip chart.

O cauză frecventă de erori este utilizarea proprietăţii Range ca argument al altei metode fără calificarea completă a
obiectului Worksheet căruia i se aplică Range. Exemplul următor

Sub SortRange()
Worksheets("Sheet1").Range("A1:B10").Sort _
Key1:=Range("A1"), Order1:=xlDescending
End Sub

nu va funcţiona corect decât dacă Sheet1 este foaia activă, altminteri calificarea argumentului Key1 nu este completă.
Pentru o execuţie independentă de context ar trebui folosit

Key1:=Worksheets("Sheet1").Range("A1")

Utilizarea indicilor de linii şi coloane

119
O celulă specifică poate fi returnată utilizând indicii numerici de linie şi coloană pentru celula referită.

• Pentru a da o valoare celulei A1 se poate utiliza:

Worksheets("Sheet1").Cells(1,1).Value = 3

• Pentru a insera o formulă în celula B1 din foaia activă:

Cells(1,2).Formula = "=5–10*RAND()"

• Pentru a fixa o variabilă obiect la domeniul format din celula A1

Set objRange = Worksheets("Sheet1").Cells(1,1)

Referinţele prin indici sunt utile mai ales la parcurgerea unui bloc de celule prin instrucţiuni de ciclare. Exemplul următor
anulează toate celulele din domeniul A1:D10, cu o valoare mai mică decât 0.01:

Sub RoundToZero()
For rwIndex = 1 to 10
For colIndex = 1 to 4
If Worksheets("Sheet1").Cells(rwIndex,colIndex) < 0.01 Then
Worksheets("Sheet1").Cells(rwIndex,colIndex).Value = 0
End If
Next colIndez
Next rwIndex
End Sub

În exemplul următor se arată o soluţie la listarea, într-o foaie separată, a tuturor denumirilor create în caietul activ şi a
domeniilor referite de acestea.

Sub ListNames()
Set newSheet = Worksheets.Add
I=1
For Each nm in ActiveWorkbook.Names
NewSheet.Cells(i,1).Value = nm.Name
NewSheet.Cells(i,2).Value = "' " & nm.RefersTo
Next nm
NewSheet.Columns("A:B").AutoFit
End Sub

Utilizarea proprietăţii Offset

Atunci când este necesară referirea la un domeniu prin deplasări relative la alt domeniu de celule, se poate utiliza
proprietatea Offset, a obiectului Range, care în argumentele RowOffset şi ColumnOffset arată deplasarea faţă de
obiectul Range curent. Este returnat un nou obiect Range.

Exemplul următor determină câteva tipuri de date din celulele domeniului A1:A10, tipurile determinate fiind înscrise, ca
text, în celula corespunzătoare din dreapta, B1:B10.

Sub ScanColumn ()
For Each c In Worksheets("Sheet1").Range("A1:A10").Cells
If Application.IsText(c.Value) Then

120
c.Offset(0,1).Value = "Text"
ElseIf Application.IsNumber (c.Value) Then
c.Offset(0,1).Value = "Number"
ElseIf Application.IsLogical (c.Value) Then
c.Offset(0,1).Value = "Boolean"
ElseIf Application.IsError (c.Value) Then
c.Offset(0,1).Value = "Error"
ElseIf c.Value = "" Then
c.Offset(0,1).Value = "(blank cell)"
End If
Next c
End Sub

Utilizarea proprietăţilor CurrentRegion şi UsedRange

Aceste două proprietăţi, explicate în continuare, sunt utile atunci când nu se ştie de la început cât de mare este domeniul
pe care se operează.

Prin regiunea curentă se înţelege un domeniu dreptunghiular de celule, limitat de linii şi coloane goale, eventual de
marginile foii de calcul şi de linii şi coloane goale. Proprietatea CurrentRegion se aplică unui obiect Range şi pot fi mai
multe regiuni curente pe o foaie de calcul, după obiectul Range căruia i se aplică proprietatea. Proprietatea returnează
un obiect Range, reflectând extensia, în sensul prezentat mai sus, al obiectului Range căruia i se aplică proprietatea.

Domeniul utilizat este determinat de celule nevide situate cel mai la stânga sus şi cel mai la dreapta jos într-o foaie de
calcul. Un asemenea domeniu conţine toate celule nevide din foaie, ca şi celule vide interpuse până la completarea unui
domeniu dreptunghiular şi este unic pe o foaie de calcul. Este natural ca proprietatea UsedRange să se aplice obiectului
Worksheet şi nu unui obiect Range. Proprietatea returnează un obiect Range.

Următorul exemplu aplică celulelor cu valori numerice dintr-o listă, care începe în celula A1, formatul numeric 0.0:

Sub FormatRange ()
Set myRange = Worksheets("Sheet1").Range("A1").CurrentRegion
MyRange.NumberFormat = "0.0"
End Sub

Exemplul care urmează presupune că foaia activă conţine date dintr-un experiment desfăşurat în timp: prima coloană
conţine datele calendaristice, a doua coloană conţine ora înregistrării valorilor, coloanele a treia şi a patra conţin
măsurătorile experimentului. Procedura prezentată combină primele două coloane într-o singură valoare de tip Date,
converteşte valoarea obţinută din GMT (Greenwich Mean Time) în PST (Pacific Standard Time) şi le formatează.
Deoarece nu se ştie dacă există şi coloane goale între cele patru coloane cu date, se utilizează UsedRange.

Sub ConvertDates ()
Set myRange = ActiveSheet.UsedRange
myRange.Columns("C").Insert
Set dateCol = myRange.Columns("C")
For Each c In dateCol.Cells
If c.Offset(0,-1).Value <>"" Then
c.FormulaR1C1 = "=RC[-2]+RC[-1] - (8/24)"
End If
Next c
dateCol.NumberFormat = "mmm-dd-yyyy hh:mm"
dateCol.Copy
dateCol.PasteSpecial Paste:=xlValues
myRange.Columns("A:B").Delete
121
dateCol.AutoFit
End Sub

Există şi alte proprietăţi şi metode care produc fie subdomenii, fie supradomenii pornind de la un obiect Range. Printre
acestea enumerăm: Areas, Cells, Columns, EntireColumn, EntireRow, Range şi Rows.

Parcurgerea unui domeniu de celule

Dintre multiplele moduri de parcurgere a celulelor dintr-un domeniu, se prezintă parcurgerile prin instrucţiunile For Each
… Next şi Do … Loop, unele fiind deja utilizate în exemplele anterioare.

Utilizarea instrucţiunii For Each … Next

Acesta este modul recomandat de parcurgere a elementelor unei colecţii.

Un exemplu anterior devine

Sub RoundToZero ()
For Each r In Worksheets(Sheets1").Range("A1:D10").Cells
If Abs(r.Value) < 0.01 Then
r.Value = 0
End If
Next r
End Sub

Pentru ca operaţiunea anterioară să aibă loc pe un domeniu selectat de utilizator, se poate utiliza metoda InputBox,
specificându-i utilizatorului să selecteze un domeniu de celule. Metoda returnează un obiect Range care reprezintă
selecţia. Codul este completat cu instrucţiuni de tratare a erorilor uzuale.

Sub RoundToZero ()
Worksheets("Sheet1").Activate
On Error GoTo PressedCancel
Set r = Application.InputBox( _
Prompt:="Select a range of cells", _
Type:=8)
On Error GoTo 0
For Each c In r.Cells
If Abs(c.Value) < 0.01 Then
c.Value = 0
End If
Next c
Exit Sub

PressedCancel:
Resume
End Sub

Dacă nu se doreşte selectarea de către utilizator a domeniului procesat, se poate utiliza proprietatea CurrentRegion sau
proprietatea UsedRegion pentru a returna obiectul Range prelucrat. De exemplu, dacă se ştie că domeniul începe cu
celula A1 şi nu include linii sau coloane vide, atunci se poate utiliza

Set r = Worksheets("Sheet1").Range("A1").CurrentRegion

122
pentru a returna întregul domeniu (compact) de celule care se prelucrează.

Următoarele două exemple arată cum se poate ascunde fiecare a doua coloană din domeniul utilizat în Sheet1. Primul
exemplu, utilizând For Each…Next

Sub HideColumns ()
Set r = Worksheets("Sheet1").UsedRange
For Each col In r.Columns
If col.Column Mod 2 = 0 Then
col.Hidden = True
End If
Next col
End Sub

Al doilea exemplu, utilizând For…Next:

Sub HideColumns ()
Set r = Worksheets("Sheet1").UsedRange
For i = 1 To r.Columns.Count
If i Mod 2 = 0 Then
r.Columns(i).Hidden = True
End If
Next i
End Sub

Utilizarea instrucţiunii Do…Loop

Atunci când procesarea unui domeniu modifică domeniul (de exemplu prin ştergerea unor linii/coloane), utilizarea
instrucţiunii For Each…Next nu produce cele mai bune rezultate. Soluţia este atunci utilizarea instrucţiunii Do…Loop.
Exemplul următor sortează o listă şi elimină liniile elementelor duplicate:

Sub RemoveDuplicates ()
Worksheets("Sheet1").Range("A1").Sort _
Key1:=Worksheets("Sheet1").Range("A1")
Set currentCell = Worksheets("Sheet1").Range("A1")
Do While Not IsEmpty(currentCell)
Set nextCell = currentCell.Offset(1,0)
If nextCell.Value = currentCell.Value Then
currentCell.EntireRow.Delete
End If
Set currentCell = nextCell
Loop
End Sub

Este de notat că structura repetitivă poate fi înlocuită prin

Do While currentCell.Value <> ""


' instrucţiunile de eliminare a liniilor cheilor duplicate
Loop

Utilizarea proprietăţii Address

123
Aplicarea proprietăţii Address returnează adresa de celule a domeniului, adresa fiind sub forma de şir de caractere.
Această utilizare este utilă, în general, pentru verificare şi depanarea codului. Exemplul următor arată o formă de
completare a unei proceduri anterioare cu instrucţiuni de control a mersului programului

Sub HideColumns ()
Set r = Worksheets("Sheet1").UsedRange
MsgBox r.Address ' doar pentru depanare
For i = 1 To r.Columns.Count
If i Mod 2 = 0 Then
r.Columns(i).Hidden = True
MsgBox r.Columns(i).Address ' doar pentru depanare
End If
Next i
End Sub

Acelaşi efect se poate obţine prin stabilirea unor expresii de urmărire (watch expressions) de forma r.Address şi
r.Columns(i).Address, valorile respective pot fi examinate în fereastra Immediate. Pentru o discuţie mai pe larg se va
studia capitolul dedicat depanării şi manevrării erorilor.

Evenimentele din Excel 97

O bună parte din codul scris într-o aplicaţie este conţinut în proceduri de răspuns la evenimente. Cunoaşterea
evenimentelor şi alegerea unor răspunsuri adecvate produc o aplicaţie senzitivă, vie, care interacţionează bine cu
utilizatorul.

În Microsoft Excel 97 se pot scrie proceduri eveniment la nivelurile: worksheet, chart, workbook şi application. În plus faţă
de versiuni anterioare, sunt posibile şi proceduri eveniment cu argumente.

Procedurile de răspuns la evenimente la nivelurile Worksheet şi Workbook sunt create în mod implicit pentru orice foaie
de calcul, foaie de diagramă sau caiet. Pentru a scrie proceduri de răspuns la evenimentele de la nivelul Chart sau pentru
Application, trebuie să se creeze un nou obiect utilizând cuvântul cheie WithEvents într-un modul clasă. (vezi discuţia din
secţiunea dedicată subiectului în acest capitol).

Permiterea şi inhibarea evenimentelor

În mod uzual, toate evenimentele sunt permise. Cu alte cuvinte evenimentele au loc, sunt recunoscute ca atare şi se
execută procedurile corespunzătoare fiecărui eveniment.

În cazul când nu se doreşte executarea procedurii de răspuns, acest lucru este controlat prin inhibarea evenimentului, cu
efectul nerecunoaşterii evenimentului de către sistem şi, drept urmare, neexecutarea procedurii asociate.

Proprietatea EnableEvents, a obiectului Application, poate primi valoarea True sau False după cum evenimentele sunt
permise sau inhibate.

Următorul exemplu execută salvarea caietului fără producerea evenimentului BeforeSave:

Application.EnableEvents = False
ActiveWorkbook.Save
Application.EnableEvents = True

124
Utilizarea evenimentelor

Completarea procedurilor implicite de răspuns la evenimente se efectuează prin accesul la codul procedurilor şi scrierea
de cod în mod uzual.

Pentru a vedea procedurile de eveniment ale unei foi (de calcul sau diagramă):

o click dreapta pe cotorul foii (pe bara de jos, unde se văd cotoarele tuturor foilor din caietul activ),
comanda View Code din meniul contextual, alegerea numelui evenimentului în lista derulantă
Procedure, sau
o meniul Tools, comanda Macro şi selectarea opţiunii Visual Basic Editor. Se selectează foaia dorită în
Project Explorer, butonul View Code şi se alege numele evenimentului din lista Procedure.

Evenimentele obiectului Worksheet

Eveniment Descriere

Activate Apare atunci când utilizatorul activează foaia. Acest eveniment se va utiliza în locul
proprietăţii OnSheetActivate

BeforeDoubleClick Apare atunci când utilizatorul execută un dublu click într-o celulă a foii. Se va utiliza în
locul proprietăţii OnDoubleClick.

BeforeRightClick Apare atunci când utilizatorul execută un click dreapta într-o celulă a foii.

Calculate Apare când utilizatorul recalculează foaia. Acest eveniment se va utiliza în locul
proprietăţii OnCalculate.

Change Apare atunci când utilizatorul schimbă o formulă dintr-o celulă. Se va utiliza în locul
proprietăţii OnEntry.

Deactivate Apare atunci când foaia este activă şi utilizatorul activează o altă foaie. Nu apare atunci
când utilizatorul mută focusul de la o fereastră la altă fereastră a aceleeaşi foi. Acest
eveniment se va utiliza în locul proprietăţii OnSheetDeactivate.

SelectionChange Apare atunci când utilizatorul selectează o celulă din foaie.

O prezentare completă şi exemple se găsesc în intrările respective din Help.

Exemplu

În codul care urmează, se reajustează dimensiunea coloanelor la fiecare recalculare:

Private Sub Worksheet_Calculate ()


Columns("A:F").AutoFit
End Sub

Este de remarcat că modelul procedurii este accesat printr-una din tehnicile descrise la "Utilizarea evenimentelor".

125
Evenimentele obiectului Chart

Declanşate atunci când utilizatorul activează sau modifică o diagramă, evenimentele recunoscute de obiectul Chart sunt
prezentate în tabelul următor.

Eveniment Descriere

Activate Apare atunci când utilizatorul activează foaia diagramă (nu apare la diagramele scufundate).
Acest eveniment se va utiliza în locul proprietăţii OnSheetActivate

BeforeDoubleClick Apare atunci când utilizatorul execută un dublu click pe diagramă. Se va utiliza în locul
proprietăţii OnDoubleClick.

BeforeRightClick Apare atunci când utilizatorul execută un click dreapta pe diagramă.

Calculate Apare când utilizatorul reprezintă în diagramă date noi sau modificate.

Deactivate Apare atunci când foaia este activă şi utilizatorul activează o altă foaie. Nu apare atunci când
utilizatorul mută focusul de la o fereastră la altă fereastră a aceleeaşi foi. Acest eveniment se
va utiliza în locul proprietăţii OnSheetDeactivate.

DragOver Apare atunci când utilizatorul draghează date peste diagramă.

DragPlot Apare atunci când utilizatorul draghează un domeniu de celule peste diagramă.

MouseDown Apare atunci când utilizatorul execută un click cu un buton al mouse-ului în timp ce pointerul
acestuia este poziţionat pe diagramă.

MouseMove Apare la mişcarea pointerului mouse-ului peste diagramă.

MouseUp Apare atunci când utilizatorul eliberează un buton al mouse-ului în timp ce pointerul acestuia
este poziţionat pe diagramă.

Resize Apare la redimensionarea diagramei.

Select Apare la selectarea unui element al diagramei.

SeriesChanges Apare atunci când utilizatorul modifică valoarea unei punct de pe diagramă.

Evenimentele foilor de diagrame sunt permise în mod implicit. Pentru a scrie proceduri de eveniment pentru diagramele
scufundate, trebuie să se creeze un nou obiect utilizând WithEvents într-un modul de clasă.

Exemplu

Se schimbă culoarea chenarului unui punct atunci când utilizatorul schimbă valoarea punctului:

Private Sub Chart_SeriesChange (ByVal SeriesIndex As Long, _


ByVal PointIndex As Long)
Set p = ActiveChart.SeriesCollection(SeriesIndex).Points(PointIndex)
p.Border.ColorIndex = 3
End Sub

126
Evenimentele obiectului Workbook

Aceste evenimente se declanşează atunci când utilizatorul schimbă un caiet sau orice foaie din caietul respectiv.

Eveniment Descriere

Activate Apare atunci când utilizatorul activează caietul.

AddInInstall Apare atunci când utilizatorul instalează caietul ca un add-in. Se va utiliza în locul macro-
ului Auto_Add.

AddInUninstall Apare atunci când utilizatorul dezinstalează caietul ca un add-in. Se va utiliza în locul
macro-ului Auto_Remove.

BeforeClose Apare înaintea închiderii caietului. Se va utiliza în locul macro-ului Auto_Close.

BeforePrint Apare înaintea tipăririi caietului.

BeforeSave Apare înainte ca utilizatorul să salveze foaia. Acest eveniment se va utiliza în locul
proprietăţii OnSave.

Deactivate Apare atunci când caietul este activ şi utilizatorul activează un alt caiet.

NewSheet Apare după ce utilizatorul creează o nouă foaie.

Open Apare la deschiderea caietului. Evenimentul se va utiliza în locul macroului Auto_Open.

SheetActivate Apare la activarea unei foi din caiet. Se va utiliza în locul proprietăţii OnSheetActivate.

SheetBeforeDoubleClick Apare la dublu click pe o celulă (nu este utilizat cu foile diagramă). Se va utiliza în locul
proprietăţii OnDoubleClick.

SheetBeforeRightClick Apare la click dreapta pe o celulă a unei foi din caiet (nu este utilizat cu foile diagramă).

SheetCalculate Apare la recalcularea unei foi (nu este utilizată cu foile diagramă). Se utilizează în locul
proprietăţii OnCalculate.

SheetChange Apare la modificarea formulei dintr-o celulă (nu este utilizată cu foile diagramă). Se
utilizează în locul proprietăţii OnEntry.

SheetDeactivate Apare la activarea altei foi din caiet. Se utilizează în locul proprietăţii OnSheetDeactivate.

SheetSelectionChange Apare la modificarea selecţiei dintr-o foaie de calcul (nu funcţionează cu foile diagramă).

WindowActivate Apare atunci când utilizatorul mută focusul pe orice fereastră a caietului. Se utilizează în
locul proprietăţii OnWindow.

WindowDeactivate Apare atunci când utilizatorul mută focusul în afara oricărei fereastre a caietului. Se
utilizează în locul proprietăţii OnWindow.

WindowResize Apare atunci când utilizatorul deschide, redimensionează, maximizează sau minimizează
orice fereastră a caietului.

Pentru explicaţii se vor studia intrările corespunzătoare din Help.

127
Exemplu

Deschiderea caietului maximizează fereastra aplicaţiei Excel:

Sub Workbook_Open ()
Application.WindowState = xlMaximized
End Sub

Evenimentele obiectului Application

Aceste evenimente se declanşează la crearea/deschiderea unui caiet sau atunci când este modificată orice foaie din
orice caiet deschis.

Eveniment Descriere
(pentru Application)

NewWorkbook Apare la crearea unui nou caiet.

SheetActivate Apare atunci când utilizatorul activează o foaie dintr-un caiet deschis. Se va utiliza în locul
proprietăţii OnSheetActivate.

SheetBeforeDoubleClick Apare la dublu click pe o celulă dintr-un caiet deschis (nu este utilizat cu foile diagramă). Se
va utiliza în locul proprietăţii OnDoubleClick.

SheetBeforeRightClick Apare la click dreapta pe o celulă a unei foi dintr-un caiet deschis (nu este utilizat cu foile
diagramă).

SheetCalculate Apare la recalcularea unei foi (nu este utilizată cu foile diagramă). Se utilizează în locul
proprietăţii OnCalculate.

SheetChange Apare la modificarea formulei dintr-o celulă (nu este utilizată cu foile diagramă). Se utilizează
în locul proprietăţii OnEntry.

SheetDeactivate Apare la activarea altei foi dintr-un caiet. Se utilizează în locul proprietăţii
OnSheetDeactivate.

SheetSelectionChange Apare la modificarea selecţiei dintr-o foaie de calcul (nu funcţionează cu foile diagramă).

WindowActivate Apare atunci când utilizatorul mută focusul pe orice fereastră deschisă în aplicaţie. Se
utilizează în locul proprietăţii OnWindow.

WindowDeactivate Apare atunci când utilizatorul mută focusul în afara oricărei fereastre a aplicaţiei. Se
utilizează în locul proprietăţii OnWindow.

WindowResize Apare atunci când utilizatorul redimensionează, maximizează sau minimizează orice
fereastră deschisă în aplicaţie.

WorkbookActivate Apare atunci când se mută focusul pe un caiet deschis

WorkbookAddInInstall Apare la instalarea unui workbook ca un add-in.

WorkbookAddInUninstall Apare la dezinstalarea unui workbook ca un add-in.

WorkbookBeforeClose Apare înainte ca un caiet deschis să fie închis.

128
WorkbookBeforePrint Apare înainte ca un caiet deschis să fie tipărit.

WorkbookBeforeSave Apare înainte ca un caiet deschis să fie salvat.

WorkbookDeactivate Apare atunci când utilizatorul mută focusul în afara unui caiet deschis.

WorkbookNewSheet Apare la adăugarea unei noi foi la un caiet deschis.

WorkbookOpen Apare atunci când utilizatorul deschide un caiet.

Utilizarea modulelor clasă cu evenimente

Deoarece diagramele scufundate într-o foaie de calcul şi obiectul Application nu au evenimente permise în mod implicit,
trebuie să se urmeze următoarele etape pentru a utiliza evenimentele recunoscute de aceste obiecte.

• Se creează un modul de tip clasă şi se declară un obiect de tip Chart sau Application cu evenimente. Pentru
crearea modulului clasă se dă comanda Class Module din meniul Insert.
• Pentru permiterea evenimentelor obiectului Application se adaugă declaraţia

Public WithEvents App As Application

• Obiectul nou creat apare în boxa Object din modulul clasă şi se pot scrie procedurile evenimentelor pentru noul
obiect.

• Se conectează obiectul declarat în modul la obiectul Application. Pentru această operaţiune, în orice modul se
dă instrucţiunea

Public X As New EventClass

unde EventClass este numele dat, de exemplu, modulului clasă creat, similar pentru X.

• după crearea instanţei X a obiectului EventClass se poate stabili obiectul App al clasei EventClass egal cu
obiectul Application Microsoft Excel.

Sub InitializeApp ()
Set X.App = Application
End Sub

• După executarea procedurii de iniţializare, obiectul App din modulul EventClass punctează către obiectul
Application Microsoft Excel şi procedurile eveniment din modulul clasă vor fi executate la declanşarea
evenimentelor.

Deşi procedura poate părea laborioasă, ideea poate fi utilizată pentru ca aceleaşi proceduri eveniment să fie asociate mai
multor obiecte.

Să presupunem că am efectuat etapele precedente pentru un obiect diagramă. S-a utilizat astfel declaraţia

Public WithEvents cht As Chart

în etapa 2 şi codul următor

129
Dim C1 As New EventClass
Dim C2 As New EventClass
Sub InitializeCharts ()
Set C1.cht = Worksheets (1).ChartObjects(1).Chart
Set C2.cht = Worksheets (1).ChartObjects(2).Chart
End Sub

pentru iniţializare.

Aceeaşi tehnică se poate utiliza şi pentru obiectele Worksheet şi Workbook pentru a utiliza evenimentele noii clase cu
mai multe foi de calcul, în plus faţă de evenimentele implicite.

Obiectele Microsoft Access

O bază de date Microsoft Access este alcătuită din diferite tipuri de obiecte. Unel sunt utilizate pentru a afişa date din
bază, altele pentru memorarea şi gestionarea datelor iar altele ca ajutor în programare.

Unele obiecte sunt furnizate de Access, altele sunt oferite de diferite componente. În continuare se discută doar obiectele
din Access: forme, rapoarte, controale şi module.

Obiectele accesibile în Microsoft Access

Deoarece Microsoft Access include mai multe componente, fiecare cu mulţimea proprie de obiecte, anumite seturi de
obiecte sunt accesibile doar dacă se specifică o referinţă la biblioteca respectivă, referinţa efectuându-se în mod uzual
prin marcarea bibliotecii în lista afişată la comanda References din meniul Tools.

Access face referinţă, în mod automat, la bibliotecile de obiecte:

o Microsoft Access 8.0. Aici sunt obiectele prezentate în acest capitol (Form, Module, Application etc.).
o Microsoft DAO 3.5. Aici sunt conţinute obiectele de acces la date (Data Access Objects – DAO) cum ar fi
TableDef, QueryDef prin care se determină structura de date şi se pot accesa datele prin cod VB. Aceste
obiecte sunt discutate într-un capitol separat.
o Visual Basic for Applications. Aici sunt conţinute trei obiecte care ajută la programare: Debug, Err şi
Collection.

Microsoft Access include, de asemenea, biblioteca Microsoft Office 8.0, dar aceasta trebuie să fie referită pentru a avea
acces la obiecte cum ar fi CommandBar, FileSearch sau Assistant.

Alte biblioteci trebuie să fie referite dacă obiectele lor sunt necesare în cadrul procesului de automatizare: de exemplu
Microsoft Excel.

Pentru a lucra cu obiectele Microsoft Access din alte aplicaţii care suportă automatizarea, în aplicaţiile respective se va
face referire la biblioteca de obiecte Microsoft Access 8.0.

Obiectele Microsoft Access

Biblioteca de obiecte Microsoft Access 8.0 conţine obiectele şi colecţiile enumerate în tabelul următor. Obiectele şi
utilizarea lor sunt descrise în continuarea capitolului.

Obiectul sau colecţia Descriere

130
Application Reprezintă aplicaţia Microsoft Access (obiect)

Form Reprezintă o formă deschisă (obiect)

Forms Conţine toate formele deschise. (colecţie)

Report Reprezintă un raport deschis (obiect)

Reports Conţine toate rapoartele curente deschise (colecţie)

Control Reprezintă un control pe o formă, raport sau secţiune sau din alt control (obiect)

Controls Conţine toate controalele de pe o formă sau raport (colecţie)

Module Reprezintă un modul standard sau un modul clasă (obiect)

Modules Conţine toate modulele deschise curent (colecţie)

Reference Reprezintă o referinţă la o bibliotecă de obiecte (obiect)

References Reprezintă toate referinţele stabilite în mod curent (colecţie)

DoCmd Reprezintă o acţiune macro din Visual Basic (obiect)

Screen Reprezintă aranjarea curentă a obiectelor pe ecran.

Obiectele Access sunt organizate în mod ierarhic, arborele de structură fiind următorul

Proprietăţile, metodele şi evenimentele asociate sunt vizibile, în mod similar tutror obiectelor accesate în VBA, prin Object
Browser. Pentru a deschide acest instrument, se deschide un modul şi apoi se dă comanda Object Browser din meniul
View (sau F2).

Obiectul Application

Obiectul Application reprezintă aplicaţia Microsoft Access şi este obiectul de nivel cel mai înalt din ierarhia de obiecte
Access, conţinând toate celelalte obiecte şi colecţii.

Obiectul Application este obiectul implicit din ierarhia de obiecte. Drept urmare, atunci când se lucrează din interiorul
aplicaţiei Access, nu este necesară referirea lui explicită când se utilizează una dintre proprietăţile sau metodele sale, sau
când se scrie o referinţă la un obiect sau o colecţie inclusă. Referirea explicită nu produce, totuşi, erori.

Specificare obiectului Application este necesară doar atunci când, prin procedeul de automatizare, se lucrează cu obiecte
din ierarhia Access în interiorul altei aplicaţii.

Utilizarea obiectului Application în automatizare

Atunci când se lucrează cu obiectele Access din alte aplicaţii, cum ar fi Excel sau Visual Basic, trebuie să se introducă o
referinţă la biblioteca de obiecte şi orice referire la un obiect Access trebuie să înceapă cu Application, care permite
intrarea în ierarhie.

Automatizarea trebuie să înceapă cu etapele:

o stabilirea, aplicaţia gazdă, a unei referinţe la biblioteca de obiecte Microsoft Access


131
o declararea unei variabile obiect care să reprezinte obiectul Application Microsoft Access
o returnarea unei referinţe la obiectul Application şu asignarea acestei referinţe la variabila obiect.

În Visual Basic Editor, aceste etape se realizează prin:

o deschiderea unui modul, comanda References din Tools, selectarea Microsoft Access 8.0 Object
Library în lista Available References. Este evident că se presupune instalarea prealabilă a produsului
Microsoft Access 97, în caz contrar referinţa nu este disponibilă.
o Pentru declararea variabilei obiect este recomandată formularea

Dim appAccess As Access.Application

o După declararea variabilei, returnarea unei referinţe la obiectul Application se poate obţine prin funcţia
CreateObject (dacă Microsoft Access nu este lansat) sau GetObject (dacă Microsoft Access este deja
lansat). Asignarea referinţei la variabila obiect definită este de exemplu:

Set appAccess = CreateObject("Access.Application.8")

o unde numărul versiunii poate lipsi dacă există o singură versiune instalată de Access.
o Dacă aplicaţia gazdă suportă New se poate utiliza o singură instrucţiune pentru declararea variabilei şi
asignarea referinţei:

Dim appAccess As New Access.Application

o diferenţa fiind că în această variantă nu este deschis efectiv Microsoft Access până când nu se lucrează
programatic cu variabila obiect, de exemplu

appAccess.NewCurrentDatabase "NewDb.mdb"

După parcurgerea etapelor descrise, se poate utiliza variabila obiect creată pentru accesul la ierarhia de obiecte Access.
Următorul exemplu, care lucrează din Excel pe baza de date standard (furnizată de Microsoft Office şi utilizată frecvent
pentru exemplificări) Northwind, deschide o formă şi lucrează cu ea. Pentru a vedea funcţionarea exemplului se va
deschide Excel, se va trece codul într-un modul şi apoi se va executa.

Sub OpenNorthwindEmployees ()

Dim appAccess As New Access.Application


Const conPath As String = "C:\Program Files\Microsoft Office\Office" _
& "\Samples\Northwind.mdb"
With appAccess
' Deschide baza de date
.OpenCurrentDatabase conPath
' Deschide forma Employees
.DoCmd.OpenForm "Employees"
' Stabileste captarea formei
.Forms!Employees.Caption = "Northwind Employees"
End With
End Sub

Prin automatizare se poate lucra cu DAO prin stabilirea prealabilă a unei referinţe la biblioteca de obiecte Microsoft DAO
3.5 şi utilizarea apoi a proprietăţii DBEngine a obiectului Application Microsoft Access pentru returnarea unei referinţe la
obiectul DBEngine DAO. Prin acest din urmă obiect se obţine acces la toată ierahia de obiect DAO.

132
Colecţia Forms

Obiectul Form reprezintă o formă Access deschisă într-unul din modurile de vizualizare Design, Form sau Datasheet.
Obiectele Form sunt grupate în colecţia Forms, care conţine doar formele deschise curent în baza de date.

În tabelul următor sunt rezumate relaţiile obiectelor Form şi ale colecţiei Forms:

Obiectul sau colecţia Este conţinut(ă) în Conţine

Form (obiect) Forms Colecţia Controls


Colecţia Properties
Obiectul Module

Forms (colecţie) Application Obiecte Form

Referirea la un obiect Form

Pentru a lucra cu o formă în Visual Basic, trebuie să se returneze o referinţă la obiectul Form corespunzător, referinţa
obţinându-se prin intermediul colecţiei Forms. O formă poate fi referită doar dacă este deschisă iar deschiderea unei
forme se realizează prin metoda OpenForm a obiectului DoCmd.

Ca orice element dintr-o colecţie, o formă poate fi referită prin nume sau prin indexul din cadrul colecţiei.

Referinţa prin nume se poate face în mod explicit, dacă se cunoaşte numele formei în momentul proiectării aplicaţiei:

Dim frm As Form


Set frm = Forms!Employees

sau prin notaţia cu paranteze, în cazul în care numele este cunoscut doar la momentul execuţiei, ca în exemplul următor:

Function SetFormCaption (strFormName As String)


Dim frm As Form
' Se deschide forma
DoCmd.OpenForm strFormName
' Se returnează o referinţă la obiectul Form
Set frm = Forms(strFormName)
' Se schimbă captarea formei
frm.Caption = Date
End Function

Referinţa prin indice este de genul Forms(1), indexarea colecţiei Forms începând cu 0 (zero). În acest mod de referire
trebuie să se lucreze cu grijă deoarece numerotarea se reface la orice închidere a unei forme, prin urmare o formă
anumită poate avea indici diferiţi în momente diferite de execuţie.

Cum colecţia Forms cuprinde formele deschise la momentul respectiv, nu se poate adăuga şi nici nu se poate elimina un
membru al colecţiei (operaţiuni posibile pentru alte colecţii din VBA). Deschiderea şi închiderea unei forme produce
operaţiunile de adăugare/eliminare a elementelor din colecţie.

Pentru cazuri singulare (cum ar fi un obiect care nu se utilizează în mod repetat), referinţa la o formă se poate efectua şi
direct, prin invocarea modulului clasă al formei:

Form_Employees.Visible = True
133
Proprietăţile obiectului Form

Dintre proprietăţile obiectului Form sunt prezentate doar câteva, considerate mai importante. Pentru celelalte se va studia
intrarea corespunzătoare din Help (Form Object).

Proprietatea Me (Form Object)

Returnează o referinţă la forma în care se execută codul curent. Proprietatea poate fi utilizată în procedurile din modulul
formei, poate fi utilizată pentru trecerea ca argument a obiectului Form fără a şti numele formei. Utilizarea proprietăţii
produce un cod independent de numele formei.

Următorul exemplu arată cum, la fiecare încărcare (deschidere) a formei, se poate modifica culoarea de fundal a secţiunii
detaliu din formă. În acest scop se scrie cod în procedura eveniment respectivă:

' Procedura se adaugă la modulul formei


Private Sub Form_Load ()
' Iniţializarea generatorului de numere aleatoare
Randomize
' Stabilirea culorii de fundal
Me.Section(acDetail).BackColor = RGB(Rnd*256, Rnd*256, Rnd*256)
End Sub

Este de notat că atunci când se lucrează cu o formă Access din altă aplicaţie, prin automatizare, nu se poate utiliza Me
pentru a referi forma din aplicaţia gazdă.

Proprietatea Section (Form Object)

O formă este divizată în Access în cinci secţiuni: detaliu (detail), antet (header), subsol (footer), antet de pagină (page
header) şi subsol de pagină (page footer). Proprietatea returnează o referinţă la o secţiune particulară, utilizarea acesteia
permite stabilirea proprietăţilor secţiunii. Pentru obiectul Form, secţiunile sunt identificate prin

Index Nume Semnificaţie

0 acDetail Form detail

1 acHeader Form header

2 acFooter Form footer

3 acPageHeader Form page header

4 acPageFooter Form page footer

Un număr de proprietăţi se aplică mai degrabă unei secţiuni dintr-o formă decât obiectului Form. De exemplu,
proprietatea BackColor se aplică unei secţiuni şi nu unei forme (a se vedea exemplul precedent). O secţiune are de
asemenea o proprietatea Controls, care returnează o referinţă la colecţia Controls pentru acea secţiune.

Următorul exemplu tipăreşte, în fereastra Debug, numele tuturor controalelor din secţiunea de detalii:

Sub ControlsBySection (frm As Form)


Dim ctl As Control
' Enumerarea controalelor din secţiunea de detalii

134
For Each ctl In frm.Section(acDetail).Controls
Debug.Print ctl.Name
Next ctl
End Sub

Proprietatea Properties (Form Object)

Returnează o referinţă la colecţia Properties a obiectului Form. Colecţia Properties conţine toate proprietăţile formei şi
pot fi enumerate prin instrucţiunea For Each…Next.

La colecţia Properties nu se poate adăuga programatic o nouă proprietate.

Următorul exemplu tipăreşte toate proprietăţile unui obiect Form

Sub EnumerateFormProperties(frm As Form)


Dim prp As Property
' enumerarea proprietăţile unei forme
For Each prp In frm.Properties
Debug.Print prp.Name, prp.Value
Next prp
End Sub

Proprietatea Module (Form Object)

Aplicată unui obiect Form, proprietatea Module returnează o referinţă la obiectul Module asociat formei. Referinţa poate
fi asignată unei variabile de tip Module.

Modulul asociat cu o formă nu există în mod automat din momentul creerii formei. Proprietatea HasModule determină
dacă o formă are un modul asociat. Dacă proprietatea Module este referită în modul proiectare, Access creează modulul
asociat şi stabileşte valoarea True pentru HasModule. Referirea la proprietatea Module a unei forme în execuţie (run-
time) pentru care HasModule este False produce eroare.

Proprietatea RecordSource (Form Object)

Prin proprietatea aceasta se leagă o tabelă sau o interogare (query) la formă. După ce proprietăţii RecordSource i-a fost
atribuit numele unei tabele sau interogări sau o instrucţiune SQL se pot afişa date din tabelă, interogare sau SQL pe
formă. Un exemplu este

Forms!frmCustomers.RecordSource = "Customers"

prin care se leagă forma de o tabelă.

Module ataşate formelor

Un obiect Form poate avea un modul asociat, care este reprezentat printr-un obiect Module. Cum acest modul nu este
creat în mod automat la crearea formei, există trei căi de creare a modulului asociat:

o click Code de pe meniul View când forma este în modul de vizualizare Design. Modulul este creat şi
salvat împreună cu forma chiar dacă nu conţine code.
o Stabilirea proprietăţii HasModule la True. Aceasta se poate efectua din foaia de proprietăţi din Access
sau din Visual Basic. Stabilirea proprietăţii la False elimină modulul şi codul conţinut.

135
o Referirea la proprietatea Module a formei din Visual Basic. Proprietatea returnează o referinţă la obiectul
Module asociat formei, creând mai întâi modulul dacă el nu există.

În lucrul cu module asociate, trebuie reţinut că o formă fără modul asociat se deschide mai repede. Prin urmare nu se vor
crea module dacă nu există necesitatea scrierii de cod pentru formă. Eliminarea modulelor inutile reduce şi dimensiunea
bazelor de date.

Un modul de formă conţine toate procedurile eveniment definite pentru formă, ca şi alte proceduri specifice formei. De
notat că o procedură care se accesează din multiple locuri ale bazei de date trebuie plasată într-un modul standard.

Crearea formelor în timpul execuţiei

Pentru generarea unei forme în timpul execuţiei (run-time) se poate utiliza funcţia CreateForm. Funcţiile asociate sunt
CreateControl şi DeleteControl care adaugă sau elimină controale de pe o formă.

Se poate, de asemenea, să se adauge programatic, în timpul execuţiei, cod în modulul asociat formei prin metodele şi
proprietăţile obiectului Module. De exemplu, metoda CreateEventProc creează o procedură eveniment pentru obiectul
specificat (aici formă, dar poate fi şi raport, control etc.). Metoda InsertLines permite inserarea unor linii de cod, ca şi
InsertText, AddFromFile, AddFromString etc.

Următorul exemplu creează o formă şi adaugă o procedură eveniment modulului asociat formei.

Function CreateFormWithCode () As Boolean


Dim frm As Form, mdl As Module
Dim lngLine As Long, strLine As String

' Permite tratarea erorilor


On Error GoTo Error_CreateFormWithCode
' creează noua formă şi returnează o referinţă la ea
Set frm = CreateForm
' returnează o referinţă la modul
Set mdl = frm.Module
' creează procedura evenimentului Load
lngLine = mdl.CreateEventProc("Load", "Form")
strLine = vbTab & "Me.Caption = " & Date
' stabileşte captarea formei în evenimentul Load
mdl.InsertLines lingLine + 1, strLine
' returnează True dacă funcţia se termină cu succes
CreateFormWithCode = True

Exit_CreateFormWitwCode:
Exit Function

Error_CreateFormWithCode:
MsgBox Err & ": " & Err.Description
CreateFormWithCode = False
Resume Exit_CreateFormWithCode
End Function

O discuţie ceva mai amplă se găseşte la secţiunea dedicată colecţiei Modules.

Colecţia Reports

136
Un obiect Report reprezintă un raport microsoft Access care este deschis în Design view, Print Preview sau Layout
Preview. Toate obiectele Report sunt membri ai colecţiei Reports. De accentuat că doar rapoartele deschise sunt
reprezentate în colecţie.

Relaţiile în sus şi în jos ale colecţiei Reports în ierarhia de obiecte sunt date în tabelul următor:

Obiectul sau colecţia Este conţinut(ă) în Conţine

Report (obiect) Reports Colecţia Controls


Colecţia Properties
Obiectul Module

Reports (colecţie) Application Obiecte Report

Obiectele Report au caracteristici similare cu obiectele Form.

Referirea obiectelor Report

Pentru a referi un raport trebuie ca acesta să fie deschis, operaţiune realizată prin metoda OpenReport a obiectului
DoCmd.

Referinţele se returnează în mod uzual, după unul dintre modelele:

Dim rpt As Report ' defineşte variabila obiect rpt de tip Report
Set rpt = Reports!Invoice ' referinţă prin nume cunoscut
Set rpt = Reports("Invoice") ' referinţă prin şirul care conţine numele
Set rpt = Reports(0) ' referinţă prin indicele din colecţie (bazat pe zero)

Module asociate rapoartelor

Ca şi un obiect Form, obiectul Report poate avea asociat un modul care este un modul clasă. Modulul de cod asociat nu
există până când nu este referit:

o click Code de pe meniul View când raportul este în modul de vizualizare Design. Modulul este creat şi
salvat cu raportul chiar dacă nu conţine code.
o Stabilirea pentru obiectul Report a proprietăţii HasModule la True. Aceasta se poate efectua din foaia de
proprietăţi din Access sau din Visual Basic. Stabilirea proprietăţii la False elimină modulul şi codul
conţinut.
o Referirea, din Visual Basic, la proprietatea Module a raportului. Proprietatea returnează o referinţă la
obiectul Module asociat raportului, creând mai întâi modulul dacă el nu există.

Crearea rapoartelor în timpul execuţiei (run time)

Pentru crearea programatică a rapoartelor se utilizează funcţie CreateReport. Controalele se pot adăuga sau elimina, în
run time, prin funcţiile CreateReportControl sau DeleteReportControl.

Funcţiile CreateForm, CreateReport

Sintaxa apelurilor este

CreateForm([database[, formtemplate]])

137
CreateReport([database[, reporttemplate]])

unde

database este un şir, identifică baza de date care conţine raportul sau forma creată. Dacă este omis, se va utiliza baza
curentă (conform returului funcţiei CurrentDb). Baza de date specificată, dacă este diferită de baza curentă, trebuie
deschisă ca o bază de date bibliotecă (vezi intrările din Help pentru "library databases").

formtemplate, reporttemplate sunt, respectiv, şiruri cu numele şabloanelor utilizate la crearea noului obiect. Dacă este
omis, se va alege în mod implicit şablonul specificat de fişa Forms/Reports din dialogul Options deschis de comanda
Options din meniul Tools.

Funcţiile deschid un obiect nou, minimizat, în modul de vizualizare Design.

Şabloanele specificate pot fi create anterior ca şabloane sau pot fi orice formă, respectiv raport, din baza de date
specificată în argumentul database.

Funcţiile CreateControl, CreateReportControl

Ambele funcţii creează un control cu atributele specificate pe o forma, respectiv pe un raport. Atât forma cât şi raportul
trebuie să fie deschise. Sintaxa este

CreateControl(formname, controltype[, section[, parent[, columnname[, left[, top[, width[, height]]]]]]])

CreateReportControl(reportname, controltype[, section[, parent[, columnname[, left[, top[, width[, height]]]]]]])

unde

formname, reportname reprezintă numele formei sau raportului unde se creează controlul.

controltype este o constantă predefinită care reprezintă tipul controlului. Se pot vedea prin Object Browser cu alegerile
Access în Project/Library şi Constants în Classes şi copia în cod. Fără explicaţii (denumirile sunt suficient de sugestive):
acLabel, acRectangle, acLine, acImage, acCommandButton, acOptionButton, acCheckBox, acOptionGroup,
acBoundObjectFrame, acTextBox, acListBox, acComboBox, acSubform, acObjectFrame, acPage, acPageBreak,
acCustomControl, acToggleButton, acTabCtl.

section este o constantă identificând secţiunea. Poate fi o constantă dintre

Constanta Semnificaţia

acDetail (Default) Detail section

acHeader Form or report header

acFooter Form or report footer

acPageHeader Page header

acPageFooter Page footer

acGroupLevel1Header Group-level 1 header (reports only)

138
acGroupLevel1Footer Group-level 1 footer (reports only)

acGroupLevel2Header Group-level 2 header (reports only)

acGroupLevel2Footer Group-level 2 footer (reports only)

Pentru grupuri suplimentare într-un raport, perechile header/footer sunt numerotate consecutiv începând cu 9

parent este un şir care identifică controlul părinte. Pentru controalele care nu sunt copii se utilizează şirul vid sau se omite
argumentul.

columnname numele câmpului unde este legat controlul, dacă este un control legat de date. Dacă nu este cazul, se
utilizează şirul vid.

left, top sunt expresii numerice ale coordonatelor relative la colţul din stânga sus, în twips.

width, height sunt expresii numerice indicând lăţimea şi înălţimea controlului, în twips.

Funcţiile CreateControl şi CreateReportControl pot fi utilizate doar în modul de vizualizare Design (vezi şi efectul
funcţiilor CreateForm, CreateReport). În stabilirea relaţiilor părinte-copil se va avea în vedere relaţia de pe formă/raport.
De exemplu, casetă text (control tată) şi eticheta asociată (control copil, subordonat). Sau, un grup de opţiuni este părinte
pentru boxele de control conţinute etc. Doar controalele label, check box, option button sau toggle button pot avea
controale părinte, deşi pot fi create şi independent.

Controalele care pot fi legate de un câmp de date sunt text box, list box, combo box, option group şi bound object frame.
În plus, controalele toggle button, option button şi check box pot fi legate de un câmp dacă nu sunt conţinute într-un grup
de opţiuni (option group).

La legarea unui câmp, proprietăţile controlului sunt modificate automat pentru a se conforma proprietăţilor
corespunzătoare ale câmpului.

Pentru a înlătura un control se vor utiliza instrucţiunile DeleteControl şi DeleteReportControl cu sintaxa

DeleteControl formname, controlname

DeleteReportControl reportname, controlname

Semnificaţia argumentelor este evidentă.

Exemplu de creare a unui raport

Folosind automatizarea din Excel, exemplul creează o tabela legată într-o bază de date Access şi realizează un raport pe
baza datelor din tabele legată.

Pentru utilizarea exemplului trebuie sa se creeze un caiet Excel cu numele Revenue.xls, să se completeze datele într-o
foaie a caietului şi să se denumească un domeniu DataRange care include datele. După aceea, se va trece codul
următor într-un modul din caiet. În proiectul Excel se vor stabili referinţe la bibliotecile de obiecte Microsoft Access 8.0 şi
DAO 3.5.

139
Este esenţial ca, înaintea execuţiei codului, să fie instalat în sistem driver-ul Microsoft Excel ISAM (Msexcl35.dll). Dacă
nu este instalat, se va executa Setup pentru a-l instala. Driver-ul Microsoft Excel ISAM permite fişierelor Excel 97 să
lucreze cu motorul de baze de date Microsoft Jet.

' se introduce în secţiunea Declarations a modulului


Dim appAccess As New Access.Application

Sub PrintReport ()
Dim rpt As Access.Report, ctl As Access.TextBox
Dim dbs As DAO.Database, tdf As DAO.TableDef, fld As DAO.Field
Dim strDB As String, intLeft As Integer

' se declară calea către baza de date Northwind (din Office)


Const conPath As String = "C:\Program Files …"

' Se deschide baza de date


appAccess.OpenCurrentDatabase conPath & "Northwind.mdb"
' se returnează referinţa la bază
Set dbs = appAccess.CurrentDb
' se creează un obiect tabelă nou
Set tdf = dbs.CreateTableDef("XLData")
' se specifică şirul de conectare la driver-ul Excel ISAM
tdf.Connect = "EXCEL 8.0; Database=C:\My Documents\Revenue.xls"
' se specifică tabela sursă ca un domeniu numit în foaie
tdf.SourceTableName = "DataRange"
' se adaugă noua tabelă legată la bază
dbs.TableDefs.Append tdf
' se creează noul raport
Set rpt = appAccess.CreateReport
' se specifică tabela legată drept sursa de date a raportului
rpt.RecordSource = tdf.Name
' se creează un control pe raport pentru fiecare câmp din tabelă
For Each fld In tdf.Fields
Set ctl = appAccess.CreateReportControl (rpt.Name, acTextBox, , , _
fld.Name, intLeft)
intLeft = intLeft + ctl.Width
Next fld

' deschiderea raportului în Print Preview


appAccess.DoCmd.OpenReport rpt.Name, acViewPreview
' restaurarea raportului
app.Access.DoCmd.Restore
' afisarea Access-ului ca aplicaţia activă
AppActivate "Microsoft Access"
End Sub

Colecţia Controls

Un obiect Control reprezintă un control de pe o formă sau dintr-un raport Access. Obiectele Control sunt grupate în
colecţia Controls. Legăturile în ierarhia de obiecte Access sunt date în tabelul următor.

Obiectul sau Este conţinut(ă) în Conţine


colecţia

140
Control (obiect) Controls Colecţia Controls când controlul
este un grup de opţiuni (option
group) sau un control tab.
Colecţia Properties
Obiect Hyperlink
Obiecte Control

Controls (colecţie) Obiecte Form Obiecte Control


Obiecte Reports
Obiecte Control, doar pentru obiectele: option
group, tab control, text box, option button, toggle
button, check box, combo box, list box, command
button, bound object frame, unbound object frame.

Există două tipuri de controale:

o preconstruite, în biblioteca de obiecte Microsoft Access 8.0, accesibile printr-o cutie de unelte,
o controale ActiveX (denumite şi controale OLE sau custom controls).

Controale Microsoft Access

Următorul tabel conţine lista controalelor predefinite. Controalele sunt cu denumirile de clasă, după cum apar în Object
Browser. Fiecare control este un obiect cu proprietăţile, metodele şi evenimentele lui. Pentru detalii se vor studia intrările
sinonime din Help.

Controlul Descriere

BoundObjectFrame Afişează o imagine, diagramă sau obiect OLE memorat într-o tabelă Access.

CheckBox Indică selectarea unei opţiuni

ComboBox Combină listă ascunsă şi o casetă text.

CommandButton Un buton cu rol de pornire a unei operaţiuni atunci când se efectuează click pe el.

Image Afişează o imagine.

Label Afişează un text explicativ.

Line Afişează o linie orizontală, verticală sau diagonală

ListBox Afişează o listă de valori.

ObjectFrame Afişează o imagine, diagramă sau obiect OLE care nu este memorat într-o tabelă.

OptionButton Indică dacă o opţiune este selectată (buton radio).

OptionGroup Afişează un set de opţiuni.

Page Afisează controale pe o pagină a unui control tab.

PageBreak Marchează începutul unui nou ecran sau a unei pagini tipărite.

141
Rectangle Afişează un dreptunghi.

SubForm/SubReport Afişează o formă în interiorul altei forme sau un raport în interiorul altui raport.

TabControl Afişează pagini multiple, fiecare conţinând o mulţime de controale.

TextBox Afişează date de tip text.

ToggleButton Indică dacă o opţiune este selectată sau nu (on/off) prin imaginea unui buton apăsat sau nu.

Controale ActiveX

Un control ActiveX este un obiect care poate fi plasat pe o formă pentru a afisa date sau efectua acţiuni. Spre deosebire
de controalele preconstruite, codul asociat este memorat în fişiere separate, care trebuiesc instalate pentru a putea utiliza
controlul ActiveX.

În Microsoft Access sunt disponibile controalele

o Calendar, care permite afişarea şi actualizarea unui calendar pe o formă. Instalarea controlului se cere la
instalarea Microsoft Access.
o WebBrowser, care permite afisarea paginilor Web şi alte documente într-o formă Access. Acest control
este instalat separat (din folderul ValuPack al CD-ului Office sau direct prin instalarea browserului
Microsoft Internet Explorer).

Referirea obiectelor Control

Un control poate fi referit repetat prin declararea unei variabile care să-l reprezinte. Declararea poate fi făcută explicit,
dacă se cunoaşte tipul obiectului:

Dim txt As TextBox

sau, dacă nu se ştie tipul controlului sau dacă variabila conţine o referinţă la un control ActiveX, ea este declarată de tip
generic Control şi poate primi referinţe la orice tip de control (alternativă utilă pentru trecerea unor argumente de tipuri
diferite de controale unei proceduri) .

Pentru referinţa unui obiect Control individual se pot utiliza mecanismele uzuale pentru colecţii:

Set txt = Forms!Employees!LastName ' care se referă la controlul TextBox


' cu numele LastName de pe forma Employees
Set txt = Me!LastName ' similar exemplului precedent, dar referinţa este
' în forma care se execută curent
Set txt = Me![Last Name] 'dacă numele conţine spaţii
Set ctl = Me.Controls(0) ' prin indice, bazat pe zero
Set ctl = Me.Controls("LastName")

Proprietăţile obiectului Control

Datorită marii varietăţi de controale, proprietăţile sunt foarte numeroase (de exemplu Text Box Control are peste 50 de
proprietăţi) încât aici se discută doar două care merită o atenţie specială.

142
Proprietatea Hyperlink (Control Object)

Prin aplicarea proprietăţii este returnată o referinţă la un obiect Hyperlink, care reprezintă un text sau grafică definind un
salt la un fişier, bookmark într-un fişier, pagină HTML pe WWW sau pe intranet.

Controalele care suportă proprietatea Hyperlink sunt combo box, command button, image, label şi text box. Fiecare
poate afişa o hiperlegătură pe care utilizatorul o poate clicka pentru navigare. Atunci când se dispune de o referinţă la un
obiect Hyperlink dintr-un control, utilizarea metodei Follow (a obiectului Hyperlink) produce saltul la locaţia indicată.

Exemplul următor conţine o funcţie care returnează True în cazul în care controlul trecut drept argument conţine o
hiperlegătură validă.

Function FollowControlHyperlink (ctl As Control) As Boolean


Const conNoHyperlink As Integer = 7976

' permiterea controlului erorilor


On Error GoTo Error_FollowControlHyperlink
' urmărirea adresei indicate
ctl.Hyperlink.Follow
' returnează True dacă saltul este corect
FollowControlHyperlink = True

Exit_ FollowControlHyperlink:
Exit Function

Error_ FollowControlHyperlink:
If Err = conNoHyperlink Then
FollowControlHyperlink = False
End If
Resume Exit_ FollowControlHyperlink
End Function

Proprietatea ControlType (Control Object)

Aplicată unui obiect Control, proprietatea indică tipul particular de control al obiectului. Utilizarea proprietăţii poate duce şi
la schimbarea tipului de control (de exemplu Text Box în Combo Box) nu numai la aflarea tipului. Valorile proprietăţii sunt

acLabel acRectangle AcLine acImage

acCommandButton acOptionButton AcCheckBox acOptionGroup

acBoundObjectFrame acTextBox AcListBox acComboBox

acSubform acObjectFrame AcPage acPageBreak

acCustomControl acToggleButton AcTabCtl

cu interpretări imediate.

Următorul exemplu verifică proprietatea ControlType pentru fiecare control de pe o formă şi stabileşte proprietatea
Locked la valoarea True pentru casetele de text şi boxele combo.

Function LockTextControls (frm As Form) As Boolean


143
Dim ctl As Control

' tratarea erorilor


On Error GoTo Error_LockTextControls

' parcurgerea controalelor


For Each ctl In frm.Controls
' se prelucrează doar controalele Text Box şi Combo Box
If ctl.ControlType = acTextBox Or ctl.ControlType = acComboBox Then
ctl.Locked = True
End If
Next ctl
' returnează True pentru succes
LockTextControls = True

Exit_LockTextControls:
Exit Function

Error_LockTextControls:
MsgBox Err & ": " & Err.Description
LockTextControls = False
Resume Exit_ LockTextControls
End Function

Controale legate de date (Data-Bound Controls)

Anumite controale din Microsoft Access pot fi legate de date, ceea ce înseamnă că ele afişează date memorate într-o
tabelă, interogare sau instrucţiune SQL. Această categorie de controale include: bound object frame, check box, combo
box, list box, option button, option group, text box, subform şi subreport.

Şi unele controale ActiveX (de exemplu Calendar control) pot fi, de asemenea, legate de date.

Controalele legate de date au o proprietate ControlSource prin care se fixează numele câmpului tabelei, interogării sau
instrucţiunii SQL din care se iau datele afişate de control. Este de notat că mai înainte de stabilirea acestei proprietăţi
trebuie să se fixeze proprietatea RecordSource a formei/raportului pentru a specifica tabela, interogarea sau
instrucţiunea SQL care furnizează date formei/raportului.

Exemplul următor stabileşte proprietatea RecordSource a unei forme şi proprietatea ControlSource a unui control text
box, numit Text0, în procedura de tratare a evenimentului de încărcare a formei.

Private Sub Form_Load ()


' sursa de înregistrări a formei
Me.RecordSource = "Employees"
' sursa de date a controlului
Me!Text0.ControlSource = "LastName"
End Sub

Controale care au o colecţie Controls

Tab control şi Option group control au, la rândul lor, o colecţie Controls care poate conţine mai multe controale.

Colecţie Controls aparţinând unui grup de opţiuni conţine controale de tip options button, check box, toggle button sau
label.

144
Controlul Tab conţine o colecţie Pages reprezentând paginile controlului (vezi figura următoare). Colecţia Pages conţine
obiecte Page care sunt controale (au ControlType = acPage).

Fiecare obiect Page are colecţia Controls a tuturor controalelor din pagina respectivă.

Celelalte controale (text box, option group, option button, toggle button, check box, combo box, list box, command button,
bound object frame şi unbound object frame) au o colecţie Controls cu cel mult un element: label reprezentând eticheta
ataşată controlului.

Colecţia Modules

Un obiect Module reprezintă un modul din Microsoft Access. Toate obiectele Module sunt incluse în colecţia Modules,
membru al obiectului Application. S-a văzut că un obiect Form sau Report poate să conţină de asemenea un singur
obiect Module.

Mulţimea tuturor modulelor dintr-o bază de date Microsoft Access constituie proiectul Visual Basic al bazei de date.
Colecţia Modules conţine doar modulele deschise curent în proiect. Modulele care nu sunt deschise pentru editare nu
sunt incluse în colecţia Modules.

Pentru a deschide un modul în Visual Basic se utilizează metoda OpenModule a obiectului DoCmd.

Relaţiile stabilite de ierarhia de obbiecte sunt

Obiectul sau colecţia Este conţinut(ă) în Conţine

Module (obiect) Colecţia Modules (Nimic)


Obiecte Form
Obiecte Report

Modules (colecţie) Obiectul Application Obiecte Module

Referirea la obiecte Module

Accesul la un modul se obţine prin intermediul colecţiei, în mod uzual. Astfel

Dim mdl As Module


Set mdl = Modules![ Utility Functions] ' returnează o referinţă
'la modulul cu numele dat

Set mdl = Modules(" Utility Functions") ' - idem-


Set mdl = Modules(0) ' returnează o referinţă
' la primul modul al colecţiei

Modulele clasă asociate formelor sau rapoartelor care sunt deschise se regăsesc în colecţia Modules.

Pentru modulele asociate formelor/rapoartelor care nu sunt deschise vezi discuţia de la prezentarea obiectelor forme şi
rapoarte.

Module standard şi module clasă

Reamintim câteva noţiuni prezentate în capitolele introductive.

145
Microsoft Access conţine două tipuri de module: module standard (standard modules) şi module de clasă (class
modules). Ambele tipuri sunt disponibile în tab-ul Modules din fereastra Database a mediului Access. O formă sau un
raport pot avea de asemenea un modul de clasă asociat.

Codul care trebuie să fie accesibil din orice procedură se va scrie într-un modul standard. Acestea sunt publice în mod
implicit, deci procedurile şi variabilele de nivel modul sunt vizibile în mod uzual în tot proiectul. De asemenea, dacă
proiectul este referit de alt proiect Access, codul dintr-un modul standard poate fi utilizat în proiectul care efectuează
referinţa.

Modulele de clasă sunt întotdeauna private. Se pot utiliza modulele clasă pentru a crea obiecte utilizate în proiectul
curent, dar ele nu se pot partaja cu alte proiecte. Procedurile Sub şi Function definite într-un modul de clasă devin
metode ale obiectului definit iar price procedură de tip Property Let, Property Get şi Property Set devin proprietăţile
obiectului.

Se pot utiliza modulele clasă asociate cu o formă sau raport pentru a defini procedurile declanşate de evenimente şi se
pot adăuga oricâte proceduri utilizate doar în modulul clasă respectiv.

Proprietăţile obiectului Module

O descriere sumară a proprietăţilor este conţinută în tabelul următor. Explicaţii detaliate se obţin din Help.

Proprietatea Descriere Observaţii

Application Returnează o referinţă la obiectul Application. Permite obţinerea accesului la


ierarhia de obiecte Access.

CountOfDeclarationLines Returnează numărul de linii de cod din secţiunea Long, numărătoarea începe cu 1
Declarations a modulului.

CountOfLines Returnează numărul de linii de cod din modul Long, numărătoarea începe cu 1

Lines Returnează textul conţinut în liniile de cod object.Lines(line, numlines)


specificate

Name Dă numele modulului

Parent Returnează o referinţă la obiectul sau colecţia


care conţine modulul

ProcBodyLine Returnează numărul liniei la care începe object.ProcBodyLine( _ procname,


definirea procedurii prockind)

ProcCountLines Returnează numărul de linii dintr-o procedură object.ProcCountLines( _ procname,


prockind)

ProcOfLine Returnează numele procedurii care conţine o object.ProcOfLine( _


linie specificată
line, pprockind)

ProcStartLine Returnează numărul liniei la care începe o object.ProcStartLine( _


procedură
procname, prockind)

146
Type Indică tipul modulului AcStandardModule sau

0, acClassModule sau 1.

Determinarea numărului de linii dintr-un modul

Liniile unui modul sunt numărate începând cu 1. Numărul ultimei linii dintr-un modul este egal cu valoarea proprietăţii
CountOfLines. Numărul ultimei linii din secţiunea Declarations a unui modul este egal cu valoarea proprietăţii
CountOfDeclarationLines.

Numerele de linii nu apar efectiv în modul, ele sunt utilizate doar pentru referinţe.

Lucrul cu procedurile

Proprietăţile Lines, ProcBodyLine, ProcCountLines, ProcOfLine şi ProcStartLine sunt utilizate pentru a obţine
informaţii despre procedurile unui modul. Procedurile pot fi de tip Sub, Function, Property Get, Property Let sau
Property Set. Primele două tipuri sunt considerate de acelaşi tip, ultimele trei privesc crearea de proprietăţi într-un modul
clasă.

Proprietatea ProcBodyLine returnează numărul liniei la care începe definirea procedurii, adică linia care include o
instrucţiune Sub, Function sau Property Get/Let/Set.

Proprietatea ProcLineStart returnează numărul liniei care urmează după separatorul de proceduri, dacă sunt selectate
opţiunile Full Module View şi Procedure Separator în fişa Module din dialogul Option (meniul Tools). Acest număr
poate fi diferit de cel returnat de ProcBodyLine, deoarece sunt considerate şi liniile comentariu, vide etc din faţa liniei de
definire. ProcStartLine returnează numărul primei linii a întregii procedurii.

Exemplul următor utilizează proprietăţile enumerate pentru a tipări o procedură în fereastra Debug (exemplul modifică
uşor exemplul din Help).

Function ProcLineInfo(strModuleName As String, _


strProcName As String) As Boolean
Dim mdl As Module
Dim lngStartLine As Long, lngBodyLine As Long
Dim lngCount As Long, lngEndProc As Long

On Error GoTo Error_ProcLineInfo


' Se deschide modulul specificat
DoCmd.OpenModule strModuleName
' Returnează o referinţă la obiectul Module
Set mdl = Modules(strModuleName)

' se numără liniile din procedură


lngCount = mdl.ProcCountLines(strProcName, vbext_pk_Proc)
' Determină linia de start
lngStartLine = mdl.ProcStartLine(strProcName, vbext_pk_Proc)

' se determină linia de definire


lngBodyLine = mdl.ProcBodyLine(strProcName, vbext_pk_Proc)
Debug.Print

' se tipăresc liniile de început

147
Debug.Print "Lines preceding procedure " & strProcName & ": "
Debug.Print mdl.Lines(lngStartLine, lngBodyLine - lngStartLine)

' determinarea numărului ultimei linii


lngEndProc = (lngBodyLine + lngCount - 1) - Abs(lngBodyLine - lngStartLine)

' tipărirea liniilor din corpul procedurii

Debug.Print "Body lines: "


Debug.Print mdl.Lines(lngBodyLine, (lngEndProc - lngBodyLine) + 1)

Exit_ProcLineInfo:
Exit Function

Error_ProcLineInfo:
MsgBox Err & " :" & Err.Description
ProcLineInfo = False
Resume Exit_ProcLineInfo
End Function

Procedura poate fi apelată, de exemplu, din baza de date exemplificatoare Northwind prin

Sub GetProcInfo()
ProcLineInfo "Utility Functions", "IsLoaded"
End Sub

Metodele obiectului Module

Tabelul următor conţine o sinteză a metodelor obiectului Module.

Metoda Descriere

AddFromFile Adaugă la modul conţinutul unui fişier text.

AddFromString Adaugă modulului conţinutul unui şir de caractere.

CreateEventProc Creează o procedură eveniment într-un modul clasă.

DeleteLines Elimină din modul liniile specificate.

Find Găseşte, într-un modul, textul specificat.

InsertLines Inserează o linie sau un grup de linii de cod la o poziţie specificată din modul.

ReplaceLines Inlocuieşte o linie dintr-un modul cu textul specificat.

Adăugare de text la un modul

Pentru a insera text într-un modul, este recomandată metoda InsertLines prin care se poate specifica linia unde are loc
inserarea.

Exemplul din Help (intrarea InsertLines Method) creează o formă nouă, adaugă un buton de comandă, creează
procedura evenimentului Click şi inserează o linie de cod cu metoda InsertLines.

148
Dacă textul care se doreşte adăugat trebuie să fie într-un modul nou, acesta se poate crea prin metoda RunCommand a
obiectului Application (comanda Module din meniul Insert trebuie să fie permisă):

RunCommand acCmdNewObjectModule

Pentru lista integrală a constantelor permise la aplicarea metodei se va vedea intrarea "RunCommand Method
Constants" în Help.

Exemplul următor utilizează metoda AddFromFile pentru a adăuga conţinutul unui fişier text la un modul nou. Modulul
creat este salvat cu acelaşi nume ca şi fişierul text.

Function AddFromTextFile(strFileName) As Boolean


Dim strModuleName As String, intPosition As Integer
Dim intLength As Integer
Dim mdl As Module

' memorarea numelui de fişier într-o variabilă


strModuleName = strFileName

' eliminarea căii din numele fişierului


Do
' găsirea caracterului \
intPosition = InStr(strModuleName, "\")
If intPosition = 0 Then
Exit Do
Else
intLength = Len(strModuleName)
' eliminare cale din şir
strModuleName = Right (strModuleName, Abs(intLength – intPosition))
End If
Loop

' eliminarea extensiei


intPosition = InStr(strModuleName, ".")
If intPosition > 0 Then
intLength = Len(strModuleName)
strModuleName = Left(strModuleName, intPosition –1)
End If

' Crearea modulului nou


RunCommand acCmdNewObjectModule
' salvarea modulului
DoCmd.Save , strModuleName
' returnarea referinţei la obiectul Module
Set mdl = Modules(strModuleName)
' adăugarea fişierului text
mdl.AddFromFile strFileName
' salvarea modulului modificat
DoCmd.Save
End Function

Observaţie. Dacă execuţia procedurii în linia care execută prima salvare a modulului are loc în modul pas cu pas, atunci
focusul este în modulul de unde se execută codul şi nu în modulul nou creat. În acest fel, Visual Basic va încerca, mai
degrabă, salvarea modulului cu focusul şi nu a modulului nou creat.

149
Evenimentele unui modul clasă

Modulele de clasă, care nu sunt asociate cu o formă sau un raport, au două evenimente: Initialize şi Terminate.

Evenimentul Initialize se declanşează la crearea unei noi instanţe a obiectului.

Terminate apare atunci când se elimină un obiect utilizator din memorie.

Pentru a crea procedurile de răspuns la evenimente, se deschide modulul clasă, se selectează Class în boxa Object şi
se alege Initialize sau Terminate în lista Procedure.

Evenimentele pot fi utilizate, de exemplu, pentru a iniţializa o variabilă la nivel de modul o dată cu crearea obiectului.

Colecţia References

Un obiect Reference reprezintă o referinţă din Microsoft Access la alt proiect sau la o bibliotecă de obiecte. Obiectele
Reference sunt conţinute în colecţia References, fiecare element din colecţie corespunzând unei referinţe selectate în
dialogul References (meniul Tools).

Colecţia References şi obiectele Reference pot fi utilizate din Visual Basic pentru a adăuga referinţe, pentru a verifica
referinţele existente sau pentru a anula referinţele care nu mai sunt necesare.

Obiectul sau colecţia Este conţinut(ă) în Conţine

Reference (obiect) References (nimic)

References (colecţie) Application Obiecte Reference

Referirea obiectelor Reference

Un obiect Reference este accesat prin intermediul colecţiei References. Un obiect referit poate fi atribuit unei variabile
obiect în mod uzual:

Dim ref As Reference


Set ref = References!VBA
Set ref = References("VBA")
Set ref = References(1) ' de remarcat că numerotarea
' colecţiei References începe cu 1

Proprietăţile obiectului Reference

Tabelul următor prezintă pe scurt proprietăţile obiectului Reference.

Proprietatea Descriere

BuiltIn Indică dacă referinţa este implicită, necesară bunei funcţionări a aplicaţiei Microsoft Access.

Collection Returnează o referinţă la colecţia References.

FullPath Returnează calea şi numele de fişier al proiectului referit sau al bibliotecii de obiecte.

150
GUID Returnează identificatorul global unic (GUID – Globally Unique Identifier) al proiectului referit sau
al bibliotecii de obiecte. Un GUID este memorat în registry-ul Windows.

IsBroken Indică dacă referinţa punctează către o referinţă validă.

Kind Indică dacă obiectul Reference punctează la un proiect Visual Basic (valoarea Project sau 1) sau
la o bibliotecă (TypeLib sau 0).

Major Returnează valoarea din stânga punctului zecimal din numărul de versiune al fişierului referit.

Minor Returnează valoarea din dreapta punctului zecimal din numărul de versiune al fişierului referit.

Name Returnează numele proiectului sau al bibliotecii de obiecte către care duce referinţa.

Metodele colecţiei References

Obiectul Reference nu are asociate metode. Metodele colecţiei References sunt

Metoda Descriere

AddFromFile Creează o referinţă la un fişier care conţine un proiect sau o bibliotecă de obiecte.
References.AddFromFile(filename)

AddFromGUID Creează o referinţă la un proiect sau bibliotecă de obiecte pornind de GUID-ul fişierului,
memorat în registry.
Object.AddFromGUID(guid)

Item Returnează un element particular al colecţiei References.

Remove Elimină un obiecte Reference din colecţia References.

Stabilirea unei referinţe în Visual Basic

Primele două metode enumerate în tabelul precedent, AddFromFile şi AddFromGUID, permit stabilirea unei referinţe în
mod programatic. Următorul exemplu creează o referinţă în timpul execuţiei.

Function AddReference (strFilePath As String) As Boolean


Dim ref As Reference

Const conReferenceExists As Long = 32813


On Error GoTo Error_AddReference
' Adaugă o referinţă la un proiect sau bibliotecă de obiecte
Set ref = References.AddFromFile(strFilePath)
AddReference = True

Exit_AddReference:
Exit Function

Error_AddReference:
If Err <> conReferenceExists Then
MsgBox Err & ": " & Err.Description
End If
AddReference = False
151
Resume Exit_AddReference
End Function
Apelul acestei funcţii poate fi efectuat după modelul

Sub SetSolutionsReferences ()
Const strRefPath As String = "C:\Program Files\Microsoft Office" _
& "\Office\Samples\Solutions.mdb"
If AddReference (strRefPath) = True Then
MsgBox "Reference set successfully."
Else
MsgBox "Reference not set successfully."
End If
End Sub

Obiectul DoCmd

Metodele obiectului DoCmd sunt utilizate pentru a executa acţiuni (macro-uri) Microsoft Access din Visual Basic. De altfel,
aceasta este singura utilitate a obiectului DoCmd, acesta neavând proprietăţi şi evenimente.

Sintaxa este

[application.]DoCmd.method [arg1, arg2, ...]

unde

application este obiectul Application, opţional

method este una dintre metodele suportate de obiect

arg1, arg2, ... sunt argumentele metodei selectate.

Omiterea argumentelor care sunt opţionale este echivalentă cu acceptarea valorilor implicite ale acestora.

Obiectul DoCmd nu suportă metode care corespund cu acţiunile

• AddMenu.
• MsgBox. Se utilizează funcţia MsgBox.
• RunApp. Se utilizează funcţia Shell pentru a executa altă aplicaţie.
• RunCode. Se execută funcţia direct în Visual Basic (instrucţiunea Call).
• SendKeys. Se utilizează instrucţiunea SendKeys.
• SetValue. Se stabileşte valoarea direct în Visual Basic (instrucţiunea Let).
• StopAllMacros. Se utilizează instrucţiunile Stop sau End.
• StopMacro. Se utilizează instrucţiunile Exit Sub sau Exit Function.

Important! Pentru o listă completă a acţiunilor, care coincide, excepând cele enumerate, cu lista metodelor obiectului, se
va urma: Help – DoCmd Object – Action Constants (lista alfabetică a acţiunilor) sau actions, reference topics (acţiuni
grupate pe categorii). Pentru explicaţii complementare se va urmări atât subiectul privind metoda cât şi subiectul privind
acţiunea sinonimă.

Pentru exemplificare prezentăm două metode ale obiectului DoCmd.

152
Metoda OpenForm

Se execută din Visual Basic acţiunea OpenForm. Sintaxa este

DoCmd.OpenForm formname[, view][, filtername][, wherecondition][, datamode]


[, windowmode][, openargs]

unde

formname este un şir cu numele valid al unei forme din baza de date curentă. Dacă se execută codul înre-o bibliotecă,
forma se va căuta mai întâi în baza de date bibliotecă şi apoi în baza curentă.

view este modul de vizualizare Access şi poate avea una din valorile: acDesign, acFormDS, acNormal (default),
acPreview. Valoarea implicită deschide forma în Form view.

filtername este un şir care conţine numele valid al unei interogări din baza de date curentă. wherecondition este un şir
care conţine o clauză validă WHERE SQL, fără cuvântul WHERE.

datamode este una dintre constantele: acFormAdd, acFormEdit, acFormPropertySettings (default), acFormReadOnly.
Argumentul fixează modul de acces la date (adăugare, editare etc.). Argumentele acoperă proprietăţile AllowEdits,
AllowDeletions, AllowAdditions şi DataEntry ale formei, proprietăţile sunt considerate în modul implicit
(acFormPropertySettings).

windowmode stabileşte modul de afişare a ferestrei formei. Poate fi o constantă: acDialog (proprietăţile Modal şi PopUp
ale formei sunt Yes), acHidden (forma este ascunsă), acIcon (forma este minimizată), acWindowNormal (valoarea
implicită, forma este afişată potrivit proprietăţilor sale).

openargs este un şir utilizat pentru stabilirea proprietăţii OpenArgs a formei. Această valoare poate fi utilizată ulterior de
cod (de exemplu într-o procedură eveniment). Argumentul este valabil doar în Visual Basic (nu există pentru acţiunea
sinonimă Access).

Metoda RunCommand

Prin această metodă, aplicabilă obiectului Application sau DoCmd, se execută o comandă dintr-un meniu predefinit sau
dintr-o bară de unelte. Sintaxa este

[object.]RunCommand command

unde

object este Application sau DoCmd, opţional.

command este o constantă intrinsecă specificând comanda care se execută.

Lista tuturor constantelor admise ca argument de comandă se poate vedea în Help (intrarea RunCommand Method
Constants) sau în Object Browser (Access în lista Project/Library, AcCommand în lista Classes).

Meniurile şi barele de unelte construite de utilizator nu pot fi accesate prin metoda RunCommand.

153
Obiectul Screen

Obiectul Screen se referă la forma, raportul, foaia de date (datasheet) sau controlul care are focusul. Acest obiect se
poate utiliza pentru a lucra cu un obiect particular de pe ecran. De exemplu, se poate utiliza proprietatea ActiveForm
pentru a returna o referinţă la forma din fereastra activă, fără a şti numele formei.

Obiectul Screen nu poate fi utilizat pentru activarea formei, raportului sau controlului. Acest efect se obţine prin metoda
SelectObject a obiectului DoCmd.

Referirea la Screen atunci când nu există nici o formă activă, raport sau control, produce o eroare de execuţie.

Proprietăţile obiectului Screen

Tabelul următor conţine proprietăţile obiectului Screen.

Proprietatea Descriere

ActiveControl Returnează o referinţă la controlul care are focusul.

ActiveDatasheet Returnează o referinţă la foaia de date care are focusul.

ActiveForm Returnează o referinţă la forma care are focusul.

ActiveReport Returnează o referinţă la raportul care are focusul

Application Returnează o referinţă la obiectul Application.

MousePointer Stabileşte sau întoarce valoarea tipului de pointer al mouse-ului.

Parent Returnează o referinţă la obiectul care conţine obiectul Screen.

PreviousControl Returnează o referinţă la controlul care a avut anterior focusul.

Tipul de pointer poate fi:

Valoare Explicaţie

0 (Default) Forma pointerului este determinată de Microsoft Access

1 Normal Select (Arrow)

3 Text Select (I-Beam)

7 Vertical Resize (Size N, S)

9 Horizontal Resize (Size E, W)

11 Busy (Hourglass)

Potrivit celor spuse anterior, utilizarea obiectului Screen trebuie să implementeze şi tratarea erorilor deoarece dacă
obiectul aşteptat nu are focusul, atunci se produce o eroare. Este de preferat să se utilizeze mai întâi metoda SetFocus
pentru a focaliza obiectul dorit şi apoi să se utilizeze Screen. Metoda SetFocus este cea asociată formei, raportului,

154
controlului ţintă. Este interzisă utilizarea obiectului Screen cu metoda OutputTo (care produce ieşirea unor date pe o
formă, raport etc.) a obiectului DoCmd.

Este de notat că proprietatea ActiveForm şi proprietatea Me nu produc în mod necesar aceeaşi referinţă. Me reprezintă
forma în care se execută curent codul, pe când ActiveForm returnează forma activă pe ecran şi care poate fi diferită de
cea în care se execută în acel moment cod Visual Basic. De exemplu, un eveniment Timer poate să apară pe o formă
care nu este activă. În acest caz Me este utilizat pentru a referi forma pe care se produce evenimentul Timer iar
ActiveForm se referă la forma activă pe ecran când se produce evenimentul Timer.

Următorul exemplu utilizează evenimentul Timer pentru a interoga forma activă la intervale regulate de timp. Forma în
care se declanşează evenimentul poate fi sau nu forma activă.

Private Sub Form_Load ()


Me.TimerInterval = 30000
End Sub

Private Sub Form_Timer ()


Const conFormNotActive As Integer = 2475
Const conFormInDesignView As Integer = 2478

On Error GoTo Error_Timer


' reconsultă sursa de date pentru forma activă
Screen.ActiveForm.Requery

Exit_Timer:
Exit Sub

Error_Timer:
If Err = conFormNotActive Or Err = conFormInDesignView Then
Resume Exit_Timer
Else
MsgBox Err & ": " & Err.Description
End If
End Sub

Observaţie. Intervalul de timp, din proprietatea TimerInterval este în milisecunde, instrucţiunea


Me.TimerInterval = 30000 stabileşte prin urmare declanşarea evenimentului la fiecare 30 de secunde. Stabilirea
intervalului se efectuează în procedura evenimentului Load.

DAO (Data Access Objects)

Biblioteca de tipuri Microsoft DAO oferă o cale de control a unei baze de date din orice aplicaţie care suportă Visual Basic
for Applications. Anumite obiecte DAO reprezintă structura bazei de date iar altele reprezintă datele însăşi. Prin
intermediul obiectelor DAO se pot crea şi gestiona baze de date locale sau la distanţă într-o multitudine de formate, se
poate lucra cu datele lor.

În acest capitol se explică cum se pot programa obiectele DAO din aplicaţiile Microsoft Office.

Lucrul cu obiectele DAO

Obiectele DAO se utilizează pentru a lucra în mod programatic cu o bază de date. Principalele acţiuni privesc:

• crearea unei baze de date, modificarea structurii tabelelor, interogărilor, indexărilor şi relaţiilor,

155
• regăsirea, adăugarea, ştergerea sau modificarea datelor din bază,
• implementarea securităţii datelor,
• lucrul cu date în diferite formate de fişiere şi legarea tabelelor din alte baze de date la baza curentă,
• conectarea la baze de date pe servere la distanţă şi construirea de aplicaţii client/server.

Observaţie. Pentru a utiliza obiectele DAO, trebuie ca la instalarea pachetului Microsoft Office să se selecteze şi boxa de
control Data Access.

Obiectele DAO sunt organizate într-o structură ierarhică. Obiectul DBEngine este de nivelul cel mai înalt şi conţine toate
celelalte obiecte şi colecţii ale ierarhiei DAO. Următorul tabel conţine o descriere sumară a obiectelor.

Obiect Descriere

Connection Conectarea prin reţea la o bază de date Open Database Connectivity (ODBC).

Container Informaţii de securitate pentru diferite tipuri de obiecte ale bazei de date.

Database Baza de date deschisă.

DBEngine Obiectul cel mai de sus al ierarhiei.

Document Informaţia de securitate pentru obiecte individuale din baza de date.

Error Informaţii de eroare privind accesul la date.

Field Câmp în obiecte TableDef, QueryDef, Recordset, Index, Relation.

Group Contul grupului în baza curentă.

Index Indexul tabelei.

Parameter Parametru de interogare.

Property Proprietate a unui obiect.

QueryDef Definiţia unei interogări salvate în baza de date.

Recordset Mulţime de înregistrări definite de o tabelă sau de o interogare.

Relation Legătura (relaţia) dintre două câmpuri de tabel sau interogări.

TableDef Definiţia unei tabele salvate în baza de date

User Contul utilizatorului în grupul de lucru curent.

Workspace Sesiunea DAO activă.

Proiectarea bazelor de date în Microsoft Access

Deşi se pot crea baze de date prin VB cu DAO, uneori, pentru baze de date cu oarecare grad de permanenţă, se poate
alege varianta de

• a proiecta baza de date în mediul Access destinat pentru asemenea operaţiuni şi

156
• deschiderea bazei cu DAO din altă aplicaţie care suportă Visual Basic.

La crearea unei baze de date în Access, următoarele lucruri sunt de reţinut.

o Când se deschide un fişier .mdb creat în Access din altă aplicaţie, nu se poate lucra cu forme, rapoarte,
macro-uri sau module Access. Formele şi rapoartele trebuiesc proiectate, deasemenea şi codul VB, în
aplicaţia unde se lucrează.
o Dacă se scrie cod pentru procesarea unei baze de date în Access, codul respectiv nu se va executa în
mod necesar şi la copierea în modulele altei aplicaţii. Pentru execuţie trebuie, în acest caz, să se
elimine/înlocuiască toate entităţile specifice Access-ului (obiecte, metode, proprietăţi sau funcţii).
o În Access se utilizează funcţia CurrentDb pentru a returna o referinţă la baza de date curent deschisă în
fereastra Access. Se poate utiliza DAO pentru a lucra cu această bază. Dacă se copie acest cod în altă
aplicaţie care are Visual Basic, se va modifica textul sursă încât să se utilizeze metoda OpenDatabase a
obiectului Workspace.
o Microsoft Access creează proprietăţi suplimentare ale obiectelor DAO. Atunci când se formează o bază
cu DAO în Visual Basic şi această bază este deschisă ulterior în microsoft Access, se pot observa şi alte
proprietăţi adăugate obiectelor. Aceste proprietăţi sunt şi ele enumerate în colecţia Properties a
obiectului DAO.

Stabilirea unei referinţe la biblioteca de obiecte DAO

Referinţa se poate realiza în mod automat, de exemplu de către Microsoft Access, sau manual prin succesiunea uzuală:
Visual Basic Editor – meniul Tools – References – selectare Microsoft DAO 3.5 Object Library. După stabilirea
referinţei se pot vedea obiectele DAO în Object Browser selectând DAO în lista Project/Library.

Pentru anumite probleme de compatibilitate, pentru proiectele mai vechi, se poate referi Microsoft DAO 2.5/3.5
compatibility library. Proba completă pentru a vedea dacă este nevoie de referirea bilbiotecii de compatibilitate este
compilarea codului sub DAO 3.5. Dacă nu există erori rezultă că nu este necesară biblioteca de compatibilitate.

Referirea obiectelor DAO în Visual Basic

Obiectele DAO pot fi referite în cod în acelaşi mod ca orice alt obiect. Deoarece obiectul DBEngine nu are o colecţie,
poate fi referit direct. Celelalte obiecte se vor referi în cadrul colecţiilor unde aparţin şi potrivit locului din ierarhia
deobiecte.

Fiecare obiect poate fi referit într-o colecţie

• prin valoarea proprietăţii Name a obiectului respectiv sau


• prin numărul de ordine din colecţie. Obiectele DAO sunt indexate plecând cu 0.

Exemple:

Databases("Salariati")
Databases(0)

Referirea unui obiect Database în cod se realizează şi prin poziţionarea în ierarhie:

Dim dbs As Database


Set dbs = DBEngine.Workspaces(0).Databases(0)

157
prin care se obţine o referinţă la prima bază de date (indicele 0 din colecţia Databases) din prima zona de lucru (indicele
0 din colecţia Workspaces), zona implicită. De notat că dacă se lucrează într-o aplicaţie diferită de Access, atunci trebuie
să se deschidă o bază de date cu metoda OpenDatabase mai înainte de a rula codul precedent.

Pentru aplicaţiile diferite de Access, calificarea obiectelor poate produce mai multă claritate, plus certitudinea referii
corecte:

Dim dbs As DAO.Database

Adăugarea de noi obiecte DAO la o colecţie

După cum s-a precizat deja, anumite obiecte DAO reprezintă structura bazei de date, celelalte oferind mijloace de lucru
cu datele din bază. Obiectele care reprezintă structura bazei sunt salvate o dată cu baza. În general, obiectele utilizate în
lucrul cu datele din bază nu sunt salvate ci sunt create de fiecare dată când este nevoie de ele.

Crearea unui nou obiect DAO care trebuie salvat cu baza de date se va completa cu utilizarea metodei Append a
colecţiei asociate de obiecte salvate.

Exemplul următor dă o imagine despre acest proces. Exmplul creează un nou obiect TableDef (care reprezintă o nouă
tabelă) cu un nou obiect Field (care reprezintă un câmp din noua tabelă). Obiectul Field creat se adaugă la colecţia
Fields a noii tabele iar noul obiect TableDef este adăugat la colecţia TableDefs a obiectului Database care reprezintă
baza de date deschisă.

Function AddTable () As Boolean


' declaraţii
Dim dbs As Database, tdf As TableDef, fld As Field
Const conPath As String = "C:\ …\Northwind.mdb"

On Error GoTo Err_AddTable


' asignarea bazei curente la variabila database
Set dbs = DAO.DBEngine.Workspaces(0).OpenDatabase(conPath)
' crearea noii tabele
Set tdf = dbs.CreateTableDef("ArchivedInvoices")
Set fld = tdf.CreateField("OrderId", dbLong)

' adăugarea la colecţiile adecvate, care se salvează


tdf.Fields.Append fld
dbs.TableDefs.Append tdf
dbs.Close
AddTable = True

Exit_AddTable:
Exit Function

Err_AddTable:
MsgBox "Error " & Err & ": " & Err.Description
AddTable = False
Resume Exit_AddTable
End Function

Observaţie. În Access se va utiliza CurrentDb pentru a returna o referinţă la baza de date curentă deschisă.

158
Lucrul cu date externe

Se poate utiliza DAO pentru lucrul cu diferite formate de baze de date. Există trei mari categorii de formate de baze de
date accesibile prin DAO.

Prima categorie este caracterizată de formatul Microsoft Jet. Se poate utiliza DAO cu toate bazele de date create cu
Microsoft Jet, incluzând cele create în Microsoft Access, Microsoft Visual Basic, Microsoft Visual C++ şi Microsoft Excel.

A doua categorie este caracterizată de formatul ISAM instalabil. Un driver ISAM care se poate instala este un driver care
oferă acces la formate de baze de date externe prin DAO şi Microsoft Jet. La instalarea aplicaţiei se poate cere instalarea
oricărui driver pentru formatele:

• Microsoft FoxPro
• dBase
• Paradox
• Microsoft Excel
• Microsoft Exchange/Outlook
• Lotus 1-2-3
• Date tabelare în fişiere HTML
• etc.

A treia categorie de formate de baze de date accesibile prin DAO este sursa de date Open Database Connectivity
(ODBC). Sursele de date ODBC, cum ar fi Microsoft SQL Server 4.2 şi mai mari, necesită un driver ODBC. Adesea o
sursă de baze ODBC este pe un server de reţea, adică ODBC este util pentru dezvoltarea aplicaţiilor client/server.
Următoarea secţiune tratează subiectul mai pe larg.

Utilizare DAO cu surse de date ODBC

Există două moduri diferite de utilizare DAO cu ODBC: – prin Microsoft Jet, sau – prin noua tehnologie numită
ODBCDirect.

Dacă se lucrează cu o baza de date creată cu Microsoft Jet database engine sau într-un format extern suportat de un
driver instalabil ISAM, toate operaţiunile DAO sunt procesate prin Microsoft Jet.

Dacă se lucrează cu o sursă de date ODBC, operaţiunile DAO se pot procesa fie prin Microsoft Jet, fie prin ODBCDirect
care ocoleşte motorul Microsoft Jet şi lucrează direct cu datele în sursa ODBC. Alegerea este în funcţie de tipul de
operaţiuni efectuate.

Se poate utiliza DAO cu Microsoft Jet, pentru surse ODC, atunci când sunt necesare avantajele Jet: abilitatea de a crea
sau modifica obiecte, unirea datelor din mai multe formate de baze de date.

Se poate utiliza ODBCDirect atunci când se execută interogări sau proceduri memorate pe un server back_end cum ar fi
Microsoft SQL Server, sau când aplicaţia client unde se lucrează necesită capacităţile specifice ODBC cum ar fi
actualizări în loturi sau interogări asincrone. ODBC poate efectua anumite operaţiuni client/server mult mai repede.

Deoarece nu toate posibilităţile DAO sunt accesibile cu ODBCDirect, Microsoft DAO mai suportă încă ODBC prin
Microsoft Jet. Se poate astfel utiliza ODBC prin Microsoft Jet, prin ODBCDirect, sau prin ambele cu o singură sursă de
date ODBC.

Metoda care este utilizată în accesarea unei surse ODBC este determinată de tipul spaţiului de lucru în care se lucrează.
Un spaţiu de lucru, reprezentat printr-un obiect Workspace, este o sesiune deschisă pentru un cont utilizator particular. O
sesiune marchează o succesiune de operaţii efectuate de motorul de baze de date, începe cu intrarea (log on)

159
utilizatorului şi se termină la ieşirea utilizatorului (log off). Operaţiunile pe care un utilizator le poate executa în timpul unei
sesiuni sunt determinate de drepturile conferite acelui utilizator. Dacă nu se specifică tipul spaţiului de lucru, DAO
creează un spaţiu în mod implicit.

Cu DAO 3.5 se poate crea oricare dintre cele două spaţii de lucru pentru operaţii ODBC. În spaţiul Microsoft Jet se
utilizează accesul prin Jet, în spaţiul ODBCDirect se va utiliza cealaltă posibilitate. Fiecare spaţiu de lucru are propriul
model de obiecte şi vor fi prezentate în continuarea capitolului.

Utilizare DAO cu Microsoft Jet

Spaţiile de lucru Microsoft Jet includ obiecte pentru definirea structurii bazei de date, cum ar fi TableDef, QueryDef,
Field, Index, Parameter şi Relation. Alte obiecte, cum ar fi Recordset, sunt utile pentru procesarea datelor din bază. O
a treia categorie de obiecte, cum ar fi User, Group, Container şi Document, servesc pentru asigurarea securităţii
datelor.

Pentru a vedea întreaga ierarhie de obiecte pentru spaţiul de lucru Microsoft Jet se va selecta Help (Microsoft Access
Programming and Language References) – Microsoft Data Access Objects (DAO) – "Data Access Object Model for
Microsoft Jet Workspaces".

In schema următoare este prezentată doar partea superioară a ierarhiei. La prezentarea fiecărui obiect se vor aduce
unele explicaţii suplimentare.

Se observă că obiectul de nivel cel mai înalt, DBEngine, nu aparţine unei colecţii, deci poate fi referit direct. Toate
celelalte obiecte sunt referite prin colecţia la care aparţin. Săgeţile fără obiect terminal punctează către structuri
nereprezentate în figură.

Obiectul DBEngine

Obiectul DBEngine, de nivel maxim în ierarhia de obiecte DAO, este obiectul implicit al modelului, astfel încât
menţionarea lui explicită poate fi omisă în multe situaţii.

Pe nivelul imediat inferior al ierarhiei se găsesc două colecţii: Workspaces – spaţiile de lucru, Errors – erorile apărute în
timpul unei operaţiuni DAO. Colecţia Workspaces este implicită şi referinţa la ea poate fi omisă.

O referinţă la primul obiect Workspace din colecţia Workspaces poate fi obţinută prin una din instrucţiunile

Set wrk = DBEngine.Workspaces (0)


Set wrk = DBEngine (0)
Set wrk = Workspaces (0)

în care se observă prezenţa opţională a obiectelor implicite.

Proprietăţile obiectului DBEngine sunt prezentate în tabelul următor.

Proprietatea Descriere

DefaultType Long, determină tipul spaţiului de lucru:


dbUseJet –Microsoft Jet database engine
dbUseODBC – ODBC data source

DefaultUser, Şiruri, numele utilizatorului şi parola


DefaultPassword

160
IniPath Şir, informaţia despre cheia din Windows Registry care conţine valorile pentru Microsoft Jet
database engine (numai spaţiile de lucru Microsoft Jet).

LoginTimeout Întreg, timpul cât se aşteaptă intrarea unu utilizator.

SystemDB Şir, calea pentru localizarea curentă a fişierului cu informaţia despre grupurile de lucru,
workgroup (doar spaţii Microsoft Jet).

Version Şir, informaţii despre versiunea DAO.

Dacă nu se creează un obiect Workspace specific, un asemenea obiect este creat în mod automat de DAO atunci când
este necesar. Atributele implicite ale acestui spaţiul sunt DefaultUser egal cu Admin iar DefaultPassword egal cu şirul
vid "".

În mod implicit, proprietatea DefaultType are valoarea dbUseJet şi spaţiul de lucru este Microsoft Jet. Proprietatea poate
fi acoperită pentru un spaţiu particular prin tipul precizat la crearea acestuia.

Metodele obiectului DBEngine sunt

Metoda Descriere

BeginTrans, Metodele care controlează efectuarea tranzacţiilor.


CommitTrans,
Rollback

CompactDatabase, Compactarea bazei de date, refacerea unei baze deteriorate.


RepairDatabase

CreateDatabase, Crearea unei baze de date sau a unui spaţiu de lucru.


CreateWorkspace

Idle Suspendă procesarea datelor din bază

OpenConnection, Deschide şi returnează o referinţă la un obiect Connection, respectiv Database.


OpenDatabase

RegisterDatabase Completează în Windows Registry informaţia ODBC.

SetOption Înlocuieşte temporar valorile din Windows Registry pentru spaţiile Microsoft Jet

Unele metode sunt prezentate în continuare. Pentru mai multe informaţii despre funcţiuni şi parametri se vor vedea
intrările respective din DAO Help.

Colecţia Workspaces

Obiectul DAO Workspace defineşte o sesiune pentru un utilizator, bazată pe permisiunile (drepturile) utilizatorului. Se
utilizează obiectul Workspace pentru a gestiona sesiunea curentă. Workspace conţine bazele de date deschise şi oferă
mecanismul necesar tranzacţiilor şi securităţii aplicaţiei. Colecţia Workspaces conţine toate obiectele active Workspace
din DBEngine, care au fost adăugate colecţiei.

La începutul lucrului cu obiecte DAO din Visual Basic, DAO creează în mod automat un spaţiu implicit. Referirea la
acesta se realizează prin

161
Dim wrk As Workspace
Set wrk = Workspaces (0)

adică se referă primul obiect din colecţie.

Spaţiile de lucru DAO pot fi partajate sau ascunse. Un spaţiu este ascuns până când utilizatorul îl marchează drept
partajat prin adăugarea obiectului Workspace la colecţia Workspaces. După adăugare, spaţiul este accesat prin
intermediul colecţiei. Un obiect Workspace necesar doar pentru o procedură particulară se poate crea dar fără
adăugarea la colecţia Workspaces.

După cum s-a mai spus, există două tipuri de obiecte Workspace: Microsoft Jet şi ODBCDirect. În Microsoft Jet se poate
utiliza DAO cu motorul de baze de date Microsoft Jet pentru a accesa date din baze de date Microsoft Jet, surse de date
ISAM instalabile şi surse de date ODBC. Într-un spaţiu ODBCDirect, se poate utiliza DAO pentru a accesa date din surse
ODBC fără a trece prin motorul Jet. Într-o aceeaşi aplicaţie se poate lucra cu ambele tipuri de spaţii de lucru.

Crearea unui spaţiu Microsoft Jet

Se utilizează metoda CreateWorkspace a obiectului DBEngine. Exemplul următor utilizează constanta de tip dbUseJet.
Dacă proprietatea DefaultType este fixată pe dbUseJet, atunci argumentul de tip nu este necesar şi se creează în mod
automat un spaţiu Microsoft Jet.

Dim wrk As Workspace


Set wrk = CreateWorkspace("JetWorkSpace", "Admin", "", dbUseJet)

noul spaţiu fiind pentru utilizatorul Admin şi fără parolă.

Noul spaţiu de lucru nu este adăugat în mod automat la colecţia Workspaces, pentru aceasta se va utiliza metoda
Append a colecţiei. Acest lucru este necesar atunci când spaţiul nou definit este utilizat şi în afara procedurii unde a fost
creat.

Metoda CreateWorkspace (obiectul DBEngine)

Sintaxa

Set workspace = CreateWorkspace(name, user, password, type)

unde

workspace este o variabilă obiect care reprezintă obiectul Workspace care se creează.

name este şirul care conţine numele unic al obiectului. Începe cu o literă, are lungimea maximă 20.

user identifică proprietarul noului obiect Workspace.

password conţine parola pentru noul obiect Workspace, un şir până la 14 caractere cu excepţia lui null.

type este opţional şi stabileşte tipul spaţiului (dbUseJet, dbUseODBC)

După utilizarea metodei este creat obiectul Workspace, începe o nouă sesiune şi obiectul poate fi referit în cod.
Obiectele Workspace nu sunt permanente, nu se pot salva iar proprietatea Name nu mai poate fi modificată după
trecerea obiectului în colecţia Workspaces.

162
Dacă tipul este stabilit la dbUseODBC şi nu există deja create spaţii Jet, atunci motorul Jet nu este încărcat în memorie
şi toată activitatea se efectuează cu sursa de date ODBC identificată în obiectul Connection.

Pentru a elimina un obiect Workspace din colecţia Workspaces, se închid toate bazele de date şi conexiunile şi apoi se
utilizează metoda Close a obiectului Workspace.

Colecţia Errors (obiectul DBEngine)

Un obiect Error conţine informaţia despre o eroare apărută în timpul unei operaţiuni DAO. Apariţia mai multor erori în
aceeaşi operaţiune se reflectă în obiecte Error distincte, mulţimea acestora formând colecţie Errors. Atunci când o nouă
operaţiune generează o eroare, colecţie Errors este golită şi completată cu noile erori. Operaţiunile DAO care nu
generează erori nu au efect asupra colecţiei Errors.

Erorile sunt indexate în colecţie în ordinea crescătoare a nivelelor de eroare. Nivelul cel mai înalt (deci ultimul obiect din
colecţie) este eroare raportată de VBA, identică cu eroarea raportată de obiectul VBA Err.

Colecţia Errors are:

• proprietatea Count, care dă numărul elementelor din colecţie


• metoda Refresh, care actualizează colecţia potrivit situaţiei curente.

Obiectul Error nu are decât proprietăţile (nu conţine metode sau colecţii)

• Description, şirul care conţine descrierea erorii


• HelpContext, este un Long cu identificatorul de context din fişierul Help asociat
• HelpFile, conţine calea completă către fişierul Help
• Number, numărul (Long) al erorii. Pentru o listă completă se va vedea intrarea Trappable Microsoft Jet and DAO
Errors din Help.
• Source, un şir conţinând numele obiectului sau aplicaţiei care a generat eroarea.

Colecţia Databases

Obiectul Database reprezintă o bază de date deschisă. Această poate fi o bază Jet sau o sursă externă de date. Colecţia
Databases conţine toate bazele de date deschise curent.

Situarea în ierarhie este

Obiectul sau colecţia Este conţinut în Conţine

Database (obiect) Colecţia Databases Colecţia Containers Colecţia QueryDefs


Colecţia Properties Colecţia Recordsets
Colecţia Relations Colecţia TableDefs

Databases (colecţie) Obiectul Workspace Obiecte Database

Deschiderea unei baze de date

Metoda OpenDatabase, a obiectului DBEngine sau a obiectului Workspace, deschide o bază de date şi returnează o
referinţă la obiectul care o reprezintă. Utilizarea metodei cu obiectul DBEngine deschide baza de date în spaţiul de lucru
implicit, ca în exemplul următor

163
Function RetrieveRecordset (strDbName As String, strSource As String ) As Boolean
Dim dbs As Database
Dim rst As Recordset

On Error GoTo Err_RetrieveRecordset


Set dbs = OpenDatabase (strDbName)
Set rst = dbs.OpenRecordset(strSource, dbOpenDynaset)
' se prelucrează înregistrările din recordset

RetrieveRecordset = True

Exit_RetrieveRecordset:
rst.Close
dbs.Close
Exit Function

Err_RetriveRecordset:
MsgBox "Eroare " & Err & ": " & Err.Description
RetrieveRecordset = False
Resume Exit_RetriveRecordset
End Function

În Microsoft Access, se utilizează funcţia CurrentDb pentru a returna o referinţă la baza de date curentă. Metoda
OpenDatabase se utilizează pentru deschiderea altei baze de date decât cea curent deschisă sau pentru a deschide
baze în spaţiul de lucru ODBCDirect.

Dim dbs As Database


Set dbs = CurrentDb
Debug.Print dbs.Name

Crearea cu DAO a duplicatelor unei baze de date (database replicas)

Diferite necesităţi de arhivare sau de lucru în reţea impun crearea şi gestionarea unor copii ale unei baze de date. Una
dintre copii este desemnată drept Design Master, celelalte copii find denumite duplicate sau replici. Replicile pot fi
menţinute pe aceeaşi maşină sau pe maşini diferite.

Adăugarea, modificarea sau ştergerea obiectelor se poate efectua doar în Design Master. Datele pot fi modificate în
Design Master şi în orice replică a bazei de date. Atunci când un utilizator modifică date dintr-o bază duplicată, utilizatorii
celorlalte replici pot să-şi sincronizeze replicile, astfel încât aceleaşi date să fie în toate copiile.

Se poate utiliza DAO pentru a face o bază replicabilă, pentru a crea replici, le sincroniza şi gestiona mulţimea replicilor.
Se pot crea, de asemenea, replici parţiale care conţin doar o submulţime de înregistrări dintr-o replică totală. Utilizarea
replicilor parţiale permite sincronizarea unei replici doar cu datele necesare şi nu cu întreaga bază de date.

Pentru ca o bază de date să admită replici trebuie să se fixeze proprietatea Replicable sau proprietatea ReplicableBool
a obiectului Database corespunzător. Aceste proprietăţi nu există pentru obiectul Database până când nu sunt create
prin metoda CreateProperty şi adăugate la colecţia Properties. După permiterea replicărilor, crearea unei baze duplicat
se realizează prin metoda MakeReplica.

Diferenţa dintre proprietăţile Replicable şi ReplicableBool este de valori: prima are o valoare şir, a doua o valoare
logică.

Următorul exemplu creează manual o copie a bazei de date, o face replicabilă şi creează o replică a bazei.

164
Function ReplicateDatabase (strDBName As String) As Boolean
Dim dbs As Database, prp As Property
Dim strBackup As String, strReplica As String
Const conPropNotFound As Integer = 3270
On Error GoTo Err_ReplicateDatabase
If InStr(strDBName, ".mdb") > 0 Then
strBackup = Left(strDBName, Len(strDBName) - 4)
Else
strBackup = strDBName
End If

strReplica =strBackup & "Replica" & ".mdb"


If MsgBox("Make backup copy of file?", vbOKCancel) = vbOK Then
strBackup = strBackup & ".bak"
FileCopy strDBName, strBackup
MsgBox "Copied file to " & "strBackup"
End If

Set dbs = OpenDatabase (strDBName, True)


dbs.Properties("ReplicaBool") = True
dbs.MakeReplica strReplica, "Replica of " & strDBName
MsgBox "Created replica '" & strReplica & "'."
dbs.Close
ReplicateDatabase = True

Exit_ReplicateDatabase:
Exit Function

Err_ ReplicateDatabase:
If Err = conPropNotFound Then
Set prp = dbs.CreateProperty("ReplicableBool", dbBoolean, True)
dbs.Properties.Append prp
Resume Next
Else
MsgBox "Error " & ": " & Err.Description
End If
ReplicateDatabase = False
Resume Exit_ReplicateDatabase
End Function

Colecţia TableDefs

Un obiect TableDef reprezintă definiţia memorată a unei tabele din bază sau a unei tabele legate din spaţiul de lucru
Microsoft Jet. Toate obiectele TableDef memorate într-o bază de date formează colecţia TableDefs. Relaţiile din ierarhie
sunt

Obiectul sau Este conţinut în Conţine


colecţia

TableDef (obiect) Colecţia TableDefs Colecţia Fields


Colecţia Indexes
Colecţia Properties

TableDefs (colecţie) Obiectul Database Obiecte TableDef

165
Crearea prin cod a unei tabele

Metoda de creare este CreateTableDef a obiectului Database. După crearea unui nou obiect TableDef, dar înainte de
adăugarea la bază, trebuie să se definească unul sau mai multe câmpuri pentru tabela definită. Sintaxa metodei
CreateTableDef este

Set tabledef = database.CreateTableDef (name, attributes, source, connect)

unde

tabledef este o variabilă obiect reprezentând obiectul TableDef care se creează.

database este o variabilă obiect reprezentând obiectul Database unde se doreşte crearea noului obiect.

name este un şir opţional, care conţine denumirea tabelei.

attributes este o constantă sau o combinaţie de constante indicând caracteristici ale tabelei. Lista este în Help - TableDef
object - Attributes Property.

source este un Variant (subtip String), opţional. Conţine numele tabelei în baza de date externă care este sursa datelor.
Şirul devine proprietatea SourceTableName a noului obiect.

connect, un Variant (subtip String), opţional. Conţine informaţia despre sursa unei baze deschise, o bază de date utilizată
într-o interogare pass-through, sau o tabelă legată. La proprietatea Connect se pot găsi mai multe informaţii.

Argumentele care se omit la crearea tabelei se vor asigna prin proprietăţi înainte de adăugarea obiectului la colecţie.
După aceea nu mai sunt disponibile toate proprietăţile.

Pentru eliminarea unui obiect TableDef se utilizează metoda Delete a colecţiei TableDefs.

Următorul exemplu realizează crearea unei tabele pentru baza de test Northwind.

Function CreateErrorsTable () As Boolean


Dim dbs As Database, tdf As TableDef, fld As Field, idx As Index
Dim rst As Recordset, intCode As Integer, strErr As String
Const conAppObjErr = "Application-defined or object-defined error"

' creează tabela Errors cu câmpurile ErrorCode şi ErrorString


Set dbs = CurrentDb

On Error Resume Next


' ştergerea unei tabele Errors existente
dbs.TableDefs.Delete "Errors"

On Error GoTo Error_CreateErrorsTable


' crearea tabelei
Set tdf = dbs.CreateTableDef("Errors")
' creare câmpuri
Set fld = tdf.CreateField("ErrorCode", dbInteger)
tdf.Fields.Append fld
Set fld = tdf.CreateField("ErrorString", dbMemo)
tdf.Fields.Append fld

166
' creare index
Set idx = tdf.CreateIndex("ErrorCodeIndex")
Set fld = idx.CreateField("ErrorCode")
With idx
.Primary = True
.Unique = True
.Required = True
End With
idx.Fields.Append fld
tdf.Indexes.Append idx

' deschidere recordset în tabela Errors


Set rst = dbs.OpenRecordset("Errors")
' stabilirea indexului pentru recordset
rst.Index = "ErrorCodeIndex")

' arătarea pointerului clepsidră


DoCmd.Hourglass True

' ciclarea în codurile de eroare


For intCode = 1 To 32767
On Error Resume Next
strErr = ""
' tentativa de apariţie a une erori
Err.Raise intCode
' verificarea dacă eroarea este VBA, DAO sau Access
' dacă eroarea nu este VBA, atunci proprietatea Description a obiectului
'Err conţine textul "Application-defined or object-defined error"
If Err.Description <> conAppObjErr Then
strErr = Err.Description
' se utilizează metoda AccessError pentru returnarea şirului descriptiv
' pentru erorile DAO şi Access.
ElseIf AccessError(intCode)<>conAppObjErr Then
strErr = AccessError(intCode)
End If

' dacă numărul de eroare are un şir descriptiv, se adaugă la tabela definită
If Len(strErr) > 0 Then
'Adăugarea noii înregistrări la recordset
rst.AddNew
' adăugarea numărului erorii la tabelă
rst!ErrorCode = intCode
' adăugarea şirului descriptiv
rst!ErrorString.AppendChunk strErr
' actualizare înregistrare
rst.Update
End If
Next intCode

DoCmd.Hourglass False
' închidere recordset
rst.Close
MsgBox "Errors table created"
' arătarea noii tabele în fereastra Database (din Access)
RefreshDatabaseWindow

167
CreateErrorsTable = True

Exit_CreateErrorsTable:
Exit Function

Error_CreateErrorsTable:
MsgBox Err & ": " & Err.Description
CreateErrorsTable = False
Resume Exit_CreateErrorsTable
End Function

Legarea unei tabele la o bază de date

Pentru a utiliza într-o bază de date tabele dintr-o sursă de date externă, aceasta trebuie legată la baza de date. Se pot
lega tabele care sunt în altă bază de date Microsoft Jet, sau tabele din alte programe şi formate de fişiere, cum ar fi
Microsoft Excel, dBase, Microsoft FoxPro etc. Acest mod este mai eficient decât să se deschidă baza de date externă
direct, mai ales dacă tabela vine dintr-o sursă de date ODBC.

Pentru a lega o tabelă la o bază de date, se utilizează metoda CreateTableDef pentru a crea o nouă tabelă. După aceea
se specifică valorile pentru proprietăţile Connect şi SourceTableName ale noului obiect creat. Se poate stabili de
asemenea proprietatea Attributes. În final se adaugă tabela la colecţia TableDefs.

Următorul exemplu leagă o foaie de calcul Excel 8.0 ca o tabelă la o bază de date. Înainte de executarea unui astfel de
exemplu trebuie să ne convingem că pe sistem este instalat driverul Microsoft Excel ISAM (Msexcl35.dll). Acest driver
permite fişierelor Excel 97 să lucreze cu Microsoft Jet database engine.

Function LinkExcelTable() As Boolean


Dim dbs As DAO.Database, tdf As DAO.TableDef

Const errNoISAM As Integer = 3170


Const conPath As String = _
"C:\Program Files … \Northwind.mdb"

On Error GoTo Err_LinkExcelTable


' returnează o referinţă la baza de date Northwind
Set dbs = OpenDatabase(conPath)
' creează un nou obiect TableDef
Set tdf = dbs.CreateTableDef("LinkedTable")
' specifică domeniul care este tabela sursă
tdf.SourceTableName = "DataRange"
' specifică şirul de conectare
tdf.Connect = "EXCEL 8.0; DATABASE=C:\My Documents\XLTable.xls"
' adăugarea noului obiect la colecţie
dbs.TableDefs.Append tdf
LinkExcelTable = True

Exit_LinkExcelTable:
Exit Function

Err_LinkExcelTable:
If Err = errNoISAM Then
Dim strErr As String
strErr = Err & ": " & Err.Description
strErr = strErr _
& " You may not have the ISAM driver installed properly …"
168
MsgBox strErr, vbOKOnly, "Error!"
Else
MsgBox "Error " & Err & ": " & Err.Description
End If
End Function

Colecţia Fields

În spaţiul de lucru Microsoft Jet, obiectul Field reprezintă un câmp dintr-o tabelă, interogare, index, relaţie sau recordset.
Colecţie Fields conţine toate obiectele Field asociate, respectiv, obiectele TableDef, QueryDef, Index, Relation sau
Recordset.

Localizarea în ierarhia de obiecte este

Obiectul sau Este conţinut în Conţine


colecţia

Field (obiect) Colecţia Fields Colecţia Properties

Fields (colecţie) Obiectul TableDef Obiecte Field


Obiectul Index
Obiectul QueryDef
Obiectul Recordset
Obiectul Relation

Colecţia Fields este colecţia implicită a unui obiect TableDef, QueryDef, Index, Relation sau Recordset, ceea ce
înseamnă că nu trebuie făcută o referinţă la colecţie în mod explicit. De exemplu, următoarele instrucţiuni returnează o
referinţă la câmpul LastName din tabela Employees din baza de date de test Northwind.

Dim dbs As Database, tdf As TableDef, fld As Field


Const conPath As String = _
"C:\Program Files\ … \Northwind.mdb"
Set dbs = OpenDatabase(conPath)
Set tdf = dbs.TableDefs("Employees")
Set fld = tdf!LastName

În colecţia Fields a unui obiect TableDef, QueryDef, Index sau Relation, obiectul Field este o unitate structurală. El
reprezintă o coloană dintr-o tabelă, având un tip particular de date. Dacă se creează o bază de date în Microsoft Access,
se pot crea câmpuri pentru toate aceste obiecte şi să se fixeze proprietăţile lor în mediul Access şi nu este necesară
utilizarea programării în acest scop.

Într-un obiect Recordset, un obiect Field conţine date şi poate fi utilizat pentru a citi date dintr-o înregistrare sau scrie
date într-o înregistrare. În interfaţa utilizator Access nu se poate lucra, totuşi, cu câmpurile obiectului Recordset; trebuie
săse facă apel la DAO.

Colecţia Fields a obiectului TableDef conţine toate câmpurile definite. Pentru un obiect QueryDef, colecţia conţine toate
câmpurile incluse în interogare din una sau mai multe tabele. Colecţia Fields a obiectului Index include câmpurile pentru
care este definit indexul.

Pentru un obiect Relation, colecţia conţine câmpurile implicate în relaţie. Tipic, există două câmpuri în colecţia Fields:
unul care este cheia primară, specificat de proprietatea Table a obiectului Relation; al doilea este câmpul extern
corespunzător, din tabela specificată de proprietatea ForeignTable a obiectului Relation.

169
Colecţia Fields a obiectului Recordset conţine câmpurile specificate în argumentul source a metodei OpenRecordset.
Argumentul source specifică sursa înregistrărilor pentru noul obiect Recordset şi poate fi un nume de tabelă, nume de
interogare sau o instrucţiune SQL care returnează înregistrări.

Proprietatea Value a obiectului Field se aplică doar unui obiect din colecţia Fields a unui obiect Recordset. Proprietatea
returnează valoare datei memorate în acel câmp în înregistrarea curentă. Deoarece Value este proprietatea implicită a
obiectului Field iar Fields este colecţia implicită a obiectului Recordset, se poate returna valoarea unui câmp fără a
specifica explicit fie Fields, fie Value. Exemplul următor este sugestiv în acest sens:

Dim dbs As Database, rst As Recordset


Const conPath As String = _
"C:\Program Files\ … \Northwind.mdb"
Set dbs = OpenDatabase(conPath)
Set rst = dbs.OpenRecordset("Employees")
' referinţa explicită la colecţie şi valoare
Debug.Print rst.Fields("LastName").Value
' referinţă explicită la valoare
Debug.Print rst!FirstName.Value
' referinţe implicite
Debug.Print rst!Title

Colecţia Indexes

Un obiect Index reprezintă un index dintr-o tabelă a bazei de date, în spaţiul de lucru Microsoft Jet. Colecţia Indexes
conţine toate obiectele Index definite pentru o tabelă particulară.

Poziţia în ierarhia de obiecte este următoarea:

Obiectul sau colecţia Este conţinut în Conţine

Index (obiect) Colecţia Indexes Colecţia Fields


Colecţia Properties

Indexes (colecţie) Obiectul TableDef Obiecte Index

Un index măreşte viteza de căutare şi sortare a tabelei. Se poate îmbunătăţi performanţa interogării bazei de date prin
indexarea câmpurilor pe ambele părţi ale joncţiunilor, câmpuri care sunt sortate, sau câmpuri care sunt utilizate drept
criterii de interogare. Totuşi, indexurile pot să mărească dimensiunea bazei şi să încetinească performanţa când se
actualizează câmpuri indexate, când se adaugă sau se elimină date. Performanţa poate fi redusă şi în cazul aplicaţiilor
multiuser. Din aceste motive utilizarea indexurilor va fi făcută cu atenţie.

Un index specifică ordinea în care înregistrările sunt accesate din tabelele bazei de date într-un obiect Recordset de tip
tabelă.

Pentru a crea un index cu DAO, operaţiune posibilă pentru unul sau mai multe câmpuri, trebuie

o metoda CreateIndex pentru obiectul TableDef.


o metoda CreateField pentru obiectul Index cu scopul creerii unui obiect Field pentru fiecare câmp
(coloană) care se include în obiectul Index.
o Stabilirea proprietăţilor obiectului Index.
o Metoda Append pentru fiecare obiect Field care se adaugă la colecţia Fields.
o Metoda Append pentru adăugarea noului obiect Index la colecţia Indexes.

170
Următorul exemplu este ilustrativ.

Sub SeekRecord ()
Const conPath As String = _
"C:\Program Files\ … \Northwind.mdb"
Dim dbs As Database, tdf As TableDef, idx As Index
Dim fld As Field, fldLast As Field, fldFirst As Field
Dim rst As Recordset

' returnarea unei referinţe la baza de date Northwind


Set dbs = DBEngine().OpenDatabase(conPath)
' returnarea unei referinţe la tabela Employees
Set tdf = dbs.TableDefs("Employees")
' crearea unui index nou pe câmpurile LastName şi FirstName
Set idx = tdf.CreateIndex("FirstLastName")
' crearea câmpurilor din index
Set fldLast = idx.CreateField("LastName", dbText)
Set fldFirst = idx.CreateField("FirstName", dbText)
' adăugarea obiectelor Field
idx.Fields.Append fldLast
idx.Fields.Append fldFirst
' fixarea proprietăţii Required
idx.Required = True
' adăugarea noului obiect index
tdf.Indexes.Append idx
' deschiderea recordset-ului de tip tabelă
Set rst = dbs.OpenRecordset("Employees")
' fixarea proprietăţii Index a obiectului Recordset
rst.Index = idx.Name
' efectuarea operaţiunii de căutare
rst.Seek "=", "King", "Robert"
' tipărirea valorilor tuturor câmpurilor cu excepţia câmpului Photo
For Each fld In rst.Fields
If fld.Type <> dbLongBinary Then
Debug.Print fld
End If
Next fld
End Sub

Observaţie. În mediul Microsoft Access se poate lucra cu mulţimea indexurilor în meniul View, comanda Indexes.

Colecţia QueryDefs

Printr-o interogare înţelegem o operaţiune, formalizată, prin care este returnată o mulţime de înregistrări care satisfac
cerinţe impuse sau se execută o acţiune specifică asupra unei mulţimi de înregistrări selectate după cerinţele din
interogare.

Un obiect QueryDef reprezintă o interogare în DAO. Obiectele QueryDef pot fi salvate cu baza de date în Microsoft Jet
sau pot fi temporare în ODBCDirect şi Jet.

Relaţiile în ierarhia de obiecte DAO sunt

Obiectul sau colecţia Este conţinut în Conţine

171
QueryDef (obiect) Colecţia QueryDefs Colecţia Fields
Colecţia Parameters
Colecţia Properties

QueryDefs (colecţie) Obiectul Database Obiecte QueryDef

Obiectele QueryDef oferă:

• folosirea proprietăţii SQL pentru a fixa sau returna definiţia interogării;


• folosirea colecţiei Parameters pentru a fixa sau returna parametrii interogării;
• utilizarea proprietăţii Type pentru a determina dacă interogarea selectează înregistrările dintr-o tabelă existentă,
creează o nouă tabelă etc.;
• utilizarea proprietăţii MaxRecords pentru a limita numărul de înregistrări returnate de o înregistrare;
• folosirea proprietăţii ODBCTimeout pentru a indica timpul de aşteptare a rezultatului unei interogări.

În spaţiul de lucru Microsoft Jet mai sunt posibile:

• utilizarea proprietăţii ReturnRecords pentru a indica, la interogări prin SQL, returnarea de înregistrări;
• utilizarea proprietăţii Connect pentru a realiza o interogare a unei baze ODBC prin SQL.

În spaţiul ODBCDirect sunt specifice

• utilizarea proprietăţii Prepare pentru a determina dacă se invocă ODBC SQLPrepare API la executarea
interogării;
• utilizarea proprietăţii CacheSize pentru depozitarea (cache) înregistrărilor returnate de interogare.

Obiectele QueryDef temporare nu sunt salvate pe disc şi nu sunt adăugate la colecţia QueryDefs. În general, interogările
temporare sunt utile atunci când frazele SQL sunt create, repetat, în timpul execuţiei.

Un obiect QueryDef permanent din spaţiul Jet poate fi gândit ca o instrucţiune SQL compilată. Astfel, interogarea este
mai rapidă decât o instrucţiune SQL executată prin metoda OpenRecordset.

Pentru a crea un obiect QueryDef se utilizează metoda CreateQueryDef.

În spaţiul Jet, dacă se precizează numele noului obiect se creează un obiect QueryDef permanent şi care este adăugat
automat la colecţia QueryDefs şi salvată în disc. Dacă se dă implicit sau explicit un nume vid, "", atunci rezultatul este un
obiect QueryDef temporar.

În spaţiul ODBCDirect o interogare este întotdeauna temporară.

Colecţia QueryDef conţine toate obiectele QueryDef deschise. Când o interogare este închisă, ea este înlăturată
automat din colecţia QueryDef.

Referinţa la un obiect permanent QueryDef este uzuală, prin intermediul colecţiei:

QueryDefs(0)
QueryDefs("name")
QueryDefs![name]

Referinţa la obiectele temporare QueryDef se poate obţine doar prin variabilele obiect la care s-au asignat interogările.

172
Crearea interogărilor permanente

Interogările permanente, salvate împreună cu baza de date, pot fi create în Visual Basic cu DAO sau în interfaţa utilizator
din Microsoft Access.

Exemplul următor constituie un model pentru crearea unei interogări.

Const conPath As String = _


"C:\Program Files\ … \Northwind.mdb"
Dim dbs As Database, qdf As QueryDef, rst As Recordset
Dim strSQL As String

strSQL = "SELECT FirstName, LastName, LastName, HireDate FROM Employees " _


& "WHERE Title = 'Sales Representative' ORDER BY HireDate;"
Set dbs = OpenDatabase(conPath)
Set qdf = dbs.CreateQueryDef("Sales Representatives", strSQL)
Set rst = qdf.OpenRecordset

Obiectul QueryDef nou creat nu trebuie adăugat la colecţia QueryDefs, deoarece prin specificarea unei valori nenule a
argumentului name se creează o interogare permanentă şi aceasta este adăugată automat la colecţie. Un nume nul ar
duce la crearea unei interogări temporare (în spaţiul ODBCDirect toate obiectele QueryDef sunt întotdeauna temporare).

Colecţia Parameters (QueryDef Object)

Un obiect Parameter reprezintă o valoare transmisă unei interogări. Colecţia Parameters conţine toate obiectele
Parameter definite de un obiect QueryDef. Localizarea în ierarhia de obiecte DAO este precizată în tabelul alăturat.

Obiectul sau colecţia Este conţinut în Conţine

Parameter (obiect) Colecţia Parameters Colecţia Properties

Parameters (colecţie) Obiectul QueryDef Obiecte Parameter

Dacă se doreşte ca utilizatorul sau aplicaţia să ofere o valoare în timpul execuţiei, prin care să se limiteze mulţimea
înregistrărilor returnate de o interogare, aceasta se realizează prin definirea parametrilor interogării.

Pentru a crea un parametru se utilizează declaraţia SQL PARAMETERS. Sintaxa declaraţiei este:

PARAMETERS name datatype [, name datatype [, …]]

Declaraţia PARAMETERS precede restul instrucţiunii SQL şi este separată prin caracterul ";", după exemplul următoarei
instrucţiuni SQL:

PARAMETERS [ Beginning OrderDate] DATETIME,[ Ending OrderDate] DATETIME;

SELECT * FROM Orders

WHERE (OrderDate Between [ Beginning OrderDate] And [ Ending OrderDate] );

173
Fiecare parametru definită în instrucţiunea SQL este reprezentată de un obiect Parameter în colecţia Parameters a
obiectului QueryDef bazat pe instrucţiunea SQL. Valoarea unui parametru se poate specifica prin fixarea proprietăţii
Value a obiectului Parameter. Exemplul următor realizează o asemenea operaţiune.

Function NewParameterQuery (dteStart As Date, dteEnd As Date) As Boolean


Dim dbs As Database, qdf As QueryDef, rst As Recordset
Dim strSQL As String

On Error Resume Next


' returnarea referinţei la baza curentă
Set dbs = CurrentDb
' construcţia şirului SQL
strSQL = "PARAMETERS [Beginning OrderDate] DATETIME, " _
& "[Ending OrderDate] DATETIME; SELECT * FROM Orders " & _
"WHERE (OrderDate Between [Beginning OrderDate] " _
& "AND [ Ending OrderDate] )';"
' eliminarea interogării dacă ea există
dbs.QueryDefs.Delete "ParameterQuery"

On Error GoTo Err_NewParameterQuery


' crearea unui nou obiect QueryDef
Set qdf = dbs.CreateQueryDef("ParameterQuery", strSQL)

' fixarea valorilor parametrilor


If dteStart > dteEnd Then
MsgBox "Start date is later than end date."
Exit Function
End If
qdf.Parameters("Beginning OrderDate") = dteStart
qdf.Parameters("Ending OrderDate") = dteEnd

' deschiderea recordset-ului din interogare


Set rst = qdf.OpenRecordset
rst.MoveLast
MsgBox "Query returned " & rst.RecordCount & " records."
NewParameterQuery = True

Exit_NewParameterQuery:
rst.Close
Set dbs = Nothing
Exit Function

Err_NewParameterQuery:
MsgBox "Error " & Err & ": " & Err.Description
NewParameterQuery = False
Resume Exit_NewparameterQuery
End Function

Funcţia poate fi apelată din fereastra Debug prin

? NewParameterQuery(#6-30-95#, #6-30-96#)

Observaţie. În Microsoft Access se pot defini parametrii unei interogări în Query Design View.

Colecţia Relations (obiectul Database)


174
Un obiect Relation reprezintă o relaţie între câmpuri din tabele sau înterogări. Colecţia Relations conţine toate obiectele
Relation ale unei baze de date. Localizarea în ierarhia de obiecte DAO a spaţiului de lucru Microsoft Jet este

Obiectul sau colecţia Este conţinut în Conţine

Relation (obiect) Colecţia Relations Colecţia Fields


Colecţia Properties

Relations (colecţie) Obiectul Database Obiecte Relation

Relaţii între tabele

Separarea informaţiilor între mai multe tabele ale unei baze de date, după criterii care ţin de subiect, categorie,
administrare etc., ridică problema reunirii informaţiilor pentru necesităţi de raportare a lor. Pentru rezolvarea acestei
probleme o primă operaţiune este aceea de a stabili relaţii între tabele.

Prin relaţie se înţelege, în problematica bazelor de date, o asociere stabilită între două câmpuri (denumite câmpuri cheie,
de regulă cu acelaşi nume) din două tabele. În acest mod înregistrările celor două tabele pot fi coordonate încât
înregistrările curente să conţină informaţii corelate după câmpurile asociate.

Relaţia lucrează prin potrivirea valorilor câmpurilor cheie. În cele mai multe cazuri, câmpurile cheie sunt cheia primară
dintr-o tabelă (s-o numim tabela A), care constituie un identificator unic pentru fiecare înregistrare, şi o cheie externă din
altă tabelă (s-o numim tabela B).

Există trei tipuri de relaţii: one-to-one, one-to-many, many-to-many după numărul înregistrărilor din cele două tabele, care
îndeplinesc condiţia de matching.

O relaţie one-to-many, cea mai frecventă, o înregistrare din tabela A poate să se potrivească cu mai multe înregistrări din
tabela B; invers, o înregistrare din tabela B are doar o înregistrare din A cu care se potriveşte.

Într-o relaţie many-to-many, o înregistrare din tabela A poate să se potrivească cu mai multe înregistrări din tabela B, iar o
înregistrare din tabela B poate să se corespundă cu mai multe înregistrări din tabela A. Acest tip de relaţie este posibil
prin definirea unei a treia tabele (tabela de joncţiune – junction table) ale cărei câmpuri chei primare sunt în relaţie cu
cheile externe din tabelele A şi B. Astfel, o relaţie many-to-many este formată din două relaţii one-to-many care implică o
a treia tabelă.

Relaţia one-to-one presupune că înregistrările din tabelele A şi B sunt în corespondenţă una la una, fiecare înregistrare
din A se poate potrivi doar cu o înregistrare din B şi reciproc. Deşi nu este o situaţie uzuală, prin aceea că legătura foarte
puternică ar presupune că informaţia trebuia grupată într-o singură tabelă, relaţia one-to-one poate fi utilizată pentru
divizarea unei tabele cu prea multe câmpuri sau izolarea unei părţi a tabelei.

Modul de relaţie creat de Microsoft Access depinde de definirea câmpurilor care sunt puse în relaţie (chei primare,
indexuri unice etc.).

Obiectul Relation

Obiectul Relation poate fi utilizat pentru a crea noi relaţii sau pentru a examina relaţiile existente în baza curentă.
Proprietăţile obiectului servesc la specificarea tipului de relaţie, a tabelelor care participă în relaţie, când să se forţeze
integritatea referenţială (integritatea referenţială – Referential integrity – este un sistem de reguli utilizate în Access pentru
a asigura că relaţiile dintre înregistrările tabelelor legate sunt valide şi că nu se şterg sau modifică date legate; integritatea
referenţială interzice adăugarea de înregistrări la o tabelă legată pentru care nu există cheie primară, modificarea valorilor
în tabela primară care conduce la înregistrări orfane în tabela legată etc.) şi când să se execute actualizările şi ştergerile

175
în cascadă (actualizări în cascadă – cascading update – pentru relaţiile care impun integritatea referenţială, o opţiune
care, în cazul modificării unei chei primare din înregistrările tabelei primare, conduce la actualizarea automată a cheilor
externe în toate înregistrările legate din tabelele externe; ştergeri în cascadă – cascading delete – similar, dar pentru
ştergeri de înregistrări: ştergerea unei inregistrări din tabela primară produce ştergerea înregistrărilor legate din tabelele
externe). Toate aceste noţiuni sunt prezentate, pe scurt, în continuare.

Adăugarea unui obiect Relation la colecţia Relations, se va crea obiectul prin metoda CreateRelation şi se adaugă la
colecţie prin metoda Append. Astfel, obiectul Relation este salvat o dată cu obiectul Database. Eliminarea unui obiect
Relation se realizează metoda Delete.

Referirea la un obiect Relation se realizează în mod uzual:

Relations(0)
Relations("name")
Relations![name]

Acţiunile principale realizate prin utilizarea obiectului Relation sunt enumerate în continuare.

• Stabilirea unei relaţii impuse între câmpuri din tabele de bază (o tabelă de bază este o tabelă a unei baze de date
Microsoft Jet) dar nu relaţii care implică tabele şi interogări legate (o tabelă legată este o bază externă, legată de
o bază de date Jet).
• Stabilirea unei relaţii neimpuse între orice tip de tabelă sau interogare – nativă sau legată.
• Utilizarea proprietăţii Name pentru a referi relaţia dintre câmpurile din tabela primară (prin tabela primară se
înţelege partea "one" dintr-o relaţie one-to-many) referită şi tabela externă (tabela de pe partea "many" a relaţiei
one-to-many) care face referirea.
• Utilizarea proprietăţii Attributes pentru a determina dacă relaţia dintre câmpuri este one-to-one şi cum să se
impună integritatea referenţială. De asemenea, tot prin Attributes, se poate determina dacă motorul Microsoft
Jet poate efectua actualizarea în cascadă şi ştergerea în cascadă în tabelele legate prin relaţii.
• Utilizarea proprietăţii Attributes pentru a determina dacă relaţia este asociere stânga (left join, include toate
înregistrările din prima tabelă – din stânga – chiar dacă nu există nici o potrivire cu înregistrări din a doua tabelă –
din dreapta) sau asociere dreapta (right join, include toate înregistrările din a doua tabelă – din dreapta– chiar
dacă nu există potriviri cu înregistrări din prima tabelă – din stânga relaţiei).
• Utilizarea proprietăţii Name a obiectelor Field din colecţia Fields a obiectului Relation pentru a stabili sau
returna numele câmpurilor din cheia primară a tabelei referite, sau setările proprietăţii ForeignName a obiectelor
Field pentru a stabili sau returna denumirile câmpurilor din cheia externă a tabelei care face referinţa.

Un obiect Relation are o colecţie Fields care conţine două câmpuri, câte unul în fiecare tabelă a relaţiei.Câmpurile
relaţiei trebuie să aibă acelaşi tip de dată şi trebuie să aibă valori comune. Se vor utiliza proprietăţile Table şi
ForeignTable ale obiectului Relation pentru a specifica tabele care iau parte la relaţie şi cum sunt legate. La crearea
unei relaţii one-to-many, tabela de pe partea "one" a relaţiei este tabela în care câmpul din legătură este cheia primară.
Prin urmare proprietatea Table trebuie să fie numele acestei tabele. Tabela de pe partea "side" a relaţiei este tabela în
care câmpul legat este cheie externă iar numele tabelei se va da proprietăţii ForeignTable.

Următorul exemplu creează o relaţie între tabelele Employees şi Orders din baza de date de test Northwind. Cele două
tabele sunt unite prin câmpul EmployeeID care este cheie primară în baza Employees – toate valorile acestui câmp sunt
unice – şi cheie externă pentru Orders – aceeaşi valoare poate să apară în mai multe înregistrări.

Function NewRelation() As Boolean


Dim dbs As Database
Dim fld As Field, rel As Relation
' calea către baza de date Northwind
Const conPath As String = _
"C:\Program Files\ … \Northwind.mdb"
On Error GoTo Err_NewRelation
176
' returnează o referinţă la baza curentă
Set dbs = OpenDatabase(conPath)
' găsirea unei relaţii EmployeesOrders deja existente
For Each rel In dbs.Relations
If rel.Table = "Employees" And rel.ForeignTable = "Orders" Then
' mesaj de ştergere a relaţiei existente
If MsgBox(rel.Name & " already exists. " & vbCrLf _
& "This relation will be deleted and re-created.", vbOK) = vbOK Then
dbs.Relations.Delete rel.Name
Else
' dacă utilizatorul răspunde cu Cancel
Exit Function
End If
End If
Next rel

' crearea noii relaţii şi stabilirea proprietăţilor ei


Set rel = dbs.CreateRelation("EmployeesOrders", "Employees", "Orders")
' stabilirea proprietăţilor pentru forţarea integrităţii referenţiale
rel.Attrbutes = dbRelationDeleteCascade + dbRelationUpdateCascade
' creare câmp în colecţia Fields a obiectului Relation, la creare se fixează Name
Set fld = rel.CreateField("EmployeeID")
' numele pentru câmpul extern
fld.ForeignName = "EmployeeID"

' adăugarea obiectelor create


rel.Fields.Append fld
dbs.Relations.Append rel
MsgBox "Relation '" &rel.Name & " ' created."
Set dbs = Nothing
NewRelation = True

Exit_NewRelation:
Exit Function

Err_NewRelation
MsgBox "Error " & Err & ": " & Err.Description
NewRelation = False
Resume Exit_NewRelation
End Function

Observaţie. În Microsoft Access se lucrează cu relaţiile prin meniul Tools – Relationships.

Colecţia Recordsets

Obiectul Recordset reprezintă o mulţime de înregistrtări din baza de date. Colecţia Recordsets conţine toate obiectele
Recordset deschise. Situarea în ierarhia de obiecte este

Obiectul sau colecţia Este conţinut în Conţine

Recordset (obiect) Colecţia Recordsets Colecţia Fields


Colecţia Properties

Recordsets (colecţie) Obiectul Database Obiecte Recordset

177
Obiectele Recordset sunt utilizate pentru modificarea datelor memorate într-o tabelă a unei baze de date (structura
tabelei poate fi modificată prin comenzi DAO sau SQL).

Crearea unui obiect Recordset se obţine din metoda OpenRecordset cu sintaxa:

Set recordset = object.OpenRecordset (source, type, options, lockedits)

Descrierea parametrilor se va vedea în Help – OpenRecordset method.

DAO oferă cinci tipuri de obiecte Recordset:

• table (doar în spaţii de lucru Jet),


• dynaset,
• snapshot,
• forward-only,
• dynamic (doar în spaţii ODBCDirect).

Observaţie. Un obiect Recordset trebuie întotdeauna închis după terminarea lucrului cu el şi înainte de a închide
obiectul Database în care a fost creat. Pentru aceasta se utilizează metoda Close a obiectului Recordset.

Obiecte Recordset de tip tabelă

Un obiect Recordset de tip tabelă reprezintă o tabelă de bază (base table) din baza de date. Toate câmpurile şi
înregistrările din tabelă sunt incluse într-un obiect Recordset de tip tabelă. Acesta poate fi utilizat într-un spaţiu de lucru
Microsoft Jet pentru a adăuga, şterge sau modifica înregistrări din tabelă.

Un obiect Recordset poate fi deschis pe tabelele de bază ale unei baze de date Jet, dar nu pe tabelele din surse ODBC
sau tabele legate. Se mai poate utiliza Recordset cu bazele de date instalabile ISAM (FoxPro, dBase sau Paradox)
pentru a deschide aceste tabele în mod direct mai degrabă decât să se lege acestea la baza de date curentă.

Informaţii complete despre un obiect table-type Recordset se obţin din DAO Help – "Table-Type Recordset Object
Summary", de unde sunt legături către toate proprietăţile şi metodele obiectului. Intrarea poate fi atinsă eventual prin
Database Object –> Summary –> Database Object, Databases Collection Summary, de unde este o legătură către
Recordsets.

Proprietatea RecordCount a unui obiect Recordset de tip tabelă returnează numărul de înregistrări din tabelă.

Obiectul Recordset de tip tabelă poate utiliza indexurile definite pentru tabela de bază. La crearea obiectului se poate
preciza în proprietatea Index numele unui index definit pentru tabelă. Metoda Seek va căuta în ordinea dată de index.

Pentru a crea un obiect Recordset de tip tabelă se va specifica valoarea dbOpenTable pentru argumentul type a
metodei OpenRecordset a obiectului Database.

Observaţie. Pentru o tabelă legată dintr-o sursă de date externă se va utiliza mai întâi metoda OpenDatabase pentru
deschiderea bazei şi apoi se deschide un obiect Recordset de tip tabelă.

Exemplul următor creează un obiect Recordset de tip tabelă, foloseşte metoda Seek pentru localizarea unei înregistrări
şi fixează înregistrarea găsită drept înregistrare curentă.

Function ReturnEmployeesRecord(strKey As String) As Boolean


Dim dbs As Database, rst As Recordset
Const conPath As String = _
178
"C:\Program Files\ … \Northwind.mdb"
On Error GoTo Err_ReturnEmployeesRecord
' returnarea referinţei la baza de date
Set dbs = OpenDatabase(conPath)
' deschidere recordset pentru tabela Employees
Set rst = dbs.OpenRecordset("Employees", dbOpenTable)
' fixarea indexului
rst.Index = "LastName"
' operaţiunea de căutare
rst.Seek "=", strKey ' valoarea căutată este argument al funcţiei
' verificarea găsirii
If rst.NoMatch = False Then
' tipărirea unor câmpuri din înregistrarea găsită
Debug.Print rst!EmployeeID, rst!FirstName & " " & rst!LastName, rst!Title
ReturnEmployeesRecord = True
Else
ReturnEmployeesRecord = False
End If

Exit_ReturnEmployeesRecord:
' închidere recordset şi bază
rst.Close
dbs.Close
Exit Function

Err_ReturnEmployeesRecord:
MsgBox "Error " & Err & ": " & Err.Description
ReturnEmployeesRecord = False
Resume Exit_ReturnEmployeesRecord
End Function

Obiecte Recordset de tip dynaset

Un obiect Recordset de tip dynaset reprezintă rezultatul unei căutări în una sau mai multe tabele. Obiectul este o
mulţime dinamică de inregistrări care se poate utiliza pentru adăugarea, modificarea sau ştergerea înregistrărilor în una
sau mai multe tabele ale bazei. Cu un obiect Recordset de tip dynaset se pot extrage şi actualiza date într-o uniune
multiplă de tabele, incluzând tabele legate din mai multe baze de date. Obiecte Recordset de tip dynaset se pot crea atât
în spaţii de lucru Microsoft Jet, cât şi în spaţii de lucru ODBCDirect. Dacă obiectul implică o sursă de date la distanţă, el
constă într-o serie de bookmark-uri, fiecare identificând unic o înregistrare din recordset. Date efective nu sunt returnate
decât la referirea lor explicită.

Pentru a determina numărul de înregistrări din recordset se aplică mai întâi metoda MoveLast astfel regăsindu-se toate
înregistrările din mulţime.

Obiectul Recordset de tip dynaset poate fi actualizat, dar nu toate câmpurile suportă operaţia. Proprietatea
DataUpdatable a obiectului Field respectiv arată dacă se poate modifica valoarea câmpului. Obiectul nu se poate
actualiza dacă

• pagina de date necesară este blocată de alt utilizator


• înregistrarea a fost deja modificată de la ultima citire
• utilizatorul nu are drepturile necesare
• cel puţin o tabelă sau un câmp este read-only
• obiectul Recordset a fost creat din mai multe tabele fără instrucţiunea JOIN

179
• obiectul include câmpuri dintr-o sursă de date ODBC, sau tabele Paradox, şi nu există un index unic pe acele
tabele.

Crearea unui obiect dynaset-type Recordset se indică utilizând constanta dbOpenDynaset pentru argumentul type al
metodei OpenRecordset, după modelul

Sub PrintHireDates ()
Dim dbs As Database, rst As Recordset
Dim strSQL As String
Const conPath As String = _
"C:\Program Files\ … \Northwind.mdb"

' deschiderea bazei de date, referirea ei


Set dbs = DBEngine.Workspaces(0).OpenDatabase(conPath)
' iniţializarea şirului SQL
strSQL = "SELECT FirstName, LastName, HireDate FROM Employees " & _
"WHERE HireDate <= #1-1-93# ORDER BY HireDate;"
' deschiderea recordsetului de tip dynaset
Set rst = dbs.OpenRecordset(strSQL, dbOpenDynaset)
' tipărirea înregistrărilor din recordset
Do Until rst.EOF
Debug.Print rst!FirstName, rst!LastName, rst!HireDate
Rst.MoveNext
Loop
' închiderea recordsetului şi a bazei
rst.Close
dbs.Close
End Sub

Obiecte Recordset de tip snapshot

Un obiect Recordset de tip snapshot este o mulţime statică de înregistrări care reprezintă rezultatul unei interogări. Un
snapshot include toate valorile pentru toate câmpurile cerute în interogare, fie că există în cod referinţe la ele sau nu.
Obiectul Recordset de tip snapshot necesită mai puţine resurse decât cel de tip dynaset, dar datele nu pot fi actualizate
în obiectul Recorset de tip snapshot.

Iniţial, la parcurgerea înregistrărilor din obiect, toate datele sunt copiate în memorie şi apoi, dacă mulţimea este prea
vastă, într-o bază de date Jet temporară de pe maşina utilizatorului. Printre înregistrările unui obiect snapshot se poate
naviga în ambele sensuri.

Pentru a crea un obiect snapshot-type Recordset se specifică valoarea dbOpenSnapshot pentru argumentul type al
metodei OpenRecordset.

Obiecte Recordset de tip forward-only

Un obiect Recordset de tip forward-only este identic cu unul de tip snapshot cu excepţia faptului că înregistrările pot fi
defilate doar înainte (nu se poate efectua decât o singură trecere prin înregistrări).

Într-un obiect recordset de acest tip există doar o singură înregistrare la un moment dat. Rezultă că nu se pot utiliza
metode cum ar fi MoveLast, MoveFirst, MovePrevious.

Obiectele de acest tip, utile atunci când înregistrările sunt parcurse doar o dată, oferă cea mai mare viteză de acces.

180
Crearea unui obiect forward-only-type Recordset este produsă de constanta dbOpenForwardOnly atribuită
argumentului type al metodei OpenRecordset.

Metodele obiectelor Recordset

În tabelul următor este o prezentare a metodelor permise pentru diferite tipuri de obiecte Recordset. Este inclus şi tipul
dinamic, disponibil doar în spaţii ODBCDirect.

Jet = operaţiune permisă în spaţiul Microsoft Jet

ODBC = operaţiune permisă în spaţiul de lucru ODBCDirect

Method Table Dynaset Snapshot Forward- Dynamic


Only

AddNew Jet Jet/ODBC ODBC * ODBC ODBC

Cancel ODBC ODBC ODBC ODBC

CancelUpdate Jet Jet/ODBC ODBC * ODBC ODBC

Clone Jet Jet Jet

Close Jet Jet/ODBC Jet/ODBC Jet/ODBC ODBC

CopyQueryDef Jet Jet Jet

Delete Jet Jet/ODBC ODBC * ODBC ODBC

Edit Jet Jet/ODBC ODBC * ODBC ODBC

FillCache Jet

FindFirst Jet Jet

FindLast Jet Jet

FindNext Jet Jet

FindPrevious Jet Jet

GetRows Jet Jet/ODBC Jet/ODBC Jet/ODBC ODBC

Move Jet Jet/ODBC Jet/ODBC Doar înainte, ODBC


fără offset

MoveFirst Jet Jet/ODBC Jet/ODBC ODBC

MoveLast Jet Jet/ODBC Jet/ODBC ODBC

MoveNext Jet Jet/ODBC Jet/ODBC ODBC

MovePrevious Jet Jet/ODBC Jet/ODBC ODBC

181
NextRecordset ODBC ODBC ODBC ODBC

OpenRecordset Jet Jet Jet

Requery Jet/ODBC Jet/ODBC Jet/ODBC ODBC

Seek Jet

Update Jet Jet/ODBC ODBC * ODBC ODBC

* În spaţiul ODBCDirect anumite operaţiuni depind de driver (dacă acesta suportă sau nu operaţiunea respectivă)

Pentru proprietăţile diferitelor tipuri de obiecte Recordset se vor studia intrările respective din Help.

Securitatea datelor

Microsoft Access dispune de două metode de asigurare a securităţii informaţiilor:

• stabilirea de parole pentru deschiderea bazelor de date şi


• securitate la nivel de utilizator, prin fixarea drepturilor de acces la diferite obiecte ale bazei de date.

Securitatea la nivel de utilizator/grup se realizează cu ajutorul obiectelor Group, împreună cu obiectele User, Container,
Document şi Workspace.

Obiectul Group reprezintă un grup de conturi iar obiectul User reprezintă un cont individual. Utilizatorii pot fi membri ai
grupurilor. Atunci când se stabileşte securitatea bazei, aceasta se efectuează pentru un obiect particular sau mulţime de
obiecte specificând tipul de drepturi pe care utilizatorul sau grupul îl are asupra obiectelor respective. Dacă un grup are o
anumită permisiune pentru un obiect, toţi utilizatorii grupului au aceeaşi permisiune. Invers, dacă un utilizator are drepturi
asupra unui obiect, grupul la care aparţine utilizatorul are aceleaşi drepturi. Grupurile pot fi create prin metoda
CreateGroup a obiectului Workspace sau User.

Obiectul Container reprezintă un set particular de obiecte dintr-o bază de date pentru care se pot atribui drepturi într-un
grup securizat. DAO oferă trei tipuri de obiecte Container; fiecare bază de date conţine cel puţin aceste obiecte având
denumirile: Databases – bazele de date salvate –, Tables – tabelele şi interogările salvate –, Relationships – relaţiile
salvate. O aplicaţie poate să definească şi obiecte Container proprii; Microsoft Access defineşte obiectele Container cu
denumirile Forms – formele salvate –, Modules – modulele salvate–, Reports – rapoartele salvate –, Scripts – macrourile
salvate. Pentru stabilirea drepturilor se stabileşte proprietatea UserName a containerului respectiv şi apoi proprietatea
Permissions adecvată.

Fiecare obiect Container conţine o colecţie Documents, fiecare element Document reprezentând un document din
bază. Atât DAO cât şi aplicaţia oferă diferite tipuri de obiecte Document, de exemplu Database (DAO), Form (Access)
etc. Pentru stabilirea drepturilor se stabileşte proprietatea UserName a documentului respectiv şi apoi proprietatea
Permissions.

Pentru informaţii detaliate se vor studia intrările din Help pentru obiectele menţionate şi legăturile propuse.

Colecţia Properties

Cele mai multe obiecte DAO conţin o colecţie Properties. Fiecare obiect Property din colecţie corespunde unei
proprietăţi a obiectului. Colecţia proprietăţilor poate fi utilizată fie pentru a determina ce proprietăţi se aplică unui obiect
particular, fie pentru a returna valorile existente ale proprietăţilor. Exemplul următor afişează în fereastra Debug toate
proprietăţile obiectului reprezentând baza de date curentă.
182
Sub DisplayProperties()
Dim dbs As Database, prp As Property

Const conPath As String = _


"C:\Program Files\ … \Northwind.mdb"

' deschide baza


Set dbs = OpenDatabase(conPath)
Debug.Print "Current Database Properties"
' enumerarea colecţiei
For Each prp In dbs.Properties
Debug.Print prp.Name
Next prp
dbs.Close
End Sub

Anumite proprietăţi ale obiectelor DAO nu există în mod automat în colecţia Properties a obiectului respectiv. Înainte de
utilizarea unei asemenea proprietăţi, trebuie să se creeze un obiect Property care să reprezinte proprietatea şi să se
adauge obiectul la colecţia Properties. Din acest moment proprietatea poate fi utilizată la fel cu toate celelalte existente
în colecţie.

Următoarea funcţie este o procedură generică utilizabilă în cazul procesării unei proprietăţi care nu există în mod implicit.
Funcţia implementează tratarea erorilor. Prima dată când se cheamă procedura apare o eroare deoarece nu există
proprietatea cerută. În handler-ul erorii se creează noul obiect Property şi se adaugă la colecţia lui. Orice apel ulterior nu
mai produce erori şi proprietatea este stabilită pe valoarea specificată.

Function SetProperty(obj As Object, strName As String, _


intType As Integer, varSetting As Variant) As Boolean
Dim prp As Property

Const conPropNotFound As Integer = 3270

On Error GoTo Error_SetProperty


' referirea explicită la colecţia Properties
obj.Properties(strName) = varSetting
SetProperty = True

Exit_SetProperty:
Exit Function

Error_SetProperty:
If Err = conPropNotFound Then
' creare proprietate, tip, valoare iniţială
Set prp obj.CreateProperty(strName, intType, varSetting)
' adăugarea la colecţia Properties
obj.Properties.Append prp
obj.Properties.Refresh
SetProperty = True
Resume Exit_SetProperty
Else
MsgBox Err & ": " & vbCrLf & Err.Description
SetProeprty = False
Resume Exit_SetProperty
End If
End Function
183
De exemplu, pentru a fixa proprietatea ReplicableBool a obiectului Database, se poate utiliza funcţia precedentă prin

Sub ReplicateDatabase()
Dim dbs As Database
Const conPath As String = _
"C:\Program Files\ … \Northwind.mdb"

Set dbs = OpenDatabase(conPath, True)


If SetProperty(dbs, "ReplicableBool", dbBoolean, True) Then
Debug.Print "Database replicated successfully."
Else
Debug.Print "Database not replicated."
End If
End Sub

De fiecare dată când se fixează sau se citeşte o proprietate care nu există în mod automat în colecţia Properties a unui
obiect, referinţa la colecţia Properties trebuie să fie explicită. De exemplu,

Debug.Print dbs.Properties("ReplicableBool")

Funcţia arătată în exemplul anterior poate fi utilizată pentru definirea unor proprietăţi proprii (introduse de utilizator) pentru
obiectele DAO. De exemplu, se poate defini o proprietate care să memoreze numele utilizatorului care a modificat ultima
dată o tabelă. Şi referinţele la proprietăţile definite de utilizator se vor efectua în mod explicit.

Anumite aplicaţii, cum ar fi Access, definesc proprietăţi proprii pentru obiectele DAO. De exemplu Microsoft Access
defineşte proprietăţi pentru obiectele TableDef, QueryDef, Field şi Document.

Accesarea datelor ODBC

Atunci când este nevoie să se lucreza cu surse de date ODBC, trebuie să se decidă dacă se va utiliza DAO cu Microsoft
Jet, ODBCDirect sau ambele. În continuare se discută pentru început avantajele fiecărui tip de acces şi alte probleme
conexe domeniului. Alegerea modului de lucru este funcţie de posibilităţile de lucru oferite în cele două spaţii.

Utilizarea Microsoft Jet pentru date ODBC

Alegerea modului de acces Jet poate fi influenţată de următoarele argumente. Posibilităţile enumerate sunt proprii
spaţiilor de lucru Microsoft Jet şi nu sunt suportate de spaţiile ODBCDirect.

o Legături actualizabile – se pot actualiza date din obiecte Recordset bazate pe legături multiple de
tabele
o Suport pentru tabele legate – se pot memora legături permanenete la date de pe server într-o bază
locală Microsoft Jet. La legarea unei tabele, se poate memora (cache) informaţia despre structura tabelei,
incluzând informaţii despre câmpuri şi indexuri, în baza locală. Acest fapt măreşte viteza de conectare la
accesările ulterioare ale sursei de date.
o Suport pentru metode Find – se pot utiliza metodele FindFirst, FindNext, FindPrevious şi FindLast
cu obiectele Recordset.
o Eşecuri (failures) parţiale ale actualizării interogărilor – dacă eşuează o interogare de mari
dimensiuni, interogarea se opreşte, dă controlul utilizatorului pentru a decide sau nu dacă se păstrează
modificările efectuate până în momentul eşecului.
o Proprietăţi definite de utilizator – se pot personaliza obiectele DAO prin adăugarea unor proprietăţi
persistente. De exemplu o proprietate Description care sămemoreze un text descriptiv al obiectului.
o Interogări încrucişate – se poate utilzia propoziţia SQL TRANSFORM pentru a crea rezumate
încrucişate (crosstab) ale datelor interogate.

184
o Acces la date eterogene – se poate lucra cu date de pe server, baze de date Microsoft Jet native
(fişiere .mdb) şi date ISAM instalabile (FoxPro, Paradox, dBASE). Se pot efectua uniri de tabele din surse
diferite.
o Utilizare programatică pentru Data Definition Language (DDL) – se poate folosi DAO pentru
operaţiuni care modifică structura bazei de date (adăugare de tabel, modificare etc.).
o Ataşare de forme şi controale – în spaţiul Jet se pot ataşa forme şi controale datelor din surse ODBC.
Spaţiul ODBCDirect nu suportă tabele legate deci nici forme sau controale.

Utilizare ODBCDirect pentru date ODBC

Cu ODBCDirect se pot accesa date de pe server utilizând modelul de obiecte DAO existent direct în topul interfeţei de
programare ODBC. ODBCDirect implementează un strat de cod peste ODBC API, care stabileşte conexiunile, creează
cursoare şi execută proceduri utilizând resurse minime de pe staţia de lucru, fără a trece prin Microsoft Jet. Avantajele
utilizării spaţiului de lucru ODBCDirect sunt enumerate în continuare.

o Acces direct – aplicaţia accesează sursa de date ODBC în mod direct. Se pot astfel îmbunătăţi
performanţele, reduce traficul de reţea şi beneficia de capacităţile de procesare ale serverului (mai mari
decât ale staţiei de lucru).
o Reducerea necesarului de resurse – netrecând prin Microsoft Jet, aplicaţia cere mai puţine resurse
locale. Dacă se utilizează ODBCDirect din Access se va ţine seama că Microsoft Access încarcă
întotdeauna Microsoft Jet (chiar dacă operaţiunile ODBCDirect nu trec pe acolo).
o Imbunătăţirea accesului la funcţionalitatea specifică serverului – se pot utiliza avantajele funcţiunilor
specifice serverului ODBC şi care nu sunt permise prin Microsoft Jet. De exemplu, în spaţiul ODBCDirect
se poate specifica locul de memorare a cursorului: la client sau la server, pentru serverele care suportă
diferite tipuri de cursoare.
o Interogări asincrone – se pot executa o interogare a bazei de date şi apoi alte operaţiuni fără a aştepta
terminarea interogării. Se pot testa proprietăţile pentru a vedea stadiul execuţiei interogării. Astfel se
poate simula concurenţa şi optimiza performanţa aplicaţiei.
o Actualizare optimistă în loturi – modificările locale se pot stoca în Recordset şi trimite apoi serverului
într-un singur lot.
o Executarea procedurilor memorate – se pot manevra intrările şi ieşirile procedurilor memorate pe
server; se pot specifica valori de intrare şi verifica valorile returnate, operaţiuni imposibile în spaţiul de
lucru Jet.

Înregistrarea unei surse de date ODBC

Pentru a putea fi utilizată, atât în spaţiul de lucru Microsoft Jet, cât şi în spaţiul ODBCDirect, o sursă de date ODBC
trebuie să fie înregistrată. Acest proces memorează informaţia despre sursa de date în Windows Registry şi oferă
această informaţie aplicaţiilor. Înregistrarea se poate efectua atât din managerul de ODBC (disponibil în mediul
Windows), cât şi din Visual Basic.

Paşii necesari înregistrării diferă după sursa de date ODBC, driverele respective necesitând informaţii specifice. În
continuare se dă, ca exemplu, înregistrarea sursei de date SQL Server utilizând managerul de ODBC:

1. Windows Control Panel => dublu click pe 32bit ODBC


2. Click Add şi apoi dublu click pe SQL Server.
3. În caseta Data Souce Name se tastează un nume (DSN). Acesta poate fi orice şir şi nu trebuie să corespundă cu
numele bazei de date sau tabelei accesate.
4. În Description se tastează o desciere a bazei de date, orice text de altfel.

185
5. În caseta Server se introduce numele serverului de reţea unde se află sursa datelor. Nu se include un dublu
backslash (\\) înaintea numelui.
6. Click Options şi se introduce numele bazei de date accesate în caseta Database Name.

Exemplul următor conţine codul necesar înregistrării programatice a unei surse de date. Pentru aceasta se utilizează
metoda RegisterDatabase a obiectului DBEngine.

Function RegisterDB() As Boolean


Dim str As String

On Error GoTo Err_RegisterDB


' construirea şirului de cuvinte cheie
str = " Description=SQL Server on Server Publishers" & _
vbCR & "OemToAnsi=No" & _
vbCR & "Network=(Default)" & _
vbCR & "Address=(Default)" & _
vbCR & Server=Publishers" & _
vbCR & "Database=Pubs"
' înregistrarea bazei de date
DBEngine.RegisterDatabase "Pubs", "SQL Server", True, str
RegisterDB = True

Exit_RegisterDB:
Exit Function

Err_RegisterDB:
MsgBox "Error " & Err &": " & Err.Description
RegisterDB = False
Resume Exit_RegisterDB
End Function

Metoda RegisterDatabase completează informaţia de conectare necesară la deschiderea sursei de date ODBC. Sintaxa
metodei este

DBEngine.RegisterDatabase dbname, driver, silent, attributes

unde

dbname este numele bazei de date,

driver este numele driverului ODBC,

silent este True dacă se nu doreşte afişarea dialogului driverului pentru fixarea atributelor,

attributes conţine şirul atributelor care se trec în Windows Registry.

186
Utilizarea DAO cu ODBCDirect

Modelul de obiecte pentru spaţiul ODBCDirect include un subset de obiecte din spaţiul Microsoft Jet la care se adaugă un
obiect nou, Connection şi clasa corespunzătoare. Diagrama următoare arată ierarhia de obiecte a spaţiului de lucru
ODBCDirect.

Obiectul DBEngine

DBEngine conţine atât spaţiile de lucru Jet, cât şi spaţiile de lucru ODBCDirect. Proprietatea DefaultType a obiectului
determină tipul spaţiului creat în mod implicit la utilizarea metodei CreateWorkspace. După cum s-a mai precizat, la
spaţiile Microsoft Jet, valoarea dbUseODBC caracterizează spaţiile ODBCDirect. Argumentul implicit poate fi acoperit
prin specificarea explicită a argumentului type la aplicarea metodei CreateWorkspace.

Observaţie. Dacă programarea este efectuată in Microsoft Access, atunci nu se va specifica Proprietatea DefaultType la
valoarea dbUseODBC deoarece poate produce rezultate neaşteptate (Access utilizează DAO şi Jet pentru multiple
operaţiuni).

Instrucţiunile următoare creează un spaţiu ODBCDirect:

Dim wrkODBC As Workspace


Set wrkODBC = DBEngine.CreateWorkspace _
("NewODBCwrk", "Admin", "", dbUseODBC)

Tipul spaţiului de lucru poate fi identificat prin proprietatea Type a obiectului Workspace. Este returnată una dintre
valorile dbUseJet sau dbUseODBC, proprietatea fiind read-only, adicănu se poate modifica tipul spaţiului de lucru odată
creat.

Colecţia Workspaces

În acest model, fără a specifica de fiecare dată, un obiect Workspace reprezintă un spaţiu de lucru ODBCDirect, iar
colecţia Workspaces conţine mulţimea tuturor spaţiilor ODBC active. Situarea în ierarhie este dată în tabelul următor.

Obiectul sau colecţia Conţinut în Conţine

Workspace (obiect) Colecţia Workspaces Colecţia Connections


Colecţia Databases / Colecţia Properties

Workspaces (colecţie) Obiectul DBEngine Obiecte Workspace

187
Un spaţiu de lucru ODBCDirect rutează, în cazul utilizării ODBC, apelurile direct la ODBC API spre deosebire de spaţiul
Microsoft Jet, care rutează mai întâi apelurile la motorul de baze de date Jet şi pe urmă la ODBC API.

Referirea la un spaţiu de lucru se efectuează în mod uzual, prin intermediul colecţiei:

DBEngine.Workspaces(index)

DBEngine.Workspaces("name")

DBEngine.Workspaces![name]

Principalele proprietăţi şi metode utilizabile sunt

• Name, UserName şi Type (proprietăţi) pentru stabilirea/aflarea proprietăţilor unei sesiuni.


• Metoda Close pentru terminarea sesiunii.
• Metoda OpenDatabase pentru a deschide o bază de date.
• Metodele BeginTrans, CommitTrans şi Rollback pentru conducerea tranzacţiilor.

Alte proprietăţi sunt prezentate în continuare.

Colecţia Connections

După crearea unui spaţiu ODBCDirect, trebuie să se conecteze la o sursă de date ODBC. Conectarea se poate efectua
prin deschiderea unei baze de date (metoda OpenDatabase, prezentată ulterior) sau prin deschiderea unui nou obiect
Connection.

Un obiect Connection reprezintă o conectare la o bază de date ODBC din spaţiul ODBCDirect. Colecţia Connections
conţine toate obiectele Connection deschise curent. La deschiderea unui nou obiect Connection, acesta este adăugat
în mod automat la colecţie. Analog, închiderea unui obiect prin metoda Close elimină din colecţie obiectul Connection
închis.

Avantajele utilizării obiectului Connection sunt

o Conectare asincronă. Operaţiunea de conectare se desfăşoară în paralel cu alte operaţiuni şi poate fi


verificată dacă s-a efectuat.
o Interogare asincronă. Similar celor anterior spuse, dar pentru interogări.
o Obiecte QueryDef. Se pot defini obiecte QueryDef care reprezintă interogările din sursa de date ODBC.

Pentru a crea un obiect Connection se utilizează metoda OpenConnection, cu sintaxa

Set connection = workspace.OpenConnection (name, options, readonly, connect)

unde

connection este numele noului obiect,

workspace este numele unui obiect Workspace de tip ODBCDirect din care se efectuează conectarea,

name este numele unei surse de date înregistrate. Obiectul Connection creat poate fi referit prin numele sursei
(DSN) sau prin indexul din colecţie,

188
options determină dacă şi când să fie întrebat utilizatorul la stabilirea conexiunii şi dacă aceasta este asincronă;
valorile se vor studia din Help - OpenConnection method,

readonly permite controlul actualizării datelor: True pentru a interzice modificarea datelor.

connect este un şir de conectare valid care conţine parametrii necesari driverului ODBC. Argumentul poate
conţine numele utilizatorului, parola etc.

Şirul de conectare trebuie să înceapă cu "ODBC;" şi să conţină o serie de valori necesare driverului pentru a accesa
datele sursei. Componentele şirului diferă după sursa de date. În mod uzual cerinţele minime sunt ID-ul utilizatorului,
parola şi DSN, după modelul:

ODBC;UID=JamesK;PWD=OpenSesame;DSN=MasterData

Dacă şirul de conectare nu conţine toate elementele necesare, driverul ODBC afişează un dialog pentru obţinerea
informaţiilor lipsă. Dialogul nu este afişat dacă şirul de conectare este completat cu informaţiile necesare.

Observaţie. La conectarea la o bază de date Microsoft SQL Server care utilizează securitatea integrată se vor omite
parametrii UID şi PWD deoarece se utilizează numele utilizator şi parola din Windows NT. De exemplu, şirul de conectare
poate fi

ODBC;UID=;PWD=;DATABASE=Pubs;DSN=Pubs

Exemplul următor ilustrează utilizarea metodei OpenConection pentru a deschide un nou obiect Connection.

Function OpenPubsConnection() As Boolean


Dim wrk As Workspace, cnn As Connection, rst As Recordset, fld As Field
Dim strConnect As String, strSQL As String

On Error GoTo Err_OpenPubsConnection


' Crearea şirului de conectare
strConnect = "ODBC;DSN=Pubs;UID=sa;PWD=;DATABASE=Pubs"
' Crearea şirului SQL
strSQL = SELECT * FROM Authors WHERE State = 'MD';"
' Crearea spaţiului de lucru ODBC
Set wrk = DBEngine.CreateWorkspace("NewODBCDirect", "sa", "", dbUseODBC)
' Deschiderea conexiunii
Set cnn = wrk.OpenConnection("Pubs", dbDriverNoPrompt, False, strConnect)
' Deschiderea recordsetului din conexiune
Set rst = cnn.OpenRecordset(strSQL,dbOpenDynaset)
' Tipărirea valorilor din recordset
Do Until rst.EOF
For Each fld In rst.Fields
Debug.Print fld.Name, fld.Value
Next fld
Debug.Print
rst.MoveNext
Loop
OpenPubsConnection = True

Exit_OpenPubsConnection:
rst.Close
cnn.Close
Exit Function
189
Err_ OpenPubsConnection:
MsgBox "Error " & Err & ": " & Err.Description
OpenPubsConnection = False
Resume Err_ OpenPubsConnection
End Function

După crearea obiectului Connection, se pot deschide obiecte Recordset şi executa interogări pe obiectul Connection.

La deschiderea unui obiect Connection, este creat un obiect Database corespunzător şi adăugat colecţiei Databases
din spaţiul de lucru. Reciproc, la deschiderea unei baze de date în spaţiul ODBCDirect este creat un obiect Connection
şi adăugat colecţiei Connections. Închiderea oricărui obiect din perechea Connection, Database produce şi închiderea
celuilalt obiect.

Observaţie. Ca şi la Database, se vor închide mai întâi toate obiectele Recordset deschise.

Deschiderea conectărilor asincrone

Acest tip de conectare, necesar mai ales când conectarea durează mai mult, timp în care se pot efectua alte operaţiuni,
este specificată prin constanta dbRunAsync dată argumentului options al metodei OpenConnection.

Dim wrk As Workspace, cnn As Connection, strConnect As String


Set wrk = DBEngine.CreateWorkspace("NewODBCDirect", "sa", "", dbUseODBC)
strConnect = "ODBC;DSN=Pubs;UID=sa;PWD=;DATABASE=Pubs"
Set cnn = wrk.OpenConnection("",dbDriverNoPrompt + dbRunAsync, False, strConnect)

Proprietatea StillExecuting a obiectului Connection poate fi testată pentru a determina stabilirea conexiunii. Pentru a
anula o conectare care ia prea mult timp se utilizează metoda Cancel a obiectului.

Colecţia Databases

Se poate utiliza metoda OpenDatabase a obiectului Workspace pentru a deschide o bază de date şi conectarea astfel la
o sursăde date ODBC. Totuşi, obiectul Database nu suportă în spaţiul de lucru ODBCDirect toate funcţiunile pe care le
oferă obiectul Connection. În special, nu se poate efectua conectarea asincronă, executa interogări asincrone sau defini
obiecte QueryDef reprezentând interogări ale sursei de date.

Pentru conectarea la o sursă ODBC prin OpenDatabase dintr-un spaţiu de lucru ODBCDirect se va specifica un şir de
conectare valid în argumentul connect al metodei, după exemplul următor.

Dim wrk As Workspace, dbs As Database


Dim strConnect As String

strConnect = ""ODBC;DSN=Pubs;UID=sa;PWD=;DATABASE=Pubs"
Set wrk = DBEngine.CreateWorkspace("NewODBCDirect", "sa", "", dbUseODBC)
Set dbs = wrk.OpenDatabase("Pubs", dbDriverNoPrompt, False, strConnect)

Pentru argumentele metodei se va studia Help - OpenDatabase method (DAO).

Dintre metodele şi proprietăţile obiectului Database, menţionăm doar câteva.

• metoda Execute pentru a efectua o interogare de tip acţiune (action query – o interogare care copie sau schimbă
date; sunt incluse adăugare, ştergere, actualizare, în opoziţie cu o interogare de tip selectare care returnează o
mulţime de înregistrări).
190
• Proprietatea Connect stabileşte o conectare la o sursă de date ODBC.
• Proprietatea QueryTimeout pentru limitarea duratei de timp în care se execută o interogare.
• Proprietatea RecordsAffected pentru a determina numărul înregistrărilor modificate într-o interogare acţiune.
• Metoda OpenRecordset pentru executarea unei interogări de tip selectare şi crearea unui obiect Recordset.
• Proprietatea Version permite determinarea versiunii motorului de baze de date care a creat baza.

Comutarea între obiectele Connection şi Database

Pentru a utiliza avantajele fiecărui tip de conectare la o sursă ODBC, se poate trece de la un obiect la altul prin
proprietatea Connection a obiectului Database sau prin proprietatea Database a obiectului Connection. Aceste
proprietăţi pot fi folosite pentru a crea obiecte Connection din obiecte Database şi, reciproc, obiecte Database din
obiecte Connection. Se pot astfel adăuga capacităţi ODBCDirect la aplicaţii care utilizează doar obiecte Database.

De exemplu, se poate utiliza un obiect Database pentru operaţiunile uzuale, dar dacă este nevoie de o interogare
asincronă, atunci se poate crea un obiect Connection din obiectul Database şi executa apoi interogarea din
Connection. Exemplul următor ilustrează această metodă.

Sub DeleteRecords()
Dim dbs As Database, strConnect As String
Dim cnn As Connection

' Deschiderea bazei de date în spaţiul de lucru implicit


strConnect = ""ODBC;DSN=Pubs;UID=sa;PWD=;DATABASE=Pubs"
Set dbs = OpenDatabase("", False, False, strConnect)

' crearea unui obiect Connection din Database.


' Dacă spaţiul de lucru este ODBCDirect, atunci interogarea se execută asincron
' Dacă spaţiul de lucru este Microsoft Jet, apare o eroare şi
' interogarea se execută sincron.

Err = 0
On Error Resume Next
Set cnn = dbs.Connection
If Err = 0 Then
cnn.Execute "DELETE FROM Authors", dbRunAsync
Else
dbs.Execute "DELETE FROM Authors"
End If
End Sub

Colecţia QueryDefs

Un obiect QueryDef reprezintă o definiţie temporară a unei interogări din spaţiul ODBCDirect. Colecţia QueryDefs
conţine toate interogările existente curent în spaţiul de lucru. Situarea în ierarhia de obiecte este dată în tabelul următor.

Obiectul sau colecţia Conţinut în Conţine

QueryDef (obiect) Colecţia QueryDefs Colecţia Parameters


Colecţia Properties

QueryDefs (colecţie) Obiectul Connection Obiecte QueryDef

191
Obiectele QueryDef create în spaţiile de lucru ODBCDirect sunt întotdeauna temporare. Ele nu pot fi salvate în sursa de
date chiar dacă li se atribuie un nume.

Executarea interogărilor asincrone

Crearea şi executarea interogărilor în spaţiile ODBCDirect sunt similare cu crearea şi executarea din spaţiile de lucru
Microsoft Jet. Interogarea se creează prin metoda CreateQueryDef a obiectului Connection şi utilizarea metodelor
Execute sau OpenRecordset pentru interogarea rezultată.

Se pot utiliza interogări asincrone încât utilizatorii să continue aplicaţia în timp ce se execută interogarea şi se poate da
utilizatorilor posibilitatea de a anula o interogare asincronă în cazul în care durează prea mult.

Exemplul următor poate constitui un model.

Function DeleteLargeSales () As Boolean


Dim wrk As Workspace, rst As Recordset
Dim cnn As Connection, qdf As QueryDef
Dim strConnect As String, strSQL As String
Dim errObj As Error

On Error GoTo Err_DeleteLargeSales


' crearea spaţiului de lucru
Set wrk = DBEngine.CreateWorkspace("ODBC","sa", "", dbUseODBC)
' crearea şirului de conectare
strConnect = ""ODBC;DSN=Publishers;UID=SA;PWD=;DATABASE=Pubs"
' deschiderea conexiunii
Set cnn = wrk.OpenConnection("", dbDriverNoPrompt, False, strConnect)
' ştergerea unei interogări anterioare
For Each qdf In cnn.QueryDefs
If qdf.Name = "DeleteLargeSales" Then
cnn.QueryDefs.Delete "DeleteLargeSales"
End If
Next qdf

' creare QueryDef


Set qdf = cnn.CreateQueryDef("DeleteLargeSales")
strSQL = "DELETE FROM sales WHERE qty = 100"
qdf.SQL = strSQL

' executarea asincron a interogării


qdf.Execute dbRunAsync

While qdf.StillExecuting
' cod care se va executa până când se termină interogarea
' Se verifică proprietatea StillExecuting pentru a detecta terminarea
Wend

DeleteLargeSales = True

Exit_DeleteLargeSales:
cnn.Close
wrk.Close
Exit Function

Err_DeleteLargeSales:
192
For Each errObj In Errors
Debug.Print errObj.Number, errObj.Description
Next errObj
DeleteLargeSales = False
Resume Exit_DeleteLargeSales
End Function

Exemplul următor utilizează metoda Execute direct pe obiectul Connection (şi nu obiectul QueryDef ca în exemplul
anterior).

Dim cnn As Connection, strConnect As String

strConnect = "ODBC;DSN=Publishers;UID=SA;PWD=;DATABASE=Pubs"
Set cnn = OpenConnection("", dbDriveNotPrompt, False, strConnect)
cnn.Execute "DELETE FROM sales WHERE qty = 100", dbRunAsync
cnn.Close

La executarea unei interogări asincrone aceasta se poate anula prin testarea metodei StillExecuting. Exemplul următor
conţine o asemenea tehnică.

Function CancelAsyncQuery() As Boolean


Dim wrk As Workspace, cnn As Connection, strConnect As String
Dim errObj As Error

On Error GoTo Err_CancelAsyncQuery


Set wrk = DBEngine.CreateWorkspace("ODBCDirect", "Admin", "", dbUseODBC)
strConnect ="ODBC;DSN=Pubs;UID=sa;PWD=;DATABASE=Pubs"
Set cnn = wrk.OpenConnection("", dbDriverNoPrompt, False, strConnect)
' Pornirea unei tranzacţii pentru a putea reface dacă este necesar
wrk.BeginTrans
cnn.Execute "DELETE FROM sales WHERE qty = 100", dbRunAsync
' Executarea altor operaţiuni

' dacă interogarea nu s-a terminat, anulează şi reface


If cnn.StillExecuting Then
cnn.Cancel
wrk.Rollback
' dacă interogarea s-a terminat, încheierea tranzacţiei
Else
wrk.CommitTrans
End If
CancelAsyncQuery = True

Exit_CancelAsyncQuery:
cnn.Close
wrk.Close
Exit Function

Err_CancelAsyncQuery:
For Each errObj In Errors
Debug.Print errObj.Number, errObj.Description
Next errObj
CancelAsyncQuery = False
Resume Exit_CancelAsyncQuery
End Function
193
Proprietatea StillExecuting şi metoda Cancel pot fi utilizate împreună cu obiectele QueryDef, Connection şi
Recordset.

Un obiect Connection suportă o singură operaţiune asincronă la un moment dat. În timpul executării unei interogări
asincrone pe o conexiune nu se mai pot executa şi alte operaţiuni DAO, cum ar fi procesarea unui recordset. Pentru a
executa interogări asincrone multiple în acelaşi timp se vor crea obiecte Connection separate şi se va executa fiecare
interogare asincronă pe un obiect Connection diferit.

Dacă se foloseşte tehnica tranzacţiilor simultan cu interogările asincrone, aplicarea metodei CommitTrans poate opri
execuţia până când se termină interogarea. Din acest motiv se va verifica StillExecuting periodic şi se va termina
tranzacţia doar după ce inteorgarea s-a încheiat (StillExecuting returnează False) sau a fost anulată.

Dacă o interogare de tip acţiune este anulată în afara unei tranzacţii, atunci actualizarea înregistrărilor s-a efectuat doar
până în momentul activării metodei Cancel şi operaţiunea nu poate fi refăcută prin Rollback. Pentru a nu permite
operaţiuni parţiale de acest tip, metoda Cancel se va utiliza doar în interiorul unei tranzacţii. În plus, dacă interogarea
asincronă este iniţiată într-o procedură şi procedura este părăsită înainte de terminarea interogării, aceasta va continua
să se execute.

Pentru a îmbunătăţi performanţa la regăsirea datelor dintr-o sursă ODBC se poate utiliza stocarea locală a înregistrărilor.
Valoarea dată în proprietatea CacheSize a obiectului QueryDef specifică numărul de înregistrări stocate. În mod implicit
se stochează 100 de înregistrări.

Sub SetCacheSize()
Dim wrk As Workspace, qdf As QueryDef, rst As Recordset
Dim cnn As Connection, strConnect As String
Set wrk = CreateWorkspace("ODBCDirect", "Admin", "", dbUseODBC)
Set cnn = wrk.OpenConnection("", dbDriverNoPrompt, False, strConnect)
strConnect ="ODBC;DSN=Pubs;UID=sa;PWD=;DATABASE=Pubs"
Set qdf = cnn.CreateQueryDef("temporary")
qdf.SQL = "SELECT * FROM roysched"
qdf.CacheSize = 200
Set rst = qdf.OpenRecordset()
' executarea operaţiunilor necesare pe recordset

rst.Close
cnn.Close
End Sub

Colecţia Parameters

Printr-un obiect Parameter se reprezintă un parametru transmis unei interogări (dacă este cazul) sau unei proceduri
memorate pe server. Utilizarea parametrilor permite o mai mare flexibilitate a interogărilor, care nu mai trebuiesc
recompilate la fiecare modificare a parametrilor căutării. Un obiect Parameter din spaţiul ODBCDirect este similar, cu mici
diferenţe, unui obiect Parameter din spaţiul Microsoft Jet. În ODBCDirect se poate schimba valoarea proprietăţii Type
(read-only în spaţiul Jet). De asemenea se poate utiliza proprietatea Direction pentru a indica dacă un parametru este de
intrare, de ieşire, ambele sau valoarea returnată de o procedură (a se vedea în Help - Direction Property).

Colecţia Recordsets

Un obiect Recordset reprezintă înregistrările care rezultă din executarea unei interogări pe un obiect Connection sau un
obiect Database, într-un spaţiu de lucru ODBCDirect. Colecţia Recordsets conţine toate obiectele Recordset deschise
curent. Situarea în ierarhia de obiecte este prezentată în tabelul următor

194
Obiectul sau colecţia Conţinut în Conţine

Recordset (obiect) Colecţia Recordsets Colecţia Fields


Colecţia Properties

Recordsets (colecţie) Obiectul Connection Obiecte Recordset


Obiect Database

Obiectele Recordset suportate în spaţiul de lucru ODBCDirect sunt de tipurile: dynaset, snapshot, forward-only şi
dinamic. Cu excepţia ultimului tip, toate celelalte tipuri de obiecte Recordset au fost prezentate la spaţiul de lucru
Microsoft Jet.

Obiecte Recordset de tip dinamic

Un obiect Recordset de tip dinamic este similar unui obiect de tip dynaset, dar este actualizat în mod dinamic, pe măsură
ce alţi utilizatori execută modificări în tabela de bază.

Pentru a crea un obiect Recordset de tip dinamic se va specifica valoarea dbOpenDynamic pentru argumentul type al
metodei OpenRecordset.

Recordseturile de tip dinamic sunt disponibile doar pentru acele drivere ODBC care oferă propriile cursoare. Înainte de
deschiderea unui Recordset dinamic trebuie să se asigure că driverul ODBC suportă acest lucru. Pentru driverele care
nu oferă cursoare proprii, deci nu suportă recordseturi dinamice, se vor deschide obiecte Recordset de tip snapshot sau
forward-only.

Avantajul utilizării obiectelor Recordset de tip dinamic este reflectarea imediată a tuturor schimbărilor din date, inclusiv
înregistrările adăugate sau şterse. Pentru a realiza acest lucru este însă necesar ca DAO să interogheze mereu tabelele
de bază, ceea ce se traduce prin performanţă redusă ca viteză. Acest tip se recomandă, prin urmare, doar pentru situaţii
unde este esenţial să se dispună de cele mai recente actualizări ale datelor.

Deschiderea asincronă a obiectelor Recordset

Pentru a deschide un Recordset în mod asincron, similar interogărilor din spaţiile ODBCDirect, se utilizează constanta
dbRunAsync ca valoare a argumentului options pentru metoda OpenRecordset. Se pot astfel utiliza metoda Cancel şi
proprietatea StillExecuting direct pe obiectul Recordset. De exemplu, la deschiderea unui Recordset care durează
foarte mult deoarece returnează un mare număr de înregistrări, utilizatorul poate fi lăsat să anuleze operaţiunea pentru a
specifica criterii mai restrictive de formare a obiectului.

La anularea (prin Cancel) a unei metode OpenRecordset, obiectul Recordset devine nevalabil şi trebuie redeschis
pentru a regăsi un obiect Recordset corect.

Pentru cazul obiectelor Recordset cu multe înregistrări este utilă aplicarea metodei MoveLast în mod asincron. Acest
fapt se realizează utilizând argumentul dbRunAsync cu metoda, sub forma

recordset.MoveLast dbRunAsync

în continuare se poate testa proprietatea StillExecuting (a obiectului Recordset) şi aplica metoda Cancel.

Colecţia Fields

În spaţiul de lucru ODBCDirect, un obiect Field reprezintă un câmp dintr-un obiect QueryDef sau obiect Recordset.
Anumite procesări sunt enumerate în continuare.
195
• Proprietatea OrdinalPosition este utilizată pentru determinarea ordinii obiectului Field în colecţia Fields.
• Proprietatea Value fixează sau returnează data memorată în câmp.
• Metodele AppendChunk, GetChunk şi proprietatea FieldSize returnează sau fixează o valoare dintr-un obiect
OLE sau câmp memo a unui obiect Recordset.
• Proprietăţile Type, Size şi Attributes determină tipul datelorcare pot fi memorate într-un câmp.
• Proprietăţile SourceField şi SourceTable determină sursa originală a datelor.
• Proprietăţile Value, VisibleValue şi OriginalValue sunt utilizate pentru verificarea completării cu succes a unei
actualizări în loturi (problema este discutată şi în continuare).

Utilizarea ODBCDirect

În această secţiune sunt prezentate câteva operaţiuni uzuale într-un spaţiul de lucru ODBCDirect: actualizarea optimistă
în loturi, lucrul cu cursoare, lucrul cu proceduri memorate.

Utilizarea actualizării optimiste în loturi

În multe aplicaţii client-server, actualizările optimiste apar pe principiul "înregistrare cu înregistrare". Aceasta se întâmplă
în mod uzual în modul

o Un utilizator editează o înregistrare.


o Utilizatorul vrea să salveze înregistrarea.
o Serverul încearcă să blocheze această înregistrare; dacă reuşeşte, înregistrarea este actualizată, în caz
contrar o violare a blocării este tratată de către aplicaţie.
o Utilizatorul se mută la altă înregistrare şi procesul se reia.

Deşi acest mod de operare funcţionează bine în multe cazuri, este uneori mai eficient ca utilizatorul să editeze mai multe
înregistrări care sunt stocate local şi abia apoi să le trimită serverului într-un singur lot pentru actualizare. Metoda se
numeşte actualizare optimistă în loturi (batch optimistic updating) şi presupune etapele:

o Crearea unui spaţiu ODBCDirect


o Stabilirea proprietăţii DefaultCursorDriver, a spaţiului de lucru, la valoare dbUseClientBatchCursor.
o Deschiderea unui obiect Connection sau Database din spaţiul ODBCDirect.
o Utilizarea metodei OpenRecordset pentru obiectul deschis în pasul precedent cu scopul de a deschide
un Recordset şi specificarea constantei dbOptimisticBatch ca valoarea a argumentului lockedits.
o Efectuarea editărilor necesare în obiectul Recordset. Toate editările sunt memorate local.
o La terminare, actualizarea sursei de date se efectuează prin metoda Update a obiectului Recordset, cu
specificarea valorii dbUpdateBatch pentru argumentul type.

Observaţie. Dacă se lansează (programatic) o actualizare în lot în timp ce o înregistrare din obiectul Recordset este
editată de utilizator, înregistrarea care se editează va fi actualizată în mod automat înainte de începerea actualizării în lot.

Exemplul următor ilustrează modul de utilizare a actualizării în lot.

Function RunInBatch()
Dim wrk As Workspace, cnn As Connection, rst As Recordset
Dim strConnect As String

' crearea spaţiului de lucru


Set wrk = DBEngine.CreateWorkspace("ODBCDirect", "Admin", "", dbUseODBC)
' stabilirea driverului de cursor implicit
wrk.DefaultCursorDriver = dbUseClientBatchCursor
' crearea şirului de conectare
strConnect = "ODBC;DSN=Pubs;DATABASE=Pubs;UID=sa;PWD=;"

196
' deschiderea conexiunii
Set cnn = wrk.OpenConnection("", dbDriverNoPrompt, False, strConnect)
' deschiderea recordsetului din conexiune
Set rst = cnn.OpenRecordset( _
"SELECT * FROM sales", dbOpenDynaset, 0, dbOptimisticBatch)

' schimbarea înregistrărilor în recordsetul local


While Not rst.EOF
rst.Edit
rst!qty = rst!qty + 1
rst.Update
rst.MoveNext
Wend

' actualizarea înregistrărilor în sursa de date


rst.Update dbUpdateBatch
End Function

Dacă mai multe înregistrări au fost editate local şi se doreşte ca înregistrarea curentă să fie actualizată înaintea
actualizării în lot, se poate apela metoda Update şi specifica dbUpdateCurrentRecord pentru argumentul type. În acest
mod se scrie înregistrarea curentă în sursa de date fără a se efectua altă actualizare, exemplul următor ilustrază metoda.

' Editarea şi actualizarea primei înregistrări


' Doar prima înregistrare este scrisă în sursa de date
rst.MoveFirst
rst.Edit
rst!qty = rst!qty + 2
rst.Update dbUpdateCurrentRecord

' actualizarea restului de înregistrări


rst.Update dbUpdateBatch

Tratarea coliziunilor

La încercarea de actualizare a unui grup de înregistrări într-un singur lot, este posibil ca alţi utilizatori să editeze în acelaşi
timp una sau mai multe înregistrări din lot, producând astfel o coliziune.

Pentru tratarea coliziunilor se va examina proprietatea BatchCollisions a obiectului Recordset. Proprietatea


BatchCollisions returnează un tablou care memorează bookmark-uri punctând către înregistrările din obiectul
Recordset pentru care au apărut coliziuni. De fiecare dată când apare o coliziune în timpul actualizării în lot, este
adăugat la tablou un pointer către îregistrarea pentru care apare coliziunea. Se poate parcurge fiecare asemenea
bookmark şi examina următoarele proprietăţii ale obiectului Field al înregistrării curente.

Proprietatea Descriere

Value Valoarea curentă a câmpului din Recordset. Aceasta corespunde valorii câmpului după apelul
metodei Update.

OriginalValue Valoarea câmpului din obiectul Recordset înainte de apelul metodei Update.

VisibleValue Valoarea câmpului după cum este memorată în baza de date.

După examinarea proprietăţilor se poate alege o opţiune dintre:

197
o Se poate forţa scrierea în baza de date a valorii curente din obiectul Recordset, suprascriind valoarea
originală a câmpului. Pentru aceasta se apelează metoda Update şi specifica True pentru argumentul
force.
o Se poate schimba valoarea curentă din obiectul propriu Recordset la valoarea originală şi forţa
schimbarea în baza de date.

Observaţie. Apelul metodei Update cu dbUpdateBatch ca argument type şi True ca argument force produce trecerea în
bază a tuturor modificărilor proprii şi suprascrierea modificărilor efectuate de alţi utilizatori. Din acest motiv este mai sigur
apelul metodei Update fără forţare şi rezolvarea ulterioară a coliziunilor prin folosirea tabloului returnat de proprietatea
BatchCollisions împreună cu Value, OriginalValue şi VisibleValue.

Următorul exemplu arată utilizarea tabloului returnat de proprietatea BatchCollision în forţarea în baza de date a
modificărilor din obiectul Recordset local.

Function BatchForceChanges()
Dim rst As Recordset, cnn As Connection, varCollision As Variant
' deschiderea recordsetului pentru actualizarea optimistă în lot
Set rst = cnn.OpenRecordset("SELECT * FROM sales", _
dbOpenDynaset, 0, dbOptimisticBatch)
' modificarea înregistrărilor din recordsetul local
While Not rst.EOF
rst.Edit
rst!qty = rst!qty + 1
rst.Update
rst.MoveNext
Wend
rst.Update dbUpdateBatch

' verificarea coliziunilor şi forţarea modificărilor


For j = 0 to rst.BatchCollisionCount - 1
varCollision = rst.BatchCollision(j)
rst.BookMark = varCollision
rst.Update dbUpdateCurrentRecord, True
Next j
End Function

Exemplul următor poate fi modificat astfel încât actualizarea înregistrărilor cu coliziuni să nu se desfăşoare una câte una,
deşi metoda de forţare globală nu este tocmai indicată.

' deschidere recordset


Set rst = _
cnn.OpenRecordset(("SELECT * FROM sales", dbOpenDynaset, 0, dbOptimisticBatch)
' modificare înregistrărilor
While Not rst.EOF
rst.Edit
rst!qty = rst!qty + 1
rst.Update
rst.MoveNext
Wend
rst.Update dbUpdateBatch, True

198
Utilizarea cursoarelor în spaţiile ODBCDirect

Un cursor indică poziţia înregistrării curente dintr-o mulţime rezultat. Majoritatea tipurilor de cursoare conţin o
reprezentare a datelor din sursa de date şi nu sunt actualizabile. Numim keyset un cursor care conţine date efective şi
care sunt actualizabile.

Cu un cursor se lucrează prin intermediul unui obiect DAO Recordset. La deschiderea unui obiect Recordset prin DAO,
ODBCDirect creează cursorul corespunzător. Fiecare tip de obiect Recordset, cu excepţia celui de tip tabelă,
corespunde unui tip diferit de cursor.

Caracteristicile cursoarelor

Se pot utiliza cursoare pentru a lucra cu mulţimi de date dintr-o sursă ODBC. Cursoarele pot:

o Să reprezinte anumite înregistrări sau toate înregistrările unei tabele


o Să reprezinte anumite înregistrări sau toate înregistrările unei uniuni de tabele
o Să nu reprezinte nici o înregistrare
o Să fie read-only sau actualizabile fie la cursor sau la nivel de câmp
o Să fie complet navigabile sau doar înainte
o Să existe fie la client, fie pe server.

Cursoare pe partea client sau pe partea server

Un cursor necesită resurse temporare pentru a-şi păstra datele. Aceste resurse pot fi în forma RAM, un fişier paginabil
cum ar fi memoria virtuală din Windows, sau fişiere/baze de date temporare. Dacă resursele sunt memorate pe maşina
clientului, cursorul este numit cursor client-side. Cu acest tip de cursor, serverul trimite datele reprezentând cursorul prin
reţea către client, ca şi datele cerute de cursor. Clientul gestionează resursele temporare necesare.

Anumite motoare de baze de date, cum ar fi Microsoft SQL Server 6.0, suportă şi cursoare de tip server-side. Cu acest tip
de cursor, serverul gestionează mulţimea de înregistrări rezultate cu resurse de pe server. Serverul returnează prin reţea
doar datele cerute de client. Utilizarea acestui tip de cursor poate creşte performanţa aplicaţiei, mai ales atunci traficul de
reţea este mare, dar apare condiţia ca serverul să poată oferi resursele necesare tuturor cursoarelor cerute de clienţi.

Alegerea tipului de cursor

La deschiderea unui obiect Recordset pe o sursă de date care nu este ODBC, constanta utilizată pentru argumentul type
al metodei OpenRecordset determină tipul de recordset deschis. La deschiderea unui Recordset pe o sursă ODBC,
acelaşi argument, type, specifică tipul de cursor pe care îl reprezintă obiectul Recordset. Fiecare tip de cursor
corespunde unui tip de recordset. Următorul tabel arată efectul valorilor argumentului type atât pentru surse de date
ODBC, cât şi pentru surse non-ODBC.

Constanta Recordset type Cursor type


(argumentul type) (surse non-ODBC) (surse de date ODBC)

dbOpenDinamic Dynamic type Dynamic

dbOpenDynaset Dynaset type Keyset

dbOpenSnapshot Snapshot type Static

dbOpenForwardOnly Forward-only type Forward-only scrolling (valoarea implicită)

199
Observaţie. Cum obiecte Recordset de tip tabelă nu există în spaţiile de lucru ODBCDirect, nu există cursor
corespunzător acestui tip de recordset.

Proprietatea DefaultCursorDriver a obiectului Workspace specifică unde este creat cursorul – la client sau pe server.
Valorile posibile pentru proprietate sunt date în tabelul alăturat.

Constanta Descriere
(proprietatea
DefaultCursorDriver)

dbUseODBCCursor Utilizare cursoare la client. Rezultate bune pentru mulţimi mici de înregistrări rezultate.

dbUserServerCursor Utilizare cursoare pe server. Performanţă mai bună pentru multe înregistrări dar poate
duce la mărirea traficului de reţea, nu toate sursele ODBC suportă această valoare.

dbUseDefaultCursor Utilizare cursoare pe server, dacă este posibil; cursoare client în caz contrar.

dbUseClientBatchCursor Utilizarea cursoarelor lor la client. Cerut la actualizările în loturi.

dbUseNoCursor Deschidere obiect Recordset ca forward-only, read-only, cu rowset = 1.

Blocarea înregistrărilor (Record Locking)

La deschiderea unui obiect Recordset se poate specifica şi tipul de blocaj al înregistrărilor intenţionat în cazul
actualizărilor. Pentru aceasta se utilizează argumentul lockedits al metodei OpenRecordset. Următorul tabel conţine
explicaţii pentru tipurile posibile de blocaj şi valorile corespunzătoare ale argumentului lockedits.

Constanta Descrierea
(argumentul lockedits) tipului de blocaj al cursorului ODBC

dbOptimistic Pagina conţinând înregistrarea este blocată doar atât timp cât înregistrarea este
actualizată prin metoda Update.

dbPessimistic Pagina cu înregistrarea este blocată cât mai devreme, de la utilizarea metodei Edit.

dbOptimisticValue Utilizarea concurenţei optimiste bazată pe valorile înregistrărilor.

dbOptimisticBatch Utilizarea actualizării optimiste în lot.

dbReadOnly Implicită pentru spaţiile ODBCDirect, interzice modificări în datele obiectului Recordset.

Anumite combinaţii de tipuri de cursoare şi de blocaj nu funcţionează împreună. De exemplu, cu cursoarele Microsoft
SQL Server 6.0, specificarea dbOpenSnapshot pentru argumentul type cere specificarea dbReadOnly pentru lockedits.
Combinaţiile care merg se vor vedea în documentaţia driverului cursorului. Utilizarea unei combinaţii nesuportate este
raportată de DAO în colecţia Errors, de unde poate fi analizată şi tratată prin alegerea următoarei combinaţii plauzibile.

Limitări ale cursoarelor

Datorită valorilor implicite prezentate în tabelele anterioare, obiectul Recordset implicit este read-only, forward-only şi nu
poate fi actualizat. Editarea înregistrărilor necesită specificarea explicită a unui tip de blocaj diferit de dbReadOnly la
aplicarea metodei OpenRecordset.

200
Deoarece nu se pot deschide recordseturi de tip tabelă în spaţiul ODBCDirect, nu se pot utiliza proprietatea Index şi
metoda Seek de regăsire a datelor. De asemenea nu se pot utiliza metodele Find: FindFirst, FindNext, FindPrevious
sau FindLast. În mediul client/server este mai eficient să se selecteze doar datele necesare şi nu mulţimi mai vaste din
care să se găsească ulterior înregistrările necesare. Această înseamnă că interogările trebuie efectuate mai atent (mai
restrictive).

Regăsirea unor mulţimi multiple de rezultate

Orice propoziţie SQL poate include mai multe propoziţii SELECT sau proceduri memorate care invocă una sau mai multe
propoziţii SELECT. Fiecare instrucţiune SELECT generează o mulţime de rezultate care trebuie să fie procesată de cod
sau ignorată mai înainte ca resursele să fie eliberate şi următoarea mulţime de rezultate să fie disponibilă pentru
procesare. Deoarece nu se ştie a priori câte mulţimi de rezultate sunt generate de o procedură memorată, codul trebuie
să fie pregătit să prelucreze un număr necunoscut de mulţimi. De notat că în cazul returnării de către o procedură
memorată a mai multor mulţimi de rezultate, nici una dintre acestea nu poate fi actualizată.

Se pot utiliza fie cursoare client-side, fie cele server-side pentru regăsirea unor multiple mulţimi de rezultate. Dacă se
utilizează cursoare client-side, mulţimile de rezultate sunt returnate de toate obiectele Recordset. Cursoarele server-side
returnează multiple mulţimi de rezultate doar la deschiderea unui Recordset de tip forward-only.

Pentru obţinerea mai multor mulţimi de rezultate

1. Stabilirea proprietăţii DefaultCursorDriver la valoarea dbUseServerCursor pentru specificarea cursoarelor


server-side
2. Crearea unui obiect QueryDef şi stabilirea proprietăţii SQL la un şir valid SQL care returnează multiple obiecte
Recordset.
3. Stabilirea proprietăţii CacheSize a obiectului QueryDef la 1 pentru a cere serverului trimiterea unei singure
înregistrări o dată. La regăsirea înregistrărilor în acest mod nu se utilizează efectiv cursorul.
4. Deschiderea obiectului Recordset pe obiectul QueryDef creat. Se dă valoarea dbOpenForwardOnly pentru
argumentul type al metodei OpenRecordset.
5. Utilizarea metodei NextRecordset pentru a accesa următorul obiect Recordset din grupul de obiecte Recordset
returnat de server. Aceasta ignorează obiectul Recordset curent şi îl înlocuieşte cu următorul obiect. Dacă nu
mai există obiecte Recordset atunci metoda NextRecordset returnează valoarea False iar obiectul curent
Recordset va fi gol (empty).

Exemplul următor tipăreşte valorile pentru fiecare câmp din fiecare înregistrare a fiecărei mulţimi de rezultate.

Function GetMultipleResults()
Dim wrk As Workspace, rst As Recordset, cnn As Connection, qdf As QueryDef
Dim fld As Field, strSQL As String, strConnect As String, fDone As Boolean

' creare spaţiu ODBCDirect


Set wrk = DBEngine.CreateWorkspace(""ODBCDirect", "Admin", "", dbUseODBC)
' creare şir de conectare
strConnect = "ODBC;DSN=Pubs;DATABASE=Pubs;UID=sa;PWD=;"
' deschidere conexiune
Set cnn = wrk.OpenConnection("", dbDriverNoPrompt, False, strConnect)
' Creare instrucţiuni SQL
strSQL = "SELECT au_lname, au_fname FROM Authors; SELECT title FROM Titles;"
' stabilirea cursorului implicit
wrk.DefaultCursorDriver = dbUseServerCursor
' Deschidere recordset
Set qdf = cnn.CreateQueryDef("", strSQL)
qdf.CacheSize = 1
' Deschiderea recordset pentru interogare

201
Ser rst = qdf.OpenRecordset(dbOpenForwardOnly)

Do Until fDone = True


' tipărirea valorilor câmpurilor
While Not rst.EOF
For Each fld In rst.Fields
Debug.Print fld.Value
Next fld
rst.MoveNext
Wend
FDone = Not rst.NextRecordset()
Loop
rst.Close
cnn.Close
wrk.Close
End Function

Lucrul cu proceduri memorate

Se pot utiliza obiecte ODBCDirect QueryDef pentru a executa proceduri memorate, inclusiv proceduri memorate care
necesită parametri de intrare şi returnează valori. Următorul exemplu creează procedura numită GetEmps, memorată pe
server.

strSQL = "CREATE PROCEDURE GetEmps AS"


strSQL = strSQL & "SELECT * FROM EMPLOYEE;"
cnn.Execute strSQL

Dacă există deşi o procedură cu acest nume, se poate utiliza instrucţiunea DROP pentru a şterge mai înainte versiunea
veche:

strSQL = "DROP PROCEDURE GetEmps;"


cnn.Execute strSQL

Se poate executa procedura memorată utilizând metoda Execute a obiectului Connection. Pentru a regăsi valoarea
returnată se creează un obiect QueryDef şi deschidem un recordset pe el.

Set qdf = cnn.CreateQueryDef("qry", "{ call GetEmps() }")


Set rst = qdf.OpenRecordset

Se utilizează obiectul Parameter pentru a lucra cu parametrii. Proprietatea Direction a obiectului Parameter comunică
DAO cum funcţionează parametrul. Driverul ODBC încearcă să determine direcţia parametrului (intrare sau ieşire) dar
proprietatea Direction este read/write aşa că direcţia poate fi schimbată. Următorul exemplu creează o procedură
memorată cu un parametru de intrare şi o valoare returnată. Procedura este executată şi se regăseşte valoarea returnată.

' crearea procedurii memorate pe server


strSQL = "CREATE PROCEDURE UpdateEmps (@invar int) AS RETURN @invar;"
cnn.Execute strSQL

' crearea QueryDef pentru a executa procedura memorată


Set qdf = cnn.CreateQueryDef("qry", "{ ? = call UpdateEmps(?) }")

' tratarea parametrilor


qdf.Parameters(0).Direction = dbParamReturnValue
qdf.Parameters(1) = 10
202
qdf.Execute

' obţinerea valorii returnate


var = qdf.Parameters(0).Value

Modelul de obiecte PowerPoint

În acest capitol se prezintă principalele obiecte din modelul de obiecte Microsoft PowerPoint 97. Pentru a vedea o
imagine a întregului model de obiecte PowerPoint ca şi enumerările complete ale proprietăţilor şi metodelor se vor
consulta, totuşi, intrările respective din Help.

Afişarea sistemului de help Microsoft PowerPoint Visual Basic este posibilă dacă la instalarea aplicaţiei PowerPoint s-a
selectat instalarea componentei Online Help for Visual Basic. Pentru a vedea conţinutul şi indexul acestui sistem de
fişiere Help, click pe Contents and Index în meniul Help din Visual Basic Editor (VBE), iar în fişa Contents din dialogul
Help Topics dublu click pe "Microsoft PowerPoint Visual Basic Reference".

Obiectul Application

La pornirea unei sesiuni PowerPoint, se creează un obiect Application. Proprietăţile şi metodele acestui obiect sunt
utilizate pentru controlarea atributelor şi comportării întregii aplicaţii şi obţinerea accesului la restul modelului de obiecte
PowerPoint.

Următoarele proprietăţi pot fi utilizate fără calificatorul Application, constituind accesori la modelul de obiecte:
ActivePresentation, ActiveWindow, AddIns, Assistant, CommandBars, Presentations, SlideShowWindows şi
Windows. Pentru alte proprietăţi şi metode este necesară calificarea. De exemplu:

Application.Quit

Cele mai utilizate proprietăţi şi metode sunt prezentate, după funcţionalitate, în continuare.

Returnarea unui obiect Application

Din cod executate în PowerPoint, obiectul Application este referit prin cuvântul cheie Application, ca în exemplul
anterior.

Dacă se atribuie unei variabile obiectul Application, variabila se va declara de tip PowerPoint.Application, după modelul

Dim appPPT As PowerPoint.Application


Set appPPT = Application

Se poate utiliza de asemenea proprietatea Application a oricărui obiect PowerPoint pentru a returna obiectul
Application PowerPoint. Această metodă este utilă atunci când este necesar să se obţină referinţa la obiectul
Application dintr-o prezentare PowerPoint scufundată în documentul altei aplicaţii. Următorul exemplu, executat din
Excel, stabileşte o variabilă la obiectul aplicaţie PowerPoint utilizând primul shape (care trebuie să fie o prezentare
PowerPoint) din foaia de calcul.

Dim appPPT As PowerPoint.Application


Set embeddedPres = Worksheets(1).Shapes(1)
embeddedPres.OLEFormat.Activate
Set appPPT = embeddedPres.OleFormat.Object. Application

203
Următorul exemplu creează un obiect Application PowerPoint din altă aplicaţie, porneşte PowerPoint şi deschide o
prezentare existentă:

Set ppt = CreateObject("Powerpoint.Application.8")


ppt.Visible = True
ppt.Presentations.Open "…numele prezentării, eventual cu cale"

Controlul aspectului ferestrei aplicaţiei

Un rezumat al proprietăţilor şi metodelor care controlează aspectul ferestrei în care se execută PowerPoint este prezentat
în tabelul următor.

Acţiunea Proprietatea sau metoda utilă

Activarea ferestrei aplicaţiei PowerPoint Metoda Activate

Verificarea faptului că fereastra aplicaţiei PowerPoint este activă Proprietatea Active

Stabilirea sau returnarea textului care apare în bara de titlu a aplicaţiei Proprietatea Caption
PowerPoint

Stabilirea sau returnarea mărimii şi poziţiei ferestrei PowerPoint pe ecran Proprietăţile Height, Left, Top şi Width

Stabilirea sau returnarea vizibilităţii ferestrei aplicaţiei. Trebuie dată valoarea Proprietatea Visible
True la crearea obiectului Application PowerPoint în altă aplicaţie pentru a
vedea PowerPoint pe ecran.

Stabilirea sau returnarea stării ferestrei aplicaţiei: maximizată, minimizată Proprietatea WindowsState
sau flotantă.

Multe dintre aceste proprietăţi şi metode se aplică, de asemenea, obiectului DocumentWindow pentru controlarea
aspectului ferestrei documentului.

Controlarea atributelor şi comportării globale a aplicaţiei

Atributele sau acţiunile caracteristice pentru întreaga aplicaţie PowerPoint sunt controlate prin proprietăţile şi metodele
prezentate în tabelul următor.

Acţiunea Proprietatea sau metoda utilă

Numele imprimantei active Proprietatea ActivePrinter

Returnarea numărului de construcţie PowerPoint Proprietatea Build

Afişarea unui subiect de Help Metoda Help

Returnarea numelui sistemului de operare Proprietatea OperatingSystem

Returnarea căii către aplicaţia PowerPoint Proprietatea Path

Părăsirea (închiderea) aplicaţiei PowerPoint Metoda Quit

204
Executarea unei proceduri Visual Basic Metoda Run

Returnarea numărului de versiune Proprietatea Version

Accesarea principalelor obiecte ale aplicaţiei

Proprietăţile enumerate în tabelul următor dau acces la principalele obiecte conţinute în obiectul Application: prezentări,
ferestre ale documentului, ferestre de vizualizare a diapozitivelor. Toate proprietăţile sunt ale obiectului Application.

Obiectul returnat Proprietatea utilizată

Presentations (colecţie) Proprietatea Presentations

Prezentarea activă Proprietatea ActivePresentation

DocumentWindows (colecţie) Proprietatea Windows

Fereastra documentului activ Proprietatea ActiveWindow

AddIns (colecţie) Proprietatea AddIns

SlideShowWindows (colecţie) Proprietatea SlideShowWindows

Accesarea obiectelor partajate de Microsoft Office

Obţinerea referinţelor de obiecte comune tuturor aplicaţiilor Microsoft Office, cum ar fi barele de meniuri şi de unelte,
FileSearch etc., este rezumată în tabelul următor.

Referinţă la Proprietatea utilizată

Office Assistant Proprietatea Assistant

Meniuri şi bare de unelte PowerPoint Proprietatea CommandBars

Căutarea fişierelor Proprietatea FileSearch

Editorul Visual Basic Proprietatea VBE

Obiectul Presentation

Se creează un obiect Presentation de fiecare dată când se deschide sau se creează un fişier (o prezentare) în
PowerPoint. Se va observa că multe dintre proprietăţile şi metodele obiectului Presentation corespund intrărilor din
meniul File. Proprietăţile şi metodele obiectului Presentation, sau ale colecţiei respective, sunt utilizate pentru a
deschide, crea, salva sau închide fişiere. Prin intermediul lor se vor controla atributele şi comportarea globală şi, de
asemenea, se va obţine acces la obiectele conţinute: slide-uri şi mastere.

Returnarea obiectului Presentation

Se va utiliza proprietatea ActivePresentation a obiectului Application pentru a returna prezentarea care este afişată în
fereastra activă. Următorul exemplu salvează prezentarea activă:

205
ActivePresentation.Save

Se poate returna oricare dintre prezentările deschise curent prin colecţia Presentations, în modul uzual de referire a unui
element dintr-o colecţie:

Presentations("Sample Presentation").Slides.Add 1, 1

adaugă un nou slide la prezentarea "Sample Presentation".

Prin proprietatea Presentation a obiectelor DocumentWindow şi SlideShowWindow se poate returna o referinţă la


prezentarea care a creat respectivele ferestre (de remarcat că proprietatea Parent returnează un obiect diferit dacă
obiectul aparţine unei prezentări scufundate). Următorul exemplu afişează numele prezentării care se execută în prima
fereastră slide show:

MsgBox SlideShowWindow(1).Presentation.Name

Pentru a returna un obiect Presentation reprezentând o prezentare scufundată, se utilizează proprietatea Object a
obiectului OLEFormat pentru forma (shape) care conţine prezentarea scufundată, după modelul

Dim embeddedPres As Presentation


Set embeddedPres = ActivePresentation.Slides(1).Shapes(3).OLEFormat.Object

prin care se atribuie variabilei embeddedPres prezentarea scufundată în al treilea shape de pe diapozitivul cu numărul 1.

Deschiderea unei prezentări existente

Metoda Open a colecţiei Presentations (returnată de proprietatea sinonimă a obiectului Application) realizează
deschiderea unei prezentări, după modelul

Dim myPres As Presentation


Set myPres = Presentations.Open _
(FileName:= " … nume fişier + cale (dacă este necesară)…")
myPres.Window(1).ViewType = ppViewSlideSorter

unde prezentarea deschisă este vizualizată în modul Slide Sorter.

Crearea unei prezentări noi

În acest scop se utilizează metoda Add a colecţiei Presentations. Este uzual ca obiectul Presentation obţinut să fie
atribuit unei variabile pentru procesare programatică ulterioară. În exemplul următor se creează o prezentare nouă şi se
adaugă un slide.

Dim myPres As Presentation


Set myPres = Presentations.Add
myPres.Slides.Add 1, ppLayoutTitle

Atribuirea unui nume semnificativ are de asemenea rolul de a permite o referire uşoară la o prezentare. În exemplul
următor se creează o nouă prezentare care este salvată imediat cu un nume prin aplicarea metodei SaveAs. Este de
remarcat că proprietatea Name a obiectului Presentation este read-only şi prin urmare nu poate fi modificată; astfel o
prezentare este identificată în mod unic prin numele său într-un proiect. Numele poate fi utilizat în mod uzual pentru a
obţine o referinţă prin intermediul colecţiei Presentations:

206
Presentations.Add.SaveAs "Sales Report"
Presentations("Sales Report").Slides.Add 1, ppLayoutTitle

Importul unei prezentări dintr-o schiţă (outline) Word

Crearea unei prezentări dintr-un outline scris în Word se realizează din Microsoft Word prin metoda PresentIt a obiectului
Document reprezentând outline-ul. Exemplul următor este ilustrativ:

Documents.Open("C:\Presentation Outline.doc").PresentIt

Activarea unei prezentări

Nu există o metodă Activate pentru obiectul Presentation. Activarea prezentării are loc o dată cu activarea uneia dintre
ferestrele de document ale prezentării:

Presentations("Sales Report").Windows(1).Activate

Controlul numerotării şi dimensiunii diapozitivelor

Proprietatea PageSetup a obiectului Presentation returnează un obiect PageSetup. Acest obiect conţine valorile pentru
orientarea pagini de note şi a diapozitivelor, dimensiuni şi numerotare. Proprietăţile obiectului PageSetup sunt similare
dialogului PageSetup din meniul File, astfel încât anumite atribuiri produc în mod automat efecte asupra altor parametri
(de exemplu o lăţime mai mare decât înălţimea produce o orientare landscape). Proprietăţile sunt:

FirstSlideNumber - returnează sau stabileşte numerotarea primului diapozitiv.

NotesOrientation, SlideOrientation - returnează sau stabilesc orientarea pe ecran şi imprimantă a notelor şi


diapozitivelor. Pot fi una dintre valorile (MsoOrientation): msoOrientationHorizontal, msoOrientationMixed sau
msoOrientationVertical.

SlideHeight, SlideWidth - returnează sau stabilesc dimensiunile unui diapozitiv, în puncte.

SlideSize - tipul de dimensiune a unui diapozitiv. Poate fi una dintre constantele predefinite (PpSlideSizeType):
ppSlideSize35MM, ppSlideSizeA4Paper, ppSlideSizeCustom, ppSlideSizeLetterPaper, ppSlideSizeOnScreen sau
ppSlideSizeOverhead.

Exemplul următor stabileşte pentru toate diapozitivele dimensiunea 11" x 8.5" şi numerotarea diapozitivelor de la 17.

With ActivePresentation.PageSetup
.SlideWidth = 11 * 72
.SlideHeight = 8.5 * 72
.FirstSlideNumber = 17
End With

Ar fi de remarcat că stabilirea explicită a dimensiunilor produce trecerea proprietăţii SlideSize la valoarea


ppSlideSizeCustom şi a proprietăţii SlideOrientation la msoOrientationHorizontal.

Stabilirea unui aspect unitar al prezentării

Se poate lucra programatic cu şabloane şi cu elementele master ale unei prezentări.

Aplicarea unui şablon se efectuează prin metoda ApplyTemplate a obiectului Presentation, după modelul
207
ActivePresentation.ApplyTemplate " … template-ul, eventual cu cale …"

Proprietăţile HandoutMaster, NotesMaster, SlideMaster sau TitleMaster ale obiectului Presentation returnează un
obiect Master care reprezintă masterul entităţii respective.

Utilizarea proprietăţilor obiectului Master permite stabilirea fundalului, modificarea schemei de culori, adăugarea de
controale ActiveX, lucrul cu stilurile de text. Orice modificare efectuată pentru Master se reflectă în categoria respectivă
de elemente ale prezentării.

Dintre proprietăţile obiectului Master prezentăm câteva în continuare, fiecare necesitând însă o căutare în Help deoarece
returnează colecţii de obiecte complexe.

Background - returnează un obiect ShapeRange reprezentând background-ul diapozitivului.

ColorScheme - returnează sau stabileşte obiectul ColorScheme reprezentând schema de culori a masterului.

HeadersFooters - returnează colecţia HeadersFooters care reprezintă antetul, subsolul, data şi numărul de pagină al
diapozitivului.

Height, Width - returnează dimensiunile, în puncte. Sunt read-only pentru un master.

Shapes - returnează colecţia Shapes reprezentând toate elementele care au foest plasate sau inserate în master.
Colecţia poate conţine desene, forme (shapes), obiecte OLE, imagini etc.

TextStyles - returnează colecţia TextStyles reprezentând trei stiluri de text: title text (stilul titlului), body text (textul din
interiorul diapozitivului) şi default text (textul din forme grafice – shapes).

Următorul exemplu stabileşte umplerea fundalului diapozitivului master:

ActivePresentation.SlideMaster.Background.Fill.PresetGradient _
msoGradientHorizontal, 1, msoGradientBrass

Dacă se doreşte ca o formă specifică, cum ar fi o imagine sau un control ActiveX, să apară pe toate slide-urile unei
prezentări, aceasta se va adăuga la master. Un control ActiveX de pe master va răspunde la evenimente din prezentarea
diapozitivelor la fiecare click pe control, pe orice slide s-ar afla.

Modificările uniforme ale textului se realizează prin intermediul stilurilor. Fiecare obiect TextStyle (din colecţia returnată
de proprietatea TextStyles) conţine un obiect TextFrame care descrie cum este plasat textul în boxa de text şi un obiect
Ruler care conţine tab stopurile şi informaţia de indentare. Proprietatea Levels a obiectului TextStyle returnează colecţia
TextStyleLevels care conţine informaţia de formatare pentru 5 nivele de listă ierarhizată (pentru titlu şi corp se va utiliza
întotdeauna nivelul întâi). Exemplul următor utilizează aceste proprietăţi pentru o formatare:

With ActivePresentation.SlideMaster.TextStyles(ppBodyStyle).Levels(1)
With .Font
.Name = "Arial"
.Size = 36
End With
With .ParagraphFormat
LineRuleAfter = False
.SpaceAfter = 6
End With
End With

208
Observaţie. Stilurile pentru titlu şi textul interior se poate stabili în mod diferit pentru fiecare master. Stilul textului din
formele gafice nu se aplică pentru fiecare master, ci este global, pentru întreaga prezentare.

Tipărirea unei prezentări

Metoda PrintOut a obiectului Presentation tipăreşte prezentarea:

ActivePresentation.PrintOut

Opţiunile de tipărire sunt fixate anterior tipăririi prin proprietăţile şi metodele obiectului PrintOptions (returnat de
proprietatea sinonimă a obiectului Presentation).

Dintre proprietăţile obiectului PrintOptions enumerăm:

OutputType care returnează sau stabileşte care elemente ale presentării se tipăresc. Poate fi o constantă de tip
PpPrintOutputType:

ppPrintOutputBuildSlides ppPrintOutputNotesPages

ppPrintOutputOutline ppPrintOutputSixSlideHandouts

ppPrintOutputSlides (implicită) ppPrintOutputThreeSlideHandouts

ppPrintOutputTwoSlideHandouts

NumberOfCopies care returnează sau stabileşte numărul de copii tipărite.

FitToPage care este True dacă la tipărire se va scala diapozitivul încât să se potrivească foii de hârtie.

Ranges care returnează obiectul PrintRanges reprezentând domeniile de dipozitive care se tipăresc.

Collate care este True (şi implicit) dacă o copie a prezentării este tipărită complet înaintea copiei următoare.

Exemplul următor utilizează câteva asemenea proprietăţi:

With ActivePresentation.PrintOptions
.NumberOfCopies = 3
.Collate = True
.Parent.PrintOut
End With

unde se remarcă faptul că proprietatea Parent returnează obiectul Presentation căruia i se poate folosi proprietatea
PrintOut.

Salvarea unei prezentări

Prima salvare a prezentării, în care i se dăun nume, se efectuează prin metoda SaveAs:

With Presentations.Add
.Slides.Add 1, ppLayoutTitle
.SaveAs "Sample"
209
End With

Următoarele salvări se obţin prin metoda Save:

ActivePresentation.Save

Închiderea unei prezentări

Pentru a închide o prezentare se aplică obiectului Presentation metoda Close:

Presentations("Sample").Close

Dacă prezentarea a fost modificată de la ultima salvare, este afişat, în mod automat, un mesaj de interogare asupra
salvării. Pentru a închide prezentarea fără salvare şi fără afişarea mesajului se stabileşte mai întâi proprietatea Saved la
True:

With Application.Presentations("Sample")
.Saved = True
.Close
End With

Configurarea şi executarea unei prezentări

Se va utiliza proprietatea SlideShowSettings a obiectului Presentation pentru a returna obiectul sinonim


SlideShowSettings care reprezintă execuţia unei prezentări de diapozitive.

Obiectul SlideShowSettings are o singură metodă, Run, care execută prezentarea potrivit parametrilor stabiliţi de
proprietăţile obiectului SlideShowSettings.

Dintre proprietăţi enumerăm câteva în continuare.

AdvanceMode returnează sau stabileşte valoarea care controlează modul de trecere la următorul diapozitiv. Poate fi o
constantă de tip PpSlideShowAdvanceMode: ppSlideShowManualAdvance, ppSlideShowRehearseNewTimings sau
ppSlideShowUseSlideTimings.

StartingSlide, EndingSlide stabilesc sau returnează diapozitivul cu care se începe execuţia prezentării şi cel unde se
termină vizionarea.

LoopUntilStopped care este True dacă prezentarea se execută ciclic până la apăsarea tastei ESC.

RangeType returnează sau fixează tipul de prezentare executată. Poate fi una dintre constantele de tip
PpSlideShowRangeType: ppShowAll, ppShowNamedSlideShow sau ppShowSlideRange.

Următorul exemplu ilustrează câteva proprietăţi:

With ActivePresentation.SlideShowSettings
.StartingSlide = 2
.EndingSlide = 4
.RangeType = ppShowSlideRange
.AdvanceMode = ppSlideShowUseSlideTimings
.LoopUntilStopped = True
.Run
210
End With

unde se remarcă faptul că ultima instrucţiune apelează metoda Run, după ce s-au fixat atributele execuţiei.

Accesul la diapozitivele prezentării

Prin metoda Slides a obiectului Presentation se obţine accesul la diapozitivele prezentării şi, de aici, la textul şi grafica
unui diapozitiv. Obiectul Slide este prezentat în secţiunea următoare.

Obiectele Slides, Slide şi SlideRange

Există trei obiecte diferite în modelul de obiecte PowerPoint care reprezintă diapozitive: colecţia Slides a tuturor
diapozitivelor dintr-o prezentare, colecţia SlideRange a diapozitivelor dintr-o submulţime de diapozitive şi obiectul Slide
care reprezintă un diapozitiv individual. În general, se va utiliza colecţia Slides pentru adăugarea unui diapozitiv şi când
se parcurg toate diapozitivele prezentării; se va utiliza obiectul Slide dacă se lucrează cu un anumit diapozitiv; se va
utiliza colecţia SlideRange pentru a formata sau lucra cu mai multe diapozitive.

Returnarea colecţiei Slides

Întreaga mulţime de diapozitive a unei prezentări este referită prin proprietatea Slides a obiectului Presentation.
Următorul exemplu inserează slide-urile din Clipboard la sfârşitul prezentării (pentru că nu s-a specificat locul lipirii prin
.Paste(index)):

Activepresentation.Slides.Paste

Returnarea obiectului Slide

O referinţă la un slide anumit se obţine prin intermediul colecţiei Slides în mod uzual prin metoda Item. Metoda fiind
implicită, menţioanrea ei este facultativă.

ActivePresentation.Slides(3).Copy

copie al treilea slide în Clipboard.

Fiecare diapozitiv al unei prezentări are ataşat un număr de identificare unic, definit automat la crearea diapozitivului.
Atunci când în proiectarea unei prezentări se inserează noi diapozitive, se şterg diapozitive, se sortează etc., referirea
prin indice nu returnează întotdeauna acelaşi diapozitiv. Referirea prin numărul de identificare conduce mereu la acelaşi
diapozitiv. Proprietatea SlideID a unui slide returnează numărul de identificare, proprietatea fiind read-only. Proprietatea
FindBySlideID permite specificarea unui slide prin ID-ul său. Exemplul următor utilizează aceste proprietăţi:

Dim newSlideID As Long


newSlideID = ActivePresentation.Slides.Add(1,ppLayoutTitleOnly).SlideID
ActivePresentation.Slides.FindBySlideID(newSlideID).Copy

Pentru a obţine o referinţă la diapozitivul afişat curent într-o fereastră document sau de slide show, se utilizează
proprietatea Slide a obiectului View al ferestrei, după modelul

Windows(2).View.Slide.Copy

Pentru a returna un slide dintr-o selecţie, se foloseşte Selection.SlideRange(index), unde index este numele sau
numărul de ordine din colecţie:

211
ActiveWindow.Selection.SlideRange(1).Layout = ppLayoutTitle

Returnarea unui obiect SlideRange

Prin Slides.Range(index), unde index este numele, indexul sau un tablou de asemenea elemente (nume sau indici), se
returnează un obiect SlideRange din colecţia Slides. Pentru diapozitivele selectate astfel se poate realiza o formatare
unitară etc.

With Activepresentation.Slides.Range(Array(1, 3))


.FollowMasterBackground = False
.Background.Fill.PresetGradient (msoGradientHorizontal, 1, msoGradientLateSunset)
End With

Adăugarea unui diapozitiv

La colecţia Slides se aplică metoda Add. Se creează un nou diapozitiv, se adaugă la colecţia tuturor diapozitivelor.
Metoda acceptă două argumente prin care se specifică locul noului slide şi layout-ul diapozitivului. Ca rezultat al aplicării
metodei se returnează un obiect Slide. Sintaxa:

expression.Add(Index, Layout)

unde

expression returnează o colecţie Slides.

Index specifică rangul noului slide în colecţia Slides (locul efectiv ocupat). Nu poate depăşi Slides.Count + 1.

Layout specifică formatul noului diapozitiv. Poate fi una dintre constantele PpSlideLayout:

ppLayoutBlank ppLayoutChart ppLayoutChartAndText

ppLayoutClipartAndText ppLayoutClipArtAndVerticalText ppLayoutFourObject

sppLayoutLargeObject ppLayoutMediaClipAndText ppLayoutObject

ppLayoutObjectAndText ppLayoutObjectOverText ppLayoutOrgchart

ppLayoutTable ppLayoutText ppLayoutTextAndChart

ppLayoutTextAndClipart ppLayoutTextAndMediaClip ppLayoutTextAndObject

ppLayoutTextAndTwoObjects ppLayoutTextOverObject ppLayoutTitle

ppLayoutTitleOnly ppLayoutTwoColumnText ppLayoutTwoObjectsAndText

ppLayoutTwoObjectsOverText ppLayoutVerticalText ppLayoutVerticalTitleAndText

ppLayoutVerticalTitleAndTextOverChart

Exemplul următor adaugă un slide titlu la începutul prezentării active.

ActivePresentation.Slides.Add 1, ppLayoutTitleOnly

212
Inserarea de diapozitive bazate pe un outline Word se realizează prin metoda InsertFromFile, după modelul

ActivePresentation.Slides.InsertFromFile _
FileName:=" … numele fişierului Word …", Index:=3

Metoda are un domeniu mai larg de aplicabilitate, sintaxa este

expression.InsertFromFile(FileName, Index, SlideStart, SlideEnd)

unde

expression returnează o colecţie Slides.

FileName este numele fişierului, eventual cu cale.

Index rangul diapozitivului din colecţia Slides specificată după care se inserează noile diapozitive.

SlideStart, SlideEnd specifică prin indicii de inceput şi de sfârşit domeniul diapozitivelor din fişier care se inserează în
colecţia Slides. Indicele omis este luat implicit drept indicele minim, respectiv maxim.

Stabilirea fundalului şi a schemei de culori

Pentru o formatare globală se vor utiliza elementele master. Dacă se doreşte ca un diapozitiv sau un grup de diapozitive
să aibă o formatare distinctă, se va utiliza proprietatea Background sau ColorScheme a obiectului Slide sau
SlideRange.

Proprietatea Background returnează un obiect ShapeRange, se aplică proprietatea Fill pentru returnarea obiectului
FillFormat şi acest obiect reprezintă umplerea fundalului. Proprietăţile şi metodele acestui obiect modifică aspectul
background-ului dorit. Este de menţionat că pentru a păstra modificările valabile doar pentru diapozitivul (diapozitivele)
procesat, proprietatea FollowMasterBackground trebuie fixată pe False.

Datorită complexităţii obiectului, FillFormat se va studia din Help, pentru a vedea multiplele proprietăţi şi metode
suportate.

Exemplul următor dă o imagine redusă a posibilităţilor de prelucrare grafică:

With ActivePresentation.Slides(1)
.FollowMasterBackground = False
.Background.Fill.PresetGradient _
msoGradientHorizontal, 1, msoGradientDaybreak
End With

metoda PresetGradient aplică un efect vizual caracterizat de trei parametri, Style, Variant şi PresetGradientType,
corespunzând dialogului Fill Effects din PowerPoint (şi nu numai).

Modificarea culorilor se poate realiza prin schimbarea schemei de culori sau prin editarea unei culori particulare dintr-o
schemă. Proprietatea ColorScheme a unui obiect Slide sau SlideRange returnează obiectul ColorScheme care
reprezintă schema de culori. Se poate schimba apoi schema sau se poate utiliza metoda Colors pentru a edita culori.
Numerotarea schemelor de culori este cea din dialogul Color Scheme din PowerPoint. Exemplele următoare ilustrează
mecanismul modificărilor.

213
With ActivePresentation
.Slides(1).ColorScheme = .ColorScheme(3)
End With

sau

ActivePresentation.Slides(1).ColorScheme.Colors(ppTitle).RGB = RGB(0,255,0)

care colorează titlul în verde. Culorile schemei de culori pot fi referite printr-o constantă de tip PpColorSchemeIndex:
ppAccent1, ppAccent2, ppAccent3, ppBackground, ppFill, ppForeground, ppNotSchemeColor, ppShadow sau ppTitle, cu
interpretările imediate din PowerPoint.

Schema de culori este pierdută la aplicarea unui template, moment în care se schimbă şi schemele de culori disponibile.

Alegerea unui layout

La adăugarea unui diapozitiv s-a văzut că se stabileşte şi layout-ul acestuia prin argumentul Layout. Returnarea sau
modificarea layout-ului se realizează prin proprietatea Layout:

ActivePresentation.Slides(1).Layout = ppLayoutTextAndChart

La modificarea layout-ului sunt totuşi păstrate şi rezervările care conţin text sau obiecte.

Adăugarea de obiecte la un diapozitiv

Se pot adăuga obiecte (cum ar fi AutoShapes, obiecte OLE, imagini) la un diapozitiv utilizând una dintre metodele
colecţiei Shapes. O referinţă la această colecţie se obţine prin proprietatea Shapes a obiectului Slide, colecţia
reprezentând întregul layer de desen de pe un diapozitiv. Operarea cu aceste obiecte este descrisă într-un capitol
separat, dedicat obiectelor desenate.

Schimbarea ordinii diapozitivelor

Pentru a schimba locul unui diapozitiv într-o prezentare se utilizează metodele Cut şi Paste prin care se ia un diapozitiv
din locul vechi şi se inserează în noua poziţie:

With ActivePresentation.Slides
.Item(4).Cut
.Paste 6
End With

care mută diapozitivul diapozitivul 4 pe locul 6 din prezentare.

Stabilirea efectelor tranziţiei diapozitivelor

Atributele tranziţiei unui diapozitiv sunt păstrate în proprietăţile obiectului SlideShowTransition, returnat de proprietatea
sinonimă SlideShowTransition a obiectului Slide sau SlideRange. Proprietăţile privind tranziţia corespund opţiunilor
disponibile prin dialogul specializat din PowerPoint: AdvanceOnClick, AdvanceOnTime, AdvanceTime, EntryEffect,
SoundEffect, Speed.

Primele două proprietăţi, AvanceOnClick şi AvanceOnTime, sunt True dacă trecerea la următorul slide are loc la click
sau după un timp fixat de AdvanceTime. Pot fi stabilite ambele tipuri de avans la True.

214
EntryEffect stabileşte modul de apariţie a noului diapozitiv. Poate avea una dintre valorile tipului enumerat
PpEntryEffect, de forma ppEffectAppear, ppEffectBlindsHorizontal, ppEffectBlindsVertical, ppEffectBoxIn şi încă alte
vreo 60 de constante, descriind efectele selectabile prin dialogurile PowerPoint.

SoundEffect returnează obiectul sinonim care controlează ce se va cânta când are loc tarnziţia. Metoda utilă (nu sunt
multe altele) este ImportFromFile prin care se specifică un fişier de tip sound.

Speed precizează ritmul efectuării tranziţiei. Returnează sau stabileşte acest ritm ca o constantă de tip
PpTransitionSpeed: ppTransitionSpeedFast, ppTransitionSpeedMedium, ppTransitionSpeedMixed sau
ppTransitionSpeedSlow.

Exemplul următor ilustrează câteva dintre aceste proprietăţi.

With ActivePresentation.Slides(1).SlideShowTransition
.Speed = ppTransitionSpeedFast
.EntryEffect = ppEffectStripsDownLeft
.SoundEffect.ImportFromFile "c:\…\bass.wav"
.AdvanceOnTime = True
.AdvanceTime = 5
End With
ActivePresentation.SlideShowSettings.AdvanceMode = _
ppSlideShowUseSlideTimings

În exemplu se remarcă faptul că proprietatea AdvanceMode ia valoarea ppSlideShowUseSlideTimings, pentru


considerarea timpului fixat la tranziţia diapozitivului.

Referirea notiţelor vorbitorului (Speaker's notes)

Proprietatea NotesPages returnează un obiect SlideRange care reprezintă paginile de note pentru un diapozitiv sau un
domeniu de diapozitive. Obiectul returnat are anumite restricţii în privinţa utilizării unor proprietăţi şi metode în raport cu
obiectul SlideRange care reprezintă un domeniu de slide-uri.

Pentru a modifica toate diapozitivele simultan se va utiliza proprietatea NotesMaster a obiectului Presentation,
proprietatea care returnează un obiect Slide reprezentând masterul notiţelor.

ActivePresentation.Slides(1).NotesPage.Shapes.Placeholders(2) _
.TextFrame.TextRange.InsertAfter " …textul care se adaugă… "

Obiectul Selection

În PowerPoint, obiectul Selection reprezintă selecţia efectuată într-o fereastră de document. Se pot utiliza metodele
obiectului Selection pentru a tăia, copia, şterge sau deselecta porţiunea selectată. Proprietatea Type a obiectului
Selection identifică tipul selecţiei (diapozitive, shape, text sau nimic). Pentru returnarea unui anumit tip de selecţie se vor
utiliza proprietăţile ShapeRange, SlideRange şi TextRange.

Observaţie. Codul bazat pe o selecţie este în general ineficient şi presupunerea selectării prealabile a unei entităţi nu
este de obicei necesară; de exemplu, se poate schimba fontul unui text şi fără a-l selecta în prealabil. Dacă proiectul VBA
porneşte de la cod obţinut prin Macro Recorder, se va modifica pentru a-l face, pe cât posibil, independent de selecţie.

Crearea unei selecţii

Se poate obţine o selecţie fie în mod manual, fie aplicând metoda Select unuia dintre obiectele Shape, ShapeRange,
Slide, SlideRange sau TextRange. Exemplul următor selectează formele 1 şi 3 de pe slide-ul 1 din prezentarea activă:
215
ActivePresentation.Slides(1).Shapes.Range(Array(1,3)).Select

Este de reţinut că se poate efectua o selecţie programatică doar dacă s-ar putea efectua aceeaşi selecţie în mod manual:
obiectul trebuie să fie accesibil, viziunea trebuie să permită selecţii de acel tip etc.

Returnarea unei selecţii

Se va utiliza proprietatea Selection a obiectului DocumentWindow pentru a returna selecţia din fereastra respectivă:

ActiveWindow.Selection.Cut

Returnarea unui obiect din selecţie

Prin proprietatea ShapesRange a obiectului Selection se returnează colecţia ShapeRange care include toate formele
desenate din selecţie. Se utilizează metoda Item pentru accesul la un obiect din colecţie. Exemplul următor taie a treia
formă desenată din selecţia existentă în fereastra activă:

ActiveWindow.Selection.ShapeRange(3).Cut

Prin intermediul proprietăţii TextRange se poate accesa textul dintr-o selecţie sau textul dintr-o formă desenată. În
continuare se prezintă principalele operaţiuni realizate prin intermediul obiectului TextRange.

Returnarea domeniului de text dintr-o selecţie.

ActiveWindow.Selection.TextRange.Copy

Prin intermediul metodelor Characters, Lines, Paragraphs, Runs, Sentences sau Words se poate obţine o porţiune
anumită de text din textul conţinut în TextRange.

Returnarea domeniului de text dintr-o formă desenată (shape) se realizează prin proprietatea TaxtRange a obiectului
TextFrame.

ActiveWindow.Selection.ShapeRange(3).TextFrame.TextRange _
.Characters(1,3).Font.Bold = True

Se utilizează proprietatea HasTextFrame pentru a vedea dacă o formă are ataşat un cadru cu text şi se utilizează
proprietatea HasText pentru a determina dacă există text în cadrul de text.

Inserarea de text, dată şi timp sau număr de slide se realizează prin intermediul metodelor InsertAfter, InsertBefore,
InsertDateTime, InsertSlideNumber sau InsertSymbol.

Prin proprietatea SlideRange a obiectului Selection se returnează colecţia SlideRange care include toate diapozitivele
selectate. Exemplul următor taie diapozitivele selectate în fereastra activă.

ActiveWindow.Selection.SlideRange.Cut

Obiectele View şi SlideShowView

La deschiderea unui fişier în PowerPoint, se creează simultan un obiect Presentation, care reprezintă conţinutul
fişierului, un obiect DocumentWindow, care reprezintă interfaţa dintre utilizator şi fişier în modul design, un obiect View,
care reprezintă un container pentru conţinutul fişierului în modul design.

216
La pornirea unui slide show, se creează un obiect SlideShowWindow, care reprezintă interfaţa între utilizator şi fişier în
modul run, şi un obiect SlideShowView, care reprezintă un container pentru conţinutul fişierului în modul run (de
execuţie).

Înţelegerea prezentărilor, ferestrelor şi a viziunilor

Modificările entităţilor care se văd pe ecranul aplicaţiei se realizează prin modificarea unuia dintre obiectele
Presentation, DocumentWindow sau View. Care anume dintre obiecte se modifică este prezentat în continuare.

Schimbările efectuate asupra conţinutului efectiv al diapozitivelor — cum ar fi adăugarea, ştergerea sau formatarea
obiectelor — sunt modificări ale prezentării şi sunt controlate de proprietăţile şi metodele obiectului Presentation ca şi de
obiectele inferioare în ierarhia de obiecte PowerPoint.

Schimbările efectuate asupra interfeţei care afişează conţinutul – cum ar fi modificarea dimensiunii ferestrei sau
comutarea afişarii în alb-negru – sunt modificări ale ferestrei documentului sau ferestrei de demonstrare a diapozitivelor şi
sunt controlate de proprietăţile/metodele obiectelor DocumentWindow sau SlideShowWindow. Aceste modificări nu
afectează conţinutul fişierului. Modiifcările ferestrei documentului se păstrează la comutarea viziunilor.

Schimbările efectuate asupra modului în care informaţia este afişată – cum ar fi dacă se vede text şi grafică sau numai
grafică, cât de mari apar pe ecran elementele – sunt modificări ale viziunii şi sunt controlate de proprietăţile şi metodei
obiectelor View şi SlideShowView. Aceste modificări nu afectează conţinutul fişierului şi nu sunt reţinute la comutarea
viziunilor.

Returnarea obiectelor View şi SlideShowView

Obiectul View reprezintă modul în care informaţia este afişată în fereastra documentului. Se utilizează proprietatea View
a obiectului DocumentWindow pentru a returna un obiect View. Următorul exemplu fixează fereastra documentului să
se ajusteze automat la dimensiunile ferestrei aplicaţiei.

Windows(1).View.ZoomToFit = True

Obiectul SlideShowView reprezintă modul în care informaţia este afişată în fereastra de slide show. Se utilizează
proprietatea View a obiectului SlideShowWindow pentru a returna obiectul SlideShowView. Următorul exemplu
execută un slide show a prezentării active cu inhibarea shortcut-urilor (metoda Run a obiectului SlideShowSettings
returnează un obiect SlideShowWindow)

ActivePresentation.SlideShowSettings.Run.View _
.AcceleratorsEnabled = False

Următorul exemplu fixează culoarea pointerului şi forma pointerului pentru al doilea slide show care se execută curent
(există doar o fereastră pe aplicaţie în care se execută un slide show, dar pot exista mai multe aplicaţii care execută slide
show-uri în acelaşi timp).

With SlideShowWindow(2).View
.PointerColor.RGB = RGB(255,0,0)
.PointerType = ppSlideShowPointerPen
End With

Navigarea printre diapozitive

Prin metoda GoToSlide a obiectului View sau SlideShowView se activează slide-ul specificat. Este de menţionat că
termenul "diapozitiv activ" depinde de viziunea curentă: în slide view sau în note view, slide-ul curent este cel afişat; în
outline view sau slide sorter view, slide-ul activ este cel selectat.
217
SlideShowWindows(1).View.GoToSlide 3

Se poate trece la primul diapozitiv prin metoda First, la ultimul diapozitiv prin Last, sau se poate trece la un slide show
denumit prin metoda GoToNamedShow. Prin ultima metodă se trece la altă prezentare de diapozitive în timpul unei alte
prezentări. Când prezentarea avansează, următorul diapozitiv arătat este următorul din prezentarea unde s-a făcut
transferul şi nu următorul din prezentarea curentă. Sintaxa este

expression.GotoNamedShow(SlideShowName)

unde

expression este obligatorie, returnează un obiect SlideShowView.

SlideShowName este obligatoriu, numele slide show-ului unde se trece controlul.

SlideShowWindows(1).View.GotoNamedShow "…slide show-ul unde se trece …"

Alipirea conţinutului Clipboard-ului la un obiect View

Prin metoda Paste a obiectului View se alipeşte conţinutul din Clipboard la viziunea din fereastra de document activă.
Următorul exemplu copie selecţia din prima fereastră în Clipboard şi o alipeşte apoi la viziunea din fereastra a doua. Dacă
operaţiunea nu poate avea loc (vezi tabelul următor) se produce o eroare.

Windows(1).Selection.Copy
Windows(2).View.Paste

Operaţiunea de alipire depinde de viziunea ferestrei. Situaţiile posibile de copiere a conţinutului din Clipboard sunt
prezentate în tabelul următor.

Viziunea Se poate alipi

Slide view sau Shapes, text sau diapozitive întregi.


notes page view Formele alipite sunt adăugate în top-ul ordinei pe z şi nu înlocuiesc formele selectate.
Dacă este selectată o formă, textul alipit va fi adăugat la textul formei; dacă este selectat text,
textul alipit înlocuieşte selecţia; dacă nu este selectat nimic, textul alipit este plasat într-un text
frame propriu.
Dacă se alipeşte un întreg slide, o imagine a slide-ului este inserată pe diapozitiv, master sau
pagina de note ca un obiect scufundat.

Outline view Text sau diapozitive întregi.


Un slide alipit este inserat înaintea slide-ului care conţine punctul de inserţie.
Nu se pot alipi forme desenate în outline view.

Slide sorter view Diapozitive întregi.


Un slide alipit este inserat la punctul de inserţie sau după ultimul slide din selecţie.
Nu se pot alipi forme sau text în slide sorter view.

Din tabel rezultă importanţa alegerii unei viziuni corecte pentru prezentare înainte de a efectua o operaţiune de
tăiere+alipire.

Stabilirea sau verificarea tipului de viziune din fereastra documentului

218
Prin proprietatea Type a obiectului View se obţine ce fel de viziune are documentul activ iar proprietatea ViewType a
obiectului DocumentWindow se utilizează pentru a stabili viziunea din fereastra documentului. Următorul exemplu
realizează o copiere cu fixarea tipului de viziune adecvat operaţiunii de alipire.

Windows(1).Selection.Copy
With Windows(2)
.ViewType = ppViewSlide
.View.Paste
End With

Alte constante pentru viziuni sunt grupate în PpViewType:

ppViewHandout, ppViewHandoutMaster, ppViewNotesMaster,

ppViewNotesPage, ppViewOutline, ppViewSlide,

ppViewSlideMaster, ppViewSlideShow, ppViewSlideSorter

ppViewTitleMaster

Interpretările sunt imediate.

Returnarea diapozitivului curent

Proprietatea Slide returnează obiectul Slide care reprezintă diapozitivul afişat în acel moment într-o fereastră de slide
show sau într-o fereastră document.

SlideShowWindows(1).View.Slide.Copy

Dacă slide-ul afişat curent este dintr-o prezentare scufundată, se poate utiliza proprietatea Parent a obiectului Slide
returnat de proprietatea sinonimă pentru a returna prezentarea scufundată (proprietatea Presentation a obiectului
SlideShowWindow sau DocumentWindow returnează prezentarea în care fereastra a fost creată şi nu prezentarea
scufundată).

Controlarea comportării obiectelor în timpul unui slide show

Întregul strat de desen de pe un diapozitiv este reprezentat de colecţia Shapes şi fiecare obiect de pe un diapozitiv – fie
că este o rezervare de loc (placeholder), o formă AutoShape sau un obiect OLE – este reprezentat de un obiect Shape.
Utilizând proprietăţile şi metodele colecţiei Shapes se pot adăuga obiecte la diapozitive şi se obţine acces la obiectele
individuale de pe un diapozitiv. Prin proprietăţile şi metodele unui obiect Shape se poate controla aspectul formei, textul
sau obiectul OLE care este conţinut şi modul în care se comportă forma respectivă în timpul unui slide show.

În continuare se discută doar despre comportarea formei desenate în slide show, aspectele celelalte fiind discutate în
capitolul dedicat desenelor din Microsoft Office.

Controlul animaţiei

Obiectul AnimationSettings conţine proprietăţile şi metodele care controlează cum şi când apare un shape pe un anumit
slide în timpul prezentării. Următorul exemplu fixează forma a doua de pe primul slide să devină animată în mod automat
după cinci secunde.

With ActivePresentation.Slides(1).Shapes(2).AnimationSettings
219
.AdvanceMode = ppAdvanceOnTime
.AdvanceTime = 5
.TextLevelEffect = ppAnimateByAllLevels
.Animate = True
End With

La lucrul cu proprietăţile obiectului AnimationSettings este important să se înţeleagă interacţiunea dintre proprietăţile
obiectului între ele şi cu proprietatea AdvanceMode a obiectului SlideShowSettings.

Efectele valorilor stabilite pentru proprietăţile obiectului AnimationSettings nu devin vizibile decât dacă forma respectivă
este animată, adică proprietatea Animate este fixată pe True.

În animarea textului proprietatea TextUnitEffect stabileşte unitatea de animaţie (cuvânt, paragraf etc) prin
ppAnimateByCharacter, ppAnimateByParagraph, ppAnimateByWord sau ppAnimateUnitMixed. Proprietatea
TextLevelEffect (care interacţionează cu precedenta la anumite valori) stabileşte nivelul ierarhic al textului animat:

ppAnimateByAllLevels ppAnimateByFifthLevel PpAnimateByFirstLevel

ppAnimateByFourthLevel ppAnimateBySecondLevel PpAnimateByThirdLevel

ppAnimateLevelMixed ppAnimateLevelNone.

Pentru introducerea temporizării în animaţie, se va stabili proprietatea AdvanceMode la ppAdvanceOnTime şi se va


indica un număr de secunde în AdvanceTime. Totodată, proprietatea AdvanceMode a obiectului SlideShowSettings
trebuie să fie ppSlideShowUseSlideTimings.

Proprietatea AfterEffect controlează ce se întâmplă după ce forma a devenit animată. Dacă forma a fost animată şi altă
formă nu este animată după ea, atunci efectele ulterioare nu sunt vizibile. În plus, efectul proprietăţii DimColor nu este
vizibil decât dacă AfterEffect este stabilit la ppAfterEffectDim.

Ordinea de animare a formelor de pe un slide este stabilită prin proprietatea AnimationOrder, proprietatea EntryEffect
stabileşte modul de apariţie a formei iar ChartUnitEffect controlează modul de animare al elementelor unei diagrame.

Controlul răspunsului la acţiunea mouse-ului

Efectul acţiunilor mouse-ului (click sau trecere peste formă) este controlat de colecţia ActionSettings. Colecţia conţine
două obiecte identificate prin indexul ppMouseClick sau ppMouseOver reprezentând, respectiv, acţiunile la click sau
trecerea mouse-ului pe deasupra formei sau textului în timpul unui slide show.

With ActivePresentation.Slides(1).Shapes(3).TextFrame. _
TextRange.ActionSettings(ppMouseClick)
.Action = ppActionHyperLink
.HyperLink.Address = "http://www.microsoft.com"
End With

Unde se remarcă utilizarea indexului de identificare a acţiunii la click pe formă şi definirea unei acţiuni prin proprietatea
Action.

Valorile posibile pentru Action sunt constantele PpActionType:

ppActionEndShow ppActionFirstSlide ppActionHyperlink

220
ppActionLastSlide ppActionLastSlideViewed ppActionMixed

ppActionNamedSlideShow ppActionNextSlide ppActionNone

ppActionOLEVerb ppActionPreviousSlide ppActionRunMacro

ppActionRunProgram.

Este de notat că anumite acţiuni sunt proprii doar unor tipuri de forme şi se vor alege acele acţiuni care sunt disponibile în
interfaţa utilizator din PowerPoint pentru forma procesată.

În următorul exemplu se stabileşte că, în slide show, atunci când a treia formă de pe al doilea diapozitiv este click-ată,
culoarea formei este momentan inversată, se aude fişierul sound "applause" şi prezentarea revine la primul slide.

With ActivePresentation.Slides(2).Shapes(3) _
.ActionSettings(ppMouseClick)
.Action = ppActionFirstSlide
.SoundEffect.Name = "applause"
.AnimateAction = True
End With

Dacă se stabileşte o proprietate a obiectului ActionSettings dar fără efectul scontat, se va verifica valoarea atribuită
proprietăţii Action. Tabelul care urmează oferă câteva precizări.

Dacă se Pentru a efectua Valoarea necesară pentru


utilizează proprietatea Action
proprietatea

Hyperlink Stabilirea proprietăţilor pentru hiperlegătura care este ppActionHyperlink


urmărită ca răspuns la acţiunea mouse-ului.

Run Returnarea/stabilirea numelui programului executat ca ppActionRunProgram


răspuns la acţiunile mouse-ului.

Run Returnarea/stabilirea numelui procedurii macro executate ca ppActionRunMacro


răspuns la acţiunea mouse-ului.

ActionVerb Stabilirea verbului OLE care va fi invocat ca răspuns la ppActionOLEVerb


acţiunea mouse-ului.

SlideShowName Stabilirea numelui slide show-ului propriu care se va ppActionNamedSlideShow


executa ca răspuns la o acţiune a mouse-ului.

Următorul exemplu utilizează proprietatea Hyperlink:

With ActivePresentation.Slides(1).Shapes(1).ActionSettings(ppMouseClick)
.Action = ppActionHyperlink
.Hyperlink.Address = "http://www.infoiasi.ro"
End With

Controlul unui clip

221
Obiectul PlaySettings, returnat prin proprietatea PlaySettings a obiectului AnimationSettings, conţine proprietăţi şi
metode care controlează cum şi când se derulează un clip media. Următorul exemplu inserează un movie numit
"Clock.avi" în primul slide din prezentarea activă, fixează execuţia automată după animaţia sau tranziţia precedentă,
specifică continuarea show-ului în timp ce se execută filmul şi specifică faptul că obiectul movie este ascuns în timpul
slide show-ului cu excepţia timpului când se execută.

Set clockMovie = ActivePresentation.Slides(1).Shapes.AddMediaObject _


(FileName:="c:\…\clock.avi", Left:=20, Top:=20)
With clockMovie.AnimationSettings.PlaySettings
.PlayOnEntry = True
.PauseAnimation = False
.HideWhileNotPlaying = True
End With

În funcţie de modul cum se inserează clipul ca un obiect OLE (utilizând comanda Object din meniul Insert sau utilizând
metoda AddMediaObject) sau ca un obiect media nativ (utilizând meniul Movies and Sounds sau metoda
AddMediaObject), se pot aplica diferite proprietăţi obiectului PlaySettings. Se regăsesc astfel opţiunile disponibile în
fişa Play Settings din dialogul Custom Animation (deschis din meniul SlideShow).

Modul preferat de inserare a clipurilor este ca obiecte native media, deoarece acestea nu necesită Windows Media Player
şi reacţionează astfel mai rapid. Multe dintre proprietăţile obiectului PlaySettings se aplică numai clipurilor media native.
Proprietatea ActionVerb, care corespunde opţiunilor listate în boxa Object din fişa PlaySettings a dialogului Custom
Animation, este singura care nu se aplică clipurilor media native.

Utilizând proprietatea Type a obiectului Shape se poate determina dacă un clip este nativ (valoarea returnată msoMedia)
sau nu. Proprietatea MediaType a obiectului Shape determină dacă este sound sau movie (ppMediaTypeMixed,
ppMediaTypeMovie, ppMediaTypeOther sau ppMediaTypeSound). Următorul exemplu fixează toate obiectele native
sound din primul slide să se execute mereu până sunt oprite manual.

Dim so As Shape
For Each so In ActivePresentation.Slides(1).Shapes
If so.Type = msoMedia Then
If so.MediaType = ppMediaTypeSound Then
so.AnimationSettings.PlaySettings.LoopUntilStopped = True
End If
End If
Next

Meniuri şi bare de unelte

Interfaţa cu utilizatorul este o parte foarte importantă a oricărei aplicaţii. Acest fapt are o pondere mult mai mare în
proiectele dezvoltate în VBA deoarece aplicaţiile gazdă (Microsoft Office, Visio, Autocad etc.) dispun de interfeţe utilizator
sofisticate de care trebuie să se apropie orice nouă componentă.

Problematica poate fi despărţită în:

o Personalizarea/modificarea interfeţei aplicaţiei de bază


o Dialogurile create de utilizator.

În acest capitol se discută prima categorie de acţiuni: tehnicile prin care se poate adapta, completa sau modifica interfaţa
cu utilizatorul propusă în mod standard în aplicaţiile Microsoft Office 97. Se prezintă atât acţiunile permise de mediu (prin
dialogul Customize – comun aplicaţiilor Word, Excel, PowerPoint, Access) asupra meniurilor şi barelor de unelte afişate,
cât şi acţiunile programatice, din Visual Basic, asupra obiectelor respective.

222
Modificarea interfeţei cu utilizatorul

Interfaţa cu utilizatorul prezentă în programele din Microsoft Office este formată din bare de meniu şi bare de unelte. Ca
răspuns la activarea unei comenzi din meniu sau a unei unelte se va realiza o acţiune a aplicaţiei gazdă sau se va
deschide un dialog pentru fixarea unor atribute ale acţiunii dorite.

Există două posibilităţi de adaptare a barelor de unelte şi a meniurilor: dialogul Customize şi Visual Basic. Deşi dialogul
diferă uşor de la o aplicaţie la alta, obiectele programabile sunt aceleaşi în toate aplicaţiile Microsoft Office (cu excepţia
Outlook).

Dialogul Customize

Prin intermediul casetei de dialog Customize se pot efectua modificări ale interfeţei utilizator în timpul proiectării aplicaţiei
Visual Basic (pentru simplitatea exprimării utilizăm formularea design-time). Cu alte cuvinte, modificări efectuate înainte
ca aplicaţia să se execute. Modificările includ: adăugarea, ştergerea, mutarea, restaurarea componentelor meniurilor şi
barelor de unelte. De asemenea stabilirea proprietăţilor acestor componente, care nu se vor modifica în timpul execuţiei
(cu formularea mai concisă run-time). Aceste modificări pot fi efectuate şi în Visual Basic, dar dacă există ambele
posibilităţi de modificare, cele din design-time, direct în mediul aplicaţiei gazdă, se realizează mai uşor.

Pentru afişarea dialogului Customize se urmează succesiunea: meniul View — Toolbars — Customize. Acelaşi efect
se obţine prin punctarea unei bare de unelte şi click dreapta. Din meniul contextual se alege apoi Customize. Dialogul
afişat este, cu mici diferenţe specifice, acelaşî în toate aplicaţiile Office 97.
Forma afişată de Microsoft Word este dată în figura alăturată.

Se observă cele trei fişe şi grupul de butoane din dreapta.

Particularităţile importante ale dialogului sunt:

o în Access, fişa Toolbars conţine un buton Properties care


afişează dialogul Toolbar Properties prin care se fixează
proprietăţile barelor de meniu sau de unelte,
o în Excel, fişa Toolbars conţine un buton Attach care afişează dialogul Attach Toolbars prin care se pot
copia (ataşa) la caietul activ bare de unelte/meniu din spaţiul de lucru al aplicaţiei,
o în Word, fişa Commands conţine o listă derulantă Save in în care se alege contextul modificărilor din
design-time (template, document etc.) şi un buton Keyboard care iniţiază un dialog de stabilire a cheilor
directe. Dialogul NewToolbar, care apare la click pe New (fişa Toolbars), conţine de asemenea
opţiunea Make toolbar available to pentru fixarea domeniului de vizibilitate.

După deschiderea dialogului Customize se urmează aceeaşi procedură pentru modificarea oricărui meniu sau toolbar,
indiferent dacă este predefinit sau construit de utilizator. Paşii uzuali sunt

o în lista Toolbars din fişa Toolbars se selectează boxele de control alăturate denumirilor acelor bare care
se afişează; orice bară nou creată este afişată în mod automat;
o click pe orice intrare de meniu (inclusiv captările de meniu/submeniu) sau control de pe o bară de unelte
pentru a o selecta; în timpul afişării dialogului Customiza meniurile şi uneltele nu sunt active/executabile,
pot fi doar selectate;
o click dreapta pe obiectul selectat şi utilizarea comenzilor din meniul contextual pentru transformările
dorite.
o În timpul afişării dialogului Customize se pot rearanja prin drag-and-drop toate intrările din
meniuri/unelte. Tragerea în caseta dialogului elimină o intrare din meniu/bară de unelte, iar operaţiunea
inversă adaugă noi intrări.

Visual Basic

223
Personalizarea meniurilor şi barelor de unelte se poate efectua programatic utilizând porţiunea reprezentând barele de
comandă din modelul de obiecte, comună tuturor aplicaţiilor din Microsoft Office. Nivelul cel mai înalt este colecţia
CommandBars, returnată de proprietatea CommandBars în toate aplicaţiile din Office. Fiecare bară de meniu, meniu
contextual sau bară de unelte este reprezentată printr-un obiect CommandBar în această colecţie. Un obiect
CommandBar conţine o colecţie CommandBarControls reprezentând
elementele de control ale barei respective.

Ierarhia acestor obiecte, pentru cazul Microsoft Word (similară în toate


celelalte aplicaţii din Office), este prezentată în figura alăturată.

Utilizarea acestor obiecte este explicată, pentru principalele acţiuni, în


continuarea acestui capitol.

Se poate scrie cod care, executat o singură dată, produce crearea sau modificarea elementelor de control din interfaţa
utilizator. Codul simulează modificările din design-time prin caseta Customize. Sunt şi situaţii în care este nevoie de o
combinaţie programare + personalizare pentru a realiza configurarea dorită a mediului aplicaţiei:

o Dacă nu se poate utiliza dialogul Customize pentru crearea unei bare noi de meniu, aceasta se va crea
prin program şi după aceea se poate configura prin dialogul Customize.
o Dacă aplicaţia gazdă nu oferă posibilitatea de afişare simultană a dialogului Customize şi a meniurilor
contextuale predefinite sau utilizator, modificarea acestora trebuie realizată în Visual Basic.
o Dacă aplicaţia gazdă nu oferă o interfaţă pentru adăugarea sau modificarea boxelor text, listelor
derulante drop-down sau combo box, trebuie utilizat codul Visual Basic pentru adăugarea şi proiectarea
acestor controale.

Se poate scrie cod şi pentru modificarea meniului sistem în timp ce aplicaţia se execută (de exemplu inhibarea unor
comenzi sau adăugarea unui meniu etc.). Aceste modificări sunt cunoscute drept modificări în run-time.

Domeniul schimbărilor asupra interfeţei utilizator

Fiecare aplicaţie Microsoft Office utilizează reguli uşor diferite privind unde şi cum se salvează modificările aduse
interfeţei utilizator. Pentru un control corect al interfeţei proiectate în aplicaţia Visual Basic este importantă înţelegerea
domeniului de valabilitate al schimbărilor.

Microsoft Access

Se pot utiliza bare de meniu proprii sau meniuri contextuale proprii în trei moduri

o Ataşate de o formă sau de un raport. Microsoft Access afişează meniurile proprii la deschiderea formei
sau la afişarea raportului în print preview. Pentru informaţii suplimentare se va studia subiectul "MenuBar
Property" în Help.
o Drept un meniu contextual ataşat unei forme, unui raport sau unui control dintr-o formă. Microsoft Access
afişează un asemenea meniu la click dreapta pe formă, raport sau control. Pentru informaţii suplimentare
se va studia subiectul "ShortCutMenuBar Property" în Help.
o Ca o bară meniu globală, a aplicaţiei. Microsoft Access afişează această bară proprie în toate ferestrele,
cu excepţia formelor sau rapoartelor care au propria bară definită. Se poate specifica bara de meniu
utilizată în aplicaţie prin dialogul Startup.

Se pot utiliza una sau mai multe bare de unelte proprii într-o aplicaţie. Se creează barele de unelte necesare şi se alege
pentru afişare una dintre metodele următoare:

o Dacă aplicaţia are doar o bară de unelte utilizator, se va utiliza commanda Toolbars (din meniul View)
pentru a o afişa; bara respectivă va apare de fiecare dată când se porneşte aplicaţia.
224
o Dacă aplicaţia are bare diferite pentru forme sau rapoarte, se va specifica bara necesară în proprietatea
Toolbar a formei sau raportului. Bara indicată se va afişa şi ascunde împreună cu forma.
o Dacă sunt necesare mai multe bare de unelte proprii pentru o formă sau raport, sau dacă se doreşte
ascunderea/afişarea barelor predefinite, se va utiliza proprietatea Visible a obiectului CommandBar în
Visual Basic sau acţiunea ShowToolbar în macro-uri.
o Dacă se doreşte ca aplicaţia să afişeze doar barele proprii, se pot ascunde barele de unelte built-in prin
comanda Startup (meniul Tools) şi se deselectează boxa de control Allow Built-in Toolbars.

Microsoft Excel

Barele de meniu sau/şi barele de unelte proprii pot fi salvate cu spaţiul de lucru sau cu caietul. La părăsirea aplicaţiei
Excel, barele de unelte din spaţiul de lucru sunt salvate automat în fişierul Username8.xlb (unde Username este numele
utilizatorului curent utilizat la intrarea în Windows 95). Dacă utilizatorul nu este logged on, fişierul este Excel8.xlb. Barele
de unelte salvate în caiet sunt memorate în fişierul caietului respectiv.

Meniurile şi barele de unelte de la nivelul workbook permit proiectarea unei interfeţe pe măsura oricărei aplicaţii (de
exemplu un add-in) şi distribuirea barelor şi procedurilor ataşate. Pentru distribuire, obiectele proiectate se vor ataşa
caietului, care conţine aplicaţia, încât barele de unelte să fie memorate în acelaşi fişier cu aplicaţia.

Mutarea unui meniu sau bară de unelte din spaţiul de lucru în caiet

• Dacă dialogul Customize nu este deschis, se va afişa prin View - Toolbars - Customize.
• În fişa Toolbars a dialogului, click pe Attach. Ca urmare a acţiunii se afişează dialogul Attach Toolbars.
• În caseta din stânga Custom toolbars se selectează numele meniului sau barei de unelte care se copie în
caietul activ.
• Click Copy. Numele obiectului copiat apare în lista din dreapta Toolbars in workbook.

Obiectul original, de la nivelul spaţiu de lucru, poate fi eliminat în mod uzual acţionând butonul Delete din dialogul
Customize, fişa Toolbars.

Dacă versiunea de la nivelul sapţiului de lucru (workspace) nu este eliminată, aceasta poate fi modificată fără afectarea
versiunii de la nivelul caietului. În această situaţie, obiectul este modificat la nivelul spaţiului de lucru, aducerea versiunii
din caiet la aceeaşi configurare se realizează doar prin repetarea procedurii descrise, adică prin copierea versiunii din
spaţiu peste versiunea din caiet.

După copierea unui obiect (meniu sau bară de unelte) în caiet, obiectul devine disponibil numai după ce utilizatorul în
deschide. O versiune salvată în caiet reţine nu numai numele şi conţinutul, ci şi asignările de cod, locul, dimensiunea,
forma, poziţia în ecran şi atributul de vizibilitate (ascuns sau vizibil).

Eliminarea unui meniu/bară de unelte salvat în caiet

Versiunea salvată în caiet poate fi eliminată prin:

• Dacă dialogul Customize nu este deschis, se va deschide după procedura uzuală.


• În fişa Toolbars click pe Attach. Se afişează dialogul Attach Toolbars.
• În zona Toolbars in workbook click pe numele obiectului care se elimină.
• Click Delete.

Observaţie. Nu se poate utiliza Visual Basic pentru a ataşa sau elimina obiecte bare de meniu sau de unelte la un caiet.

La deschiderea unui caiet care conţine obiecte de interfaţă pe măsură, Microsoft Excel determină mai întâi dacă există
deja un obiect cu aceeaşi denumire în spaţiul de lucru. Dacă nu, este creată un nou meniu sau bară de unelte în spaţiul

225
de lucru şi se copie în acest nou obiect bara de meniu sau de unelte din caiet. În acest mod se dispune de un obiect care
poate fi modificat, ascuns etc., obiect care îşi salvează modificările în spaţiul de lucru la părăsirea aplicaţiei Excel.

Nu există nici un mijloc prin care să se redenumească un meniu sau toolbar, încât la redeschiderea caietului spaţiul de
lucru conţine deja obiectul cu numele respectiv şi Microsoft Excel utilizează copia creată anterior în locul obiectului din
caiet. Procedurile ataşate rămân totuşi cele din caiet, adică aplicaţia distribuită trăieşte în continuare prin intrările de
meniuri sau unelte păstrate în spaţiul de lucru. Acest mod de operare are accentul pus pe acţiunile utilizatorului, care are
dreptul să-şi organizeze spaţiul de lucru după voie.

Pentru a restaura versiunea originală distribuită, utilizatorul trebuie să elimine copia din spaţiul de lucru prin procedura
explicată anterior.

Microsoft Word

Word memorează meniurile şi barele de unelte în şabloane, similar macrourilor. La modificarea unui meniu sau toolbar,
modificările sunt memorate implicit în template-ul Normal şi modificările sunt accesibile în mod global, adică un
asemenea obiect poate fi afişat chiar dacă documentul este bazat pe un alt şablon.

Un toolbar memorat într-un alt template este disponibil doar dacă şablonul respectiv este ataşat documentului activ sau
dacă şablonul este încărcat ca un template global (a se vedea meniul Tools, comanda Templates and Add-ins).

Dacă se memorează o bară de unelte în document, afişarea ei este posibilă doar dacă documentul respectiv este activ.

La distribuirea unei aplicaţii Visual Basic cu meniuri şi bare de unelte personale, aceste trebuie memorate într-un şablon
propriu sau într-un document. Deoarece fiecare utilizator are propriul template Normal, aplicaţiile Visual Basic nu trebuie
să modifice şablonul Normal. Este recomandat de asemenea să se elimine obiectele personale din interfaţă la părăsirea
aplicaţiei.

Dacă două obiecte toolbar cu acelaşi nume sunt disponibile simultan (unul într-un şablon, altul în document), ambele sunt
listate în dialogul Customize şi pot fi afişate separat sau împreună în acelaşi timp.

În Visual Basic se poate adăuga, modifica sau elimina bare meniu sau de unelte în orice document sau template. Totuşi,
deoarece proprietatea CommandBars se aplică doar obiectului Application, contextul trebuie fixat înainte de efectuarea
modificărilor. Similar utilizării zonei Store in din fişa Commands, dialogul Customize, în Visual Basic se va stabili
valoarea proprietăţii CustomizationContext pentru a specifica un obiect Document sau Template, reprezentând locul
unde se execută modificări. Proprietatea CustomizationContext se fixează înaintea utilizării proprietăţii CommandBars
ceea ce asigură returnarea unei referinţe la colecţia corectă (din document sau din template).

Microsoft PowerPoint

Obiectele personale sunt memorate întotdeauna în spaţiul de lucru. La părăsirea aplicaţiei PowerPoint, barele de unelte
din spaţiul de lucru sunt salvate în fişierul Username.pcb (unde Username este numele logon al utilizatorului). Dacă
utilizatorul nu este logged on, fişierul este Powerpnt.pcb.

Deoarece obiectele din interfaţă nu sunt vizibile în timpul prezentării, customizarea este limitată la schimbarea meniurilor
şi uneltelor accesibile în design mode. Se poate utiliza fie dialogul Customize, fie Visual Basic. Dacă aplicaţia Visual
Basic oferă o interfaţă modificată pentru proiectarea prezentărilor, se va utiliza Visual Basic pentru modificarea interfeţei
şi este o bună idee aceea ca la părăsirea aplicaţiei să se elimine modificările efectuate.

Componente ale interfeţei utilizator

Meniurile sunt liste cu comenzi din care utilizatorul poate să aleagă. Meniurile oferă un mod convenabil şi consistent de a
grupa comenzi asociate după funcţiuni şi un mod simplu de acces al utilizatorului. Anumite comenzi pot să determine
226
afişarea unor submeniuri, pe diferite nivele de organizare. Există de asemenea meniuri contextuale (shortcut menus) care
oferă o modalitate de grupare a comenzilor uzuale aplicabile în contextul limitat al unei acţiuni specifice.

Se pot asigna chei de acces pentru a permite afişarea imediată a unui meniu, ca şi asignarea unor taste directe la
comenzi. În plus, meniurile ocupă mai puţin loc decât barele de unelte (nu toate comenzile sunt afişate permanent).

Barele de unelte conţin controale care permit executarea comenzilor des utilizate. Barele de unelte sunt adecvate pentru
prezentarea atributelor individuale (cum ar fi bold, italic etc.), pentru comenzile care se pot reprezenta vizual (cum ar
chenare, dimensiunile liniilor etc.) şi pentru comenzile pentru care se doreşte accesul printr-un simplu click. Barele de
unelte rămân mereu vizibile şi acest fapt conduce la o parcurgere mai uşoară pentru determinarea comenzii dorite.
Dezavantajele includ necesitatea mouse-ului (controalele nu pot fi accesate din tastatură) şi ocuparea spaţiului de lucru în
detrimentul documentului principal.

Pentru prezentarea unui set complex de opţiuni se va utiliza o casetă de dialog. Dacă se doreşte plasarea unei unelte
mai aproape de datele asociate, cea mai bună soluţie poate fi plasarea unui control direct în document.

Mai multe informaţii pot fi găsite în capitolul Controale ActiveX şi dialoguri.

Sistemul de meniuri

În fiecare aplicaţie Microsoft Office, sistemul de meniuri este compus dintr-o mulţime de meniuri şi câte o mulţime de
intrări în fiecare meniu. Fiecare menu este fie un meniu, un submeniu sau un meniu contextual. În continuare termenul de
componentă se referă în mod generic la un meniu sau o intrare într-un meniu.

O bară de meniu este o bară aşezată în partea superioară a ferestrei active şi care afişează numele tuturor meniurilor
care sunt permise în aplicaţie la un moment dat. O aplicaţie din Microsoft Office poate să modifice bara de meniu afişată
ca urmare a modificării ferestrei active (de exemplu editarea unui obiect chart) sau ca răspuns la instrucţiuni Visual Basic.

Un meniu este o listă de intrări care apare (se derulează) la click pe numele meniului din bara de meniu.

Un submeniu (child menu) este un meniu ataşat de o latură a altui meniu (parent menu), adiacent unei captări particulare
a submeniului, localizată în meniul părinte. Fiecare captare de submeniu este marcată cu o săgeată punctând spre
dreapta. Submeniurile se pot adăuga şi la meniurile contextuale. Un submeniu este afişat atunci când se punctează
captarea corespunzătoare din meniul părinte.

Un meniu contextual este un meniu flotant în document şi care conţine un grup de comenzi adecvate pentru o anume
acţiune (de exemplu procesarea unui paragraf). Meniul contextual este afişat atunci când utilizatorul execută un click
dreapta pe un obiect care are ataşat un asemenea meniu.

Acţiuni de adaptare a sistemului de meniuri

Sistemul de meniuri se poate modifica într-o aplicaţie Microsoft Office în diferite moduri:

o crearea de noi bare de meniu


o adăugarea de noi meniuri la barele preconstruite sau personale
227
o adăugarea de noi intrări (comenzi sau captări de submeniuri) la meniuri şi submeniuri existente (built-in
sau custom)
o adăugarea şi modificarea meniurilor contextuale
o atribuirea de macrouri la intrări din meniuri.

În plus, în orice moment se poate restaura meniul sistem predefinit la starea implicită (cea afişată la instalarea aplicaţiei).

Adăugarea de componente personale sau


modificarea componentelor built-in

Fiecare aplicaţie din Office are un meniu sistem propriu. Componentele acestuia pot fi modificate sau se pot crea şi
modifica componente personale.

Se alege modificarea unui meniu predefinit atunci când intervenţia este minimă (de exemplu includerea unui meniu care
este legat de o macro).

Dacă este necesară o intervenţie masivă, atunci se preferă crearea unei noi bare de meniu şi adăugarea componentelor
proprii pe această bară.

Utilizarea submeniurilor

Dacă un meniu devine prea populat, atunci se impune împărţirea comenzilor pe submeniuri. În acest mod se oferă
utilizatorului mai puţină informaţie la un moment dat şi aplicaţia creşte în claritate.

Organizarea submeniurilor se poate baza pe entităţile procesate (comenzi, clienţi etc.) sau pe acţiunile suportate de
entităţi (adăugare, editare etc.).

Utilizarea meniurilor contextuale

Dacă se doreşte ca utilizatorul să aibă acces la comenzile (măcar cele mai uzuale) aplicabile în contextul unui obiect
selectat, comenzi care, în mod uzual, sunt dispersate în mai multe meniuri, soluţia este oferită de meniurile contextuale.
Comenzile dorite se vor adăuga meniurilor contextuale built-in. În Microsoft Access se pot crea şi meniuri contextuale
proprii asociate unor obiecte din aplicaţie.

Utilizarea controalelor Text Box, List Box şi Combo Box

Deşi este posibil să se adauge, prin cod Visual Basic, controale predefinite, sau proprii, de tip textbox, listbox sau combo,
la meniuri de orice fel, asemenea controale sunt mai adecvate pentru plasarea în bare de unelte.Casetele text din meniuri
pot fi utile în anumite situaţii pentru afişarea sau returnarea unei proprietăţi. Aceeaşi utilitate o poate avea un control de
tip listă sau combo. Neajunsul principal este acela că selectarea unei intrări dintr-o listă închide meniul (utilizatorul trebuie
să redeschidă meniul pentru a revedea alegerea etc.).

Dacă se doreşte adăugarea controalelor de tipurile enumerate (built-in sau proprii) se vor utiliza tehnici descrise în
secţiuni ale acestui capitol.

Modificările sistemului de meniuri în timpul proiectării (design-time)

Modificările descrise aici sunt cele efectuate înainte ca aplicaţia să se execute. Sunt incluse adăugarea, ştergerea,
mutarea, restaurarea componentelor din meniuri, ca şi fixarea proprietăţilor acestora.

228
Adăugarea unei bare de meniu proprii

În Microsoft Access există posibilitatea adăugării unei bare proprii de meniu atât în Visual Basic, cât şi prin dialogul
Customize. În Microsoft Excel, Word şi PowerPoint adăugarea se poate efectua doar prin Visual Basic.

Dialogul Customize (doar Microsoft Access)

• Deschiderea dialogului Customize,


• Fişa Toolbars, click New
• În boxa Toolbar name se tastează numele noii bare şi click OK.
• Click Properties pentru afişarea dialogului Toolbar Properties.
• În zona Type se alege Menu Bar.

Noua bară de meniu este adăugată listei din caseta Toolbars a fişei Toolbars (caseta Customize).

Visual Basic

Prin metoda Add a colecţiei CommandBars se creează o nouă bară de meniu; argumentul MenuBar al metodei Add
determină când obiectul CommandBar creat poate fi afişat ca o bară de meniu. Exemplul următor realizează această
operaţiune:

Set cstm = CommandBars.Add(Name:="Custom Menu Bar", Position:=msoBarTop, _


MenuBar:=True, Temporary:=False)

Adăugarea meniurilor

Se poate adăuga un meniu la orice bară de meniu built-in sau proprie. Deoarece o aplicaţie Office poate afişa diferite
bare de meniu built-in în contexte diferite, este necesar uneori ca adăugarea să aibă loc la mai multe bare de meniu,
pentru ca utilizatorul să aibă acces la meniul adăugat indiferent de contextul curent al aplicaţiei.

La adăugarea unui meniu se poate specifica o cheie de acces, litera care apare subliniată la afişarea meniului.

Observaţie.Deşi o aplicaţie Microsoft Office poate să listeze barele de unelte cu meniurile contextuale din fişa Toolbars
a dialogului Customize, utilizatorul nu poate nici adăuga meniuri contextuale, nici să şteargă meniuri contextuale. Se pot
doar adăuga noi intrări, modifica intrările existente sau elimina unele intrări din meniurile contextuale. Anumite operaţiuni
suplimentare sunt posibile totuşi în Access şi Excel, acţiuni descrise ulterior.

Dialogul Customize

• Afişarea dialogului Customize.


• Vizualizarea barei de meniu dorite prin selectarea în lista Toolbars.
• În fişa Commands click New Menu în lista Categories.
• Se trage itemul New Menu din cutia Commands la poziţia dorită de pe bara de meniu.
• Click dreapta pe noul menu şi completarea numelui în zona Name. Un ampersand (&) situat înaintea unui
caracter din nume îl transformă în cheie de acces la meniu.

Adăugarea comenzilor este descrisă ulterior în acest capitol.

Dialogul Customize oferă şi posibilitatea de adăugare a unui meniu built-in la o bară de meniu proprie sau built-in.
Comenzile adăugate pot fi personalizate fără ca originalul să fie afectat.

229
• Afişarea dialogului Customize.
• Vizualizarea barei de meniu dorite prin selectarea în lista Toolbars.
• În fişa Commands click Built-in Menus în boxa Categories.
• Se trage un meniu built-in din boxa Commands în poziţia dorită.

Visual Basic

Pentru adăugarea unui meniu se utilizează metoda Add a colecţiei CommandBarControls. Prin aceasta se adaugă un
meniu la bara reprezentată de obiectul CommandBar implicat. Argumentul Type al metodei Add trebuie dat drept
msoControlPopup pentru a indica afişarea unui meniu activarea controlului adăugat. Controalele care afişează meniuri
sunt cunoscute drept controale pop-up. Argumentul Before indică poziţia noului meniu între cele deja
existente.Proprietatea Caption a obiectului CommandBarPopup returnat de metoda Add este utilizată pentru stabilirea
numelui şi cheii de acces la noul meniu. Exemplul următor adaugă un nou meniu la bara meniu a unui caiet Excel:

Set cstmAccounting = CommandBars ("Worksheet Menu Bar").Controls _


.Add(Type:=msoControlPopup, Before:=9)
cstmAccounting.Caption = "&Accounting")

După specificarea tastei de acces (prin &), numele poate fi specificat pentru referinţă fie cu sau fără caracterul
ampersand.

Adăugarea submeniurilor

Un meniu (child menu) este un meniu ataşat de o latură a altui meniu (parent menu), adiacent unei intrări din meniul
părinte (titlul submeniului – submenu caption), afişat la selectarea titlului. Se pot adăuga submeniuri la meniuri, alte
submeniuri sau la meniurile contextuale. Similar cu definirea unui meniu, mai întâi se defineşte un submeniu vid la care
se adaugă apoi intrările dorite.

Dialogul Customize

• Se afişează dialogul Customize


• Dacă bara de meniu care conţine meniul la care se face ataşarea nu este vizibilă se activează prin Toolbars.
• În fişa Commands click New Menu în boxa Categories.
• Se trage New Menu din boxa Commands în poziţia de pe meniu unde se ataşează. Dacă ataşarea este pe un
nivel inferior, se trage mai întâi pe meniu şi pe urmă din titlu în titlu până se deschide nivelul unde are loc
ataşarea.
• Click dreapta pe noul submeniu pentru a-i fixa numele în zona Name. Se va utiliza caracterul & pentru stabilirea
cheii de acces.

Adăugarea intrărilor se discută în continuarea capitolului.

Visual Basic

Adăugarea programatică este similară adăugării unui meniu la o bară de meniu, diferă doar nivelul din ierarhia de
obiecte:

Set cstmAcctProduct = CommandBars("Worksheet Menu Bar").Controls("Accounting") _


.Controls.Add(Type:=msoControlPopup)
cstmAcctProduct.Caption = "&Product"

adăugarea are loc la meniul Accounting creat în exemplul de la meniuri. Cheia directă este litera "P". Se observă că
valoarea argumentului Type este tot msoControlPopup, argumentul Before, neutilizat în exemplu, permite fixarea poziţiei

230
noului submeniu între intrările meniului părinte. Este de remarcat că titlul submeniului se inserează o dată cu submeniul şi
nu există anterior.

După definirea titlului submeniului acesta poate fi utilizat la obţinerea unei referinţe atât cu ampersand. cât şi fără.

Adăugarea şi gruparea comenzilor

Se poat adăuga comenzi la orice meniu propriu sau built-in, modifica aspectul lor şi separa vizual în grupuri logice.

Deşi se pot adăuga boxe text, boxe liste sau boxe combo la meniuri/submeniuri, ele nu sunt recomandate. Locul lor este
de regulă pe barele de unelte. Dacă totuşi se doreşte o asemenea adăugare se va utiliza reţeta dată la discutarea barelor
de unelte.

Dialogul Customize

Pentru adăugarea unei comenzi built-in:

• Se afişează dialogul Customize.


• Dacă bara de meniu care conţine meniul la care se face ataşarea nu este vizibilă se activează prin Toolbars.
• În fişa Commands se selectează o categorie de comenzi din boxa Categories. Comenzile din categoria
selectată sunt listate în boxa Commands.
• Se trage comanda dorită din boxa Commands în poziţia adecvată din meniu. Navigarea în cazul unei ierarhii de
meniuri se realizează prin dragare pe meniu, apoi pe titlul submeniului etc.

Se poate realiza copierea unei comenzi built-in prin afişarea meniului care o conţine şi tragerea comenzii simultan cu
apăsarea tastei CTRL.

Dialogul Customize oferă şi posibilitatea de adăugare a unei comenzi proprii la o bară de meniu proprie sau biult-in. Cum
fiecare aplicaţie din Microsoft Office prezintă tehnici diferite pentru realizarea acestei operaţiuni, în continuare se discută
separat fiecare aplicaţie.

Microsoft Access

Adăugarea la un meniu a unei intrări care execută un macro se realizează după aceeaşi procedură ca la adăugarea unei
comenzi built-in la un meniu. În boxa Categories click All Macros. Se trage macro-ul dorit în poziţia sa din meniu.

Pentru adăugarea unei intrări care execută o procedură funcţie se urmează de asemenea aceeaşi paşi ca la adăugarea
unei comenzi built-in: în Categories se alege orice categorie şi se trage o comandă oarecare pe meniul dorit. După
aceea, prin click dreapta şi selectare Control Properties se deschide dialogul sinonim. În zona Caption se trece noul
nume al comenzii iar în On Action se tastează o expresie care execută procedura Visual Basic de forma:
=functionname().

Microsoft Excel

Se urmează aceeaşi paşi ca în procedura pentru adăugarea unei comenzi built-in la un meniu:; în caseta Categories
click Macros şi se trage Custom Menu Item din caseta Commands la poziţia dorită pe meniu. Click dreapta pe noua
intrare şi apoi click pe Assign Macro. În Macro Name din dialogul Assign Macro se precizează numele macroului ataşat
intrării.

Microsoft Word

231
Se urmează aceeaşi paşi ca în procedura pentru adăugarea unei comenzi built-in la un meniu:; în caseta Categories
click Macros, în caseta Commands apare lista procedurilor ataşate şi se trage macroul dorit în poziţia adecvată din
meniu.

Observaţie. Dacă în Word se scrie o procedură al cărui nume coincide cu numele unei comenzi built-in (sau dacă o
procedură cu numele "MAIN" există într-un modul cu nume identic comenzii), procedura va înlocui funcţionalitatea
predefinită a comenzii built-in de fiecare dată când modulul de cod este disponibil. Orice copie a intrării de meniu (care
activa comanda built-in), de pe orice meniu, va executa procedura înlocuitoare.

Microsoft PowerPoint

Se procedează la fel ca în Microsoft Word.

Modificarea aspectului unei comenzi

Pentru orice comandă de pe un meniu se poate afişa o imagine alăturată numelui comenzii. Controlul aspectului este
obţinut prin meniul contextual afişat în timp ce dialogul Customize este activ. Stilul intrării de meniu poate fi doar text sau
text şi imagine. Acţiunile uzuale sunt

o Utilizarea unui buton predefinit: click dreapta pe comandă, Change Button Image şi selectarea imaginii
dorite din caseta afişată.
o Copierea imaginii unui alt buton: click dreapta pe butonul a cărui imagine se copie, Copy Button Image,
click dreapta pe butonul unde se copie imaginea şi Paste Button Image.
o Copierea unei imagini dintr-un program de grafică: în programul de grafică se deschide imaginea dorită,
selectarea şi copierea imaginii (preferabil de mărime 16×16 pixeli), comutarea la aplicaţia Office, click
dreapta pe comandă şi click Paste Button Image.
o Editarea imaginii curente a unui buton: click dreapta pe comandă, Edit Button Image, se editează
imaginea în dialogul afişat şi OK.
o Restabilirea imaginii originale (sau nimic dacă nu există imagine implicită): click dreapta şi ResetButton
Image.

Gruparea comenzilor

Comenzile asociate după funcţionalitate se pot grupa prin separarea între linii. Liniile însăşi nu sunt intrări separate de
meniu, apariţia lor fiind un atribut al comenzii care începe un nou grup. Pentru a începe un grup (prima intrare cu o linie
deasupra):

o Se afişează dialogul Customize.


o Se afişează bara de meniu pe care se află meniul dorit.
o Click dreapta pe intrarea de meniu care începe grupul şi click pe Begin Group. La deschiderea ulterioară
a meniului contextual comanda Begin Group apare cu marcajul de selectare şi un nou click anulează
linia de început de grup.

Visual Basic

Se utilizează metoda Add a colecţiei CommandBarControls pentru adăugarea unei noi intrări la obiectul CommandBar
care reprezintă un meniu sau un submeniu particular. Pentru adăugarea unei comenzi built-in se va specifica numărul ID
al comenzii în argumentul Id al metodei Add.

Următorul exemplu adăugă comanda Spelling la meniul numit "Quick Tools" de pe bara de meniu "Custom Menu Bar".

Set mySpell = CommandBars("Custom Menu Bar").Controls("Quick Tools") _


.Controls.Add(Id:=2)
232
Informaţii suplimentare se găsesc în secţiunea "Identificarea intrărilor şi controalelor din meniuri şi bare de unelte".

Pentru adăugarea unei comenzi proprii, se adaugă o intrare nouă în meniu şi se fixează proprietatea OnAction la
procedura iniţiată de respectiva intrare. Argumentul Type al metodei Add va avea valoarea msoControlButton indicând
o comandă.

Exemplul următor, pentru Microsoft Excel, adaugă un meniu Open Database la meniul File. Comanda adăugată execută
procedura OpenDatabaseProc.

Set databaseItem = CommandBars("Worksheet Menu Bar").Controls("File") _


.Controls.Add(Type:=msoControlButton, Before:=3)
With databaseItem
.Caption = "Open Database"
.OnAction = "OpenDatabaseProc"
End With

Există multe proprietăţi ale obiectelor reprezentând comenzile din meniuri, proprietăţi care pot fi fixate în Visual Basic.
Pentru mai multe informaţii se va studia obiectul CommandBarButton din Help.

Textul descriptiv afişat la punctarea controlului poate fi dat în proprietatea TooltipText. În DescriptionText se poate da
un text afişat în bara de stare a aplicaţiei etc.

Proprietatea Style stabileşte tipul butonului, cu imagine ataşată sau nu, constantele predefinite sunt (MsoButtonStyle):
msoButtonAutomatic, msoButtonIcon, msoButtonCaption sau msoButtonIconandCaption.

Pentru a începe un grup se va fixa proprietatea BeginGroup a unui obiect CommandBarButton, CommandBarPopup,
sau CommandBarComboBox la True. Atribuirea valorii False va elimina linia despărţitoare de grupul precedent. Astfel

databaseItem.BeginGroup = True

adaugă o linie înaintea intrării definite în exemplul precedent.

Se utilizează Control(index), unde index este titlul sau indexul unei intrări, pentru a returna obiectul care reprezintă
intrarea.

Dintre metode menţionăm doar metoda SetFocus prin care se stabileşte focalizarea pe respectiva comandă (acţionarea
tastaturii are efect direct asupra controlului) şi metoda Execute prin care se execută procedura ataşată controlului.

Adăugarea şi modificarea meniurilor contextuale

Meniuri contextuale definite de utilizator pot fi create doar în Microsoft Access sau Excel. Aplicaţiile Word şi PowerPoint
nu dispun de această posibilitate.

Crearea meniurilor contextuale se poate efectua prin dialogul Customize (în Access) sau prin Visual Basic (în Access şi
Excel). În Access, meniurile contextuale pot fi asociate rapoartelor, formelor şi controalelor dintr-o formă, un meniu
contextual fiind afişat la click dreapta pe obiectul ataşat. În Excel există evenimentul BeforeRightClick la care se poate
răspunde prin modificarea unui meniu contextual existent sau prin afişarea unui meniu contextual propriu.

Modificarea meniurilor contextuale predefinite de aplicaţii se poate efectua în mod uzual în toate aplicaţiile din Microsoft
Office.

Dialogul Customize

233
Pentru Microsoft Access se poate utiliza dialogul Customize pentru adăugarea unui meniu contextual:

o Se afişează dialogul Customize.


o În fişa Toolbars click New.
o În boxa Toolbar name se introduce numele noului menu contextual şi OK. Este afişat un meniu flotant,
vid, cu numele dat.
o Click Properties pentru afişarea dialogului Toolbar Properties.
o În Type se selectează Shortcut Menu.

Pentru afişarea noului menu contextual din dialogul Customize se va selecta checkboxul de la Shortcut Menus din fişa
Toolbars. Meniul creat este listat ultimul în bara afişată.

Visual Basic

Prin metoda Add a colecţiei CommandBars se creează un nou meniu contextual dacă se fixează valoarea
msoBarPopup pentru argumentul Position al metodei, după modelul

Set cstm = CommandBars.Add(Name:="Shortcuts1", Position:=msoBarPopup, _


MenuBar:=False, Temporary:=False

Completarea cu comenzi, modificarea unui meniu contextual se efectuează prin procedeele descrise la editarea
meniurilor/submeniurilor. Prin CommandBars(name), unde name este numele meniului contextual, se returnează
obiectul CommandBar reprezentând meniul contextual. Operând cu elementele colecţiei Controls disponibilă din
obiectul CommandBar se poate personaliza meniul contextual.

Ştergerea componentelor meniu

Se poate elimina, cu excepţia meniurilor contextuale şi a barelor de meniu built-in, orice componentă de meniu: intrări
proprii sau built-in, meniuri proprii sau built-in, bare de meniu proprii.

Prin eliminarea componentelor built-in se poate adapta aplicaţia proiectată în Visual Basic la necesităţile utilizatorului atât
prin simplificarea interfeţei (mai ales pentru utilizatori lipsiţi de experienţă) cât şi prin introducerea accesului direct la
fucţionalitatea proiectului.

Este de notat că se pot restaura componentele built-in eliminate, dar nu şi componentele proprii. Acestea trebuiesc create
din nou.

Dialogul Customize

Cu dialogul Customize deschis se poate elimina orice componentă de meniu prin

o Se deschide dialogul Customize


o Se afişează bara de meniu unde se află componenta dorită.
o Click dreapta pe componenta respectivă şi click pe Delete în meniul contextual afişat.

Pentru ştergerea unei întregi bare de meniu proprie, se deschide dialogul Customize, fişa Toolbars, click pe numele
barei şi click pe butonul Delete. În acest mod nu se poate elimina o bară de meniu predefinită.

Visual Basic

Se utilizează metoda Delete pentru a şterge o bară de meniu proprie, un meniu/submeniu drop-down propriu sau nu, sau
o intrare proprie sau built-in. Nu se poate elimina o bară de meniu built-in sau un meniu contextual.

234
Următorul exemplu Excel elimină meniul Edit din bara de meniu pentru diagrame.

CommandBars("Chart Menu Bar").Controls("Edit").Delete

Următorul exemplu şterge o bară de meniu proprie

CommandBars("Custom Menu Bar").Delete

Restaurarea componentelor de meniu built-in

Dialogul Customize

Utilizarea acestui dialog pentru restaurarea componentelor meniu/submeniu la configuraţia originală se face prin:

o Afişarea dialogului Customize.


o Vizualizarea barei de meniu necesare.
o Click dreapta pe meniul/submeniul care se restaurează şi click pe Restore în meniul contextual.

Pentru a restaura în totalitate o bară de meniu built-in, se deschide dialogul Customize, click pe numele barei de meniu
în lista Toolbars din fişa sinonimă şi click pe butonul Restore. Prin restaurarea barei de meniu, toate meniurile şi
submeniurile conţinute sunt de asemenea restaurate.

Visual Basic

Metoda Reset aplicată obiectului reprezentând o componentă buit-in produce restaurarea componentei, după modelul

CommandBars("Chart Menu Bar").Controls("Edit").Reset

aplicabilă în Excel sau

CommandBars("Menu Bar").Reset

care restaurează, în Word, bara de meniuri sistem.

Modificările sistemului de meniuri în execuţie (run-time)

Sistemul de meniuri create în timpul proiectării poate fi programat astfel încât să răspundă dinamic la modificarea
condiţiilor din timpul execuţiei. Se poate înlocui bara de meniu implicită cu o bară proprie. Dacă o anumită intrare nu este
adecvată într-un context dat, atunci ea poate fi inhibată sau eliminată. O intrare care reprezintă o opţiune cu două stări,
se poate reprezenta imaginea ei ca un buton apăsat sau nu. Se poate, de asemenea, redenumi o comandă după
acţiunea posibilă asupra unei entităţi (de genul Hide — Show).

Este de înţeles că toate aceste modificări pot fi efectuate în timpul execuţiei prin cod Visual Basic.

Afişarea unei bare de meniu

Pentru afişarea unei bare proprii de meniu în locul bare de meniu active, se fixează proprietatea Visible a obiectului
CommandBar corespunzător la valoarea True. Noua bară de meniu vizualizată înlocuieşte în mod automat bara activă.
Prin fixarea proprietăţii Visible la False, se reface bara de meniu implicită, operaţiune recomandată înaintea părăsirii
proiectului Visual Basic.

235
La pornirea aplicaţiei Microsoft Office este afişată bara de meniu implicită. În Word se poate totuşi înlocui bara implicită a
aplicaţiei la pornire deoarece ultima bară de meniu afişată la oprirea aplicaţiei Word poate fi salvată în template-ul Normal
şi restaurată în mod automat. În celelalte aplicaţii, ca şi în Word, se utilizează evenimentul Open pentru fixarea pe True a
proprietăţii Visible pentru bara de meniu proprie, sau se utilizează un macro activat de utilizator sau prin program.

Afişarea dinamică a componentelor de meniu

Dacă o componentă de meniu se aplică doar unui document particular, este recomandabil ca această componentă să
apară doar atunci când documentul este activ; acest mod de operare reduce aglomerarea inutilă a interfeţei. Se poate
limita viaţa unei componente de meniu doar la perioada în care este deschis sau activ documentul căruia i se aplică.

O alternativă este ca asocierea document – componentă de meniu să se gestioneze prin stabilirea proprietăţii Visible la
True sau False după cum este necesară, sau nu, componenta respectivă. Procedeul poate fi utilizat inclusiv pentru o bară
de meniu şi este, uneori, de preferat procedeului prin care se adaugă/şterge o componentă.

Pentru a afişa în mod dinamic componentele de menu, se scriu procedurile de răspuns la evenimente prin care se
afişează sau se ascund, se creează sau se şterg componentele respective. Dacă, însă, aplicaţia gazdă nu suportă
evenimente, atunci nu se pot personaliza componentele în mod dinamic. O alternativă este, pentru aceste aplicaţii,
asignarea procedurilor la proprietatea OnAction a altor elemente de meniu. Dacă aplicaţia permite controale ActiveX,
atunci se poate modifica interfaţa aplicaţiei container ca răspuns la un eveniment suportat de un control ActiveX.

Observaţie. Deoarece Word memorează personalizările în documente sau şabloane, componentele proprii sunt vizibile
atunci când documentul sau şablonul este disponibil în contextul curent şi ascunse atunci când documentul sau template-
ul nu este disponibil. Prin contrast, deoarece Microsoft Excel memorează personalizările la nivel de spaţiu de lucru,
modificarea dinamică a interfeţei se realizează prin schimbarea proprietăţii Visible în proceduri eveniment.

Permiterea şi inhibarea componentelor de meniu

Dacă se doreşte oprirea utilizatorului de la selectarea unei intrări de meniu, comanda respectivă poate fi inhibată. O
comandă inhibată apare pe meniu într-o culoare ştearsă şi nu poate fi activată. Acest atribut este stabilit de proprietatea
Enabled care la True permite accesul la comandă iar la False interzice accesul. Proprietatea nu se poate fixa pentru
intrări built-in de meniu şi nici pentru un submeniu ca obiect (pot fi inhibate însă toate intrările submeniului).

Următorul exemplu Excel adaugă comanda Open Database la meniul File a barei de meniu pentru foaia de calcul şi apoi
inhibă comanda adăugată:

CommandBars("Worksheet Menu Bar").Controls("File") _


.Controls.Add("Open Database").Enabled = False

Dacă proprietatea este stabilită la nibvelul unui meniu, ca în exemplul următor, toate comenzile meniului sunt interzise:

CommandBars("Worksheet Menu Bar").Controls("File").Enabled = False

Indicarea stării unei intrări de meniu

Dacă o intrare a unui meniu reprezintă o opţiune cu două stări, este posibil să se modifice aspectul imaginii comenzii
încât să arate ca un buton apăsat sau ridicat, potrivit stării opţiunii. Aceasta se realizează prin stabilirea proprietăţii State
a intrării. Proprietatea poate avea una dintre valorile (constantele MsoButtonState): msoButtonUp, msoButtonDown sau
msoButtonMixed.

Exemplul următor (în Excel) comută între cele două stări ale unei comenzi proprii inserate în meniul View:

236
Sub DatabaseView()
With CommandBars("Worksheet Menu Bar").Controls("View").Controls("Database")
If .State = msoButtonUp Then
.State = msoButtonDown
' comutare la viziunea database
Else
.State = msoButtonUp
' comutare la viziunea worksheet
End If
End With
End Sub

În timpul execuţiei se poate schimba imaginea butonului prin lucrul cu proprietatea FaceId pentru a schimba imaginea în
momentul schimbării stării comenzii. Pentru a specifica imaginea de buton care să fie afişată alături de comandă, trebuie
să se găsească comanda built-in cu imaginea dorită, să se determine ID său şi să se atribuie această valoare proprietăţii
FaceId (schimbarea proprietăţii FaceId nu modifică funcţionalitatea comenzii). Următorul exemplu Excel amplifică
exemplul precedent prin schimbarea imaginii în funcţie de stare.

Sub DatabaseView()
With CommandBars("Worksheet Menu Bar").Controls("View").Controls("Database")
If .State = msoButtonUp Then
.FaceId = 987
.State = msoButtonDown
' comutare la viziunea database
Else
.FaceId = 1
.State = msoButtonUp
' comutare la viziunea worksheet
End If
End With
End Sub

Redenumirea unei intrări de meniu

Proprietatea Caption conţine denumirea intrării. Modificând valoarea proprietăţii se poate prezenta utilizatorului o
comandă adecvată contextului curent. Exemplul următor arată cum se poate utiliza acest fapt. Se începe prin inserarea
unei comenzi Open Database, moment în care comanda se înlocuieşte cu comanda Close Database, adecvată
contextului:

CommandBars("MyMenuBar").Controls("File").Controls("Open Database") _
.Caption = "Close &Database"

La redenumirea intrării trebuie avut grijă ca alte proceduri care se referă la comandă să utilizeze în referinţe noul nume.

Se poate utiliza, evident, o variabilă care se referă la intrarea de meniu, ceea ce înlătură problemele suplimentare care
apar la redenumire:

Set openDatabase = CommandBars(("MyMenuBar"). _


Controls("File").Controls("Open Database")

Schimbarea titlului se efectuează prin

openDatabase.Caption = "Close &Database"

237
Bare de unelte

Fiecare aplicaţie Microsoft Office oferă un sistem de bare de unelte (toolbar) conţinând controale pe care utilizatorul le
acţionează pentru a avea acces la comenzile frecvente. Fiecare toolbar poate să apară depozitat (docked) la una dintre
laturile ferestrei aplicaţiei sau ca o fereastră flotantă poziţionată oriunde în spaţiul de lucru. Fiecare control de pu un
toolbar este control grafic prin care utilizatorul poate schimba informaţii cu aplicaţia Visual Basic.

Afişarea unei bare de unelte într-o aplicaţie Office se realizează prin meniul View, comanda Toolbars şi click pe numele
barei dorite. Imaginea ataşată barei respective devine selectată. Un nou click ascunde bara de unelte. Bare de unelte
adiţionale pot fi văzute în dialogul Customize, în lista din Categories.

Există mai multe tipuri de controale care apar pe o bară de unelte, discutate în continuare.

Cel mai comun tip de unealtă este un buton de control simplu, cu o imagine. Grafica, denumită imaginea butonului, este
o reprezentare vizuală a comenzii sau opţiunii activate de respectivul control. Utilizatorul poate să acţioneze un buton
pentru a executa o acţiune (de exemplu butonul New creează un nou document) sau să comute între două stări posibile
(cum ar fi butonul Bold).

Alt tip de control este un buton de control care conţine o imagine şi o paletă derulabilă ataşată. Utilizatorul
acţionează săgeata în jos a controlului penbtru a afişa paleta de unde selectează opţiunea dorită. Acţionarea butonului
(nu a săgeţii) aplică opţiunea selectată (indicată prin grafică). Un exemplu de acest gen este controlul Font Color.

Un control poate fi de tip text box, list box sau combo box. Utilizatorul poate fie tasta text în zona de text, fie acţiona
săgeata în jos şi selecta un element al listei. De exemplu, controlul Font Size de pe bara de unelte Word Formatting
permite înscrierea direct a mărimii fontului sau selectarea dintr-o listă disponibilă de mărimi.

Ultimul tip de unealtă este controlul pop-up, care afişează un meniu cu alte controale. În esenţă un asemenea control
este similar cu un meniu, exemplul fiind butonul Draw care produce la activare afişarea barei de unelte Drawing.

Observaţie. Deşi sunt identice ca aparenţă şi comportare, controalele de pe barele de unelte nu sunt aceleaşi cu
controalele ActiveX. Nu se pot adăuga controale ActiveX la bare de unelte şi nu se pot adăuga controale de toolbar la
documente sau forme.

Principii de adaptare a barelor de unelte

Aplicaţiile Microsoft Office oferă o mare varietate de modalităţi pentru modificarea barelor de unelte: se pot crea noi bare
de unelte, se pot adăuga noi butoane la barele existente, se poate modifica imaginea de pe un buton, se pot asigna
macro-uri, texte ToolTip de ajutor, text asociat afişat în bara de stare a aplicaţiei.

Dacă se modifică o bară built-in sau se creează o bară de unelte proprie depinde de numărul de modificări intenţionate
sau de dorinţa proiectantului. Este recomandabil ca adăugarea sau modificarea unui număr mic de butoane să se
efectueze pe o bară de unelte predefinită, în timp ce proiectele mari să dispună de bare de unelte proprii. Indiferent de
calea aleasă, configuraţia standard poate fi restaurată oricând.

Modificările pot fi efectuate în timpul proiectării (design-time) sau în timpul execuţiei (run-time) prin proceduri Visual Basic.
Este preferabil ca modificările principale să se efectueze în timpul proiectării şi doar eventualele modificări dinamice,
funcţie de acţiunile utilizatorului, să se efectueze în run-time. O schimbare frecventă a sistemului de meniuri poate
îngreuna acţiunile utilizatorului.

Utilizarea meniurilor

La orice bară de unelte, built-in sau proprie, se pot adăuga controale pop-up, aceleaşi ca la crearea
meniurilor/submeniurilor. Această acţiune este un compromis acceptabil între modificarea unei bare de meniu şi
238
introducerea unui mare număr de butoane unelte. Reamintim butonul Draw, sau AutoShapes, de pe bara de unelte
Drawing care deschide un meniu.

Adăugarea meniurilor, submeniurilor şi intrărilor la o bară de unelte se realizează în modul descris în secţiunile
precedente care se referă la personalizarea meniurilor.

Utilizarea controalelor Text box, List box şi Combo box

Controale de tip text box, list box şi combo box se pot adăuga atât la barele de unelte built-in cât şi la barele proprii.
Aceste controale pot fi utile pentru obţinerea repetată a unor informaţii de la utilizator sau pentru executarea unei
proceduri dependente de valoarea controlului.

Dialogul Customize suportă adăugarea unor controale predefinite (built-in) la orice bară de unelte. Pentru adăugarea
unor controale proprii se va utiliza Visual Basic prin care se pot proiecta şi adăuga controale de tipurile discutate aici.
Dacă dialogul Customize este deschis, se poate modifica lăţimea oricărui control (built-in sau propriu) text box, list box
sau combo box.

Modificările barelor de unelte în timpul proiectării (design-time)

În această secţiune se prezintă crearea unei noi bare de unelte, adăugarea de controale noi (built-in sau proprii),
eliminarea controalelor dintr-o bară de unelte, gruparea controalelor şi schimbarea dimensiunilor controalelor text box, list
box şi combo box. Se poate de asemenea modifica sau edita imaginea de pe un control.

Adăugarea unei bare de unelte

Dacă se doreşte ca uneltele proprii să fie conţinute într-o bară de unelte separată, procesul se desfăşoară în două etape:
crearea barei şi adăugarea controalelor (similar lucrului cu barele de meniu). Se poate utiliza dialogul Customize sau
Visual Basic.

Dialogul Customize

• Se afişează dialogul Customize


• În fişa Toolbars click New.
• În Toolbar name se introduce numele noii bare de unelte şi OK. Se afişează o bară de unelte flotantă, cu numele
introdus. La aceasta se pot adăuga controale.

Noul toolbar este adăugat la lista Toolbars de pe fişa Toolbars a dialogului Customize.

Visual Basic

Se utilizează Add a colecţiei CommandBars pentru a crea o nouă bară de unelte. Prin fixarea argumentului Position la
msoBarLeft, msoBarTop, msoBarRight, msoBarBottom sau msoBarFloating se stabileşte dacă obiectul
CommandBar creat este flotant sau aliniat la o latură (docked).

Urmatorul exemplu creează şi afişează o bară de unelte nouă numită "Custom Tools".

Set cstm = CommandBars.Add(Name:="Custom Tools", Position:=msoBarFloating, _


MenuBar:=False, Temporary:=False)
cstm.Visible = True

239
Adaugarea şi gruparea controalelor

Pe lângă adăugarea controalelor la orice bară de unelte, acestea pot fi separate prin linii după funcţionalitate.

Dialogul Customize

Prin dialogul Customize se pot adăuga controale built-in în modul următor:

• Se afişează dialogul Customize


• Prin fişa Toolbars se vizualizează bara de unelte care se modifică.
• În fişa Commands se alege categoria necesară de comenzi. Comenzile categoriei sunt afişate în caseta
Commands.
• Se trage controlul care se adaugă din lista Commands în poziţia sa de pe bara de unelte.

Pentru adăugarea controalelor proprii fiecare aplicaţie Office are particularităţile ei, prezentate în continuare.

Microsoft Access

Pentru adăugarea unui control care execută un macro se urmează paşii descrişi anterior dar în Categories (fişa
Commands) se selectează All Macros. Se trage apoi macroul dorit din lista Commands pe bara de unelte.

Pentru un control care execută o procedură de tip Function se procedează similar în primii paşi dar pe bară se trage
orice control (din orice categorie). După poziţionarea pe bara de unelte, click dreapta pe control şi deschiderea dialogului
Control Properties în care se fixează numele în Caption şi acţiunea de executare a procedurii Visual Basic în On
Action. Expresia trebuie să aibă sintaxa: =functionname().

Microsoft Excel

Se urmează aceiaşi paşi descrişi anterior, dar în Categories se alege Macros, se trage controlul Custom Button din
lista Commands în poziţia stabilită pe bara de unelte. Click dreapta pe noul control şi Assign Macro in meniul
contextual. În dialogul Assign Macro se selectează macroul executat de buton.

Microsoft Word

Similar procedurii de la Excel, în Categories se alege Macros şi se trage din lista Commands denumirea procedurii
dorite pe bara de unelte care se modifică. Utilizând meniul contextual afişat pentru noul control se stabilesc atributele
sale.

Este de revăzut şi observaţia făcută la subiectul similar de la meniuri privind procedurile proprii care au acelaşi nume cu
controalele built-in.

Microsoft PowerPoint

Se procedează la fel ca în Word.

Modificarea aparenţei unei unelte

Aspectul unui buton de pe o bară de unelte poate fi o imagine, un text sau ambele. Aspectul este determinat de stilul
butonului, fixat prin comenzile din meniul contextual disponibil în timp ce este activ dialogul Customize.

Stilurile posibile pentru un buton sunt descrise în tabelul următor.

240
Stilul Aspectul butonului

Default Style Numai imaginea butonului

Text Only (în meniuri) Numai imaginea butonului

Text Only (în rest) Numai numele

Image And Text Imaginea şi numele

Atunci când dialogul Customize este activ, se poate schimba imaginea de pe buton într-unul din modurile descrise la
procedura similară de la intrările unui meniu.

Gruparea controalelor

Într-un mod similar celui de la gruparea comenzilor de pe un meniu, pentru a începe un grup cu un control se activează
dialogul Customize şi în meniul contextual al controlului se alege Begin Group. O nouă activare a acestei comenzi
elimină linia separatoare de grup.

Visual Basic

Se utilizează metoda Add a colecţiei CommandBarsControls pentru adăugarea unui nou control la obiectul
CommandBar care reprezintă toolbarul care se modifică. Adăugarea unui control built-in se efectuează specificând
numărul ID al controlului în argumentul Id al metodei Add. Următorul exemplu adaugă controlul built-in Spelling la bara
numită "Quick Tools".

Set mySpell = CommandBars("Quick Tools").Controls.Add(Id:=2)

Pentru adăugarea unui control propriu se adaugă un nou control şi apoi se fixează proprietatea OnAction pe procedura
Visual Basic executată la clickarea controlului. În argumentul Type se dă valoarea msoControlButton pentru a arăta că
este bvorba de un buton. Se poate stabili proprietatea FaceId la ID-ul unui control built-in pentru a-i da o imagine definită.

Următorul exemplu (în Excel) adaugă un buton pe bara de unelte Standard, înaintea butonului Save. Butonul reprezintă
procedura OpenDatabaseProc. Exemplul stabileşte imaginea butonului la o grilă (ID 987).

Set databaseItem = CommandBars("Standard").Controls. _


Add(Type:=msoControlButton, Before:=3)
With databaseItem
.OnActiona = "OpenDatabaseProc"
.FaceId = 987
End With

Pentru a începe un nou grup se fixează pe True proprietatea BeginGroup a obiectului CommandBarButton,
CommandBarPopup sau CommandBarComboBox reprezentând controlul.

Se utilizează Controls(index), unde index este titlul sau indicele controlului, pentru a returna obiectul reprezentând
controlul.

Adăugarea şi iniţializarea controalelor text box, list box şi combo box

Dacă un control de acest tip este built-in, adăugarea lui se poate efectua prin dialogul Customize în mod similar
adăugării altor controale built-in.
241
Pentru adăugarea şi iniţializarea conţinutului unui control propriu de tip text box, list box sau combo box se poate utiliza
doar Visual Basic. Prin metoda Add a colecţiei CommandBarControls se poate crea un asemenea control specificând
drept tip al controlului (în argumentul Type) una dintre valorile

Controlul Argumentul Type

Text box msoControlEdit

List box msoControlDropDown

Combo box msoControlComboBox

Se poate folosi proprietatea Style a unui control text box, list box sau combo box pentru a indica dacă titlul (textul) apare
în stânga boxei respective.

Următorul exemplu adaugă un control combo box cu eticheta "Quarter" la o bară de unelte proprie şi atribuie controlului
macro-ul cu numele "ScrollToQuarter".

Set newCombo = CommandBars("Custom1").Controls. _


Add(Type:=msoControlComboBox)
With newCombo
.AddItem "Q1"
.AddItem "Q2"
.AddItem "Q3"
.AddItem "Q4"
.Style = msoComboNormal
.OnAction = "ScrollToQuarter"
End With

La executarea aplicaţiei Visual Basic, procedura atribuită controlului în proprietatea OnAction este apelată de fiecare
dată când se modifică controlul. În procedură se poate utiliza proprietatea ActionControl a obiectului CommandBars
pentru a găsi care control a fost schimbat şi a returna valoarea modificată. Proprietatea ListIndex returnează intrarea
introdusă în combo box.

Eliminarea unui control dintr-o bară de unelte

Eliminarea controalelor poate fi necesară atât pentru că unele acţiuni sunt executate prin interfaţa proprie proiectată, cât
şi pentru simplificarea interfeţei cu un utilizator mai puţin experimentat.

Restaurarea configuraţiilor standard este posibilă pentru barele de unelte built-in. Barele de unelte şi controalele proprii
trebuiesc create din nou în vederea restaurării unei configuraţii iniţiale.

Dialogul Customize

Pentru a şterge un control:

o Se deschide dialogul Customize.


o Se afişează bara de unelte care se modifică prin fişa Toolbars.
o Click dreapta pe controlul care se elimină şi comanda Delete din meniul contextual.

242
Pentru a elimina o întreagă bară de unelte proprie se deschide dialogul Customize, click pe numele barei în lista
Toolbars a fişei sinonime şi click pe butonul Delete. Nu se pot elimina barele built-in (acestea se afişează sau nu prin
View – Toolbars etc.).

Visual Basic

Se utilizează metoda Delete pentru a elimina din colecţia corespunzătoare un obiect de control sau bară de unelte
proprie. Nu se poate elimina o bară de unelte built-in.

Următorul exemplu Excel elimină controlul Print din bara de unelte Standard.

CommandBars("Standard").Controls("Print").Delete

iar pentru a şterge o bară proprie de unelte

CommandBars("Custom Bar").Delete

Restaurarea barelor de unelte built-in

Din dialogul Customize

o Se afişează dialogul Customize.


o În fişa Toolbars se selectează bara de unelte care se restaurează.
o Click Restore.

În Visual Basic se utilizează metoda Reset:

CommandBars("Standard").Reset

Barele de unelte proprii nu se restaurează în mod automat; ele se creează din nou.

Modificările barelor de unelte în timpul execuţiei (run-time)

Barele de unelte pot fi programate astfel încât să răspundă dinamic la schimbările de condiţii din timpul execuţiei.
Acţiunile posibile uzuale sunt interzicerea accesului la un buton şi comutarea imaginii apăsat/ridicat.

Afişarea sau ascunderea controalelor şi barelor de unelte

Pentru mărirea spaţiului de lucru sau pentru simplificarea interfeţei cu utilizatorul, o bară de unelte poate fi afişată doar
atunci când este necesară. Vizibilitatea unei bare este dependentă de valoarea proprietăţii Visible, cu valorile True şi
False. Fixarea valorii True este echivalentă cu selectarea barei în lista Toolbars din dialogul Customize şi click pe OK.

Următoarea procedură Excel, atribuită intrării de meniu View MyToolbar din meniul View, comută stările intrării din meniu
şi proprietatea Visible a barei de unelte de fiecare dată când utilizatorul face click pe intrarea din meniu.

Sub ViewMyAppToolbar()
With CommandBars("Worksheet Menu Bar").Controls("View"). _
Controls("View MyToolbar")
If .State = msoButtonUp Then
.State = msoButtonDown
CommandBars("MyAppTools").Visible = True
Else
243
.State = msoButtonUp
CommandBars("MyAppTools").Visible = False
End If
End With
End Sub

Atunci când o bară de unelte este vizibilă, utilizatorul poate acţiona orice control de pe ea. Prin fixarea proprietăţii Visible
drept True sau False se poate efectiv adăuga sau elimina un control din spaţiul de lucru al utilizatorului fără a şterge
efectiv controlul.

Observaţie. Deoarece Microsoft Word salvează personalizările la nivel de documente sau şabloane, barele de unelte
proprii şi controalele proprii sunt vizibile doar dacă documentul sau template-ul este disponibil. Microsoft Excel salvează
personalizările la nivel de spaţiu de lucru şi se va utiliza proprietatea Visible în coduri activate de evenimente pentru a
modifica dinamic interfaţa cu utilizatorul.

Mutarea şi redimensionarea barelor de unelte

Adaptarea proeminenţei pe ecran a unei bare de unelte la contextul curent a aplicaţiei se poate efectua şi prin
schimbarea locului pe ecran, a dimensiunilor.

Proprietăţile Height, Width, Left, Top şi Position permit manevrări de poziţie şi dimensiune pentru un obiect
CommandBar.

Restaurarea barelor de unelte built-in

Metoda Reset realizează restaurarea unui obiect predefinit. Următorul exemplu realizează refacerea tuturor barelor de
unelte built-in şi eliminarea tuturor barelor proprii. Pentru aceasta se foloseşte proprietatea BuiltIn care returnează True
pentru un obiect predefinit.

For Each cb In CommandBars


If cb.BuiltIn Then
cb.Reset
Else
cb.Delete
End If
Next

Observaţie. Prin restaurarea barelor built-in se elimină şi toate controalele proprii inserate în acele bare. Se poate pierde
astfel accesul la o procedură din aplicatia Visual Basic. Pentru a ocoli această capcană se recomandă ca eliminarea
controalelor proprii de pe o bară de unelte built-in să se efectueze individual, în funcţie de contextul curent şi nu prin
restaurare globală.

Permiterea şi interzicerea accesului la controale

Ca alternativă la afişarea şi ascunderea controalelor se poate permite sau interzice accesul prin manevrarea proprietăţii
Enabled. Proprietatea poate fi utilizată şi pentru aflarea stării curente a controlului.

Următorul exemplu inhibă butonul al treilea de pe bara Standard.

CommandBars("Standard").Controls(3).Enabled = False

Un control interzis produce un beep la acţionare şi nu lansează procedura asociată.

244
Indicarea stării activ/inactiv a unui buton

Pentru butoanele care comută între două stări, proprietatea State, cu valorile msoButtonDown şi msoButtonUp, poate
fi utilizată, similar exemplelor de la meniuri, pentru reprezentarea grafică a celor două opţiuni posibile.

Modificarea controalelor Text box, List box şi Combo box

Dacă se utilizează controale proprii de tip text box, list box sau combo box, în timpul execuţiei se poate modifica textul
afişat în zona text a controlului sau adăuga/elimina intrări în listele controalelor.

Proprietatea Text reflectă textul afişat în zona text a controlului şi poate fi fixată pe o valoare reflectând modificări din
aplicaţie.

Metodele AddItem şi RemoveItem permit procesarea listelor din controale.

Alte proprietăţi şi metode se vor studia din Help. De exemplu există posibilitatea declarării unui antet de listă (intrări
separate de celelalte printr-o linie).

ID-uri de controale şi intrări de meniu

Fiecare aplicaţie Office conţine un set unic de bare de meniuri şi de unelte şi un set unic de intrări de meniuri şi de
controale, doar o mică parte dintre acestea apar efectiv în aplicaţie. De asemenea, după cum s-a explicat la începutul
capitolului, fiecare aplicaţie are un mod unic de memorare a meniurilor şi barelor de unelte.

În timp ce funcţionalitatea asociată cu fiecare intrare built-in de meniu şi cu fiecare unealtă aparţine unei aplicaţii Office
specifice, titlul, imaginea de pe buton, lăţimea şi alte proprietăţi implicite sunt memorate într-o resursă partajată de toate
aplicaţiile. Referinţele la componentele conţinute în această unică resursă se fac prin numerele ID specifice intrărilor de
meniu şi uneltelor.

Aceeaşi resursă comună conţine de asemenea proprietăţile implicite ale controalelor pop-up care afişează meniurile built-
in. Totuşi, aceste controale pop-up nu conţin şi intrările meniurilor built-in, cu alte cuvinte controalele pop-up sunt vide.

Referirea la ID-uri poate fi ocolită prin utilizarea dialogului Customize. Sunt însă situaţii când referinţa este necesară:

o Se doreşte atribuirea unui intrări la un meniu/bară de unelte predefinită sau proprie iar intrarea respectivă
nu este disponibilă din dialogul Customize în design-time.
o Se adaugă o intrare built-in la un meniu sau la o bară de unelte în run-time.
o Se doreşte copierea unei imagini de buton la alt buton în run-time.

Se poate atribui ID-ul unui element built-in la argumentul Id al metodei Add pentru colecţia CommandBarsControls, sau
se poate atribui ID-ul unui element la proprietatea FaceId a oricărui control propriu sau built-in.

Observaţie. Chiar dacă resursa partajată conţine informaţie despre orice element de interfaţă din toate aplicaţiile Office,
nu se pot adăuga într-o aplicaţie intrări şi controale a căror funcţionalitate este conţinută în altă aplicaţie. Se poate totuşi
copia, şi în cazul funcţionalităţilor distincte, imaginea butoanelor de la o aplicaţie la alta.

Pentru determinarea ID-urile elementelor de interfaţă dintr-o aplicaţie Office, se poate urma una din căile:

o Într-un modul se scrie cod pentru atribuirea unui element de meniu sau control dintr-o bară de unelte la o
variabilă obiect. Se utilizează apoi mijloacele de debug pentru a vedea valoarea proprietăţii Id a
obiectului. Numărul obţinut se memorează şi poate fi ulterior utilizat.

245
o Se execută următoarea procedură într-o aplicaţie Office pentru a crea un document text care conţine lista
ID-urilor şi titlurilor tuturor comenzilor built-in din aplicaţie.

Public Sub outputIDs()


Const maxId = 4000
Open "c:\ids.txt" For Output As #1
' crearea unei bare temporare cu toate elementele disponibile asignate
Set cbr = CommandBars.Add("Temporary", msoBarTop, False, True)
For i = 1 To maxId
On Error Resume Next
cbr.Controls.Add ID:=i
Next
On Error GoTo 0
' scrierea ID şi titlu pentru fiecare control
For Each btn In cbr.Controls
Write #1, btn.ID, btn.Caption
Next
' eliminarea barei de comandă şi închiderea fişerului de ieşire
cbr.Delete
Close #1
End Sub

o Executarea procedurii următoare într-o aplicaţie Office pentru a crea un set de bare de unelte proprii care
conţin atâtea butoane câte valori valide de proprietate FaceId există în Office; fiecare imagine de buton şi
textul ToolTip este fixată la o asemenea valoare. Se poate referi încrucişat ID-ul unei comenzi built-in la
proprietatea FaceId a unui buton de pe aceste bare şi reciproc.

Sub MakeAllFaceIds()
' Make fourteen bars with 300 faces each.
' Note that maxId is greater than last valid ID, so
' error will occur when first invalid ID is used
Const maxId = 3900
On Error GoTo realMax
For bars = 0 To 13
firstId = bars*300
lastId = firstId + 299
Set tb = CommandBars.Add
For i = firstId To lastId
Set btn = tb.Controls.Add
btn.FaceId = i
btn.ToolTipText = "FaceId = " & i
Next
tb.Name = ("Faces " & CStr(firstId) & " to " & CStr(lastId))
tb.Width = 591
tb.Visible = True
Next
' Delete the button that caused the error and set toolbar name
realMax:
btn.Delete
tb.Name = ("Faces " & CStr(firstId) & " to " & CStr(i–1))
tb.Width = 591
tb.Visible = True
End Sub

246
Notă. ID-urile controalelor pop-up pentru meniurile built-in sunt în domeniul 30002 – 30426. Reamintim că aceste ID-uri
returnează copii vide ale meniurilor predefinite.

Forme grafice (shapes) şi stratul de desen

Visual Basic dispune de un model de obiecte, reprezentând stratul de desen, comun aplicaţiilor Microsoft Word, Microsoft
Excel şi Microsoft PowerPoint. Obiectul cel mai sus în ierarhia acestui model este colecţia Shapes, care conţine toate
obiectele grafice – AutoShapes, forme libere, obiecte OLE, imagini – care pot fi incluse în stratul de desen al
documentului. Este de notat că formele grafice incluse în stratul de text din Word nu sunt incluse în colecţia Shapes.

Pentru o discuţie mai amplă privind controalele ActiveX, care sunt o categorie specială de forme grafice, se va vedea
capitolul Dialoguri şi controale ActiveX.

Observaţie. Pentru simplificarea exprimării se utilizează termenul "formă" pentru shape, deşi "formă grafică" ar fi mai
potrivit în contextul subiectului.

Obiectele Shape, ShapeRange şi Shapes

Există trei obiecte diferite care reprezintă formele: colecţia Shapes, reprezentând toate formele din stratul de desen dintr-
un document Microsoft Excel, Word sau PowerPoint, colecţia ShapeRange, care reprezintă o submulţime de forme din
stratul de desen şi obiectul Shape, care reprezintă o formă grafică individuală. În general, se utilizează colecţia Shapes
atunci când se adaugă forme pe stratul de desen sau se parcurg toate formele; se utilizează obiectul Shape când se
doreşte formatarea sau procesarea unei anumite forme grafice şi se utilizează colecţia ShapeRange când se doreşte
procesarea/formatarea unui grup de forme grafice.

O colecţie ShapeRange poate conţine oricâte elemente. Dacă include un singur obiect, este similară unui obiect Shape.
Se poate utiliza o colecţie ShapeRange care conţine toate elementele din Shapes pentru a formata toate formele în
acelaşi timp. Proprietăţile şi metodele care se aplică obiectului Shape se pot aplica de asemenea şi colecţiei
ShapeRange.

Returnarea colecţiei Shapes

O referinţă la colecţia Shapes se obţine prin proprietatea sinonimă aplicată unui obiect document. Exemplul următor
selectează toate formele din stratul de desen:

myDocument.Shapes.SelectAll

Returnarea obiectului Shape

Un obiect Shape poate fi obţinut prin intermediul colecţiei Shapes, în modul general de obţinere a unui element dintr-o
colecţie, după unul dintre exemplele următoare:

myDocument.Shapes(3).Duplicate
myDocument.Shapes("Red Square").Duplicate

Fecare formă are un nume atribuit în mod implicit, cum ar fi "Rectangle 3", obţinut la adăugarea formei la colecţia
Shapes. Prin proprietatea Name se poate atribui un nume sugestiv. Acest lucru se poate realiza concomitent cu
adăugarea/crearea formei:

myDocument.Shapes,AddShape(msoShapeRectangle, 144, 144, 72, 72) _


.Name = "Red Square"

247
Această metodă, care utilizează obiectul returnat de metoda AddShape, poate fi utilizată şi cu alte proprietăţi sau metode
ale obiectului Shape.

Returnarea colecţiei ShapeRange

Prin referinţe de tipul Shapes.Ranges(index), unde index este fie numele, fie indicele, fie un tablou de denumiri sau de
indici, se returnează o colecţie ShapeRange care reprezintă un subset a colecţiei Shapes. Exemplul următor umple
formele 1 şi 3 din myDocument:

myDocument.Shapes.Range(Array(1, 3)).Fill.PresetGradient _
msoGradientHorizontal, 1, msoGradientLateSunset

Se utilizează Selection.ShapeRange pentru a returna o colecţie ShapeRange care reprezintă toate formele din selecţie.
Prin Selection.ShapeRange(index), unde index este un indice sau un nume de formă, se obţine accesul la un obiect
Shape din selecţie:

ActiveWindow.Selection.ShapeRange(1).Fill.PresetGradient _
msoGradientHorizontal, 1, msoGradientLateSunset

Observaţie. Macro recorderul generează cod bazat pe selecţie. Atunci când se scrie cod direct, sau se editează codul
generat de macro recorder, se poate crea un cod mai eficient prin returnarea formelor direct din colecţia Shapes.

Desenarea unei forme pe un Document, Worksheet sau Slide

Adăugarea unei forme pe stratul de desen se efectuează printr-una dintre metodele colecţiei Shapes dedicate acestui
scop. Fiecare tip de formă se obţine printr-o metodă specifică şi acestea sunt enumerate în tabelul următor.

Tipul de formă grafică Metoda Parametri

Callout AddCallout (Type, Left, Top, Width, Height, Anchor)

Note ataşabile (doar PowerPoint) AddComment (Left, Top, Width, Height)

Linie sau curbă care conectează două forme diferite AddConnector (Type, BeginX, BeginY, EndX, EndY)

Curbă Bézier AddCurve (SafeArrayOfPoints)

Control nativ de formular Excel (doar Microsoft AddFormControl (Type, Left, Top, Width, Height)
Excel)

Etichetă AddLabel (Orientation, Left, Top, Width, Height)

Linie AddLine (BeginX, Beginy, EndX, EndY)

Sound sau movie (doar PowerPoint) AddMediaObject (FileName, Left, Top, Width, Height)

Control ActiveX (doar Word; pentru Excel şi AddOLEControl (ClassType, Left, Top, Width, Height,
PowerPoint se utilizează AddOLEObject) Anchor)

Obiect OLE scufundat sau legat AddOLEObject (ClassType, FileName, LinkToFile,


DisplayAsIcon, IconFileName, IconIndex,
IconLabel, Left, Top, Width, Height,
Anchor)

248
Imagine AddPicture (FileName, LinkToFile,
SaveWithDocument, Left, Top, Width,
Height, Anchor)

Rezervare de loc pentru text sau pentru un obiect AddPlaceholder (Type, Left, Top, Width, Height)
grafic (doar PowerPoint)

Linie poligonală închisă sau deschisă AddPolyline (SafeArrayOfPoints)

AutoShape (formă predefinită) AddShape (Type, Left, Top, Width, Height)

TextBox AddTextbox (Orientation, Left, Top, Width, Height)

WordArt AddTextEffect (PresetTextEffect, Text, FontName,


FontSize, FontBold, FontItalic, Left, Top,
Anchor)

Titlu de diapozitiv (doar PowerPoint) AddTitle –

Formă liberă BuildFreeform (EditingType, X1, Y1)

ConvertToShape –

Între parametri se remarcă Left şi Top care specifică poziţia formei, Width şi Height care fixează dimensiunile obiectului
grafic. Pentru explicaţii suplimentare asupra parametrilor care nu sunt suficient de expliciţi se vor studia intrările
respective din Help.

Editarea unei forme

Prin intermediul proprietăţilor şi metodelor obiectelor Shapes şi ShapeRange se pot modifica formele grafice
reprezentate. Acestea pot fi repoziţionate în document, redimensionate, eliminate; se poate schimba aspectul lor şi li se
poate adăuga text.

Determinarea proprietăţilor şi metodelor adecvate

Proprietăţile şi metodele care controlează atributele şi comportarea comune tuturor tipurilor de forme se aplică direct
obiectelor Shapes şi ShapeRange. Proprietăţile şi metodele care se aplică doar unor categorii de forme sunt încapsulate
în obiecte secundare care se accesează prin obiectul Shape.

Proprietăţi şi metode comune

În această categorie sunt incluse proprietăţile care controlează dimensiunea şi poziţia formei (Left, Top, Height, Width)
şi metode care controlează comportări generice de editare (cum ar fi Duplicate şi Zorder). Un exemplu uzual este

With myDocument.Shapes(1)
.Height = 50
.Width = 100
End With

Proprietăţi şi metode specifice

Atributele specifice unui anumit tip de formă sunt grupate sub obiecte secundare, cum ar fi FillFormat, conţinând
proprietăţile care se aplică formelor cu culori de umplere, sau CalloutFormat, conţinând toate proprietăţile baloanelor
249
(callouts). Pentru a lucra cu acest tip de atribute trebuie să se returneze mai întâi obiectele care le conţin. De exemplu, se
utilizează proprietatea Fill pentru a returna obiectul FillFormat şi se poate aplica apoi proprietatea ForeColor:

myDocument.Shapes(1).Fill.FillColor.RGB = RGB(255,0,0)

În tabelul următor sunt prezentate obiectele accesibile din obiectul Shape şi care conţin proprietăţile şi metodele
specifice. Se remarcă faptul că nu toate denumirile proprietăţilor conţin cuvântul "Format" existent în obiectul returnat
(precum Fill care returnează FillFormat).

Proprietatea obiectului Shape Obiectul returnat Aplicabil la

Callout CalloutFormat Baloane de dialog

ConnectorFormat (Excel şi ConnectorFormat Conectori de forme


PowerPoint)

ControlFormat (Excel) ControlFormat Controale de formular native

Fill FillFormat Forme cu culori de umplere (toate cu excepţia liniilor)

Line LineFormat Toate formele (LineFormat reprezintă linia sau chenarul)

LinkFormat LinkFormat Obiecte OLE legate, imagini legate (doar Word), câmpuri
legate (doar Word)

OLEFormat OLEFormat Obiecte OLE

PictureFormat PictureFormat Imagini şi obiecte OLE

Shadow ShadowFormat Toate formele

TextEffect TextEffectFormat Obiecte WordArt

ThreeD ThreeDFormat Forme care pot fi reliefate

WrapFormat (doar Word) WrapFormat Forme care pot fi înconjurate de text

Încercarea de a returna obiecte secundare (cum ar fi CalloutFormat, ConnectorFormat, OLEFormat, PictureFormat


sau TextEffectFormat) dintr-un tip inadecvat de formă produce eroare. Pentru alte obiecte (FillFormat, LineFormat,
ShadowFormat sau ThreeDFormat) nu se produce eroare chiar dacă forma container nu suportă obiectul returnat.

Pentru a nu avea probleme se va utiliza proprietatea Type şi, când este aplicabilă, proprietatea AutoShapeType, înainte
de aplicarea unei metode sau proprietăţi specifice şi se va introduce o secvenţă de tratare a erorii.

For Each sh In myDocument.Shapes


If sh.Type = msoLinkedOLEObject Then
sh.LinkFormat.Update
End If
Next

250
Culorile de umplere ale formelor

Prin culorile de umplere se înţelege nu numai culoarea efectivă utilizată pentru colorarea suprafeţei formei ci şi efectele
utilizate la colorare, precum şi posibilitatea de a utiliza o imagine drept fundal etc. Obiectul FillFormat reprezintă întreaga
umplere a formei, proprietăţile şi metodele sale permit stabilirea culorii, tipului, transparenţei. Deoarece atributele legate
de culori şi tipuri de umplere sunt interdependente, stabilirea unui atribut produce, de regulă, modificări ale altor atribute,
astfel încât să se obţină o mulţime consistentă de atribute. Din acelaşi motiv multe atribute sunt read-only, valorile lor fiind
atribuite în funcţie de metodele utilizate.

Tipul de umplere se stabileşte printr-una dintre metodele Background (doar PowerPoint), OneColorGradient,
Patterned, PresetGradient, PresetTextured, Solid, TwoColorGradient, UserPicture sau UserTextured,
corespunzând opţiunilor disponibile în interfaţa utilizator a aplicaţiilor. Prin proprietăţile read/write BackColor, ForeColor,
Transparency şi Visible se poate controla aspectul umplerii.

Deoarece sunt foarte multe valori predefinite pentru proprietăţi sau argumentele metodelor, valorile respective se vor lua
din intrările Help corespunzătoare obiectelor implicate.

Următorul exemplu adaugă o formă dreptunghiulară la document, fixează cele două culori şi tipul de gradient pentru
umplere:

Public Sub fil()


Dim sh As Shape
Set sh = ThisDocument.Shapes.AddShape(msoShapeRectangle, 90, 90, 90, 50)
sh.WrapFormat.Type = wdWrapTight
With sh.Fill
.ForeColor.RGB = RGB(200, 0, 0)
.BackColor.RGB = RGB(0, 200, 170)
.TwoColorGradient msoGradientHorizontal, 1
.Visible = msoTrue
End With
End Sub

Adăugarea de umbre şi efecte 3-D

Proprietatea Shadow a obiectului Shape returnează un obiect ShadowFormat prin care se controlează umbririle formei.
Următorul exemplu produce adăugarea unei umbre albastre semitransparente, cu dimensiune de 4 puncte:

With sh.Shadow
.Transparency = 0.5
.ForeColor.RGB = RGB(0, 0, 255)
.Visible = msoTrue
.OffsetY = 4
.OffsetX = 4
End With

Proprietatea ThreeD a obiectului Shape returnează un obiect ThreeDFormat care controlează reliefarea formei.
Următorul exemplu adaugă efectul de extrudare şi precizează o adâncime de 50 de puncte, purpurie, perpendiculară şi
luminată de sus

With sh.ThreeD
.Visible = msoTrue
.Depth = 50
.ExtrusionColor.RGB = RGB(255, 0, 255)

251
.Perspective = msoFalse
.PresetLightingDirection = msoLightingTop
End With

Este normal ca acest efect să nu fie suportat de anumite forme.

Adăugarea de text la o formă

Zona din interiorul unei forme care poate conţine text este numită cadru cu text, text frame, şi este reprezentată de un
obiect TextFrame. Acest obiect, returnat de proprietatea TextFrame, conţine textul propriu-zis, precum şi proprietăţile şi
metodele care controlează alinierea şi ancorarea cadrului cu textul.

Doar formele built-in de tip AutoShapes bidimensionale au asociate cadre cu text. Înaintea referirii obiectului TextFrame
se verifică disponibilitatea acestuia prin proprietatea HasTextFrame (valabilă în PowerPoint) sau prin verificarea
proprietăţii Type. Se poate utiliza şi tratarea erorilor în cazul în care proprietatea TextFrame poate fi aplicată unui obiect
care nu o suportă.

În Microsoft Word se utilizează proprietatea TextRange a obiectului TextFrame pentru a returna un obiect Range care
reprezintă textul din cadrul respectiv:

ActiveDocument.Shapes(1).TextFrame.TextRange.Text = " … "

În Microsoft Excel se utilizează proprietatea Characters a obiectului TextFrame pentru a returna un obiect Characters
care reprezintă textul din interiorul cadrului:

ActiveWorksheet.Shapes(1).TextFrame.Characters.Text = " … "

În PowerPoint, se utilizează proprietatea TextRange a obiectului TextFrame pentru a returna un obiect TextRange care
reprezintă domeniul textului din cadrul respectiv:

ActivePresentation.Slides(1).Shapes(1).TextFrame.TextRange.Text = " … "

Lucrul cu obiecte OLE

Proprietăţile şi metodele obiectului OLEFormat, cum ar fi Activate şi DoVerb, controlează obiectul OLE conţinut într-o
formă. Obiectul OLEFormat este returnat de proprietatea OLEFormat a obiectului Shape:

With myDocument.Shapes(3)
If .Type = msoEmbeddedOLEObject Or _
.Type = msoLinkedOLEObject Then
.OLEFormat.DoVerb
End If
End With

Utilizarea proprietăţii Object a obiectului OLEFormat returnează obiectul OLE conţinut în forma desenată specificată (în
Excel trebuie să se utilizeze de două ori proprietatea Object într-o linie, separate de operatorul punct, pentru a returna
obiectul OLE).

Următorul exemplu, executat din Word sau PowerPoint, adaugă text la celula A1 a primei foi de calcul dintr-un caiet Excel
conţinut în forma a treia din myDocument.

With myDocument.Shapes(3)

252
.OLEFormat.Activate
.OLEFormat.Object.Worksheets(1).Range("A1").Value = " noul text "
End With

Proprietatea Application a obiectului OLE, returnat de proprietatea sinonimă, dă acces la obiectul din vârful ierarhiei
modelului de obiecte al aplicaţiei care a creat obiectul OLE. Următorul exemplu, executat din Microsoft Excel (se va
remarca dubla utilizare a proprietăţii Object), afişează numele aplicaţiei în care a fost creat fiecare obiect OLE scufundat
în foaia activă:

For Each s In ActiveSheet.Shapes


If s.Type = msoEmbeddedOLEObject Then
s.OLEFormat.Activate
MsgBox s.OLEFormat.Object.Object.Application.Name
End If
End With

Lucrul cu mai multe forme

Pentru a lucra cu mai multe forme se poate parcurge o colecţie Shapes sau ShapeRange şi lucra cu fiecare element al
colecţiei sau se poate construi o colecţie ShapeRange cu toate formele grafice care se prelucrează şi se aplică metode
sau proprietăţi întregii colecţii ShapeRange.

Există şi posibilitatea, disponibilă în interfaţa utilizator, de a grupa mai multe forme grafice, precum şi posibilitatea de
aliniere a formelor.

Dacă operaţiunea dorită se poate executa în interfaţa utilizator pe o selecţie multiplă de forme grafice, atunci construirea
unei colecţii ShapeRange este recomandată.

Dacă operaţiunea nu se poate efectua în interfaţa utilizator pe o selecţie multiplă, atunci parcurgerea unei colecţii,
Shapes sau ShapeRange, este calea adecvată. Parcurgerea poate fi efectuată printr-o structură uzuală For Each …
Next:

For Each sh In myDoc.Shapes


If sh.Type = msoAutoShape Then
sh.TextFrame.TextRange.InsertAfter " (version 1)"
End If
Next

Construirea unui ShapeRange

Dacă este necesară obţinerea unui domeniu de forme care să conţină doar forme de anumite tipuri, se va utiliza o
instrucţiune condiţională de testare a atributelor şi se va adăuga denumirea sau indicele formei selectate la un tablou
dinamic. Se va construi apoi un obiect ShapeRange utilizând acest tablou.

Următorul exemplu construieşte un domeniu de forme cu toate formele de tip AutoShapes din document şi apoi le
grupează.

With myDocument.Shapes
numShapes = .Count
If numShapes > 1 Then
numAutoShapes = 0
ReDim autoShpArray(1 To numShapes)
For i = 1 To numShapes
253
If .Item(i).Type = msoAutoShape Then
numAutoShapes = numAutoShapes + 1
autoShpArray(numAutoShapes) = .Item(i).Name
End If
Next
If numAutoShapes > 1 Then
ReDim Preserve autoShpArray(1 To numAutoShapes)
Set asRange = .Range(autoShpArray)
asRange.Group
End If
End If
End With

Lucrul cu colecţia ShapeRange

Atunci când se aplică proprietăţi sau metode colecţiei ShapeRange, se va ţine seama de următoarele principii:

• Aplicarea unei metode colecţiei este echivalentă cu aplicarea acelei metode la fiecare obiect Shape din colecţie.
• Stabilirea unei proprietăţi a colecţiei este echivalent cu stabilirea acelei proprietăţi fiecărui obiect Shape din
colecţie.
• proprietate a colecţiei care returnează o constantă, returnează valoarea comună dacă toate obiectele
componente au o aceeaşi valoare, sau constantă "mixed" (de exemplu msoLineDashStyleMixed pentru stilul de
punctare a liniei).
• proprietate a colecţiei care returnează un tip de dată simplu, cum ar fi Long, Single sau String, returnează
valoarea proprietăţii pentru a formă dacă toate formele au aceeaşi valoare a proprietăţii.
• Valoarea anumitor proprietăţi poate fi returnată sau stabilită numai dacă există exact o formă în colecţie. Dacă
există mai multe forme în colecţie, atunci apare o eroare. Acest fapt apare atunci când se utilizează o proprietate
sau metodă care se poate aplica doar pentru un obiect.

Aceste principii acţionează şi atunci când se lucrează cu proprietăţi sau metode ale formelor, grupate în obiecte
secundare ale colecţiei ShapeRange (cum ar fi FillFormat).

Următorul exemplu construieşte un obiect ShapeRange din două forme numite şi aplică ambelor o umplere de tip
gradient.

Set myRange = myDoc.Shapes.Range(Array("Big Star", "Little" Star"))


myRange.Fill.PresetGradient msoGradientHorizontal, 1, msoGradientBrass

Metodele Align şi Distribute sunt utilizate pentru alinierea sau distribuirea uniforma a formelor dintr-o colecţie
ShapeRange. Prin metoda Zorder se poate modifica ordinea pe Z care determină ordinea de suprapunere a formelor.

Metoda Group realizează gruparea tuturor formelor dintr-o colecţie ShapeRange. Prin Ungroup, Regroup se realizează
operaţiunile sinonime din interfaţa utilizator.

Dacă se doreşte lucrul cu o formă individuală dintr-un grup, dar fără a renunţa la grupare în prealabil, se utilizează
proprietatea GroupItems a obiectului Shape care reprezintă grupul. Proprietatea returnează un obiect GroupShapes şi
metoda Item a acestui obiect returnează o formă individuală din grupul de forme:

With myDocument.Shapes
.AddShape(msoShapeIsoscelesTriangle, 10, 10, 100, 100).Name = "shpOne"
. AddShape(msoShapeIsoscelesTriangle, 150, 10, 100, 100).Name = "shpTwo"
. AddShape(msoShapeIsoscelesTriangle, 300, 10, 100, 100).Name =
With .Range(Array("shpOne", "shpTwo", "shpThree")).Group

254
.Fill.PresetTextured msoTextureBlueTissuePaper
.GroupItems(2).Fill.PresetTextured msoTextureGreenMarble
End With
End With

Tratarea erorilor şi depanarea programelor

Acest capitol arată cum să se utilizeze uneltele de depanare şi verificare a programelor oferite de Visual Basic Editor.
Sunt prezentate şi modurile în care se pot controla erorile din execuţie (run-time errors) apărute în urma încercării de a
executa operaţiuni interzise.

Informaţiile din acest capitol se aplică proiectelor VBA din Microsoft Excel 97, Word 97 şi PowerPoint 97.

Cum se gestionează erorile

În mod ideal, procedurile Visual Basic n-ar trebui să conţină cod de tratare a erorilro. Realitatea arată însă că probleme
hardware sau acţiuni neanticipate ale utilizatorului pot să producă erori în execuţie, ca urmare programul se opreşte şi
există puţine şanse ca utilizatorul să continue execuţia aplicaţiei. Sunt posibile şi erori care deşi nu opresc execuţia
produc rezultate ulterioare eronate.

De exemplu, procedura următoare returnează True dacă fişierul specificat există şi False dacă nu, dar nu conţine
instrucţiuni de tratare a erorilor.

Function FileExists (filename) As Boolean


FileExists = (Dir(filename) <>"")
End Function

Funcţia Dir returnează primul fişier care se potriveşte numelui specificat sau un şir de lungime zero în cazul când nu
există nici o potrivire.

Codul anterior pare a fi corect şi acoperitor pentru toate situaţiile posibile. Totuşî, dacă litera de drive specificată nu este
validă, apare eroarea "Device unavailable". Dacă unitatea este de floppy disk, funcţia va funcţiona corect doar dacă în
unitate este o dischetă şi poarta este închisă. În caz contrar Visual Basic va semnala eroarea "Disk not ready" şi execuţia
se opreşte.

Pentru a ocoli asemenea situaţii, trebuie să se utilizeze modalităţile de error-handling din VBE pentru a intercepta erorile
(sau "a prinde" - trapping) şi a executa acţiuni corective. La apariţia unei erori, Visual Basic stabileşte diferite proprietăţi
ale obiectului reprezentând eroare, Err, cum ar fi numărul erorii, descrierea etc. Obiectul Err poate fi utilizat într-o rutină
de tratare a erorii astfel încât aplicaţia poate răspunde inteligent la o situaţie de eroare.

De exemplu, probleme legate de unitate, cum ar fi o unitate invalidă sau o unitate de floppy fără dischetă, pot fi tratate
după modelul următor.

Function FileExists (filename) As Boolean


Dim Msg As String
' Trecerea la tratarea erorilor
On Error GoTo CheckError
FileExists = (Dir(filename) <> "")
' nu a apărut nici o eroare
Exit Function
CheckError: ' secvenţa de tratare a erorii apărute
' definirea constantelor care reprezintă eroarea
Const mnErrDiskNotReady = 71, mnErrDeviceUnavailable = 68
255
' vbExclamation, vbOK, vbCancel, vbCritical şi vbOKCancel
' sunt constante definite în biblioteca VBA
If (Err.Number = mnErrDiskNotReady) Then
Msg = "Put a floppy disk in the drive and close the door"
' Afişarea mesajului
If MsgBox(Msg, vbExclamation & vbOKCancel) = vbOK Then
Resume
Else
Resume Next
End If
ElseIf Err.Number = mnErrDeviceUnavailable Then
Msg = "This drive or path does not exist: " & filename
MsgBox Msg, vbExclamation
Resume Next
Else
Msg = "Unexpected error #" & Str(Err.Number) & " occurred: " _
& Error.Description
' Afişarea mesajului
MsgBox Msg, vbCritical
Stop
End If
Resume
End Function

În acest cod, proprietatea Number a obiectului Err conţine numărul asociat cu eroarea aparută; proprietatea Description
conţine o scurtă descriere a erorii. Instrucţiunea Resume returnează controlul la instrucţiunea care a produs eroarea iar
Resume Next returnează controlul la instrucţiunea următoare celei care a produs eroarea.

Proiectarea unei rutine de tratare a erorilor

O secvenţă de tratare a erorilor, error handler, este o rutină care captează şi răspunde la erori în aplicaţie. Asemenea
secvenţe se pot adăuga la orice procedură unde se anticipează posibilitatea unei erori (se poate presupune că orice
instrucţiune Visual Basic poate produce o eroare, cu excepţia cazurilor când se ştie explicit că acest fapt nu poate avea
loc). Procesul de proiectare a unui error handler necesită trei paşi:

1. Stabilirea, sau permiterea, unei captări de erori prin specificarea locului din program unde se va efectua transferul
controlului atunci când apare o eroare.

Instrucţiunea On Error permite captarea erorii şi transferul controlului execuţiei la eticheta specificată.

2. Scrierea unei rutine de tratare a erorilor, care să răspundă tuturor erorilor anticipate. Dacă execuţia şi-a transferat
controlul în această secvenţă, se zice că secvenţa este activă (capcana de prindere a erorii este activă).

3. Ieşirea (părăsirea) secvenţei error-handling.

Detalii sunt oferite în secţiunile care urmează.

Stabilirea capcanei de erori

O capcană de erori este activată atunci când se execută o instrucţiune On Error, care specifică o secvenţă de tratare a
erorilor. Capcana rămâne deschisă atât timp cât procedura care o conţine este activă, adică până când este executată o
instrucţiune Exit Sub, Exit Function, Exit Property, End Sub, End Function sau End Property din procedura care
include secvenţa de tratare a erorilor. Deşi numai o capcană de erori poate fi permisă la un moment dat în orice

256
procedură, se pot crea mai multe capcane alternative care să fie activate la diferite momente. O capcană de erori poate fi
inhibată prin utilizarea instrucţiunii On Error GoTo 0.

Pentru activarea unei capcane de erori se utilizează instrucţiunea On Error GoTo line, unde line este eticheta care
identifică secvenţa de instrucţiuni, din procedură, care tratează erorile.

Scrierea unei rutine de tratare a erorilor

Primul pas în scrierea unei rutine error-handling este adăugarea unei etichete de linii pentru marcarea începutului
secvenţei de tratare a erorilor. O convenţie comună este aceea de a plasa codul error-handler la sfârşitul procedurii şi a-l
preceda de o instrucţiune Exit Sub, Exit Function sau Exit Property. Aceasta permite procedurii să nu execute codul de
tratare a erorilor atunci când nu apar erori.

Corpul rutinei de tratare a erorilor conţine cod de identificare a erorii apărute, prin structuri Select Case sau
If...Then...Else. Este obligatoriu ca o alternativă să se refere la erorile neanticipate şi care nu sunt tratate individual.

Proprietatea Number a obiectului Err conţine un cod numeric reprezentând cea mai recentă eroare. Utilizarea obiectului
Err în combinaţie cu structurile Select Case sau If...Then...Else, se pot lua acţiuni specifice fiecărei erori.

Ieşirea din rutina de tratare a erorilor

Următorul tabel cuprinde instrucţiunile prin care se poate ieşi dintr-o secvenţă error-handling. Acest fapt înseamnă, în
general, cedarea controlului execuţiei către altă instrucţiune din procedura activă.

Instrucţiunea Descriere

Resume [0] Execuţia programului se reia cu instrucţiunea care a cauzat eroarea sau cel mai recent apel
al procedurii conţinând rutina error-handling. Este utilizată pentru a repeta o operaţiune după
ce s-a corectat situaţia care a produs eroarea.

Resume Next Reia execuţia programului cu instrucţiunea imediat următoare celei care a cauzat eroarea.
Dacă eroarea a apărut în afara procedurii care conţine codul de eroare, execuţia se reia cu
instrucţiunea imediat următoare apelului la procedura unde a apărut eroarea, dacă procedura
apelată nu are activată o secvenţă de eroare.

Resume line Reia execuţia programului cu instrucţiunea având eticheta specificată în line, unde line este o
etichetă de linie (sau un număr de linie diferit de zero) care se găseşte în aceeaşi procedură
ca şi error-handler-ul.

Err:Raise Declanşează eroarea de execuţie având numărul specificat. Atunci când o asemenea
Number:=number instrucţiune este executată în interiorul rutinei de eroare, Visual Basic caută lista de apeluri
pentru altă rutină de tratare a erorilor. (Lista de apeluri este lanţul de proceduri apelate pentru
a ajunge în punctul curent de execuţie. Informaţii suplimentare se găsesc în secţiunea
"Ierarhia tratării erorilor.)

Diferenţa dintre Resume şi Resume Next

Diferenţa este că Resume continuă execuţia cu instrucţiunea care a generat eroarea (instrucţiunea este reexecutată), în
timp ce Resume Next continuă cu instrucţiunea care urmează celei care a generat eroarea. În general, se utilizează
Resume atunci când eroarea poate fi corectată. Se poate scrie cod care să nu arate utilizatorului căa avut loc o eroare,
sau cod care să permită utilizatorului să corecteze eroarea.

257
Exemplul următor încearcă efectuarea unei împărţiri "sigure", fără a afişa erorile care pot să apară: "Division by zero"
(numitor egal cu zero, numărător nenul), "Overflow" (şi numitorul şi numărătorul sunt egali cu zero) sau "Illegal procedure
call" (un operand este o valoare nenumerică, sau nu poate fi considerat numeric). In toate cele trei cazuri procedura
următoare returnează Null.

Function Divide (numer, denom) As Variant


Const mnErrDivByZero = 11, mnErrOverFlow = 6, mnErrBadCall = 5
On Error GoTo MathHandler
Divide = numer / denom
Exit Function
MathHandler:
If Err.Number = mnErrDivByZero Or Err.Number = mnErrOverFlow _
Or Err.Number = mnErrBadCall Then
Divide = Null
Else
MsgBox "Unanticipated error " & Err.Number & ": " & _
Err.Description, vbExclamation
End If
Resume Next
End Function

Reluarea execuţiei la o linie specificată

Prin Resume line se dă controlul execuţiei la linia specificată. Următorul exemplu ilustrează utilizarea acestei instrucţiuni
într-o variantă a procedurii FileExists prezentată într-un exemplu anterior.

Function VerifyFile As String


Const mnErrBadFileName = 52, mnErrDriveDoorOpen = 71
Const mnErrDeviceUnavailable = 68, mnErrInvalidFileName = 64
Dim strPrompt As String, strMsg As String, strFileSpec As String
strPrompt = "Enter file specification to check:"
StartHere:
strFileSpec = "*.*"
strMsg = strMsg & vbCRLF & strPrompt
' Let the user modify the default
strFileSpec = inputBox(strMsg, "File Search", strFileSpec, 100, _
100)
' Exit if user deletes default
If strFileSpec = "" Then Exit Function
On Error GoTo Handler
VerifyFile = Dir(FileSpec)
Exit Function
Handler:
Select Case Err.Number
Case ErrInvalidFileName, ErrBadFileName
strMsg = "Your file specification was invalid; _
try another."
Case mnErrDriveDoorOpen
strMsg = "Close the disk drive door and try again."
Case mnErrDeviceUnavailable
strMsg = "The drive you specified was not found. _
Try again."
Case Else
Dim intErrNum As Integer
intErrNum = Err.Number
258
Err.Clear
Err.Raise Number:=intErrNum ' Regenerate the error
End Select
Resume StartHere ' The user can try another file name
End Function

Dacă este găsit un fişier care se potriveşte specificaţiei, funcţia returnează numele fişierului. Dacă nu se potriveşte nici un
fişier, funcţia returnează un şir de lungime zero. În cazul apariţiei unei dintre erorile anticipate, se afişează mesajul
corespunzător (prin intermediul variabilei strMsg) şi utilizatorul poate încerca un nou nume prin reluarea de la eticheta
StartHere.

Dacă apare o eroare diferită de cele anticipate (şi posibile în operaţiunea efectuată), pe ramura de program Case Else se
regenerează eroarea încât următoarea capcană de erori din lista de apeluri poate să intre în acţiune. Acest fapt este
necesar din cauză că dacă eroarea nu ar fi regenerată, codul ar continua să se execute la linia Resume StartHere. Prin
regenerare, eroarea apare din nou şi noua eroare va fi captată la următorul nivel din stiva de apeluri.

Ierarhia de tratare a erorilor

Un error-handler permis este unul care a fost activat prin executarea unei instrucţiuni On Error şi nu a fost interzis (prin
On Error GoTo 0 sau prin părăsirea procedurii care îl conţine). Un error-handler activ este cel care se execută curent.
Pentru a fi activ, o secvenţă error-handling trebuie să fie mai întâi permisă, dar nu toate secvenţele permise sunt şi active.
De exemplu, după o instrucţiune Resume, un handler este dezactivat dar rămâne permis.

La apariţia unei erori într-o procedură, care nu are o secvenţă error-handling permisă, sau într-o rutină error-handling
activă, Visual Basic caută lista de apeluri pentru a găsi o altă rutină permisă de tratare a erorilor. Lista de apeluri este
secvenţa de apeluri care conduce la procedura curentă; ea este afişată în dialogul Call Stack, disponibil în modul break
prin meniul View, comanda Call Stack.

Căutarea în lista de apeluri

Presupunem următoarea succesiune de apeluri:

1. O procedură eveniment apelează procedura A.

2. Procedura A cheamă procedura B.

3. Procedura B apelează procedura C.

În timp ce se execută C, celelalte proceduri sunt suspendate. Dacă apare o eroare în procedura C iar procedura nu are
un error- handler, Visual Basic caută înapoi în lista de apeluri - mai întâi B, apoi A, apoi procedura de eveniment, dar atât
- şi execută prima secvenţă întâlnită de tratare a erorii. Dacă nu există nici o asemenea secvenţă, atunci se afişează un
mesaj implicit de eroare şi se opreşte execuţia aplicaţiei.

Dacă Visual Basic găseşte o secvenţă error-handling, execuţia continuă în acea rutină, ca şi cum eroarea ar fi apărut în
procedura care conţine rutina error handling respectivă. Dacă o instrucţiune Resume sau Resume Next este executată
în rutina error handling, execuţia continuă după cum este arătat în tabelul următor.

Instrucţiunea Rezultatul

Resume Apelul la procedura pe care Visual Basic tocmai a cercetat-o în lista de apeluri este reexecutat.
În apelurile considerate mai sus, dacă procedura A are un error handler permis care include o
instrucţiune Resume, Visual Basic reexecută apelul la procedura B.

259
Resume Next Execuţia se întoarce la instrucţiunea care urmează ultimei instrucţiuni executate în acea
procedură. Aceasta este instrucţiunea care urmează apelului la procedura pe care Visual Basic
tocmai a cercetat-o în lista de apeluri.
În lista de apeluri exemplificată, dacă procedura A are un error handler permis care include o
instrucţiune Resume Next, execuţia se întoarce la instrucţiunea de după apelul la procedura B.

De notat că instrucţiunea executată este în procedura unde s-a găsit rutina de tratare a erorilor şi nu în mod necesar în
procedura unde a apărut eroarea. Dacă nu se ţine seama de acest aspect esenţial al tratării erorilor, execuţia poate
părea de neexplicat în momentul apariţiei unei erori. Pentru o verificare mai simplă a codului, se poate trece în modul
break în momentul apariţiei unei erori, după cum este explicat ulterior în acest capitol ("Oprirea tratării erorilor").

Dacă erorile tratate în secvenţa error-handler nu includ eroarea apărută, se poate produce o eroare neanticipată în
procedura care are un error handler permis: procedura poate să bucleze la infinit, în special când error handlerul execută
o instrucţiune Resume. Pentru a preveni o asemenea situaţie, se va utiliza metoda Raise a obiectului Err într-o secvenţă
Case Else (sau similară) din handler. Aceasta generează o eroare din secvenţa de tratare activă, forţând Visual Basic să
caute în lista de apeluri un handler care să se ocupe de eroarea apărută.

Efectul unei căutări regresive în lista de apeluri este greu de prevăzut, deoarece depinde de instrucţiunea Resume sau
Resume Next executată. Trebuie gândit că execuţia nu se reia, în mod necesar, în procedura unde a apărut eroarea, ci
în procedura unde este un error-handler activ.

Indicaţii pentru o tratare complexă a erorilor

La scrierea unei aplicaţii Visual Basic mari, care utilizează diverse module, codul de tratare a erorilor poate fi foarte
complex. Se vor urmări următoarele linii generale:

o În timpul verificării/depanării codului, se va utiliza metoda Raise a obiectului Err pentru a regenera
eroarea în toate secvenţele de eroare pentru cazurile neanticipate. Pe lângă o căutare ierarhică pentru
un handler care să trateze eroarea, Visual Basic va afişa un mesaj de eroare pentru acele erori care nu
sunt tratate în cod. Se pot identifica astfel erori posibile şi care pot fi considerate la o nouă dezvoltare a
aplicaţiei.
o Se va utiliza metoda Clear dacă trebuie să se iniţializeze în mod explicit obiectul Err după tratarea unei
erori. Acest fapt este necesar atunci când se utilizează tratarea pe loc a erorilor cu On Error Resume
Next. Visual Basic apelează automat metoda Clear de fiecare dată când execută orice tip de instrucţiune
Resume, Exit Sub, Exit Function, Exit Property sau orice instrucţiune On Error.
o Dacă nu se doreşte ca altă procedură din lista de apeluri să capteze eroarea, se va utiliza instrucţiunea
Stop pentru a forţa terminarea codului. Instrucţiunea Stop permite examinarea contextului erorii în
mediul de dezvoltare.
o Se va scrie o procedură error handler de siguranţă (fail-safe) sigură care să fie apelată de toate
secvenţele de tratare a erorilor ca ultimă acţiune pentru erorile care nu sunt gestionate. Această
procedură poate efectua o terminare controlată a aplicaţiei prin descărcarea formelor şi salvarea datelor.

Testarea tratării erorilor prin generarea de erori

Simularea erorilor este utilă în timpul verificării aplicaţiei sau când se doreste tratarea unei condiţii particulare ca şi cum ar
fi echivalentă unei erori de execuţie. De exemplu, se scrie un modul care utilizează un obiect definit într-o aplicaţie
externă şi se doreşte ca erorile returnate de acel obiect să fie tratate de restul aplicaţiei precum erorile Visual Basic.

Pentru a testa toate erorile posibile se vor genera erorile prin cod. Această operaţiune implică metoda Raise a obiectului
Err. Metoda are sintaxa

object.Raise number, source, description, helpfile, helpcontext

260
unde

object este obiectul Err.

number este un întreg Long identificând natura erorii. Erorile Visual Basic (atât Visual Basic cât şi definite de utilizator)
sunt în domeniul 0-65535. La stabilirea proprietăţii Number pentru coduri proprii de eroare în module clasă se va adăuga
numărul de cod propriu la constanta vbObjectError. De exemplu, generarea erorii cu numărul 1050 implică atribuirea
valorii vbObjectError + 1050 la proprietatea Number.

source este opţional, şir denumind obiectul sau aplicaţia care generează eroarea. La stabilirea acestei proprietăţi pentru
un obiect se va utiliza project.class. Dacă nu se precizează sursa se utilizează ID-ul proiectului Visual Basic curent.

description este optional, şir care descrie eroarea. În cazul când nu se specifică acest argument se atribuie şirul implicit
pentru o eroare Visual Basic (cum este returnat de funcţia Error) sau "Application-defined or object-defined error" în cazul
unei cod propriu de eroare.

helpfile este optional, calea completă către un fişier Microsoft Windows Help în care se poate găsi ajutor pentru eroarea
generată. Implicit se va utiliza informaţia asociată cu fişierul Visual Basic Help.

helpcontext este optional, ID de context pentru intrarea din fişierul de ajutor. În mod implicit se consideră informaţia unei
erori Visual Basic, dacă există.

În cazul utilizării metodei Raise fără specificarea anumitor argumente iar valorile proprietăţilor obiectului Err conţin valori
care nu au fost curăţate, aceste valori sunt luate în considerare.

Este de menţionat că instrucţiunea Error poate fi utilizată de asemenea pentru generarea de erori, dar obiectul Err
dispune de o informaţie mai bogată. Acest fapt este util în special la crearea modulelor clasă.

Se poate simula orice eroare Visual Basic prin considerarea numărului de cod al erorii respective.

Definirea erorilor proprii

În afara erorilor definite de Visual Basic, utilizatorul poate să definească erori proprii, care să permită identificarea unor
condiţii proprii aplicaţiei proiectate, captarea acestor erori efectuându-se mai departe după procedura generală. Procesul
de definire se realizează prin adăugarea de noi numere de eroare la constanta vbObjectError.

Constanta vbObjectError rezervă numere de la offsetul propriu la suma offsetului cu 512. Utilizând un număr mai mare
decât acesta asigură că numerele proprii de eroare nu intră în conflict cu viitoarele versiuni de Visual Basic.

Pentru a defini numere de eroare proprii se adaugă constante la secţiunea de declaraţii a modulului:

' Error constants


Const gLostCarrier = 1 + vbObjectError + 512
Const gNoDialTone = 2 + vbObjectError + 512

Se poate utiliza ulterior metoda Raise pentru noile numere de eroare, cu utilizarea eventuală a descrierilor proprii de
eroare.

Tratarea inline a erorilor

Atunci când se testează apariţia erorilor imediat după fiecare linie de cod care poate produce erori, se zice că tratarea
erorilor este inline. Utilizând acest mod de tratare a erorilor, se pot scrie funcţii şi instrucţiuni care returnează numerele de
261
eroare apărute; se poate genera o eroare Visual Basic într-o procedură şi gestiona eroarea în procedura apelantă; se
poate scrie o funcţie care să returneze o dată de tip Variant şi utiliza acest rezultat în procedura apelantă.

Returnarea numerelor de eroare

Cea mai simplă metodă de acest gen este crearea unor funcţii şi instrucţiuni care returnează, atunci când apar erori,
numere de eroare (sau constante cu această semnificaţie) în loc de valorile uzuale. De exemplu

Function FileExists (p As String) As Long


If Dir (p) <> "" Then
FileExists = conSuccess
Else
FileExists = conFailure
End If
End Function

care poate fi utilizată prin

Dim ResultValue As long


ResultValue = FileExists ("C:\Testfile.txt")
If ResultValue = conFailure Then
... ' se trateaază eroarea
Else
... ' se procesează fişierul
End If

Lucrul esenţial în tratarea inline a erorilor este testarea apariţiei unei erori imediat după instrucţiunea sau apelul de funcţie
care poate să producă eroarea. În acest mod se poate proiecta un handler care anticipează exact tipul de erori care pot
să apară. Această abordare nu necesită ca o eroare de execuţie să apară efectiv.

Tratarea erorilor în procedura apelantă

Altă metodă pentru a indica apariţia unei erori este să se genereze o eroare Visual Basic în procedură activă şi să se
trateze eroarea într-un handler inline din procedura apelantă.

Exemplul următor arată o variantă a procedurii FileExists în care se generează un număr de eroare în cazul eşecului.
Înaintea apelului funcţiei, instrucţiunea On Error Resume Next stabileşte proprietăţile obiectului Err dar nu precizează o
rutină error-handling.

Instrucţiunea On Error Resume Next este urmată de codul de tratare a erorii. Acesta testează proprietăţile obiectului Err
pentru a vedea dacă a apărut o eroare. Dacă Err.Number nu conţine zero, atunci a apărut o eroare.

Function FileExists (p As String)


If Dir (p) <> "" Then
Err.Raise conSuccess
Else
Err.Raise conFailure
End If
End Function

Dim ResultValue As Long


On Error Resume Next
ResultValue = FileExists ("C:\Testfile.txt")

262
If Err.Number = conFailure Then
... ' se tratează eroarea
Else
... ' se continuă programul
End If

Următorul exemplu, mai complex, utilizează atât valoarea returnată, cât şi un argument pentru a detecta apariţia unei
erori.

Function Power (X As Long, P As Integer, ByRef Rezult As Long) _


As Long
On Error GoTo ErrorHandler
Result = X^P
Exit Function
ErrorHandler:
Power = conFailure
End Function

' Apelul funcţiei Power


Dim lngReturnValue As Long, lngErrorMayBe As Long
lngErrorMayBe = Power (10, 2, lngReturnValue)
If lngErrorMayBe = conFailure Then
... ' tratarea erorii
Else
... ' continuarea programului
End If

Utilizarea datelor de tip Variant

Altă cale pentru a returna informaţii despre erorile eventuale este utilizarea datelor de tip Variant şi funcţiile asociate,
potrivit exemplului următor. O variabilă de tip Variant are un indicator privind tipul de dată conţinută şi acest tag poate fi
fixat ca un cod de eroare Visual Basic.

Function Power (X As Long, P As Integer) As Variant


On Error GoTo ErrorHandler
Result = X^P
Exit Function
ErrorHandler:
Power = CVErr(Err.Number) ' converteşte codul de eroare în tagged Variant
End Function

' Apelul funcţiei Power


Dim varReturnValue As Variant
varReturnValue = Power (10, 2)
If IsError (varReturnValue) Then
... ' tratarea erorii
Else
... ' continuarea programului
End If

Tratarea centralizată a erorilor

Atunci când se adaugă cod de tratare a erorilor la o aplicaţie, tratarea inline produce tratări repetate ale aceloraşi erori.
Codul poate fi redus prin scrierea unor proceduri apelate repetat de secvenţele error handling.

263
Funcţia FileErrors din exemplul următor afişează un mesaj adecvat erorii produse şi, când este posibil, permite
acoperirea erorii. Este returnat procedurii apelante un cod cu acţiunea de urmat. Este de notat că, undeva în program, se
vor defini constantele utilizate.

Function FileErrors () As Integer


Dim intMsgType As Integer, strMsg As String
Dim intResponse As Integer
' Valoarea returnată Înţeles
' 0 Resume
' 1 Resume Next
' 2 Eroare netratabilă
' 3 Eroare necunoscută
intMsgType = vbExclamation
Select Case Err.Number
Case mnErrDeviceUnavailable ' error 68
strMsg = " That device appears unavailable."
intMsgType = vbExclamation + 4
Case mnErrDiskNotReady 'error 71
strMsg = "Insert a disk in the drive and close the door."
Case mnErrDeviceIO 'error 57
strMsg = " Internal disk error."
intMsgType = vbExclamation + 4
Case mnErrDiskFull ' error 61
strMsg = " Disk is full. Continue?"
intMsgType = vbExclamation + 3
Case mnErrBadFileName, mnErrBadFileNameOrNumber ' error 64, 52
strMsg = " That filename is illegal."
Case mnErrPathDoesNotExist ' error 76
strMsg = " That path doesn't exist."
Case mnErrBadFileMode ' error 54
strMsg = " Can't open your file for that type of access."
Case mnErrFileAlreadyOpen ' error 55
strMsg = " This file is already open."
Case mnErrInputPastEndOfFile ' error 62
strMsg = " This file has a nonstandard end-of-file marker,"
strMsg = strMsg & "or an attempt was made to read beyond"
strMsg = strMsg & "the end-of-file marker."
Case Else
FileErrors = 3
Exit Function
End Select
intResponse = MsgBox (strMsg, intMsgType, "Disk Error")
Select Case intResponse
Case 1, 4 ' butoanele OK, Retry
FileErrors = 0
Case 5 ' butonul Ignore
FileErrors = 1
Case 2, 3 ' butoanele Cancel, End
FileErrors = 2
Case Else
FileErrors = 3
End Select
End Function

264
Această procedură tratează erorile comune legate de fişiere şi unitatea de dischetă. Pentru celelalte erori se returnează
valoarea 3. Procedura apelantă va trebui apoi să trateze această eroare, să o genereze încă o dată prin metoda Raise
sau să cheme altă procedură care să trateze eroarea neanticipată.

Inhibarea tratării erorilor

Dacă o capcană de erori a fost permisă într-o procedură, aceasta este scoasă automat la părăsirea procedurii. Sunt
situaţii când este necesară anularea capcanei înainte de părăsirea procedurii gazdă. Acest fapt este realizat de
instrucţiunea On Error GoTo 0. După executarea acestei instrucţiuni, Visual Basic detectează erorile dar nu sunt captate
în procedură. Instrucţiunea poate fi utilizată oriunde, inclusiv în interiorul unei rutine error handler.

Depanarea programelor care au rutine de tratare a erorilor

Atunci când se depanează programe, analiza comportării poate fi complicată în cazul captării erorilor de către rutinele
error handler. Posibilitatea de a transforma în comentarii liniile On Error din fiecare modul simplifică analiza dar este
stânjenitoare.

Este de preferat modalitatea prin care tratarea erorilor este inhibată şi, de fiecare dată când apare o eroare, se intră în
modul break. Pentru aceasta, se va selecta opţiunea Break on All Errors din fişa General a dialogului Options (meniul
Tools). Selectarea acestei opţiuni are ca efect, la apariţia unei erori, intrarea în modul break şi afişarea ferestrei Watch
cu codul care a produs eroarea.

Tratarea erorilor din obiectele referite

În procedurile care fac referinţă la unul sau mai multe obiecte este mult mai dificil să se determine unde apare o eroare,
mai ales dacă eroarea apare într-un obiect al altei aplicaţii. De exemplu, să considerăm o aplicaţie care constă dintr-un
modul formă (MyForm), care face referinţă la un modul clasă (MyClassA), care face referinţă la un obiect Microsoft Excel
Worksheet.

Dacă obiectul Worksheet nu rezolvă o eroare particulară apărută în foaia de calcul ci o regenerează, Visual Basic va
trece eroarea către obiectul care se referă la obiectul Worksheet., adică MyClassA. Visual Basic remapează în mod
automat erorile netratate apărute în obiecte din afara Visual Basic către codul de eroare 440.

Obiectul MyClassA poate fie să trateze eroarea (ceea ce este preferabil), fie să o regenereze. Interfaţa specifică faptul că
orice obiect care regenerează o eroare apărută într-un obiect referit nu poate să propage pur şi simplu eroarea (să
transmită codul de eroare 440), ci trebuie să o remapeze la un număr de eroare cu semnificaţie definită. Acest număr
poate fi un număr Visual Basic (dacă se poate efectua o asemenea echivalare), sau un număr propriu, adăugat după
procedura explicată anterior.

De câte ori este posibil, un modul clasă va trebui să trateze orice eroare care apare în interiorul modulului şi orice eroare
care apr în obiecte referite şi nerezolvate de obiectele însele. Există totuşi erori care nu pot fi tratate din cauză că nu pot fi
anticipate. Există şi cazuri când este mai potrivită o tratare a erorii de către obiectul care face referinţa decât de obiectul
referit.

Atunci când apare o eroare în modulul unei forme, Visual Basic generează unul dintre numerele de eroare predefinite.

Observaţie. Dacă se creează o clasă publică, trebuie ca fiecare secvenţă care tratează o eroare non-Visual Basic să fie
bine documentată. Alţi programatori care se referă la această clasă trebuie să cunoască cum să trateze erorile transmise
de obiectul respectiv.

La regenerarea unei erori, celelalte proprietăţi ale obiectului Err se vor lăsa neschimbate. Dacă eroarea transmisă nu
este tratată, proprietăţile Source şi Description pot fi afişate pentru a ajuta utilizatorul să ia măsuri corective.

265
Tratarea erorilor transmise din obiecte referite

Un modul clasă ar putea să includă următoarea secvenţă pentru tratarea erorilor pe care le poate aborda şi regenerarea
celor care nu pot fi rezolvate. Secvenţa este explicată după prezentarea codului.

MyServerHandler:
Select Case ErrNum
Case 7 ' eroarea out-of-memory
...
Case 440 ' erori din obiecte externe
Err.Raise Number:=vbObjectError + 9999
' eroare din alt obiect Visual Basic
Case Is > vbObjectError And Is < vbObjectError + 65536
ObjectError = ErrNum
Select Case ObjectError
' acest obiect tratează erorile pe baza
' documentaţiei obiectului de unde provine eroarea
Case vbObjectError + 10
...
Case Else
' remaparea erorii ca o eroare obiect generică şi regenerarea ei
Err.Raise Number:=vbObjectError + 9999
End Select
Case Else
' remaparea erorii ca o eroare obiect generică şi regenerarea ei
Err.Raise Number:=vbObjectError + 9999
End Select
Err.Clear
Resume Next

Instrucţiunea Case 440 captează erorile care apar într-un obiect referit extern aplicaţiei Visual Basic. În acest exemplu,
eroarea este propagată utilizând valoarea 9999, deoarece este dificil pentru acest tip de handler central să determine
cauza erorii. Apariţia unei astfel de erori este, de obicei, rezultatul unei erori fatale de automatizare (o eroare care
produce oprirea execuţiei componentei) sau din cauza unui obiect care nu a tratat corect o eroare captată. Eroarea 440
nu ar trebui propagată decât în cazul unei erori fatale. Dacă această secvenţă ar fi scrisă pentru un handler inline (vezi
secţiunea "Tratarea inline a erorilor"), ar fi posibil să se determine cauza erorii şi să se corecteze.

Instrucţiunea Case Is > vbObjectError And Is < vbObjectError + 65536 capteazăerorile care au originea într-un obiect din
aplicaţia Visual Basic, sau din obiectul care conţine handlerul. Numai asemenea obiecte pot produce erori în domeniul
specificat.

Documentaţia pentru codul de eroare oferită pentru obiect trebuie să definească codurile posibile, semnificaţia lor, astfel
încât această porţiune a handlerului să poată fi scrisă adecvat erorilor anticipate. Codurile de eroare efective pot fi
documentate fără offsetul vbObjectError sau pot fi documentate după ce s-a adăugat deplasarea, în care caz
instrucţiunea Case Else trebuie să scadă deplasarea vbObjectError. Pe de altă parte, erorile obiectelor pot fi constante,
arătate în biblioteca de tipuri a obiectului şi vizibile în Object Browser. În acest caz se utilizează constanta de eroare în
Case Else şi nu codul de eroare.

Orice eroare care nu este tratată trebuie să fie regenerată cu un nou număr, după cum este în instrucţiunea Case Else.
În aplicaţia proprie se poate proiecta un handler care să anticipeze acest nou număr definit. Dacă aplicaţia este o clasă
publică, trebuie să fie inclusă în documentaţie o explicaţie a acestei noi erori.

Ultima instrucţiune Case Else captează şi regenerează orice altă eroare care nu a fost tratată anterior. Deoarece această
parte a capcanei va prinde erori care au sau nu adăugată deplasarea vbObjectError, remaparea se va efectua simplu

266
către un cod generic "unresolved error". Acest cod se va adăuga la vbObjectError indicând oricărui handler că această
eroare provine dintr-un obiect referit.

Depanarea tratării erorilor din obiecte referite

Deoarece depanarea aplicaţiilor care se referă la obiecte create în Visual Basic sau la clase definită în module clasă este
dificilă, se recomandă selectarea opţiunii Break in Class Module din fişa General a dialogului Options (meniul Tools).
Cu această opţiune selectată, orice eroare dintr-un modul clasă duce la intrarea clasei în modul break a debuggerului,
permiţând analiza erorii.

Depanarea programelor

Tehnicile de depanare prezentate în acest capitol utilizează uneltele de analiză oferite de Visual Basic. Mediul de
dezvoltare Visual Basic nu poate să identifice sau să fixeze erorile, dar oferă unelte pentru a analiza fluxul execuţiei şi
cum se schimbă valorile variabilelor şi proprietăţilor. Se poate considera că uneltele de depanare ajută la examinarea
aplicaţiei pentru a înţelege ce se întâmplă şi de ce.

Uneltele de depanare oferite de Visual Basic includ puncte de oprire (breakpoints), expresii de oprire (break expressions),
expresii de urmărire (watch expressions), executarea codului pas cu pas (instrucţiune cu instrucţiune sau procedură cu
procedură) şi afişarea valorilor variabilelor şi proprietăţilor. Sunt oferite de asemenea posibilităţi speciale cum ar fi
editarea codului şi continuarea execuţiei (edit-and-continue), stabilirea următoarei instrucţiuni care să se execute după o
eroare şi testarea cu aplicaţia în modul break.

Tipuri de erori

Există trei tipuri de erori care se pot intâlni într-un program.


Erori de compilare. Acestea rezultă din scrierea incorectă a codului. Aceste erori sunt detectate de Visual Basic la
compilarea codului.
Erori de execuţie. Acestea apar în timpul execuţiei aplicaţiei (şi sunt detectate de Visual Basic) atunci când o instrucţiune
încearcă să efectueze o operaţiune imposibilă (de genul împărţirii prin zero).
Erori de logică. Acestea apar atunci când aplicaţia nu se execută în modul gândit la proiectare. O aplicaţie poate să fie
corctă sintactic, să se execute fără a efectua operaţiuni imposibile şi totuşi să producă rezultate incorecte. Doar
testarea aplicaţiei şi analiza rezultatelor poate spune că aplicaţia funcţionează corect.

Unelte de depanare

Nu există artificii magice pentru depanare şi nu există o secvenţă fixă de operaţiuni care să lucreze întotdeauna. În
esenţă, ajutorul oferit în depanare este pentru o mai bună înţelegere a mersului aplicaţiei. Se poate astfel fotografia
starea aplicaţiei la un moment dat, instantaneul obţinut cuprinzând valori ale variabilelor, expresiilor şi proprietăţilor,
precum şi numele apelurilor active de proceduri.

Bara de unelte Debug Imaginea alăturată arată bara de unelte Debug din mediul Visual Basic Editor.

267
În tabelul următor se explică pe scurt funcţionalitatea uneltelor principale din această bară.

Unealta de depanare Scop

Run/Continue Comută din modul design în modul run (Run) sau din modul break în modul run (Continue).

Break Comută din run time în modul break.

Reset Comută din run time sau modul break în modul design.

Toggle Breakpoint Defineşte o linie într-un modul, unde Visual Basic suspendă execuţia aplicaţiei.

Step Into Execută următoarea linie executabilă din aplicaţie şi intră în proceduri.

Step Over Execută următoarea linie executabilă din aplicaţie dar nu intră în proceduri.

Step Out Execută restul de cod din procedura curentă şi se opreste la linia următoare din procedura
apelantă.

Locals Window Afişează valoarea curentă a variabilelor locale.

Immediate Window Permite executarea de cod sau interogarea unei valori în timp ce aplicaţia este în break mode.

Watch Window Afişează valorile unor expresii selectate.

Quick Watch Listează valoarea curentă a unei expresii în timp ce aplicaţia este în modul break.

Call Stack În timp ce aplicaţia este în modul break, afişează o cutie de diaolg care arată toate procedurile
care au fost apelate dar încă nu s-au executat complet.

Secţiunile următoare aduc explicaţii suplimentare asupra modului de utilizare efectivă a acestor unelte.

Evitarea "bug"-urilor

Respectarea următoarelor reguli poate conduce la evitarea introducerii unor bug-uri în aplicaţie.

o Aplicaţia se proiectează cu atenţie prin notarea evenimentelor importante şi a modului în care codul va
răspunde la fiecare eveniment. Fiecare procedură generală, ca şi fiecare procedură eveniment trebuie să
aibă un scop specific, bine definit.
o Se vor include cât mai multe comentarii. La întoarcerea în cod şi analiza comportării aplicaţiei,
comentariile privind scopul fiecărei rutine sunt de un real ajutor.
o Se vor utiliza, pe cât posibil, referinţe explicite. Variabilele obiect se declară după cum sunt listate
obiectele în cutia Classes din Object Browser şi nu prin tipuri Variant sau Object.
o Se va dezvolta sau adapta o schemă consistentă de construcţie a denumirilor pentru variabilele şi
obiectele din aplicaţie.
o Se va utiliza declaraţia Option Explicit pentru a ocoli erorile de tastare a identificatorilor şi confundarea
unui control cu altul.

Design Time, Run Time şi Break Mode

Se utilizează Visual Basic în design time pentru a crea o aplicaţie şi în run time pentru a o executa. În break mode
execuţia programului este suspendată astfel încât se pot examina şi modifica date. Bara de titlu Visual Basic arată
întotdeauna modul utilizat curent.

268
Caracteristicile celor trei moduri şi tehnicile pentru comutarea între ele sunt listate în următorul tabel.

Mod Descriere

Design time Lucrul la crearea unei aplicaţii se execută în acest mod. Se pot proiecta formulare, trasa controale, scrie
cod etc. Nu se poate executa cod sau utiliza unelte de depanare, cu excepţia stabilirii de puncte de oprire
şi creării de expresii de urmărire.
Pentru a trece la run time click pe butonul Run. Pentru trecerea în break mode click pe Step Into din
meniul meniul Run şi aplicaţia intră în modul break la prima instrucţiune executabilă.

Run time În timpul execuţiei, când aplicaţia are controlul, se interacţionează cu aplicaţia ca orice alt utilizator. Se
poate vedea codul dar nu se poate schimba.
Pentru a trece în design time se acţionează butonul Reset iar pentru a trece în break mode click pe
butonul Break.

Break mode Execuţia este suspendată în timpul rulării aplicaţiei. Se poate vedea şi edita codul, examina sau modifica
date, reporni aplicaţia, sfârşi execuţia sau continua din punctul de oprire.
Pentru comutarea în run time, click pe butonul Continue (acelaşi cu Run). Trecerea în design time se
obţine prin butonul Reset.
Se poat fixa puncte de oprire şi expresii de urmărit în design time, dar celelalte unelte de depanare
lucrează doar în modul break.

Utilizarea ferestrelor de depanare

Cu ajutorul ferestrelor de depanare se pot monitoriza valorile expresiilor şi variabilelor în timp ce se parcurg instrucţiunile
aplicaţiei. Există trei ferestre de depanare: Immediate, Watch şi Locals. Pentru afişarea oricăreia dintre aceste ferestre
se activează comanda corespunzătoare din meniul View sau butonul corespunzător de pe bara Debug.

Fereastra Immediate arată informaţia care rezultă din instrucţiunile de depanare din cod sau care este cerută prin
instrucţiuni scrise direct în fereastră.

Fereastra Watch arată valorile curente ale expresiilor urmărite (watch expressions), acelea pentru care s-a hotărât
monitorizarea. O expresie de oprire (break expression) este o expresie santinelă care produce intrarea Visual Basic în
modul break atunci când o anumită condiţie definită devine adevărată. În fereastra Watch, coloana Context indică
procedura, modulul, sau modulele în care fiecare expresie santinelă este evaluată. Fereastra Watch poate afişa o
valoare pentru o expresie urmărită numai dacă instrucţiunea curentă este în contextul specificat; în caz contrar, coloana
Value afişeazăun mesaj indicând că instrucţiunea nu este în context.

Fereastra Locals arată valorile oricărei variabile din domeniul procedurii curente. După cum execuţia trece din procedură
în procedură, conţinutul ferestrei Locals se modifică pentru a reflecta doar variabilele aplicabile procedurii curente. O
variabilă care reprezintă un obiect apare în fereastra Locals cu un semn plus (+) în stânga numelui său. Se poate
efectua click pe semn pentru a expanda variabila, afişa proprietăţile obiectului şi valorile curente. Dacă o proprietate a
obiectului conţine un alt obiect, acesta poate fi expandat de asemenea. Aceeaşi examinare se poate aplica pentru
variabilele care conţin tablouri sau tipuri definite de utilizator.

Utilizarea modului break

În design time se poate schimba aspectul sau codul aplicaţiei, dar nu se pot vedea efectele schimbărilor. În run time se
poate urmări cum se comportă aplicaţia, dar nu se poate interveni direct în cod.

Modul Break opreşte execuţia aplicaţiei şi oferă un instantaneu al condiţiilor în orice moment. Variabilele şi valorile
proprietăţilor sunt păstrate, astfel încât se poate analiza starea curentă a aplicaţiei şi introduce modificări care afectează
execuţia aplicaţiei. Când aplicaţia este în modul break se pot efectua următoarele acţiuni:
269
o Modificarea codului aplicaţiei.
o Observarea stării interfeţei.
o Determinarea apelurilor procedurilor.
o Urmărirea valorilor variabilelor, proprietăţilor şi instrucţiunilor.
o Schimbarea valorilor variabilelor şi proprietăţilor.
o Controlarea fluxului execuţiei prin aflarea/stabilirea instrucţiunii următoare.
o Execuţia imediată a unor instrucţiuni Visual Basic.
o Controlarea manuală a operării aplicaţiei.

Intrarea în modul break la o instrucţiune cu probleme

În timpul depanării unui program este uneori de dorit oprirea aplicaţiei în acel loc din cod unde se bănuieşte existenţa
unei probleme. Acesta este unul dintre motivele pentru care Visual Basic prevede puncte de oprire şi instrucţiuni Stop.
Un punct de oprire (breakpoint) defineşte o instrucţiune sau o mulţime de condiţii unde Visual Basic opreşte execuţia în
mod automat şi trece aplicaţia în modul break fără a executa instrucţiunea care conţine punctul de oprire.

Se poate intra în modul break şi manual, prin oricare dintre acţiunile

o CTRL+BREAK
o Comanda Break din meniul Run
o Butonul Break de pe bara de unelte Debug.

Este posibil să se oprească execuţia atunci când aplicaţia nu are de lucru (idle - este între procesarea unor evenimente).
Când se întâmplă acest fapt, execuţia nu se opreşte la o linie specifică, dar Visual Basic comută oricum la modul break.

Se poate intra automat în modul break automat atunci când se întâmplă oricare dintre următoarele condiţii:

o O instrucţiune generează o eroare de execuţie netratată.


o O instrucţiune generează o eroare de execuţie şi a fost selectat Break on All Errors în fişa General
(meniul Tools).
o O expresie de oprire definită în dialogul Add Watch s-a modificat sau a devenit True, după cum a fost
definită.
o Execuţia atinge o linie cu un punct de oprire.
o Execuţia atinge o instrucţiune Stop.

Fixarea unei erori run-time şi continuare

Anumite erori din execuţie rezultă din neglijenţa cu care este scris codul. Aceste erori pot fi corectate uşor prin declararea
variabilelor, modificarea denumirilor etc. După o asemenea corectură programul poate continua chiar din linia unde s-a
oprit. Acest fapt se realizează prin acţionarea comenzii Continue (meniul Run) sau butonul Continue. La continuarea
aplicaţiei se poate verifica fixarea erorii.

Dacă se selectează opţiunea Break on All Errors, Visual Basic inhibă tratarea erorilor din cod, încât la orice eroare
semnalată se intră în modul break. Erorile vor fi captate de secvenţele de tratare doar dacă opţiunea Break on All Errors
nu este selectată.

Anumite erori, cum ar fi schimbarea declaraţiilor de variabile, adăugarea unor noi variabile etc., necesită repornirea
aplicaţiei. În acest caz Visual Basic prezintă un mesaj care lasă repornirea aplicaţiei la voia utilizatorului.

Monitorizarea datelor prin expresii de urmărire

Atunci când un calcul nu produce rezultatul aşteptat sau apar probleme când o anumită proprietate sau variabilă ia o
valoare particulară, este de interes să se poată identifica momentul în care o expresie îşi schimbă sau atinge o valoare.
270
Visual Basic monitorizează în mod automat expresiile definite de utilizator drept expresii santinelă (de urmărit). La
trecerea aplicaţiei în modul break, aceste expresii apar în fereastra Watch.

Se poate de asemenea instrui o expresie urmărită să treacă aplicaţia în modul break atunci valoarea ei se modifică sau
devine True (pentru condiţii). Acest mod de operare reduce, de obicei, parcurgerea pas cu pas a proiectului până când se
atinge o anumită condiţie (de exemplu, o variabilă de ciclare ajunge la o anumită valoare, sau un indicator dintr-o
procedură este modificat).

Adăugarea, editarea sau eliminarea unei expresii urmărite

Toate operaţiunile din titlu se pot efectua atât în design time, cât şi în modul break. Pentru a adăuga o expresie santinelă
se utilizează dialogul Add Watch afişat din meniul Debug.

Se utilizează dialogul Edit Watch, afişat tot din meniul Debug, pentru modificarea sau eliminarea unei expresii definite.
Cele două dialoguri, Add Watch şi Edit Watch, au aceeaşi structură de controale cu excepţia butonului Delete care
apare doar în dialogul Edit Watch.

Componentele comune celor două dialoguri sunt prezentate în tabelul următor.

Componenta Descriere

Zona text Expression Conţine expresia pe care expresia urmărită o eveluează. Această expresie este o
variabilă, o proprietate, un apel de funcţie sau orice altă expresie validă. În dialogul Add
Watch această boxă de text conţine expresia curentă (dacă există).

Grupul de opţiuni Context Stabileşte domeniul variabilelor urmărite în expresie. Se va completa atunci când există
variabile sinonime cu domenii diferite. Se poate restrânge domeniul la o procedură
specifică sau la un modul anumit, sau se poate extinde la întreaga aplicaţie prin
selectarea intrărilor All Procedures şi All Modules. Visual Basic poate evalua mai uşor o
variabilă într-un context restrâns.

Grupul de opţiuni Watch Type Stabileşte cum răspunde Visual Basic la expresia urmărită:
- urmăreşte expresia şi afişează valoarea în fereastra Watch atunci când aplicaţia intră
în modul break;
- aplicaţia intră în modul break automat atunci când se modifică valoarea expresiei sau
când aceasta devine True.

Observaţie. Se poate adăuga o expresie urmărită prin tragerea expresiei dintr-un modul în fereastra Watch.

Utilizarea urmăririi rapide

Când aplicaţia este în modul break, se poate verifica valoarea unei proprietăţi, variabile sau expresii pentru care nu s-a
definit în prealabil o expresie de urmărire. Se foloseşte în acest scop dialogul Quick Watch (din meniul Debug sau de pe
bara sinonimă). Dialogul arată valoarea expresiei selectate înrtr-un modul. Pentru a continua urmărirea acestei expresii,
se acţionează butonul Add (inhibat dacă operaţiunea de urmărire nu este posibilă); fereastra Watch este afişată etc.

Utilizarea unui punct de oprire

În execuţie, un punct de oprire (breakpoint) produce oprirea execuţiei programului exact înaintea unei linii specifice de
cod. Atunci Visual Basic execută o procedură şi se ajunge la o linie de cod care are fixat un punct de oprire, atunci
aplicaţia este trecută în modul break.

271
Se poate stabili sau anula un punct de oprire în modul break, în design time sau în run time dacă aplicaţia este inactivă
(idle). Pentru a fixa un punct de oprire se efectuează un click pe marginea din stânga ferestrei modulului, în dreptul
instrucţiunii (vezi figura de mai sus). Instrucţiunea astfel marcată este colorată potrivit culorii specificate în dialogul
Options (meniul Tools), fişa Editor Format. Prin click pe indicatorul de breakpoint se anulează punctul de oprire
respectiv.

Se remarcă în figura anterioară că instrucţiunea curentă este şi ea marcată prin culoare şi un indicator pe latura din
stânga a ferestrei de cod. Atunci când se atinge un punct de oprire şi aplicaţia este oprită, se poate examina starea
curentă a aplicaţiei, focusul putând fi mutat între forme, module, ferestrele de depanare.

Aplicaţia este oprită exact înaintea executării liniei care conţine punctul de oprire. Dacă se doreşte observarea efectului
executării acestei instrucţiunii se va acţiona Step Into sau Step Over.

Pentru izolarea unei probleme reamintim că o instrucţiune poate să contribuie indirect la eroare datorită atribuirii unor
valori incorecte. Examinarea valorilor variabilelor şi proprietăţilor se efectuează în modul break prin ferestrele Locals,
Quick Watch, expresii urmărite şi fereastra Immediate.

Utilizarea instrucţiunii Stop

O alternativă la fixarea unui punct de oprire este plasarea unei instrucţiuni Stop. La întâlnirea unei instrucţiuni Stop,
Visual Basic opreşte execuţia şi comută în modul break. Deşi Stop acţionează ca un breakpoint, instrucţiunea nu poate fi
fixată sau inhibată în acelaşi mod.

Reamintim că o instrucţiune Stop opreşte doar temporar execuţia în timp ce o instrucţiune End opreşte execuţia,
reiniţializează variabilele şi produce întoarcerea la modul design. O aplicaţie oprită prin Stop poate fi continuată prin
Continue din meniul Run.

Executarea unor secvenţe de cod selectate

Dacă se poate identifica instrucţiunea care a cauzat eroarea, un singur breakpoint poate localiza problema ivită. Este mai
frecventă situaţia în care o întreagă secvenţă de cod este bănuită că produce execuţia incorectă a aplicaţiei. În acest caz,
un breakpoint izolează zona de cod şi se parcurge apoi întreaga porţiune pas cu pas prin Step Into şi Step Over. Dacă
este necesar, se poate de asemenea sări peste instrucţiuni sau reîntoarce execuţia la o nouă linie.

Pentru comenzile descrise în tabelul următor trebuie ca aplicaţia să fie în modul break.

Modul de parcurgere Descriere

Step Into Execută instrucţiunea curentă şi se opreşte la următoarea linie, chiar dacă ea este în altă
procedură.

Step Over Execută întreaga procedură apelată de linia curentă şi se opreşte la linia următoare liniei curente.

Step Out Execută restul procedurii curente şi se opreşte la instrucţiunea următoare celei care a apelat
procedura curentă.

272
Utilizarea comenzii Step Into

Se utilizează Step Into pentru a executa o singură instrucţiune. Visual Basic trece temporar în run time, execută
instrucţiunea curentă şi avansează la următoarea instrucţiune, revine în modul break. Pentru acest tip de operaţiune se
acţionează butonul Step Into din bara Debug.

În cazul scrierii mai multor instrucţiuni pe o aceeaşi linie, Visual Basic le va considera separat (punctele de oprire apar
doar la prima instrucţiune din linie).

Utilizarea comenzii Step Over

Comanda Step Over se aplică tot instrucţiunii curente, dar aceasta trebuie să conţină un apel la o procedură. Dacă prin
comanda Step Into s-ar trece în procedură pas cu pas, prin Step Over procedura este executată ca o unitate şi se trece
apoi la instrucţiunea următoare în procedura curentă. Pentru acest tip de operaţiune se acţionează butonul Step Over din
bara Debug.

Acest tip de acţiune este util atunci când procedura apelată este verificată. Totuşi, dacă în procedura apelată există o
instrucţiune Stop sau este definit un punct de oprire, atunci execuţia este stopată în acele locuri.

Utilizarea comenzii Step Out

Prin comanda Step Out se măreşte viteza de parcurgere a secvenţelor de cod în sensul că dacă se ştie că restul
instrucţiunilor dintr-o procedură nu pot crea probleme, atunci ele pot fi executate în bloc şi nu pas cu pas. Se revine în
procedura apelantă, la instrucţiunea următoare apelului. Pentru acest tip de operaţiune se acţionează butonul Step Out
din bara Debug.

Trecerea peste secţiuni de cod

În modul break se poate selecta o instrucţiune oarecare, mai departe pe firul execuţiei, şi click pe Run To Cursor din
meniul Debug permite reluarea execuţiei din punctul selectat. Se pot astfel sări secvenţe neinteresante de cod.

Stabilirea instrucţiunii următoare

O acţiune similară celei descrise în secţiunea anterioară este selectarea unei instrucţiuni oriunde în procedura curentă şi
click Set Next Statement din meniul Debug. Se pot astfel urmări doar anumite fire de execuţie sau se pot reexecuta
anumite secvenţe pentru alte valori date variabilelor/proprietăţilor.

Indicarea instrucţiunii următoare

Prin click pe Show Next Statement din meniul Debug se plasează punctul de inserţie în linia care urmează a fi
executată. Este o modalitate utilă mai ales când se depanează o secvenţă error handler şi nu se ştie exact care este
următoarea instrucţiune. Comanda este disponibilă doar în modul break.

Monitorizarea listei de apeluri (Call Stack)

Dialogul Call Stack, afişat prin meniul/bara de unelte Debug, arată o listă a apelurilor active de proceduri. Dialogul poate
fi afişat doar în modul break. Apelurile active sunt cele care au iniţiat proceduri care nu au fost complet executate. Prin
lista afişată se poate trasa ordinea de apeluri care au dus la instrucţiunea curentă. Cu cât asemenea lanţuri de apeluri
sunt mai lungi, cu atât depanarea aplicaţiei este mai dificilă.

În lista din dialogul Call Stack toate apelurile active sunt prezentate într-o serie de apeluri înlănţuite. Ea plasează cea mai
timpurie procedură apelată la baza listei şi adaugă apelurile următoare în topul listei. Informaţia dată pentru fiecare

273
procedură începe cu numele modulului, urmat de numele procedurii. Prin butonul Show din dialog se afişează
instrucţiunea dintr-o procedură care trece controlul aplicaţiei către următoarea procedură din listă.

Observaţie. Deoarece dialogul Call Stack nu indică variabila asignată unei instanţe a unei clase, nu se poate distinge
între instanţe multiple ale claselor.

Testarea datelor şi procedurilor cu fereastra Immediate

În procesul de depanare sau de experimentare a unei aplicaţii, este adesea necesar să se execute proceduri individuale,
să se evalueze expresii sau să se atribuie noi valori variabilelor sau proprietăţilor. Toate aceste acţiuni pot fi executate din
fereastra Immediate. Expresiile sunt evaluate şi rezultatele sunt tipărite în fereastra Immediate.

Tipărirea informaţiilor în fereastra Immediate

Există două metode pentru tipărirea în fereastra Immediate

• Includerea unor instrucţiuni Debug.Print în codul aplicaţiei,


• Introducerea direct în fereastra Immediate a instrucţiunilor care utilizează metoda Print.

Aceste tehnici oferă următoarele avantaje în raport cu utilizarea expresiilor urmărite:

• Aplicaţia nu trebuie oprită pentru a obţine informaţii. Datele şi mesajele sunt afişate pe măsură ce aplicaţia se
execută.
• Informaţiile sunt afişate într-o fereastră separată (Immediate), încât nu se interferează cu ieşirea văzută de
utilizatori.

Tipărirea din codul aplicaţiei

Metoda Print trimite ieşirea către fereastra Immediate atunci când se include calificarea cu obiectul Debug. De exemplu

Debug.Print "Salary = "; Salary

Această tehnică lucrează cel mai bine atunci când există un loc particular în aplicaţie în care variabila urmărită (aici
Salary) se modifică. De exemplu, instrucţiunea anterioară poate aparţine unei structuri repetitive.

Tipărirea din fereastra Immediate

Dacă aplicaţia este în modul break, se poate muta focalizarea în fereastra Immediate pentru a examina date. Aici se pot
evalua expresii valide, inclusiv expresii care se referă la proprietăţi. Modulul activ curent determină domeniul de referinţă.

Orice instrucţiune care utilizează metoda Print poate fi înscrisă şi la terminarea cu ENTER se va evalua expresia şi se va
afişa rezultatul. Un semn de întrebare (?) poate înlocui metoda Print:

? ActiveDocument.Name

executată din Microsoft Word, afişează în fereastra Immediate numele documentului Word activ.

Atribuirea de valori

În modul break, se pot atribui valori la proprietăţi şi variabile. Următorul exemplu prezintă o schemă de utilizare a ferestrei
Immediate pentru calcule. Fiecare linie (cu excepţia celor care afişează rezultatele) se va termina cu ENTER:

274
x=2
? x+3
5
y=3
? x*y
6

Se poate modifica valoarea unei proprietăţi sau a unei variabile din proiect şi relua apoi executarea aplicaţiei. Dacă
Option Explicit este prezentă în modulul curent, toate variabilele invocate în fereastra Immediate trebuie să fie declarate
în modul. Domeniul se aplică apelurilor de proceduri ca şi variabilelor.

Testarea procedurilor cu fereastra Immediate

În fereastra Immediate se poate evalua orice instrucţiune executabilă validă Visual Basic, dar nu se acceptă declaraţii de
date. Se pot utiliza apeluri la proceduri care permit astfel testarea procedurii cu diverse seturi de argumente.

X = Quadratic(2,8,8)
DisplayGraph 50, Arr1
Form_MouseDown 1,0,100,100

La apăsarea tastei ENTER, Visual Basic comută la run time pentru a executa instrucţiunea şi se întoarce apoi în modul
break. În acest moment se pot vedea rezultatele şi efectele asupra variabilelor şi proprietăţilor.

Se poate apela orice procedură din forma activă curent, ca şi orice procedură dintr-un modul, cu excepţia cazului în care
procedura este Private, caz în care se poate apela doar în timpul executării modulului.

O procedură poate fi executată în mod repetat, fiecare apel este menţinut de Visual Basic ca o instanţă separată.
Aceasta permite testarea separată a diferitelor seturi de argumente. Dialogul Call Stack menţine o listă a procedurilor
executate de fiecare comandă din fereastra Immediate. Se poate prin urmare utiliza Call Stack pentru a selecta orice
instanţă a procedurii şi afişa apoi valorile variabilelor din procedură.

Observaţie. Deşi cele mai multe instrucţiuni sunt suportate de fereastra Immediate, o structură de control este permisă
doar dacă poate fi exprimată complet pe o linie: se utilizează caracterul ":" pentru separarea instrucţiunilor care alcătuiesc
structura de control.

Verificarea numerelor de eroare

Se poate utiliza fereastra Immediate pentru a afişa mesajul asociat cu un număr specific de eroare. De exemplu, tastarea
instrucţiunii

Error 58

produce o casetă cu mesajul asociat erorii

File already exists

Trucuri utile în fereastra Immediate

o După introducerea unei instrucţiuni, aceasta se poate reexecuta prin mutarea punctului de inserţie înapoi
în instrucţiune şi ENTER.
o Înainte de ENTER se poate edita instrucţiunea curentă.

275
o Se poate utiliza mouse-ul sau săgeţile pentru a naviga în fereastra Immediate. Nu se apasă ENTER
decât pe instrucţiunea care se execută.
o CTRL+HOME mută punctul de inserţie la linia de început a ferestrei; CTRL+END îl mută la ultima linie.
o Tastele HOME şi END mută punctul de inserţie la începutul şi, respectiv, sfârşitul liniei curente.

Consideraţii speciale

Anumite evenimente care sunt o parte comună cu utilizarea Microsoft Windows pot să ridice probleme speciale pentru
depanarea unei aplicaţii. Este important să fim conştienţi de aceste probleme pentru a nu complica procesul de
depanare.

Dacă rămânem conştienţi de modul în care modul break poate pune evenimentele în dezacord cu ceea ce aplicaţia
aşteaptă, avem o şansă să găsim soluţii. În anumite proceduri de evenimente, trebuie săutilizăm instrucţiuni Debug.Print
pentru a monitoriza valorile variabilelor/proprietăţilor în loc să utilizăm expresii santinelă sau puncte de oprire.

Oprirea execuţiei în procedurile evenimentelor MouseDown sau KeyDown

Dacă se opreşte execuţia în timpul unei proceduri eveniment MouseDown, se poate lăsa butonul mouse-ului sau utiliza
mouse-ul pentru alte taskuri. Când se continuă execuţia, totuşi, aplicaţia presupune că butonul mouse-ului este încă
apăsat. Nu se va obţine evenimentul MouseUp până când nu se apasă din nou butonul mouse-ului şi apoi se eliberează.

Când se apasă butonul mouse-ului în run time, se opreşte execuţia în evenimentul MouseDown dacă aici este un
breakpoint. În acest scenariu nu se va obţine niciodată evenimentul MouseUp. Soluţia este eliminarea breakpoint-ului din
procedura MouseDown.

Dacă execuţia se opreşte în timpul procedurii KeyDown, se aplică din nou consideraţiile anterioare. Dacă există un
breakpoint în procedura evenimentului KeyDown, nu se va obţine niciodată evenimentul KeyUp.

Oprirea execuţiei în procedurile evenimentelor GotFocus şi LostFocus

Dacă se opreşte execuţia în procedurile evenimentelor GotFocus sau LostFocus, temporizarea sistemului de mesaje
poate cauza rezultate inconsistente. Pentru aceasta se vor utiliza instrucţiuni Debug.Print în locul punctelor de oprire din
procedurile care tratează evenimentele GotFocus şi LostFocus.

Distribuirea soluţiilor Microsoft Excel 97, Word 97 şi PowerPoint 97

În acest capitol se discută probleme privind distribuirea soluţiilor dezvoltate pentru Microsoft Excel 97, Word 97 şi
PowerPoint 97. Pe lângă modul efectiv de distribuire sunt reamintite şi operaţiuni preparatorii cum ar fi protejarea codului,
erori posibile etc.

Pregătirea soluţiei pentru distribuire

În momentul în care s-a închegat o soluţie trebuie să se ia o serie de decizii în vederea distribuirii soluţiei. Prima decizie
este cum să se împacheteze proiectul: ca un simplu document sau ca un add-in (sau template în Word).

Dacă se decide distribuirea ca un add-in, este important să se decidă cum şi când se va încărca: automat sau la cerere.

În sfârşit, trebuie să se decidă asupra modului de protejare a codului şi, evident, asupra unei ultime verificări în ceea ce
priveşte corectitudinea codului (de obicei ultimul bug apare chiar înainte de punctul final al proiectului).

Alegerea modului de împachetare a soluţiei

276
Atunci când se ascrie o soluţie în Visual Basic for Applications, se obţine un proiect asociat unui document. La distribuirea
soluţiei trebuie să se decidă dacă utilizatorul trebuie să aibă acces la document şi codul asociat sau numai la cod.

Dacă se doreşte accesul atât la document cât şi la cod, se va distribui documentul – adică document Word, caiet Excel
sau prezentare PowerPoint. Acest caz este frecvent la scrierea unei soluţii verticale – o soluţie foarte specifică pentru un
utilizator foarte specific. De exemplu, dacă se creează în Microsoft Word un formular de testare a performanţei, atunci
atât documentul cât şi codul care îl automatizează trebuie să fie accesibil utilizatorului.

Dacă, pe de altă parte, se doreşte ca numai codul (proiectul) să fie accesibil, atunci se va distribui ca un add-in (Microsoft
Excel şi PowerPoint) sau ca un template global (Word).

Observaţie. Utilizatorii nu au acces la foile de calcul dintr-un add-in deoarece acestea sunt ascunse automat la crearea
unui add-in dintr-un caiet. În mod similar, atunci când o prezentare PowerPoint este organizată ca un add-in, slide-urile
sale sunt eliminate automat. Pentru o discuţie suplimentară se va citi secţiunea "Salvarea soluţiei ca un Add-in sau Global
Template".

Se poate interzice accesul utilizatorului la documentul asociat proiectului, fie din cauză că documentul nu este pentru
utilizator, fie pentru că el conţine date pe care utilizatorul nu trebuie să le modifice sau să le vadă. Acesta este cazul când
soluţia conţine proceduri care extind şi adaptează setul de opţiuni ale aplicaţiei – proceduri care sunt proiectate să aibă o
largă aplicabilitate, independente de un document specific. De exemplu, dacă se scriu proceduri care automatizează
sarcini de formatare a foilor de calcul, utilizatorul trebuie să aibă acces la aceste proceduri din orice caiet deschis, dar nu
trebuie să acceseze caietul asociat proiectului.

La distribuirea soluţiei ca un add-in sau template trebuie să se decidă separat dacă se va proteja codul proiectului.

Controlul încărcării unui Add-in sau Global Template

Dacă se decide distribuirea soluţiei proprii ca un add-in sau template, este normal să se decidă momentul încărcării
acestuia. Utilizatorul poate întotdeauna să încarce un add-in utilizând dialogul Template and Add-Ins sau Add-Ins
(meniul Tools), dar nu aceasta este soluţia cea mai bună. Sa alternativă se poate stabili ca un add-in sau template global
să se încarce automat la pornirea aplicaţiei. Sau, pentru a nu încetini pornirea aplicaţiei, se poate alege încărcarea ca
răspuns la un eveniment anumit sau prin alegerea unei comenzi. În sfârşit, se poate încărca un add-in sau un template
global în mod programatic.

Încărcarea unui Add-In sau Global Template la start

Posibilităţile unui add-in devin accesibile unui utilizator doar după ce add-in-ul este încărcat. De exemplu, când un
template global este încărcat, Word mixează meniurile, barele de unelte, intrările AutoText şi macrourile din template cu
meniul Word. Din acest motiv se poate intenţiona ca încărcarea add-inului sau a template-ului să aibă loc la activarea
aplicaţiei Word, Excel sau PowerPoint.

Pentru a încărca add-inuri sau template-uri în mod automat la pornirea aplciaţiei, trebuie să se palseze în folderul Office
Startup, localizat de obicei pe calea "Program Files\Microsoft Office\ Office\Startup".

În Microsoft Excel se poate de asemenea palsa un add-in în folderul Xlstart sau în folderul desemnat ca un folder de
pornire alternativ. Acest fapt se realizează prin atribuirea unei căi şi a unui nume de folder la cheia

HKEY_CURRENT_USER\Software\Microsoft\Office\8.0\Excel\Microsoft Excel\AltStartup

din Windows registry.

Încărcarea automată a unui Add-In în Microsoft Excel prin comanda OPEN din Windows Registry

277
În plus faţă de memorarea unui add-in într-unul dintre folderele de pornire (vezi secţiuena precedentă), se poate utiliza
comanda OPEN din Windows Registry pentru a specifica fişierele addÎn care se încarcă automat la pornirea aplicaţiei
Excel.

Trebuie să se creeze câte o comandă OPEN în cheia de registru

HKEY_CURRENT_USER\Software\Microsoft\Office\8.0\Excel\Microsoft Excel

pentru fiecare fişier add-in. Pentru cazul mai multor fişiere se utilizează OPEN pentru primul fişier, OPEN1 pentru al
doilea, OPEN2 pentru al treilea etc.

Sintaxa pentru comanda OPEN este

OPEN =[ /Switch] pathandfilename

unde

/Switch poate fi /R sau /F. Comutatorul /R deschide fişierul read-only iar /F este utilizat pentru a cere încărcarea caietelor.
Microsoft Excel citeste doar atâta informaţie dintr-un workbook câtă este necesară pentru referirea funcţiilor utilizator. Un
exemplu este

HKEY_CURRENT_USER\Software\Microsoft\Office\8.0\Excel\Microsoft Excel\OPEN = /R

"C:\OFFICE\OFFICE\LIBRARY\ANALYSIS\ANALYS32.XLL"

Comanda OPEN este suportată doar din motive de compatibilitate şi este necesară pentru cererea de încărcare a
macrourilor. Alternativă recomandată este prezentată ulterior în acest capitol, o dată cu Init Commands şi Init Menus.

Încărcarea automată a unui Add-In în Microsoft PowerPoint utilizând valoarea AutoLoad din Windows Registry

Operaţiunea de încărcare automată a unui add-in prin valorile din Windows Registry se poate efectua şi în PowerPoint,
dar valorile fixate sunt altele decât în Excel.

Numele fişierului add-in se va da, în Windows Registry, ca subcheie fie sub HKEY_CURRENT_USER, fie sub
HKEY_LOCAL_MACHINE. Valoarea Path a cheii trebuie să fie locaţia add-in-ului. Valoarea AutoLoad se va fixa pe 1
pentru o încărcare automată.

Încărcarea Add-In-urilor care au fost încărcate în sesiunea precedentă

Un add-in încărcat şi înregistrat în sesiunea curentă Excel sau PowerPoint va fi încărcat automat la o nouă pornire a
aplicaţiei.

Un template global încărcat în Word rămâne disponibil pentru sesiunea curentă, dar nu este reîncărcat automat la o nouă
pornire a aplicaţiei.

Observaţie. Un add-in adăugat listei din dialogul Add-Ins (utilizând butonul Add New) din Excel sau PowerPoint este
înregistrat sub HKEY_CURRENT_USER. În continuare, aceste add-in-uri înregistrate vor fi accesibile doar pentru
utilizatorul intrat pe maşină în momentul adăugării.

278
Încărcarea programatică a unui Add-In sau Global Template

Colecţia Addins permite instalarea prin program a unui add-in sau template global.

În Word sau Microsoft Excel se va stabili la True proprietatea Installed a obiectului Addin:

Addins("C:\…\Gallery.dot").Installed = True

În PowerPoint, proprietatea Loaded a obiectului Addin se va stabili la True pentru înregistrarea automată, aceeaşi
valoare dându-se proprietăţii Registered pentru a înregistra add-in-ul.

With Addins("C:\…\mytools.ppa")
.Loaded = True
.Registered = True
End With

Încărcarea programatică a unui add-in ca răspuns la un eveniment

Dacă se doreşte încărcarea programatică a unui add-in ca răspuns la un eveniment, codul care comandă această
operaţiune se plasează în procedura de eveniment.

Deschiderea şi încărcarea programatică a unui template global prin linia de comandă

Se utilizează următoarea linie de comandă, de exemplu, unde path este locaţia fişierului Add-in.dot, pentru a instala un
add-in numit Add-in.dot, şi executarea unei proceduri numită Main din modulul denumit Add-inInstall:

WinWord "<Path>\Add-in.dot" /mAdd-inInstall

Word are un număr de argumente pe linia de comandă. Comutatorul /m execută codul din modulul specificat. De notat că
nu există nici un spaţiu după "m" şi că nu se specifică procedura Main; doar o procedură denumită Main se va executa, în
lipsa unei asemenea proceduri nu se execută nimic la încărcarea modulului. În continuare este un exemplu de procedură
Main.

' numele modulului este Add-inInstall, pentru a funcţiona cu


' linia de comandă din exemplul anterior
Option Explicit
Sub Main()
'Check to see if Add-In is loaded in Add-In list
Dim wkbAddin As Word.AddIn
On Error GoTo ErrorHandler
Set wkbAddin = AddIns(ThisDocument.Name)
If wkbAddin Is Nothing Then
' Add the template to the add-ins collection and install it
Set wkbAddin = AddIns.Add(ThisDocument.FullName, True)
End If
' If template is the active document close it
If ThisDocument.Name = ActiveDocument.Name Then
' The Add-in should not be dirty
ThisDocument.Close
End If
Exit Sub
Errorhandler:
' Only ignore "Subscript out of range" errors
279
Select Case Err.Number
Case 9, 5941
Err.Clear
Resume Next
Case Else
' Assert the error when in Debug mode
#If DebugMode Then
AssertError
#End If
' Insert other error handling code here
End Select
End Sub

Descărcarea programatică a unui Add-in sau Template

Un add-in rămâne încărcat până când se termină sesiunea curentă, până la descărcarea prin program sau până la
descărcarea prin dialogul Add-Ins (sau Templates and Add-ins) activat prin meniul Tools. Prin descărcarea unui add-in
se salvează memoria disponibilă.

În Word sau Microsoft Excel, pentru descărcarea unui add-in sau template global, se stabileşte la False proprietatea
Installed a obiectului Addin.

Addins(C:\…\Gallery.dot").Installed = False

În PowerPoint, proprietatea Loaded a obiectului Addin se va stabili pe False pentru descărcare, iar proprietatea
Registered se va stabili pe False pentru a înlătura înregistrarea add-in-ului.

Încărcarea la cerere

Încărcarea unui add-in sau template la pornirea aplicaţiei poate să crească semnificativ timpul pornirii aplicaţiei. Se poate
utiliza atunci încărcarea la cerere pentru a amâna încărcarea până atunci când utilizatorul apelează o comandă sau o
procedură din add-in.

Este de menţionat că wizard-urile şi add-in-urile iniţiate de o comandă din menu sunt încărcate, în mod automat, la
cerere.

Există mai multe tehnici pentru a stabili încărcarea la cerere, specifice diferitelor aplicaţii.

Observaţie. Dacă se intenţionează utilizarea unui add-in sau template ca o bibliotecă de cod, apelată din alte proiecte,
nu trebuie ca aceasta să fie încărcată explicit deoarece Visual Basic va încărca add-in-ul sau template-ul referit la cerere,
atunci când o procedură din bibliotecă este apelată.

Utilizarea referinţelor explicite în Microsoft Excel

Prima metodă de încărcare la cerere este utilizarea unei referinţe explicite atunci când se atribuie un nume de macro la o
unealtă. Următoarea linie cheamă procedura MySub care stă în modulul ThisWorkbook din caietul (add-in) "C:\My
Documents\MyTools.xla":

'C:\My Documents\MyTools.xla'!ThisWorkbook.MySub

Add-in-ul este încărcat doar atunci când este executat macro-ul.

280
Pentru soluţii care sunt distribuite utilizând un program de instalare se va vedea secţiunea "Adăugarea de meniuri şi
submeniuri la Microsoft Excel fără încărcarea unui Add-In".

Încărcarea la cerere a bibliotecilor de funcţii în Microsoft Excel

Dacă se distribuie o soluţie care conţine o bibliotecă de funcţii macro ar fi de dorit încărcarea la cerere a acestei biblioteci.
De asemenea, în mod normal este de dorit ca funcţiile să fie listate în Function Wizard. Pentru încărcarea la cerere a
funcţiilor este nevoie de macro-uri XLM (Microsoft Excel 4.0 macro sheets). Aceste macro-uri sunt de obicei doar
"învelişuri" pentru funcţii Visual Basic.

Atunci când Microsoft Excel vede că un Add-In este marcat pentru încărcarea la cerere, el citeşte doar anteturile macro-
urilor funcţii; raţiunea de prezentare sub formă XLM este aceea că informaţia din anteturi poate fi citită fără a încărca
Visual Basic for Applications (care se va încărca doar atunci când este necesar).

Modificarea unui add-in pentru a beneficia de încărcare la cerere

1. Se adaugă la caietul add-in o foaie Microsoft Excel 4.0 macro: click dreapta pe un tab Worksheet şi selectare
Insert, din dialog se va selecta Ms Excel 4.0 Macro.
2. Crearea unui macro funcţie care înveleşte o funcţie Visual Basic.

o În prima celulă se scrie numele funcţiei.


o În celula de sub numele funcţiei se inserează funcţia Argument(Name_Text, Data_Type_ID).
o Name_Text este numele parametrului. Ideal ar fi ca acesta să fie numele parametrului funcţiei din VBA
pe care se presupune că-l reprezintă.
o Data_Type_ID este ID-ul care determină tipul de dată pe care Excel îl acceptă pentru acest argument;
acest parametru este opţional.
o Se repetă paşii b, c şi d pentru fiecare parametru din funcţia VBA.
o Dacă este necesar să se specifice tipul rezultatului se va utiliza funcţia Result(Data_Type_ID).
o Funcţia Return(value) semnalează sfânrşitul macro-ului funcţie.
o Se selectează toate celulele care conţin macro-ul.
o Se selectează Define din submeniul Name (meniul Insert).
o Se denumeşte domeniul cu numele funcţiei.
o Se selectează butonul radio Function din grupul Macro.
o Click pe Add şi apoi OK.

1. Se selectează Insert din bara de meniu şi Define din submeniul Name. Se adaugă numele "__DemandLoad"
care se referă la "=TRUE" (se tastează exact aşa în boxa Refers To). Este de observat că există două caractere
"_" în faţa lui DemandLoad. Click Add, apoi Close.
2. Se stabileşte proprietatea IsAddin a obiectului Workbook la TRUE.
3. Se salvează caietul.

În continuare este un exemplu de macro care înfăşoară o funcţie VBA.

MyFunction
=ARGUMENT("szArgOne")
=ARGUMENT("intArgTwo")
=RETURN(vMyFunction(szArgOne, intArgTwo))

Funcţia VBA fiind de forma

Function vMyFunction (szArgOne As String, intArgTwo As Integer) As String



End Function

281
Aceşti paşi permit ca add-in-ul să fie încărcat la cerere. După ce este încărcat, add-in-ul nu este descărcat din memorie
până când se termină instanţa curentă a aplicaţiei Excel.

Adăugarea meniurilor în Excel fără încărcarea unui Add-in

Microsoft Excel 97 are două chei noi de registru, care sunt citite la pornirea aplicaţiei şi care creează intrări de meniu
oferind puncte de intrare într-un add-in; acest add-in se încarcă doar atunci când este cerut de o comandă dintr-un meniu,
care se referă la add-in. Cheile respective sunt Init Menus şi Init Commands. În continuare se prezintă de asemenea şi
cheia Delete Commands, care permite eliminarea unor intrări de meniu.

Cheia Init Menus

(HKEY_CURRENT_USER\Software\Microsoft\Office\8.0\Excel\Init Menus) conţine câte o valoare String pentru fiecare


menu adăugat unei mare de meniu built-in. Fiecare nume de valoare este unic şi identifică meniul creat. Şirul are sintaxa:

Value_name = Menu_bar_num, Menu_name,Menu_position[, Menu_parent]

Argument Descriere

Menu_bar_num Numărul barei de meniu built-in la care se doreşte adăugarea meniului. Barele de meniu se
schimbă după tipul foii active. Numerele sunt:
3 Nil menu bar (nu există caiet deschis)
10 worksheet, dialog sheet, macro sheet 4.0
11 chart sheet
12 modul Visual Basic

Menu_name Numele noului meniu

Menu_position Poziţia noului meniu pe bara meniu. Aceasta poate fi numele unui meniu după care se plasează
cel nou, sau un număr indicând poziţia noului meniu de la stânga barei meniu.

Menu_parent Este opţional: dacă se defineşte un submeniu, acesta este numele sau numărul meniului care
va conţine noul submeniu, definirea căruia fiind controlată de restul parametrilor.

Cheia Init Comands

(HKEY_CURRENT_USER\Software\Microsoft\Office\8.0\Excel\Init Commands) conţine câte o valoare de tip string pentru


fiecare comandă adăugată unui meniu. Fiecare nume de valoare este unic şi identifică comanda adăugată. Şirul are
sintaxa

Value_name = Menu_bar_num,Menu_name,Command_name,Macro,

Command_position,[ Macro_key] ,[ Status_text] ,[ Help_reference]

parametrii fiind explicaţi în tabelul următor.

Argument Descriere

Menu_bar_num Numărul barei de meniu built-in la care se doreşte adăugarea meniului. Barele de meniu
se schimbă după tipul foii active. Numerele sunt:
10 Worksheet, dialog sheet, macro sheet 4.0

282
11 Chart sheet
12 modul Visual Basic

Menu_name Numele meniului sau submeniului. Submeniurile sunt indicate printr-un şir
"meniu\submeniu", caracterul backslash delimitând numele meniului de cel al submeniului.
Submeniul trebuie să fie existent deja sau să fie declarat în cheia Init Menu.

Command_name Numele noii comenzi.

Macro Referinţa la o procedură dintr-un caiet add-in. Alegerea comenzii deschide add-in-ul şi
execută procedura. Procedura va şterge comanda adăugată de această cheie de registru
şi o va înlocui cu o comandă care va executa procedura necesară.

Command_position Poziţia noii comenzi în meniu. Aceasta poate fi numele unei comenzi după care se
plasează cea nouă, sau un număr indicând poziţia noii comenzi pe meniu. Dacă este omis,
comanda apare la sfârşitul meniului.

Macro_key Este opţional, cheia ataşată procedurii, dacă există.

Status_text Este opţional, mesajul afişat în bara de stare atunci când se selectează comanda.

Help_reference Este opţional, numele fişierului şi numărul intrării pentru un Help ataşat comenzii.

Cheia Delete Commands

Se poate utiliza cheia Delete Commands pentru a şterge comenzi din meniurile buil-in. Add-In Manager (comanda Add-
Ins din meniul Tools) citeşte şi scrie valori în cheia Delete Commands. Cheia conţine câte un şir pentru fiecare
comandă care este ştearsă din meniu. Fiecare nume de valoare este unic şi identifică comanda eliminată. Şirul are
sintaxa

Value_name = Menu_bar_num,Menu_name,Command_position

Argument Descriere

Menu_bar_num Numărul barei de meniu built-in unde se doreşte modificarea meniului. Barele de meniu se
schimbă după tipul foii active. Numerele sunt:
3 Nil menu bar (nu există caiet deschis)
10 worksheet, dialog sheet, macro sheet 4.0
11 chart sheet
12 modul Visual Basic

Menu_name Numele meniu

Menu_position Poziţia comenzii pe bara meniu. Aceasta poate fi numele unei comenzi sau un număr indicând
poziţia comenzii în meniu.

Observaţie. Este recomandabil să nu se elimine comanda Exit din meniul File dacă nu s-a creat o cale alternativă de
părăsire a aplicaţiei Microsoft Excel.

Încărcarea la cerere în PowerPoint

Pentru o încărcare la cerere a unui add-in PowerPoint, singura posibilitate este să se creeze un DLL pentru a adăuga
intrări de meniuri şi bare de unelte atunci când PowerPoint este încărcat.
283
Pentru a adăuga un DLL, se creează o cheie cu numele add-in-ului DLL sub cheia \Office\8.0\PowerPoint\DLL Addins\
din Windows Registry. Sub cheia creată se adaugă trei valori denumite: AutoLoad, InitFunction şi Path.

o AutoLoad – <DWORD> – este 0 sau 1. O valoare egală cu 1 arată că DLL este încărcat automat la
pornirea aplicaţiei PowerPoint.
o InitFunction – <STRING> – numele funcţiei din DLL pe care PowerPoint trebuie să o apeleze o dată ce
DLL este încărcat. Această funcţie din DLL va crea intrările de meniu şi barele de unelte dorite.
o Path – <STRING> – calea completă şi numele fişierului DLL.

Acest DLL trebuie să adauge intrările necesare în meniuri, să creeze barele de unelte şi să stabilească proprietăţile
OnAction prin referirea complet calificată a numelor de macro-uri dintr-un fişier add-in VBA (*.ppa, *.ppz).

Încărcarea la cerere din Word

Pentru implementarea unei scheme de încărcare la cerere, trebuie să se utilizeze cod cu legare târzie. În această situaţie
codul răspunde de deschiderea şi închiderea template-urilor (vezi şi secţiunea "Apelul procedurilor utilizând referinţe cu
legare târzie").

Scrierea codului executat la încărcarea sau descărcarea unui Add-in sau Global Template

Se poate scrie cod care să se execute ca răspuns la încărcarea sau descărcarea unui add-in. De exemplu, atunci când
se încarcă un add-in se poate executa o procedură care să afişeze o bară de unelte dând acces la funcţiunile add-in-ului.
În mod similar, la descărcarea add-in-ului, aceeaşi bară de unelte se poate elimina prin executarea unei proceduri
speciale. Fiecare aplicaţie are totuşi un mod propriu de realizare a acestor acţiuni.

Microsoft Excel – evenimentele AddinInstall şi AddinUninstall

Fiecare add-in are două evenimente, AddinInstall şi AddinUninstall, care sunt declanşate la încărcarea şi, respectiv,
descărcarea add-in-ului, atât prin dialogul Add-ins cât şi programatic. Aceste evenimente sunt locurile ideale de plasare
a intrărilor în cheile Init Menus şi Init Commands din Windows Registry.

Se poate utiliza evenimentul Open a unui caiet pentru a efectua înregistrarea caietului şi adăugarea lui la dialogul Add-
In. În următorul exemplu se prezintă o structură generală de utilizare a procedurilor evenimentelor AddinInstall şi
AddinUninstall.

Option Explicit
Private Sub Workbook_AddinInstall()
' Add code to customize the Microsoft Excel User Interface (UI) here
MsgBox "Addin Installed"
End Sub
Private Sub Workbook_AddinUninstall()
' Add code to remove customization of the Microsoft Excel UI here
MsgBox "Addin Uninstalled"
End Sub
Private Sub Workbook_Open()
' Check to see if add-in is loaded in Microsoft Excel's AddIn list
Dim wkbAddIn As Excel.AddIn
On Error GoTo Errorhandler
Set wkbAddIn = AddIns(ThisWorkbook.Name)
If wkbAddIn Is Nothing Then
' Setting the CopyFile argument to true will cause the add-in
' to be copied to the local harddisk if it is on a removeable
' medium.

284
Set wkbAddIn = AddIns.Add(ThisWorkbook.FullName, True)
' Thenext line will cause the Workbook.AddInInstalled event
' to fire.
wkbAddIn.Installed = True
End If
' Initialize add-in here.
Exit Sub
Errorhandler:
' Only ignore "Subscript out of range" errors.
If Err.Number = 9 Then
Err.Clear
Resume Next
Else
' Assrt the error when in Debug mode.
#If DebugMode Then
AssertError
#End If
' Insert other error handling code here.
End If
End Sub

Microsoft PowerPoint – Procedurile Auto_Open şi Auto_Close

Deşi nu suportă evenimente, un add-in PowerPoint suportă procedura Auto_Open care se execută la încărcarea
fişierului add-in şi procedura Auto_Close care se execută la descărcarea fişierului add-in.

Procedurile Auto_Open şi Auto_Close se execută doar dacă ele se găsesc în fişierul add-in. Prezenţa lor într-un fişier
de prezentare (*.ppt) nu produce nici un efect.

Microsoft Word – Procedurile AutoExec şi AutoExit

La crearea unui template în Word, se poat crea procedurile numite AutoExec şi AutoExit, care se execută atunci când
template-ul este încărcat sau descărcat. De exemplu, se pot utiliza AutoExec şi AutoExit pentru a afişa sau ascunde bare
de unelte atunci când utilizatorul încarcă sau descarcă template-ul.

Se pot crea de asemenea module cu denumirile AutoExec şi AutoExit, fiecare conţinând o procedură de tip Sub denumită
Main. Procedura Main din modulul AutoExec se va executa la încărcarea proiectului, iar Main din modulul AutoExit atunci
când proiectul este descărcat.

Observaţie. Dacă fişierul este deschis ca un document, macroul AutoExec sau modulul sinonim nu se vor executa. În
locul acestora se execută procedura AutoOpen sau/şi procedura de eveniment Document_Open (vezi intrarea de Help -
Using Events with the Document Object).

Următorul exemplu iniţiază monitorizarea evenimentelor aplicaţiei încât se pot utiliza evenimentele obiectului
Application. Primele două rutine trebuie să fie plasate într-un modul clasă denumit CAppEvents, ultimele trebuie să fie
plasate într-un modul standard numit AutoExec. Procedura Main din modulul AutoExec, apelată automat la încărcarea in
memorie a template-ului care conţine proiectul, instanţiază clasa CAppEvents. Evenimentul Class_Initialize leagă
variabila App la obiectul Application. Visual Basic va executa apoi procedura evenimentului DocumentChange de fiecare
dată când documentul activ se schimbă.

' Class module named CAppEvents


Public WithEvents App As Word.Application
Private Sub Class_Initialize()
' Make the class self_initializing by connecting the object declared
285
' in the class mnodule with the Application object.
Set App = Application
End Sub
Private Sub App_DocumentChange()
' Display a message box with the active document name
If Documents.Count > 0 Then MsgBox ActiveDocument.Name
End Sub

' In a standard module named AutoExec


Global AppEvent As CAppEvents
Public Sub Main()
' Instantiate and initialize the CAppEvents class. This is all
' that is needed to have the above class work.
Set AppEvent = New CAppEvents
End Sub

În Word se poate dori includerea codului care să gestioneze un add-in în procedurile evenimentelor Open, Close şi New
ale unui document, care se execută atunci când un template global este deschis sau închis ca un document sau când
este creat un nou document pe baza şablonului. Se pot utiliza de asemenea procedurile evenimentelor Startup, Quit şi
DocumentChange ale obiectului Application. În acest caz se va revedea modul în care se pot utiliza evenimentele
obiectului Application.

Observaţie. Dacă într-un document există atât macro-urile AutoClose, AutoNew şi AutoOpen, cât şi procedurile
evenimentelor similare, atunci se vor executa atât macro-uri cât şi procedurile.

Verificarea finală a codului

Înaintea împachetării soluţiei ca un add-in sau un template global, este utilă o ultimă verificare pentru eliminarea unor
erori frecvente, amintite în continuare.

Verificarea referinţelor la ActiveWorkbook sau ActiveDocument

Reamintim că dacă proiectul VB dintr-un add-in sau template global conţine o referinţă explicită sau implicită la
documentul activ sau la caietul activ, el sa ve referi în execuţie la acel document sau caiet care se va întâmpla să fie activ
în momentul aplicării referinţei. Pentru referinţa la add-in sau template se va utiliza prin urmare ThisWorkbook sau
ThisDocument.

De exemplu, ambele proceduri scrise în continuare apelează foaia denumită "Addin Definition" în caietul care este activ în
momentul execuţiei codului. Prima procedură conţine o referinţă explicită, prin ActiveWorkbook. A doua procedură are o
referinţă implicită: deoarece nu se referă explicit la un caiet anumit, referinţa este presupusă în caietul activ.

Sub ExplicitReference()
Set rMnuTable = ActiveWorkbook.Worksheets("Addin Definition). _
Range("MenuDefinition")
Add_Menu rMnuTable
End Sub
Sub ImplicitCode()
Set rMnuTable = Worksheets("Addin Definition). _
Range("MenuDefinition")
Add_Menu rMnuTable
End Sub

Următorul cod utilizează proprietatea ThisWorkbook pentru a realiza o referinţă la caietul în care se execută codul –
adică în caietul add-in.
286
Sub CorrectCode()
Set rMnuTable = ThisWorkbook.Worksheets("Addin Definition). _
Range("MenuDefinition")
Add_Menu rMnuTable
End Sub

Apelul rutinelor din alte proiecte

Dacă se doreşte apelarea unor funcţii, proceduri şi clase care sunt definite în alt proiect, proiectul apelant trebuie să aibă
o referinţă la proiectul apelat. Este de notat că nu se pot crea referinţe la prezentări PowerPoint decât în cazul în care
acestea sunt salvate ca add-in-uri PowerPoint; după salvarea ca un add-in prezentarea poate fi referită din alte
prezentări.

Este evident că pentru a utiliza referinţe la proiecte trebuie ca proiectele implicate să poarte denumiri diferite (de regulă,
la începutul utilizării VBA, proiectele se lasă cu denumirile implicite). Numele implicit al unui proiect se poate
vedea/modifica fie în fereastra Properties, fie în Project Name din dialogul Project Properties (obţinut prin click dreapta
în VBE şi alegerea project name Properties).

Referinţa la un alt proiect se realizează manual prin dialogul References ( meniul Tools) sau programatic prin metoda
AddFromFile a colecţiei References. Linia următoare stabileşte o referinţă din caietul activ la proiectul din add-in-ul
MyTools.xla:

ActiveWorkbook.VBProject.References.AddFromFile "C:\Tools\MyTools.xla"

Este însă de notat că înainte de a stabili programamtic o referinţă, trebuie (în Word, Excel, PowerPoint) stabilită o
referinţă la biblioteca de tipuri Visual Basic for Applications Extensibility. Această bibliotecă oferă obiectele care permit
lucrul programatic cu proiectul VBA.

Observaţie. Rutina Auto_Open dintr-un add-in referit nu este executată la încărcare prin referinţă dintr-un alt add-in sau
prezentare.

Evitarea referinţelor nerezolvate

La salvarea şi distribuirea unui add-in sau template, referinţele stabilite pentru proiectul asociat rămân valabile. Totuşi,
dacă add-in-urile sau şabloanele referite nu sunt la aceleaşi locaţii pe maşina utilizatorului cum erau pe maşina de
dezvoltare, referinţele nu vor putea fi rezolvate la beneficiar şi soluţia nu va fi executată.

În PowerPoint, Visual Basic încearcă să rezolve referinţa prin căutarea în acelaşi folder cu proiectul apelant.

În Word şi Microsoft Excel, Visual Basic încearcă rezolvarea referinţelor prin căutare în locaţiile:

1. În acelaşî folder cu add-in-ul sau template-ul apelant.


2. În folderul rădăcină a aplicaţiei gazdă.
3. În folderul System şi Windows.
4. În toate folderele variabilei de mediu Path.

În Microsoft Excel, Visual Basic priveşte de asemenea în folderele adăugate la valoarea Add-in Path din registry.

Dacă o referinţă nu este rezolvată după completarea căutării prezentate, execuţia este oprită.

În continuare sunt enumerate câteva metode care pot fi utilizate în evitarea/rezolvarea referinţelor nerezolvate.

287
o Toate fişierele se vor livra în acelaşi folder. Aceasta este soluţia comună.
o În Excel se poate actualiza cheia de registry Add-ins Path. Microsoft Excel 97 oferă cheia de registru

HKEY_CURRENT_USER\Software\Microsoft\Office\8.0\Excel\Microsoft Excel\Add-in Path

care punctează către folderele unde Microsoft Excel priveşte pentru add-in-uri. Valoarea Add-in
Path este un şir care constă din căi multiple delimitate de caractere ";". La instalarea aplicaţiei
Excel, programul Setup adaugă căile către folderele Library, Analysis şi Solver. Alte programe de
instalare pot să modifice valoarea Add-in Path. Modificarea trebuie să fie "politicoasă": noile
intrări se vor adăuga celor existente. Programele de tip uninstall trebuie să elimine doar
porţiunea din valoare adăugată la instalare.

o Adăugarea folderului soluţiei la variabila de mediu Path.

Se pot utiliza funcţiile API GetEnvironmentVariable şi SetEnvironmentVariable pentru


adăugarea temporară a folderului soluţiei, sau se poate utiliza scrierea în instrucţiunea Path din
Autoexec.bat pentru o adăugare permanentă.

Exemplul următor utilizează funcţiile GetEnvironmentVariable şi SetEnvironmentVariable pentru a modifica temporar


variabila de mediu Path.

Option Explicit
Private Declare Function GetEnvironmentVariable Lib "kernel32" _
Alias "GetEnvironmentVariableA" (ByVal lpName As String, _
ByVal lpBuffer As String, _
ByVal nSize As Long) As Long
Private Declare Function SetEnvironmentVariable Lib "kernel32" _
Alias "SetEnvironmentVariableA" (ByVal lpName As String, _
ByVal lpValue As String) As Long
' AppWord is a user defined compile directive
#If AppWord = True Then
Public Sub AutoExec()
AppendEnvironmentPath ThisDocument
End Sub
#End If
'AppExcel is a user defined compile directive
#If AppExcel = True Then
Public Sub Workbook_Open()
AppendEnvironmentPath ThisWorkbook
End Sub
#End If
Private Sub AppendEnvironmentPath (ThisDocObject As Object)
Const ENV_PATH As String = "Path"
Dim iRet As Long
Dim szPath As String
SzPath = String(1024, 0)
' Retrieve the current environment setting.
IRet = GetEnvironmentVariable(ENV_PATH, szPath, 1024)
If iRet Then
' iRet contains the length of the returned string.
' trim any trailing characters
szPath = Mid$(szPath, 1, iRet)
' See if the template path is included in the path statement.
If InStr(1,szPath, ThisDocObject.Path, vbTextCompare) = 0 Then

288
' Path is not part of the environment.
szPath = szPath & ";" & ThisDocObject.Path
iRet = SetEnvironmentVariable (ENV_PATH, szPath)
If iRet = 0 Then
' Handle error here. Template path was not appended to
' environment.
Err.Raise vbObjectError + Err.LastDllError, _
ThisDocObject.Name & ".AppendEnvironmentPath", _
"Path environment was not set."
End If
End If
Else
' should raise an error here. This should never happen …
Err.Raise vbObjectError + Err.LastDllError, _
ThisDocObject.Name & ".AppendEnvironmentPath", _
"No path environment was found."
End If
End Sub

o Se poate scrie un add-in agent de referinţă (reference broker) care să adapteze referinţele pentru a
maşină specifică. Un asemenea agent de referinţă ar trebuie să verifica referinţa şi să lege înainte ca
soluţia să se execute (sau la momentul încărcării). Acest tip de componentă este bună pentru soluţii
trietajate (three-tier). Agentul trebuie să lege dinamic componenta front-end de componenta back-end pe
baza versiunii, nivelului de securitate sau alţi parametri determinaţi de administrator. Această tehnică
poate fi utilizată la actualizarea automată a componentelor. O cale pentru determinarea dacă o referinţă
este validă este utilizarea proprietăţii IsBroken a obiectului Reference. Proprietatea IsBroken este True
dacă referinţa nu se referă la o intrare validă în Windows Registry.

Apelul unei rutine dintr-un Add-in PowerPoint fără fixarea unei referinţe

Dacă se doreşte încărcarea temporară a unui fişier add-in şi executarea unei rutine din fişier, se va utiliza o instrucţiune
Application.Run şi imediat apoi se va descărca fişierul add-in. La executarea Application.Run, Microsoft PowerPoint va
încărca add-in-ul şi Va executa macroul specificat. Pentru a descărca fişierul se utilizează proprietatea Loaded, după
modelul:

Sub CallAddInMacro()
Application.Run "…\MyAddIn.ppa!MyMacro"
AddIns("MyAddIn").Loaded = False
End Sub

Ultima instrucţiune poate fi înlocuită şi cu

AddIns(AddIns.Count).Loaded = False

Apelul rutinelor folosind referinţe legate târziu

Se poate apela orice procedură publică, proprietate sau variabilă din modulul ThisDocument sau ThisWorkbook al unui
document sau caiet utilizând o referinţă târzie la obiectul asociat Document sau Workbook. De exemplu, următoarele
instrucţiuni atribuie obiectul Document, returnat de Open, unei variabile obiect. După aceea se apelează procedura
MySub din modulul clasă ThisDocument al documentului:

Dim objDoc As Object


Set objDoc = Documents.Open(szFileName)
289
objDoc.MySub

Dacă documentul reprezentat de variabila objDoc nu are, în modulul său ThisDocument, o procedură publică denumită
MySub, atunci apare o eroare de execuţie. În acest mod se poate apela cod doar din module ThisDocument sau
ThisWorkbook. Dacă se doreşte apelul unor proceduri din alte module, clase sau forme ale proiectului asociat
documentului/caietului deschis, se vor scrie proceduri intermediare în modulul ThisDocument sau ThisWorkbook pentru
a le accesa.

Observaţie. Procedeul descris nu funcţionează în PowerPoint deoarece nu există un modul ThisPresentation în proiect.

Protejarea sau neprotejarea codului

Stabilirea proprietăţii IsAddin nu protejează codul sursă al proiectului. Pentru protejarea codului se va marca Lock
project for viewing (meniul Tools, project Properties, fişa Protection) şi se va fixa o parolă. Dacă se fixează doar
parola, fără blocarea accesului la cod, acesta poate fi văzut dar nu pot să deschidă dialogul project Properties fără
cunoaşterea parolei. După stabilirea parolei proiectul se va salva obişnuit prin Save (meniul File din Visual Basic Editor).

Pentru înlăturarea protecţiei se va elimina marcarea boxei de control Lock project for viewing şi parola introdusă.

Salvarea soluţiei ca un Add-in sau Global Template

Fiecare aplicaţie din Microsoft Office are un mod propriu de creare a unui add-in. În Microsoft Excel şi PowerPoint se
salvează fişierul într-un format specific. În Word se salvează documentul ca un fişier template (.dot).

Crearea unui Add-in în Excel

La transformarea unui caiet într-un add-in, foile caietului sunt ascunse şi procedurile din proiect sunt ascunse utilizatorului
(procedurile nu mai apar în dialogul Macros).

Pentru crearea unui add-in Excel, se fixează pe True proprietatea IsAddIn a caietului care conţine codul. O cale de
realizare a acestui lucru este salvarea unei copii a caietului respectiv ca un add-in Excel prin selectarea tipului de fişier
Microsoft Excel Add-In (*.xla) în dialogul Save As.

Proprietatea poate fi stabilită şi manual din VBE: se selectează "ThisWorkbook" în Project Explorer şi se modifică
proprietatea IsAddIn în Properties Window. După ce proprietatea IsAddIn este fixată pe True, caietul este ascuns în
Microsoft Excel.

Proprietatea se poate stabili şi programatic.

Observaţie. Dacă este nevoie să se modifice elementele caietului după crearea add-in-ului, se fixează proprietatea
IsAddIn la False, caietul devine vizibil şi editabil. După modificare se reface proprietatea IsAddIn şi se salvează caietul.

Crearea unui Add-in PowerPoint

Atunci când se salvează o copie a prezentării ca un add-in, toate diapozitivele prezentării sunt înlăturate şi numai
proiectul VB asociat este compilat şi memorat în noul fişier add-in PowerPoint (*.ppa). Procedurile din add-in sunt
ascunse şi nu apar în dialogul Macros.

Înaintea salvării prezentării ca un add-in se recomandă salvarea normală ca o prezentare (fişier .ppt) şi apoi crearea unei
copii ca add-in prin alegerea tipului PowerPoint Add-In (*.ppa) în dialogul Save As.

Dacă este nevoie de modificări, acestea se efectuează în fişierul .ppt şi se salvează din nou ca un add-in (fişier .ppa).
290
Crearea unui template global Word

Microsoft Word nu suportă un format de fişier de tip add-in, similar cu Excel sau PowerPoint. Un template global, sau un
template care a fost încărcat în memorie încât macro-urile sale sunt disponibile din orice document, este echivalentul
Word al unui add-in.

Pentru crearea unui template global se alege Document Template (*.dot) în Savve As Type din dialogul Save As.

Depanarea unui Add-in sau Global Template

Pentru depanare se utilizează, cu unele particularităţi, deprotejarea codului şi efectuarea acţiunilor uzuale de verificare a
codului.

Depanarea unui Add-in Excel

Pentru depanarea unui add-in Excel o dată încărcat, se înlătură protecţia proiectului respectiv. Dacă este necesar să se
vadă caietul asociat se fixează proprietatea IsAddIn la False.

Depanarea unui Add-in PowerPoint

Aplicaţia PowerPoint necesită fixarea unei valori de registru pentru depanarea unui add-in, deoarece nu se afişează în
mod implicit în Project Explorer add-in-urile încărcate. Pentru vizibilitatea acestora se va fixa sub cheia

HKEY_CURRENT_USER\Software\Microsoft\Office\8.0\PowerPoint\Options

valoarea DebugAddins la 1. Următoarea pornire a aplicaţiei PowerPoint va afişa în Project Explorer toate add-in-urile
încărcate. Din acest moment se poate deproteja codul etc.

Prin fixarea valorii 1 pentru DebugAddins se onorează şi punctele de oprire din macro-urile atribuite acţiunilor din slide
show (dialogul Action Setting din meniul SlideShow).

Depanarea unui template global Word

Se deschide template-ul global, se deprotejează dacă este necesar şi se efectuează depanarea in mod uzual.

Distribuirea soluţiilor prin Setup Wizard

Microsoft Office Developer's Edition include un Setup Wizard prin care se poate crea un program Setup de instalare a
soluţiei oferite. Prin intermediul unor dialoguri succesive se preia informaţia necesară construirii unei mulţimi de foldere –
imagini de disc – cu programul de instalare şi fişierele necesare. Aceste foldere se pot copia pe dischete sau locaţie de
reţea etc.

În continuare sunt enumerate facilităţile rezolvate de wizard-ul de instalare:

o Copierea fişierelor în locaţiile necesare.


o Crearea shortcut-urilor Windows pentru pornirea soluţiei.
o Adăugarea cheilor din Windows Registry necesare.
o Definirea componentelor selectabile la instalare.
o Instalarea versiunii run-time de Access.
o Instalarea unor componente Microsoft Office: Graph 97, Replication Manager, drivere ISAM (indexed
sequential access method), fişiere necesare pentru ODBCDirect.
o Executarea unei aplicaţii sau deschiderea unui fişier după terminarea instalării.
291

Potrebbero piacerti anche