Gestiunea Cd Urilor Dintr O Biblioteca de Firma

INTRODUCERE

Informația este o notiune de larga generalitate si reprezinta traducerea legaturilor cauza-efect din lumea reala. Pentru a utiliza corect aceasta notiune este necesar sa se faca distinctia intre informatii si date.

Informatia trebuie privita ca o triada a elementelor : entitate, atribut, valoare.

Entitatea formeaza obiectul informatiei si este complet definita doar daca se iau in considerare toata atributele sale alaturi de valorile lor. Atributul este o proprietate a entitatii. Valoarea este o masura a proprietatii sau atributului asociat entitatii.

Datele constituie reprezentarea simbolica a informatiilor intr-o forma conventionala, convenabila unei comunicari. Ele au o interpretare si sunt prelucrate de om direct sau cu ajutorul calculatorului.

Metodele si tehnicile de organizare adatelor au evoluat in cadrul procesului de perfectionare a sistemelor informatice, fiind determinate de :

cresterea continua a complexitatii activitatilor, care a condus la cresterea volumului de informatii generate si prelucrate ;

cresterea ritmului de dezvoltare a societatii, care a determinat ca dimensiunea timpului de raspuns a sistemelor infomatice la cererile de informatii sa devina unul din criteriile de apreciere a gradului de organizare a datelor si, respectiv, a eficientei sistemelor informatice

evolutia mijloacelor de culegere, transmitere si prelucrare a datelor.

Prima etapa a fost organizarea datelor in “fisiere pe aplicatii” cand proiectantii sistemelor informatice gestionau in mod izolat fisiere, in vederea rezolvarii problemelor particulare ale unui departament.

A doua etapa se caracterizeaza prin separarea nivelului logic de cel fizic de organizare a datelor, utilizandu-se fisiere organizate indexat sau aleator.

Cerintele complexe impuse sistemelor informatice moderne au creat necesitatea ca mai multi utilizatori sa aiba acces la aceeasi colectie de date. Utilizarea metodelor clasice cu fisiere duce la o crestere a redundantei datelor si o crestere a timpului de raspuns. In aceste conditii au aparut fisierele integrate sau sistemele de fisiere ( etapa a treia ).

Trecerea la fisiere integrate nu a rezolvat problema independentei programelor de aplicatii de modul de organizare a datelor. Solutia a fost detasarea din programul de aplicatii a descrierii fisierelor si a legaturilor dintre ele. Se ajunge astfel la primele banci de date ( etapa a patra, care marcheaza un salt calitativ in organizarea datelor ).

O banca de date este formata din:

– baza de date – colectie de date aflate in interdependenta, impreuna cu descrierea lor ;

– un sistem de gestiune a bazei de date ( SGBD ) – un set de programe si proceduri specializate, destinate gestiunii si prelucrarii complexe a datelor din baza de date ;

– un set de proceduri manuale si automate – specifice domeniului pentru care se organizeaza baza de date, precum si reglementarile administrative destinate bunei functionari a intregului sistem.

O baza de date este deci o colectie de date creata pentru a satisface mai multi utilizatori, asigurand o redundanta minima, o independenta a programelor fata de date, o optimizare a structurilor fizice care vor fi ignorate cu totul de utilizatori, o protectie a datelor memorate.

Avantajele organizarii in baze de date sunt :

Independenta datelor memorate – asigurata de separarea nivelului de descriere a datelor de nivelul de utilizare a lor ; astfel asigurandu-se si integritatea programelor de aplicatie la schimbarile ce au loc in baza de date ;

Nivelul redus de redundanta – redundanta devine un fenomen controlabil;

Securitatea datelor – se pot aplica restrictii in ceea ce priveste accesul neautorizat la date in vederea extragerii sau distrugerii unor date cu caracter confidential;

Integritatea datelor – asigurarea corectitudinii datelor in orice moment al functionarii sistemului;

Facilitati de utilizare a datelor fara ca utilizatorii sa cunoasca in intregime baza de date;

Accesarea bazei de date din diferite noduri ale retelei de catre utilizatori diferiti.

Oferta bogata de pachete de gestiune care permit gestionarea unor date foarte complexe in conditii de eficienta maxima, asigurand in plus utilizatorilor programatori instrumentele necesare conceptiei programelor lor, dar si utilizatorilor neinformaticeni o interfata “prietenoasa”.

BAZE DE DATE RELATIONALE

Denumirea acestor baze de date provine de la tipul de model utilizat in exploatarea lor – modelul relational, ale carui nume si metode provin, la randul lor, de la notiunea matematica relatie.

O baza de date relationala este o colectie de date stocate in fisiere, numite tabele. Programele dBASE ( ca si toate celelalte SGBD-uri din aceeasi familie ) au la baza teoria algebrelor relationale, dar identifica notiunea de relatie cu cea de fisier. Fiecare tabel este conectat cu cel putin un alt tabel prin intermediul unui camp comun care defineste relatia.Pentru a discuta despre structura relationala a datelor este necesara cunoasterea catorva termeni : domeniu, relatie, atribut, schema unei relatii.

Domeniul este un ansamblu de valori caracterizat printr-un nume;se poate defini explicit prin enumerarea tuturor valorilor lui sau implicit prin precizarea proprietatilor pe care le are domeniul respectiv.

Se numeste produs cartezian al multimilor D1,D2,…,Dn finite si nu neaparat distincte, multimea tuplurilor (v1,v2,…,v n), unde v1,v2,…,v n apartin respectiv multimilor D1,D2,…,Dn .

Relatia este un subansamblu al produsului cartezian al mai multor domenii,caracterizat de un nume si care contine tupluri de o anumita semnificatie (tuplul reprezinta exprimarea generala a unei multimi).

Exemplu: D1*D2*…*Dn <v1,v2,…,v n>

D1*D2*D3 <v1,v2,…,v3> <”Maria”,F,45>

<”Vasile”,B,47>

Atributul reprezinta unitatea fundamentala a unei baze de date relationale si se mai numeste camp. Este data de coloana unei tabele de date si se caracterizeaza printr-un nume; sunt elemente individuale de informatie si se folosesc pentru a creste flexibilitatea datelor.

Fiecare coloana din tabelul de mai sus defineste un camp distinct.Pe toate liniile, informatiile din aceeasi coloana au aceeasi semnificatie.De exemplu, numele unei persoane este un camp, varsta este alt camp, iar sexul este al treilea. Daca se doreste stocarea unor informatii suplimentare, fiecare informatie individuala constituie un camp. Pentru fiecare persoana inregistrata in tabel exista mai multe campuri care o individualizeaza. Luate impreuna, aceste campuri definesc o inregistrare. In general inregistrarile se prezinta sub forma de linii.

Tabelul descrie o grupare de un nivel mai inalt decat o inregistrare, cuprinzand o colectie de inregistrari. Presupunand ca avem un tabel asemanator care contine informatii despre o categorie de persoane alese dupa un anumit criteriu, aceste doua tabele au un element comun – numele persoanei.

Combinatia acestor doua tabele si a relatiei dintre ele constituie un exemplu simplu de baza de date relationala.

Schema unei relatii este compusa din numele relatiei urmat de lista atributelor si domeniile asociate fiecarui atribut.

Relatie ( A: D1, A: D2, …,A: Dn )

Persoana ( Nume:D1,Sex: D2,Varsta: D3)

Schema unei relatii se mai numeste si intensia relatiei si reprezinta o expresie a proprietatilor comune si invariante ale tuplurilor care compun relatia, ramanand neschimbata atata timp cat este folosita relatia. Extensia unei relatii poarta numele de relatie de baza si este ansamblul tuplurilor care compun la un moment dat relatia ( multimea inregistrarilor existente la un moment dat intr-un tabel ), fiind stocata fizic in spatiul asociat bazei de date.

DEFINIREA BAZELOR DE DATE, A TABELELOR ȘI

A INDECȘILOR

Crearea tabelelor pentru o aplicatie

Daca se urmareste tinerea evidentei imprumuturilor dintr-o biblioteca de CD-uri, este necesar sa se creeze o lista provizorie cu informatiile care sunt primite la efectuarea unui imprumut :

data imprumutului

numele persoanei care a facut imprumutul

adresa persoanei care a facut imprumutul

lista CD-urilor imprumutate de o anumita persoana

lista tuturor CD-urilor imprumutate

Aceasta lista utilizeaza mai multe categorii de date evidente pentru stocarea informatiilor referitoare la un imprumut. Prima categorie priveste informatiile referitoare la persoana care face imprumutul. Cea de a doua categorie tine evidenta informatiilor comune tuturor imprumuturilor, insa nu specifice CD-urilor individuale comandate. Aceasta categorie poate sa contina data efectuarii imprumutului si numarul CD-urilor imprumutate. A treia categorie contine detalii despre imprumut. In aceasta categorie se poate planifica cate o inregistrare sau mai multe pentru fiecare CD care sa contina detalii referitoare la descrierea continutului acestuia,.

1.Stabilirea categoriilor de date necesare

Pentru o evidenta cat mai riguroasa, este necesar sa se retina cat mai multe date referitoare la client. Astfel, ar fi indicat sa se cunoasca si locul de munca al acestuia, numarul de telefon etc. Simpla pastrare a numelui persoanei care a efectuat un imprumut s-ar putea sa nu fie cea mai facila metoda de a regasi fisierul daca se cunoaste doar numele. De aceea, trebuie sa fie despartit intr-un camp prenume si un camp nume. In mod similar, adresa este compusa din una sau mai multe linii reprezentand strada, blocul, apartamentul, orasul etc. Fiecare element trebuie pastrat intr-un camp distinct. Chiar si numarul de telefon s-ar putea sa nu fie suficient pentru clientii care au numere de interior.

Ceea ce trebuie facut intr-o astfel de situatie se numeste atomizarea informatiilor referitoare la client. Fiecare atom defineste un singur element care individualizeaza clientul.

Rezultatele atomizarii pot fi cele din lista urmatoare :

ID (un identificator unic pentru fiecare utilizator)

locul de munca (poate fi si departamentul in cadrul unei firme)

numarul de telefon

interior (numar in cadrul centralei)

data ultimului imprumut

2. Denumirea fiecarei date individuale

Pentru fiecare data individuala trebuie sa se stabileasca un nume de camp. In mod traditional FoxPro limita lungimea numelor campurilor la 10 caractere. In schimb, in Visual FoxPro, se pot defini nume de campuri cu o lungime de pana la 128 de caractere, insa numai atunci cand campul este definit intr-o baza de date. Intrucat initial se defineste un tabel de sine statator, numit tabel liber, trebuie respectata limita de 10 caractere.

In versiunile FoxPro anterioare, au fost create numeroase conventii de denumire pentru a face programele mai lizibile. Ele diferentiaza variabilele dupa tip domeniu si dupa faptul ca sunt variabile de memorie sau variabile de tabel. Una dintre metodele uzuale defineste campurile unui tabel ca incepand cu un prefix format din doua caractere, urmat de un caracter subliniere. Acest prefix identifica baza de date si este unic in toata aplicatia. Restul de sapte caractere pot fi orice identificator unic din tabel. Campurile similare din tabele distincte pot avea acelasi identificator de sapte caractere.

In cadrul acestei conventii de denumire, variabilele de memorie incep si ele cu doua caractere – primul reprezinta domeniul, iar al doilea tipul variabilei. Al treilea caracter poate fi si de aceasta data un caracter subliniere. Totusi, exista tendinta de a se renunta la caracterele de subliniere.

Printre avantajele utilizarii acestei conventii de denumire a variabilelor de memorie si a campurilor se numara urmatoarele :

posibilitatea de a folosi comenzile SCATTER si GATHER fara pericolul suprascrierii variabilelor din alt tabel sau al interferentei cu alte variabile de memorie

in instructiunile SQL poate fi omis prefixul care identifica tabelul

campurile sunt usor de asociat cu tabelul de care apartin

domeniul si tipul variabilelor de memorie este identificat imediat

campurile tabelelor nu se confunda cu variabilele de memorie in codul sursa.

Printre dezavantajele acestei morie in codul sursa.

Printre dezavantajele acestei conventii de denumire se numara urmatoarele :

transferul datelor intre tabele este mai complicat, necesitand instructiuni REPLACE individuale pentru fiecare camp sau includerea unor clauze FIELD lungi in care sa fie enumerat fiecare camp

interogarea relationala prin exemple nu poate identifica acele campuri aflate in relatie ( fara crearea unor relatii permanente )

pierderea a doua sau trei caractere din zece ingreuneaza crearea unor nume de campuri sugestive

3.Selectarea tipului de date adecvat pentru datele individuale

Stabilirea informatiilor care urmeaza sa fie salvate intr-un tabel reprezinta doar o prima etapa a definirii structurii unui nou tabel. In continuare trebuie analizata fiecare data individuala si stabilit daca trebuie stocata sub forma de sir de caractere, sub forma numerica, sub forma de data calendaristica sau sub forma unui alt tip de data. In plus, pentru campurile caracter si numerice, trebuie stabilit numarul de caractere necesare.

4.Crearea structurii tabelelor

Sa presupunem ca se urmareste crearea unui proiect. Ca si in cazul majoritatii functiunilor, FoxPro prevede mai multe metode pentru a face acest lucru. Se poate alege File, New din meniul principal , de exemplu. In urma acestei comenzi apare caseta de dialog New. Se selecteaza Project drept tipul fisierului si se executa clic pe New File, dupa care fisierului I se atribuie un nume.

In momentul crearii unui proiect, FoxPro il deschide automat. Proiectele au cadre de pagina. Fiecare cadru reprezinta un alt tip de fisiere, tip indicat de etichetele din partea superioara a paginii. Pentru a selecta o pagina se executa clic pe eticheta corespunzatoare.Pentru a crea un tabel se executa clic pe eticheta Data. Se creeaza un tabel liber selectand FreeTabels si executand clic pe New.

In continuare, VFP solicita un nume de fisier, de data aceasta pentru tabel. FoxPro va afisa caseta de dialog Table designer. Acest formular are un obiect cadru de pagina cu doua pagini. Prima pagina defineste structura tabelului, iar a doua defineste indecsii. Pentru a defini structura tabelului, trebuie introduse informatiile definite anterior, insotite de tipurile campurilor, latimile si numarul de zecimale. Ultima coloana a acestei structuri stabileste daca campul curent accepta valori nule. Conform exemplului de mai sus, fiecare persoana care poate efectua imprumuturi din baza de CD-uri este identificata printr-un indicativ (ID) unic.

5.Modificarea structurii tabelelor

Este de asteptat ca, pe durata de viata a unui proiect , sa fie necesara modificarea structurii unui tabel. Amploarea unei modificari poate fi clasificata dupa cat de mult se schimba fisierul tabel si fisierele index. De exemplu , adaugarea unui camp este o modificare minora, deoarece nu are nici un impact asupra campurilor existente – desi necesita rescrierea intregului fisier DBF. Redenumirea unui camp reprezinta si ea o modificare minora : de obicei, nu se intampla nimic altceva decat modificarea antetului fisierului DBF. In schimb, daca se redenumeste un camp care apare intr-un index, trebuie realizata si actualizarea indexului sau a etichetei. Eliminarea campurilor, atat timp cat nu sunt parte a unui index sau a unei etichete, necesita rescrierea intregului fisier DBF, ceea ce poate duce la pierderea datelor. Atunci cand se schimba tipul unui camp, FoxPro incearca sa converteasca datele la noul tip, insa este posibil sa distruga automat datele daca nu stie ce sa faca sau atunci cand conversia nu are sens.

6.Indecsii structurali si nestructurali

Programul FoxPro permite folosirea indecsilor structurali si nestructurali, numiti si indecsi compusi. Acestia sunt fisiere index speciale, care pot contine definitiile mai multor indecsi intr-un singur fisier fizic. Astfel, se pot stoca intr-un singur fisier definitiile tuturor indecsilor asociati unui fisier DBF, inlaturandu-se probleme de tipul gasirii unor pointeri de index nesincronizati sau neglijarii deschiderii unor fisiere index.

7.Definirea indecsilor normali si a indecsilor unici

Definitiile indecsilor incep cu numele etichetei, in stanga, urmat de tipul indexului, expresia etichetei si un filtru. Sagetile din stanga numelor indica daca indexul este in ordine ascendenta (sageata in sus) sau descendenta (sageata in jos)

Tipul de index Regular (normal) indica faptul ca FoxPro stocheaza in index valoarea generala de expresia indexului pentru fiecare linie a tabelului. Daca mai multe inregistrari au aceeasi expresie, FoxPro stocheaza expresia de mai multe ori, cu pointeri distincti pentru fiecare inregistrare.

Un alt tip de index este Unique (unic). In cazul tipului unic sunt incluse numai valorile unice ale indexului. Daca mai multe inregistrari genereaza aceeasi valoare a expresiei indexului, este stocata numai prima intalnita. Daca se defineste un index unic, s-ar putea ca nu toate inregistrarile sa fie incluse in index.

8.Definirea cheilor candidat si a cheilor primare

Al treilea tip de index, numit candidat (Candidate), creeaza un index unic, insa include fiecare inregistrare din tabel. Indecsii candidat interzic prezenta valorilor dublate ale expresiei indexului pentru oricare doua inregistrari din tabel.

Uneori, este posibil ca un singur tabel sa aiba mai multe campuri care identifica in mod unic fiecare inregistrare. Fiecare asemenea index este un index candidat si o potentiala cheie primara. Cu toate acestea, fiecare tabel poate avea o singura cheie primara. Deseori cheile primare creeaza relatii intre mai multe fisiere si servesc drept valori de cautare intr-un tabel la care se face referire.

9.Indexarea dupa expresii complexe

FoxPro nu limiteaza expresiile indecsilor la un singur camp. Practic orice combinatie de campuri poate fi folosita drept expresie a unui index.

Crearea unei baze de date

In Visual FoxPro o baza de date este o colectie de tabele. Se poate lucra si cu tabele individuale, asa cum ar fi in vechiul stil FoxPro. Totusi, Visual FoxPro ofera cateva imbunatatiri semnificative atunci cand este nevoie de o sortare a tabelelor aflate in baza de date.

Pentru inceput se poate crea un container baza de date pentru stocarea tabelelor. Comanda urmatoare creeaza si denumeste o noua baza de date intr-o singura etapa :

CREATE DATABASE BIBLIOTECA

Daca exista una sau mai multe baze deschise, baza de date curenta este afisata intr-o caseta, iar lista derulanta permite trecerea la alta. Intr-un program se pot obtine numele si calea bazelor de date curente cu functia DBC() si se poate schimba baza de date curenta cu instructiunea SET DATABASE TO. Pentru a determina numele si calea tuturor bazelor de date deschise, se foloseste functia ADATABASE(). aceasta creeaza un masiv bidimensional , primul element fiind numele bazei de date, iar al doilea fiind calea. Atunci cand se adauga tabele intr-o baza de date, ele apar in fereastra Database Designer. atunci cand se adauga mai multe tabele apar bare de derulare. Pentru fiecare tabel sunt afisate campurile, urmate de indecsii tabelului. O cheie micuta, situata in fata numelui unui index, identifica indexul primar. Relatiile dintre tabele sunt ilustrate cu linii de conectare. Pentru a consulta un tabel, se executa dublu clic pe el.

1.Adaugarea tabelelor existente la baza de date

Pentru a adauga un tabel existent la baza de date curenta, se executa clic pe butonul Add Table din bara cu instrumente Database Designer. definitiile tabelelor se pot trata ca orice fereastra, deci pot fi trase si redimensionate dupa dorinta. Pentru modificarea oricarui tabel , acesta se selecteaza si se executa clic pe butonul Modify Table din bara cu instrumente Database Designer.

Una dintre primele modificari care se pot face este redenumirea campurilor folosind nume lungi de campuri, insa odata facut acest lucru numele lungi trebuie folosite intotdeauna. Nu se pot folosi nici numele mai scurte stocate in fisierul DBF, nici numele trunchiate la zece caractere. Spatiile nu sunt permise in numele campurilor.

Se pot, de asemenea, adauga reguli de validare la nivel de camp in caseta de dialog Table Designer. Se poate folosi orice expresie logica atunci cand se defineste o regula de validare. Se poate apela chiar o functie pentru testele care sunt prea complexe pentru a fi exprimate intr-o singura instructiune. Singura restrictie este ca functia sa returneze.T. sau.F. Regulile de validare a campurilor sunt declansate atunci cand se incearca parasirea campului sau cand valoarea campului se modifica datorita unei instructiuni INSERT sau REPLACE.

Pentru fiecare camp al tabelului se poate adauga o valoare prestabilita. De exemplu, pentru a declara data curenta a sistemului drept valoare prestabilita, se plaseaza functia DATE() in caseta de text Default Value. Rezultatul expresiei pentru valoarea prestabilita trebuie sa fie compatibil ca tip cu campul insusi, in caz contrar FoxPro generand o eroare. FoxPro plaseaza valoarea prestabilita in campul tabelului ori de cate ori se adauga o noua inregistrare in tabel.

FoxPro utilizeaza valorile titlurilor drept anteturi ale coloanelor atunci cand se afiseaza tabelul in fereastra Browse sau Edit.Dar titlul se poate defini si pe baza altui camp sau a unei variabile, cea mai frecventa optiune fiind insa introducerea unui text simplu in caseta de text Caption.

2.Chei primare si chei candidat

Este de retinut faptul ca numai un index care indeplineste conditiile pentru a fi index candidat poate fi numit index primar. Aceasta inseamna ca expresia indexului face referire la fiecare inregistrare din tabel cu o valoare unica. Indexul primar se foloseste pentru a forma relatii cu alte tabele.

Testarea cheilor primare si a cheilor candidat are loc atunci cand VFP actualizeaza inregistrarea. De aceea este posibil sa nu se primeasca un mesaj de eroare daca valoarea cheii nu este unica decat in momentul parasirii inregistrarii.

3.Relatii permanente

Relatiile permanente definesc relatiile intre tabele si sunt stocate in caseta de dialog Database Designer. Visual FoxPro le foloseste automat la fiecare deschidere ulterioara a tabelelor. Aceasta caracteristica este utila mai ales pentru crearea tabelelor de cautare, a validarilor si a mediului de date al formularelor si rapoartelor.

Relatiile permanente sunt numite asa prin contrast cu relatiile temporare., create cu comanda SET RELATION. Motivul pentru care relatiile create cu aceasta comanda sunt temporare este ca FoxPro le dizolva atunci cand se paraseste programul sau cand se lanseaza comanda SET RELATION fara parametri. Relatiile permanente se mentin de la o rulare la alta a aplicatiilor.

Pentru a defini o relatie se executa clic pe numele unui index dintr-un tabel si se trage peste un index din alt tabel. FoxPro va afisa caseta de dialog Edit Relationship, in care FoxPro completeaza automat numele.Se pot defini relatii de tip unu-la-unu si relatii de tip unu-la-mai-multe. FoxPro aplica o serie de reguli simple atunci cand defineste tipul relatiei. In primul rand presupune ca tabelul initial se afla in partea stanga a relatiei si trebuie sa fie un index candidat sau un index primar. Daca in continuare se realizeaza o conexiune cu un index primar sau cu un index candidat din al doilea tabel , FoxPro stie ca este vorba de o relatie unu-la-unu, deoarece acestia sunt indecsi unici, care include fiecare inregistrare din tabel. Conectarea la orice alt index (normal sau unic) permite existenta mai multor inregistrari in partea dreapta a relatiei ; prin urmare FoxPro presupune ca este vorba de o relatie una-la-mai-multe. este de retinut faptul ca un index unic nu interzice prezenta mai multor inregistrari avand aceeasi valoare a indexului, dar pastreaza un pointer catre prima.

Pentru a rupe o relatie care nu mai este necesara sau este definita incorect, se executa clic pe ea si se apasa tasta Delete.

4.Modificarea proprietatilor tabelelor prin program

In trecut modificarea proprietatilor unui tabel dintr-un program era o operatie dificila, care necesita ca programul sa creeze o noua copie modificata a tabelului, dupa care sa copieze datele din vechiul tabel in cel nou. Cu Visual FoxPro aceasta sarcina a devenit mai simpla prin adaugarea a doua comenzi noi, ALTER TABLE si ALTER COLUMN. Aceasta posibilitate se refera numai la tabelele care fac parte dintr-o baza de date.

CONCEPTE AVANSATE DE GESTIONARE A BAZELOR DE DATE

Factorul care are influenta cea mai mare asupra succesului unei aplicatii de baze de date este proiectarea propriu-zisa a bazei de date. Modul in care se organizeaza datele individuale intr-un tabel si modul in care se creeaza relatii intre tabelele unei baze de date reprezinta temelia aplicatiei.

Normalizarea datelor

Cel mai important lucru care trebuie facut atunci cand se incepe o noua aplicatie este proiectarea structurii tabelelor. Un set de tabele bine concepute, pe langa faptul ca permite atingerea obiectivului aplicatiei, ofera flexibilitatea de a raspunde la probleme care nu fusesera anticipate. In timp ce in cazul unei structuri nenormalizate, generarea rapoartelor ar fi necesitat programarea manuala, greoaie, in cazul unei structurari corecte, ele se scriu aproape de la sine cu generatorul de rapoarte.

In general, structura datelor asigura succesul sau determina esecul unei aplicatii mai mult decat orice alta caracteristica individuala. Visual FoxPro se bazeaza pe modelul de baza de date relationala, propus initial de E.F. Codd in 1970. El si-a bazat modelul pe principiile matematice care guverneaza teoria multimilor relationale. El a demonstrat ca prin respectarea catorva reguli foarte stricte, care definesc crearea multimilor, datele se pot manipula cu usurinta. Aceste tehnici au devenit cunoscute sub numele de normalizarea datelor.

In primul rand, intreaga teorie referitoare la bazele de date relationale este axata pe conceptul definirii relatiilor intre fisierele continand tabele plate cu ajutorul campurilor cheie. Cu cat exista mai multe tabele, cu atat programului FoxPro ii sunt necesare mai multe relatii pentru conectarea lor. Toria multimilor nu impune ca fiecare tabel sa fie conectat direct cu toate celelalte tabele. Totusi, intrucat fiecare tabel este conectat cel putin cu un alt tabel, toate tabelele din baza de date se afla in relatie directa sau indirecta.

Pentru a analiza conceptele privind normalizarea, acest paragraf studiaza inceputul procesului de dezvoltare a aplicatiei, imediat dupa stabilirea datelor necesare.

1.Dependente functionale

Presupunand ca au fost stabilite deja care sunt campurile de date necesare, urmatoarea etapa consta in impartirea lor in tabele. Singura metoda de a stabili ce campuri trebuie incluse in fiecare tabel este prin intermediul analizei dependentei functionale.

Dependenta functionala defineste relatia dintre un atribut sau un grup de atribute ale unui tabel si un alt atribut sau grup de atribute ale altiua. In cazul de fata, atributele se refera la campuri. Deci, trebuie vazut ce campuri depind de alte campuri. Se vor grupa in acelasi tabel acele atribute care au aceeasi dependenta. Practic, numarul dependentelor functionale determina numarul de tabele necesare.

Daca se urmeaza aceasta metoda de grupare a campurilor, tabelul rezultant va fi deja foarte aproape de o forma normalizata. Totusi, va trebui sa se verifice daca sunt indeplinite cel putin primele trei reguli ale datelor normalizate :

Prima forma normala : elimina campurile care se repeta si valorile ne-atomizate

A doua forma normala : impune ca fiecare coloana sa fie dependenta de fiecare parte a cheii primare

Atreia forma normala : impune ca toate campurile non-primare sa depinda numai de campurile primare.

2.Ratiuni pentru incalcarea regulilor de normalizare

Regulile de normalizare nu sunt legi ; ele sunt simple linii directoare care ajuta la evitarea crearii unor structuri de date care limiteaza flexibilitatea aplicatiei sau ii reduc eficienta. Exemplul care urmeaza reprezinta o situatie in care incalcarea regulilor de normalizare ar putea avea sens.

Sa presupunem ca trebiue conceput un sistem de gestiune a unei biblioteci care sa impiedice un abonat sa imprumute mai mult de cinci CD-uri simultan. S-ar putea concepe acest sistem prin normalizarea fisierului care tine evidenta CD-urilor imprumutate. Acesta ar trebui sa verifice ca exista cel mult cinci inregistrari pentru fiecare abonat. In schimb, o singura inregistrare cu cinci campuri, cate unul pentru fiecare CD, ar putea simplifica dezvoltarea aplicatiei ( evident, o solutie alternativa ar fi adaugarea unui camp in tabelul principal de abonati care sa calculeze numarul de CD-uri imprumutate de fiecare abonat ).

Caracteristici avansate ale dictionarului de date Visual FoxPro

Una din caracteristicile avansate a fost deja mentionata : dictionarul de date Visual FoxPro cu capacitatea sa de a atribui nume de campuri de 128 de caractere. Desi aceasta caracteristica reprezinta o imbunatatire remarcabila fata de limita de 10 caractere a tabelelor libere, ea are dezavantajul ca este dificila trecerea la numele de 10 caractere, o data ce s-a folosit nume de camp de 128 de caractere.

1.Validari la nivel de camp

O alta caracteristica importanta este adaugarea regulilor de validare la nivel de camp si a mesajelor de validare. Visual FoxPro utilizeaza automat regulile de validare atat in mediul interactiv, cat si in formulare fara sa fie necesar sa se scrie cod sursa suplimentar. Acest tip de validare se mai numeste si validare declarativa, prin contrast cu validarea procedurala, care se bazeaza pe scrierea de cod sursa in proceduri sau in functii pentru validarea modificarilor efectuate asupra campurilor.

Visual FoxPro declanseaza regulile de validare la nivel de camp ori de cate ori se modifica valoarea unui camp si se incearca parasirea campului. De asemenea, Visual FoxPro utilizeaza regulile de validare si in unele comenzi (APPEND, BROWSE, UPDATE etc).

2.Campuri cu valori prestabilite

Se poate folosi definitia extinsa a tabelului pentru a furniza o valoare prestabilita pentru un camp. Visual FoxPro o foloseste atunci cand se adauga o noua inregistrare in tabel. Valorile prestabilite servesc mai multor scopuri :

impiedica lasarea unui camp necompletat

furnizeaza cea mai probabila valoare

asigura faptul ca testele de validare nu vor esua pentru simplul fapt ca un utilizator sare un camp.

3.Titluri si comentarii

Campurile titlu pot contine pana la 128 de caractere. Ele sunt afisate drept anteturi ale coloanelor atunci cand se deschide un tabel in fereastra Browse.

Visual FoxPro nu utilizeaza nicaieri campul Comments. Acest camp este pus la dispozitia utilizatorului pentru ca acesta sa poata explica semnificatia campului, sa justifice o anumita valoare prestabilita sau sa arate cum functioneaza validarea campului.

4.Validare la nivel de inregistrare

O regula de validare din caseta de dialog Table Properties reprezinta o validare la nivel de inregistrare. Visual FoxPro declanseaza aceasta regula atunci cand se modifica valoarea unui camp din inregistrare si se incearca trecerea la alta inregistrare. Atunci cand se foloseste validarea la nivel de camp, codul sursa de validare nu poate modifica nici un camp din inregistrarea curenta si nici nu poate deplasa indicatorul de inregistrare. In schimb, poate compara valoarea unui camp cu valoarea altuia.

Validarea inregistrarii poate fi mai complexa decat o expresie. Poate fi o functie definita de utilizator care va apela codul sursa de validare salvat in baza de date sub forma unei proceduri rezidente. Orice apel al unei expresii sau functii de validare trebuie sa returneze un rezultat logic. Daca este returnata valoarea.F., Visual FoxPro pastreaza indicatorul de inregistrari la aceeasi inregistrare si nu salveaza modificarile facute asupra ei. In plus, afiseaza textul de validare.

5.Declansatori

Urmatoarele trei optiuni din caseta de dialog Table Properties se numesc declansatori. Visual FoxPro ii executa atunci cand se insereaza, actualizeaza sau elimina o inregistrare din tabel . Ca si in cazul regulilor de validare a inregistrarilor, trebuie pastrat codul sursa al declansatorilor in baza de date sub forma unor proceduri stocate. Se pot folosi declansatorii pentru calcule sau validari suplimentare atunci cand se efectueaza oricare dintre aceste trei operatii. Exista totusi cateva lucruri care nu se pot face cu ajutorul declansatorilor si anume :

nu se poate deplasa indicatorul de inregistrari in zona de lucru curenta

nu se poate modifica valoarea nici unui camp din inregistrarea curenta

nu se poate inchide zona de lucru curenta sau deschide un alt fisier in aceeasi zona de lucru.

6.Integritate referentiala

In general, integritatea referentiala defineste operatiile permise intre tabele conectate prin relatii. Premisa de baza este ca valorii unei chei externe din tabelul parinte trebuie sa-I corespunda o cheie de cautare sau o cheie primara intr-un alt tabel (numit tabel fiu). Integritatea referentiala trateaza inregistrarile care nu indeplinesc aceste criterii drept invalide.

PARTAJAREA DATELOR IN RETEA

Una din principalele probleme ale procesarii datelor este cea ridicata de conflictele care survin atunci cand doi utilizatori incearca sa acceseze simultan aceleasi date. In multe aplicatii, cel care salveaza ultimul modificarile castiga jocul actualizarii. Datele acestei persoane reprezinta modificarile finale si definitive efectuate asupra bazei de date, in detrimentul oricaror actualizari anterioare.

Sistemul Visual FoxPro al firmei Microsoft protejeaza intr-o oarecare masura acest tip de activitate permitand utilizatorului sa foloseasca o metoda ( fie automata, fie explicita ) de blocare a inregistrarii sau a tabelului inaitea actualizarii datelor. Atunci cand tabelul si inregistrarea sau inregistrarile aferente sunt accesate, blocarea impiedica orice alt utilizator sa acceseze zona respectiva pana in momentul in care primul utilizator nu a terminat operatiile de editare si nu a parasit in bune conditii zona.

1.Coliziuni de fisiere, conflicte si blocari definitive

In locul utilizarii exclusive a datelor de catre un singur utilizator, informatiile pot fi partajate de un departament sau de un grup de utilizatori. Solutia uzuala este de a elimina datele de pe unitatea de disc locala si a le instala intr-un calculator server de fisiere la care au acces toti cei care au nevoie de fisierele respective. O alternativa o reprezinta partajarea hard-discului local. Prima abordare este cea mai uzuala, in schimb, retelele de tip ‘peer’ devin din ce in ce mai populare.

Urmatoarea problema o constituie stabilirea modului in care vor fi gestionate conflictele electronice ivite atunci cand doua persoane incearca sa acceseze aceleasi date, activitatea aceasta fiind cunoscuta sub numele de conflict de fisiere. Programele destinate sa functioneze intr-un mediu partajat trebuie sa posede un mecanism pentru evitarea consecintelor unor asemenea situatii.

Intr-o aplicatie partajata, conflictele de fisiere survin atunci cand doi utilizatori incearca sa acceseze simultan aceeasi inregistrare a aceluiasi fisier. O aplicatie trebuie sa previna evenimente de asemenea natura prin arbitrarea conflictelor intre utilizatori.

Un eveniment destul de intalnit in mediile partajate este blocarea definitiva. Aceasta survine atunci cand un utilizator a blocat o inregistrare sau un tabel, dupa care incearca sa blocheze a doua inregistrare sau tabel care a fost blocata anterior de un alt utilizator. In acelasi timp, al doilea utilizator incearca sa blocheze inregistrarea care a fost deja blocata de primul utilizator. In consecinta, ambele calculatoare vor ramane blocate,asteptandu-l pe celalalt utilizator sa incheie efectuarea modificarilor, ceea ce nu se va intampla niciodata.

Aceste paragrafe sugereaza crearea unei arhitecturi deschise, care sa permita tuturor utilizatorilor accesul liber la orice element din retea. Acest stil de gestionare a retelei, desi nu este intotdeauna acceptabil, este foarte utilizat.

Un pas inainte in directia urmatorului nivel de securitate sugereaza utilizarea unui nivel structurat de securitate a retelei, conform caruia anumimitor utilizatori sa li se acorde privilegii.

2.Tipuri de blocaje

Atunci cand se dezvolta aplicatii multiutilizator pot sa apara doua tipuri de blocaje : de fisier si de inregistrare.

2.1.Blocarea inregistrarilor sau a fisierelor ?

In aplicatiile in care trebuie asigurat accesul mai multor utilizatori, trebuie avut in vedere ca accesul la date sa fie permis numai utilizatorilor care il solicita. Un blocaj de inregistrare, daca este corect aplicat, impiedica accesul in mod scriere al altor utilizatori in afara celui care a solicitat blocarea. Pe de alta parte, un blocaj de fisier blocheaza tabelul la nivel fizic, impiedicandu-I pe ceilalti utilizatori sa scrie date in tabel atat timp cat primul utilizator editeaza una sau mai multe inregistrari ale tabelului. Blocarea inregistrarilor si a fisierelor nu ii impiedica pe ceilalti utilizatori sa citeasca date din inregistrarile sau fisierele blocate, ci interzice scrierea datelor.

Este de preferat blocarea inregistrarilor deoarece acestea interzic accesul doar la inregistrarile individuale, nu la intregul tabel.

2.2.Blocari automate sau blocari manuale ?

Exista doua metode de blocare a datelor in ceea ce priveste protejarea datelor in raport cu operatiile de manipulare afisierelor : automata si manuala.

In functie de necesitati, blocarea fisierelor poate avea loc fie automat, fie prin intermediul unei metode manuale. FoxPro va incerca sa blocheze automat inregistrarile atunci cand sunt utilizate anumite comenzi de actualizare a datelor. In tabelul urmator sunt date cateva dintre comenzile care blocheaza automat inregistrarile :

In masura posibilului, este de preferat sa se foloseasca comenzi care blocheaza inregistrari individuale in locul celor care blocheaza intregul tabel. Aceasta afirmatie se bazeaza pe faptul ca se evIta supraincarcarea retelei cauzata de blocarea unui fisier si riscul ca fisierul sa fi fost deja blocat de alt utilizator. In Visual FoxPro, un fisier poate fi blocat numai daca nu contine inregistrari blocate.

Functiile de blocare manuala testeaza starea de blocare a unei inregistrari sau a unui tabel. Daca in urma testarii se constata ca inregistrarea nu este blocata, inregistrarea ( sau tabelul ) va fi blocata si utilizatorul poate sa inceapa sa foloseasca fisierul. Pentru a bloca manual un tabel, trebuie folosita una din functiile LOCK(), FLOCK() sau RLOCK(). Daca se foloseste una dintre aceste comenzi pentru a bloca o inregistrare sau un tabel, trebuie elemInate aceste blocaje de indata ce nu se mai utilizeaza inregistrarea sau tabelul.

3.Cum se procedeaza atunci cand inregistrarea necesara este blocata ?

Cand apare o astfel de situatie, se va vedea mesajul de eroare ‘Record is in use by another’ si este necesar sa se astepte cu efectuarea editarilor.

Atunci cand se editeaza campuri situate in tabele aflate in relatie, inregistrarile aferente sunt blocate pentru a evita dubla editare. In schimb, daca inregistrarea curenta sau oricare dintre inregistrarile corelate sunt blocate de alt utilizator, tentativa de blocare va esua. Atunci cand tentativa de blocare reuseste, FoxPro permite editarea inregistrarii. Blocajul este elIminat atunci cand se trece la alta inregistrare, se activeaza alta fereastra sau se efectueaza o alta activitate.

INTRODUCERE IN PROGRAMAREA ORIENTATA PE OBIECTE

Majoritatea specialistilor sunt de parere ca modul actual de dezvoltare a codurilor procedurale este sortita pieirii. Printre ratiunile pe care se bazeaza o asemenea afirmatie sunt urmatoarele :

necesitatea de dezvoltare a unor aplicatii extrem de complexe ;

necesitatea de reducere a intervalului de timp dintre conceptie si livrare ;

necesitatea unei abordari grafice pentru comunicarea cu utilizatorii ;

necesitatea de accesare a datelor dintr-o mare diversitate de formate si platforme ;

proliferarea mediilor client/server ;

necesitatea de a asigura utilizatorului un control sporit asupra aplicatiilor;

Toate aceste motive au exercitat o presiune imensa asupra metodelor de programare traditionala. A venit momentul trecerii la un nou model de programare – programarea orientata pe obiecte. Visual FoxPro se inscrie in acest model de programare pastrand insa legatura cu trecutul pentru a mentine compatibilitatea cu toate aplicatiile FoxPro anterioare.

OBIECTE SI CLASE

Visual FoxPro extinde definitia obiectului fata de versiunile anterioare ale programului FoxPro. Majoritatea “lucrurilor” interfetei FoxPro sunt obiecte : ferestrele, butoanele, campurile.

Un obiect poseda :

*proprietati, care identifica atributele fizice ale lucrurilor ( pentru un buton de comanda dintr-un formular atribute pot fi : pozitia pe formular, latimea, inaltimea, culoarea, textul care eticheteaza butonul );

*metode, care sunt actiuni ce pot fi efectuate de obiecte ( pentru un formular doua metode sunt Open si Close )

CLASE DE BAZA

Visual foxPro prevede 28 de clase de baza predefinite, pe baza carora se pot crea noi obiecte. In tabelul urmator sunt enumerate clasele de baza ale limbajului Visual foxPro :

Visual foxPro imparte in continuare aceste clase de baza in clase container si clase control. O clasa container poate gazdui alte obiecte in interiorul ei. De exemplu, un formular apartine clasei container deoarece se pot plasa in interiorul sau alte obiecte, cum ar fi casete de validare, casete de editare, casete de text, linii si altele. Clasele control nu pot contine alte obiecte. O data ce se plaseaza un obiect control intr-un container, orice referire la obiectul respectiv trebuie sa contina si o referire la container.

De remarcat faptul ca, desi rapoartele contin obiecte cum ar fi etichete, campuri si forme, acestea nu sunt obiecte. Ele nu au proprietati, evenimente sau metode ca un formular. De altfel, nici raportul in sine nu este un obiect deoarece raportul sau obiectele pe care le contine nici nu trebuie sa urmeze noul model, bazat pe obiecte, pentru ca utilizatorii nu interactioneaza cu rapoartele.

Mostenire

Clasa de baza atribuie valori prestabilite unor proprietati. Practic,toate proprietatile unei clase de baza trebuie sa aiba valori prestabilite, chiar daca este vorba de siruri vide.

Atunci cand un obiect este creat, el copiaza nu numai proprietatile, metodele si evenimentele clasei parinte, dar si valorile prestabilite. El mosteneste aceste informatii. Se pot crea la infinit noi clase din cele deja existente, fiecare noua clasa creata mostenind toate elementele predecesoarei. Mai mult, unele obiecte pot avea mai multe clase parinte, mostenind toate proprietatile acestora.

Instanta

In dictionarul limbii engleze, instanta este definita ca fiind un caz sau un exemplar. Orice obiect creat este o instanta a clasei parinte. De aceea , procesul crearii obiectului se numeste instantiere. Daca se creeaza o alta instanta a obiectului, ea va fi identica cu prima, cu exceptia titlului ( titlul celei de a doua instante are un numar de secventa diferit de prima ).

Incapsularea proprietatilor

Chiar daca procedeele de mai sus creeaza doua forme apartinand aceleiasi clase de baza, fiecare dintre ele este independenta de cealalta. Un aspect important este ca desi formele sunt independente, numele proprietatilor fiecareia sunt identice. Versiunile anterioare ale programului foxPro suportau numai doua tipuri de variabile – publice si private. Din pacate, nici unul din aceste tipuri nu este adecvat in cazul de fata. Obiectele necesita ca variabilele asociate proprietatilor sa fie locale instantei si, in acelasi timp, sa poata fi apelate din exteriorul definitiei obiectului. Cu alte cuvinte, este necesar ca aceste variabile sa fie incapsulate in interiorul obiectelor. Prin urmare, se poate folosi acelasi nume de proprietate in mai multe obiecte. Pentru a afisa orice instanta a unei proprietati, se foloseste sintaxa urmatoare :

? <nume obiect>.<nume proprietate>

Visual foxPro numeste acest tip de notatie – notatie cu punct. Ea asociaza proprietatile cu obiectele vizate deoarece este posibil sa existe mai multe obiecte active cu aceeasi proprietate. Daca se incearca afisarea unei proprietati fara a folosi numele obiectului, Visual foxPro va considera ca se doreste valoarea unui camp al unui tabel sau a unei variabile de memorie. Daca tabelul curent are un camp cu numele respectiv sau daca exista o variabila de memorie cu acest nume, Visual foxPro afiseaza valoarea.In caz contrar, afiseaza mesajul :

Variable ‘<nume proprietate>’ is not found.

Atribuirea mai multor pseudonime unui obiect

Numele unui obiect contine un pointer ( o referinta ) la o zona a memoriei unde este stocata informatia propriu-zisa despre obiect. De aceea nu exista nici un motiv pentru a nu avea mai mult de o variabila cu acelasi pointer. De exemplu, expresia urmatoare defineste o a doua varibila care indica acelasi formular indicat de formular1.

Formular2 = formular1

Formular2 nu este o alta instanta a clasei form. Este doar un alt nume ( un pseudonim ) pentru formular1.

Eliberarea obiectelor

Pentru a elibera ferestrele create cu comanda define window , se pot folosi in continuare comenzile traditionale. Pentru a elimina individual, se foloseste comanda RELEASE WINDOW <fereastra> ; pentru a le elimina pe toate simultan, se foloseste CLEAR WINDOWS.

Pentru a elimina un obiect formular, comanda RELEASE WINDOW nu va functiona decat daca se stie numele formularului, nu titlul sau pseudonimul folosit in locul numelui obiectului. In general, eliberarea numelui unui obiect elimina totodata si obiectul. Daca insa au fost create mai multe pseudonime, comanda RELEASE elimina numai una dintre cele doua ferestre.Aceasta deoarece Visual foxPro elimina un obiect numai daca se elibereaza toate referintele la el ( pseudonimele ), lucru care se poate face utilizand comanda

RELEASE ALL LIKE formular*

Incapsularea obiectelor

La fel ca si numele variabilelor, clasele de obiecte nu pot contine blancuri. De asemenea, utilizarea majusculelor si a literelor mici pentru denumirea ferestrelor si obiectelor, desi tine de preferintele fiecaruia, ar trebui sa respecte o coventie standard de denumire. Visual FoxPro este complet insensibil la majuscule.

Numele obiectelor, dupa cum s-a mentionat anterior, nu sunt obiectele propriu-zise, ci mai curand simpli pointeri catre locatiile de memorie care stocheaza informatiile obiectelor. Se pot privi proprietatile unui control ca fiind elementele unui masiv. Pentru a face referire la orice element al unui masiv, este nevoie de numele masivului si de numarul elementului. In cazul de fata, numele obiectului este echivalentul numelui masivului, iar numele proprietatii identifica elementul. Atunci cand se plaseaza un obiect in altul se adauga pur si simplu un nou element la masivul primului obiect pentru a stoca pointerul la noul obiect. Deoarece numele obiectelor sunt pointeri la obiectul real, se poate face ca FoxPro sa parcurga ierarhia de pointeri pentru a gasi referinta obiectului de pe cel mai de jos nivel si pentru a o stoca separat.

Utilizarea codului pentru crearea subclaselor

In continuare se va arata ca exista o metoda mult mai flexibila pentru a crea obiecte ale claselor de baza.

1.Definirea unei subclase

O subclasa nu este un obiect ; poate fi privita mai degraba ca o copie a unui model principal folosit pentru crearea obiectelor. Se pot crea subclase din orice clasa de baza cu ajutorul comenzii DEFINE CLASS. Instructiunea urmatoare reprezinta o definitie completa, dar simpla, a unei subclase :

DEFINE CLASS TestWind AS FORM

END DEFINE

DEFINE CLASS creeaza o noua clasa bazata pe o clasa existenta, Form, si ii atribuie un pseudonim, TestWind. Acesta noua clasa este o subclasa. Totusi, aceste instructiuni par sa nu faca nimic. Ca si functia CREATEOBJECT , ele definesc ceva in memorie, insa doar atat. De aceea se foloseste functia de mai sus pentru a crea o instanta a noii clase. Aceasta va returna un pointer caruia I se va putea atrbui numele unei variabile. Pentru a crea un obiect apartinand noii clase TestWind, se apeleaza functia CREATEOBJECT . De data aceasta insa, in locul clasei de baza FORM numele clasei este numele noii subclase, TestWind.

Avantajul acestei abordari este ca se poate crea o aplicatie cu un aspect personalizat, cum ar fi spre exemplu existenta unor ferestre cu fondul galben si textul rosu. Aceste informatii se pot incapsula in definitia noii clase. In continuare, orice formular creat folosind aceasta clasa mosteneste aceste culori.

O data cu trecerea anilor, specificarea culorilor a devenit mai complexa , fapt care se datoreaza posibilitatii monitoarelor de a lucra cu 16, 64, 256 sau chiar 16 777 216 de culori .

Iata de ce Visual FoxPro opteaza pentru o abordare stiintifica a problemei si defineste culorile ca reprezentand amestecuri a trei culori primare : rosu, verde si albastru. De altfel, termenul RGB provine tocmai de la initialele acestor culori in limba engleza. Fiecare culoare primara are o valoare cuprinsa intre 0 si 255, reprezentand cantitatea din culoarea respectiva. Fiecare culoare afisabila este reprezentata ca o combinatie a valorilor celor trei culori primare.

De exmplu , specificarea valorii 0 pentru toate cele trei culori primare semnifica faptul ca nu se doreste nici una din aceste culori. Aceasta absenta a culorii creeaza negrul. In mod similar, specificarea valorii maxime (255) pentru fiecare culoare primara desemneaza culoarea alba.

2.Adaugarea unor noi proprietati in definitia unei subclase

Pentru a adauga noi proprietati in definitia unei subclase, este suficient sa se includa numele proprietatii imediat dupa instructiunea DEFINE CLASS , urmata de valoarea prestabilita. Desi se pot initializa valorile prestabilite ale proprietatilor folosind orice tip de variabila, nu se poate defini valoarea prestabilita folosind o expresie. Nu exista nici o limita in privinta numarului de proprietati pe care le poate avea o clasa.Ca regula generala, daca nu se foloseste in mod explicit o proprietate prin intermediul unei metode, atunci aceasta nu isi justifica existenta.

3.Adaugarea controalelor intr-un container

Atunci cand se defineste o noua clasa care deriva dintr-o clasa de baza existenta, se pot adauga noi proprietati. Avand un formular cu mai multe controale elementare, necesare tuturor utilizatorilor si dorind adaugarea unor controale avansate, rezervate utilizatorilor experimentati inseamna ca este nevoie de un formular care poate fi extins la cerere. Acest lucru se poate face utilizand un buton, care va fi adaugat formularului initial in urma utilizarii optiunii ADD OBJECT. Prin utilizarea acestei optiuni, butonul de control este incorporat in definitia subclasei. Prin urmare, el poate fi mostenit. Dupa adaugarea butonului, este necesar ca evenimentului CLICK sa I se asocieze o metoda, pentru ca acesta sa reactioneze.

Evenimente

Evenimentele sunt cele care pun totul in miscare in programarea orientata spre obiecte. Executia unui clic cu mouse-ul este un eveniment. Apasarea unei taste este un eveniment.

1. Recunoasterea evenimentelor

In majoritatea cazurilor numele evenimentelor in Visual FoxPro sunt destul de sugestive. Cu toate acestea, in tabelul urmator sunt prezentate cateva evenimente alaturi de scurte descrieri.

Majoritatea obiectelor utilizeaza maxim zece evenimente, iar dintre acestea doua sau trei sunt comune tuturor obiectelor. Nu se pot modifica evenimentele pe care un obiect le recunoaste si nici nu se pot adauga altele noi.

2.Asocierea metodelor la evenimente

Pentru a asocia unele actiuni unui eveniment este necesar sa se plaseze o procedura in segmentul de cod DEFINECLASS. Atunci cand se defineste procedura pentru un eveniment, trebuie ca numele evenimentului sa fie precedat de numele obiectului, deoarece pot exista in aceeasi clasa mai multe obiecte diferite care au acelasi eveniment. Este necesara folosirea obligatorie a referintelor relative (cuvinte cheie, care reprezinta scurtaturi de referinte la obiecte) pentru generalizarea referintelor care vor fi incapsulate in definitia unei clase. Tabelul urmator prezinta cateva cuvinte cheie utilizate pentru a face referire la obiecte si definitiile lor :

Se pot adauga proprietati si metode unui obiect, nu se poate adauga insa un nou eveniment. Nu se pot modifica tipurile de evenimente recunoscute de Visual FoxPro pentru nici un control.

Referentierea obiectelor

Exista mai multe moduri pentru a face referire la obiecte. Se poate folosi un pseudonim deoarece un obiect poate avea mai multe nume care sa faca referire la el. De asemenea, atunci cand un obiect contine mai multe obiecte, se poate face referire la obiectele individuale folosind o ierarhie de nume de obiecte sau se poate asocia un nou pseudonim care sa reprezinte orice portiune a ierarhiei. In continuare sunt mentionate doua noi metode de a face referire la obiecte, prin intermediul masivelor, respectiv prin rezolvarea domeniului.

1.Utilizarea masivelor de obiecte

Daca se construieste un formular care are un grup de butoane (sau alte controale ) inrudite, fiecare obiect se poate defini printr-o referinta distincta la obiectul respectiv. In acest caz ar fi nevoie insa de cate o procedura distincta pentru fiecare eveniment al fiecarui obiect. Prin gruparea obiectelor intr-un masiv, se poate folosi o singura procedura pentru fiecare eveniment comun, definind actiunile individuale prin intermediul unei instructiuni CASE. Masivele de obiecte sunt similare masivelor de orice alt tip de variabile. De exemplu, fiecare membru poate contine un alt tip de obiect. Primul obiect ar putea fi un buton de comanda, urmatorul, un buton radio si asa mai departe. Daca se redimensioneaza masivul, Visual FoxPro initializeaza elementele adaugate cu valoarea.F.. Daca se reduce dimensiunea masivului, obiectele la care fac referire elementele eliminate sunt eliberate.

Pe de alta parte, nu se poate asocia un obiect unui intreg masiv cu o singura comanda asa cum se asociaza valori altor masive. De asemenea, nu se poate modifica nici o proprietate comuna tuturor obiectelor in intregul masiv cu o singura instructiune.

2.Metode de referentiere folosind operatorul de rezolutie a domeniului

Mostenirea poate fi performanta. Atunci cand se creeaza subclase, se mostenesc toate proprietatile si metodele clasei anterioare. Se pot adauga noi proprietati si metode in subclasa. Se pot, de asemenea, rescrie metodele unei clase anterioare.

Daca se doreste insa si adaugarea de cod unei metode,nu sunt probleme deosebite daca este vorba de o linie, doua. Dar daca se impune repetarea a zeci de linii, exista riscul ca modificarile sa nu fie efectuate in mod consecvent in toate copiile. O solutie mai buna decat aceasta o reprezinta utilizarea referirii la codul din clasa initiala. Astfel se poate folosi un operator de rezolutie a domeniului (::) pentru a face referire la o metoda a unei clase aflate mai sus in ierarhia de mosteniri. Daca pentru acest caz se ruleaza programul, caseta de mesaje a clasei initiale va fi urmata de o caseta de mesaje apartinand clasei nou construite.

Crearea claselor personalizate

Se pot crea clase personalizate care nu au elemente vizuale. Ele constau in intregime din proprietati si metode. Aceste clase nu rezerva spatiu pentru evenimente si metode care nu au sens pentru obiecte non-vizuale. De exemplu, nu sunt necesare evenimente pentru mouse, evenimente drag-and-drop, evenimente de activare etc.

Se defineste o variabila de memorie intr-o procedura utilizata drept metoda pentru un obiect personalizat. Mai mult, variabila este declarata publica. O problema deosebita ce poate sa apara este imposibilitatea accesarii acestei valori a variabilei din alta parte a aplicatiei, decat aceea in care a fost definita. Motivul pentru care se intampla acest lucru este ca toate variabilele definite si utilizate in definitia unei clase devin incapsulate in ea. Aceasta inseamna ca ele nu exista nicaieri altundeva decat in obiectul respectiv. Daca se doreste accesarea unei variabile care este definita intr-o metoda a unei clase, trebuie fie sa se initializeze variabila si sa I se declare domeniul in exteriorul obiectului, fie sa se defineasca ca fiind o noua proprietate care poate fi accesata folosind notatia cu punct.

Crearea unei biblioteci de clase

Daca obiectul creat este un obiect vizual, se poate beneficia de capacitatea oferita de Visual FoxPro de a crea o biblioteca de clase. Ulterior, se poate atasa si folosi aceasta biblioteca comuna in aplicatii.

Pentru a initia o bibliotaca de clase, aceasta trebuie creata :

CREATE CLASSLIB USEFOX

Aceasta instructiune creeaza un fisier fizic cu extensia VCX pe discul curent sau pe cel prestabilit. se poate furniza un nume si o cale pentru a crea fisierul pe orice disc si in orice director. De asemenea, se poate specifica o extensie diferita de VCX. Totusi, extensia prestabilita fiind VCX, daca in aceasta instructiune sau oriunde altundeva nu se specifica extensia, este utilizata biblioteca de clase.

Pentru biblioteca de clase trebuie creata o clasa, care poate fi personalizata prin folosirea oricarei clase de baza suportate de Visual FoxPro. Se poate face de asemenea referire la o clasa personalizata prin includerea clauzei FROM <NumeBibliotecaDeClase> care indica programului VPF unde sa o caute.

Pentru a utiliza o biblioteca de clase, este necesar ca aceasta sa fie deschisa cu comanda urmatoare :

SET CLASSLIB TO \USINGFOX.300\PROGRAMS\USEFOX.VCX

Daca exista mai multe biblioteci de clase, se adauga cuvantul ADDITIVE la sfarsitul comenzii.

MOTIVATIA LUCRARII

Aplicatia “Smart Box” are drept scop gestionarea unei biblioteci de CD –uri.

Necesitatea tot mai mare de stocare a datelor si a unor suporturi de date de capacitati tot mai mari duce la solutia CD –urilor, care sunt ieftine si performante avand in vedere raportul calitate-pret. Acest lucru a generat o explozie a numarului acestora. Ceea ce impune, in cazul unei firme cu un numar relativ mare de CD- uri, folosirea unei aplicatii PC. Este de asemenea o solutie comoda si sigura.

Sa consideram un exemplu : daca acasa avem la dispozitie 5 CD –uri cu soft, 3 cu muzica comprimata, 5 cu muzica necomprimata, 5 cu jocuri, 20 reviste si 5 prieteni care ar dori sa imprumute cate unul sau doua din aceste CD-uri, ar fi o adevarata povara sa luam un caiet sa scriem de fiecare data numele CD –ului, sa incepem sa cautam unde ar putea fi imprumutat un CD care ne este necesar urgent. Asadar, o aplicatie ca aceasta este binevenita. Cu atat mai mult, intr-o firma cu 100 angajati care doresc sa imprumute din biblioteca de probabil 50 sau 100 de CD –uri ar fi imposibil de tinut o evidenta corecta si rapida fara ajutorul calculatorului.

Nucleul lucrarii este baza de date “smartbox.dbc”. Contine tabelele necesare, relatiile permanente, triggerele si procedurile aferente unei baze de date relationale.

S-au folosit avantajele programarii orientate pe obiecte. Utilizarea claselor da aplicatiei o structura organizata, accesibila programatorului.

PREZENTAREA BAZEI DE DATE “SMART BOX”

Pentru indeplinirea scopului principal al aplicatiei vom folosi urmatoarele tabele principale :

A) tabela “IMPRUMUTURI” care sa cuprinda, in principiu, urmatoarele date:

numele departamentului care imprumuta

numele angajatului care poarta responsabilitatea pentru CD- ul imprumutat

numele CD- ului

data imprumutarii

B) tabela “ARHIVA” cu evidenta CD-urilor imprumutate si returnate. Se doreste ca in timp sa se observe ce CD- uri au fost mai folosite, cine a imprumutat mai multe CD-uri. In plus nu se doreste ca in tabela de imprumuturi sa apara si cele returnate, pentru o mai usoara utilizare a aplicatiei.

C) tabela “ITEMS” care cuprinde CD- urile, avand in componenta urmatoalere campuri:

numele CD-ului

domeniul din care face parte softul de pe el

luna si anul in care au fost scoase pe piata – de exemplu pentru CD-urile anexate diverselor reviste este bine sa stim luna si anul revistelor respective, care pot sa fie diferite de luna si anul in care introducem informatia in aplicatia “SmartBox:”.

data curenta

eticheta CD- ului inscriptionata de catre fabrica producatoare pe CD, necesara pentru identificarea fara posibilitate de eroare a unui CD.

Pe langa aceste tabele principale, care cuprind datele necesare in primul rand, luand in considerare normalizarea datelor si dependenta functionala, mai sunt necesare urmatoarele tabele:

tabela de departamente de utilizatori

tabela de utlizatori din departamentele de mai sus

tabela cu tipuri de CD-uri. De exemplu film, documentare, muzica, etc.

La crearea tabelelor din baza de date s-a tinut cont de urmatoarele principii:

stocarea informatiilor o singura data reduce riscul aparitiei erorilor

prevenirea stergerii informatiilor de valoare

neincluderea datelor calculate sau derivate din alte date

stocarea informatiilor in campuri de tip si marime optime si cat mai mici din punct de vedere logic

Structura bazei de date este urmatoarea :

Relatiile de integritate referentiala respecta urmatoarele reguli :

Tabela “DEPARTAMENTE”

Campul “id_dpt” are rol de identificator unic pentru fiecare departament. Este deci cheie primara si va fi folosit pentru integritatea referentiala in relatia cu celelalte tabele.

Tabela “UTILIZATORI”

Campul “id_ut” este identificator pentru utilizatori.

Campul “nume_ut” defineste numele utilizatorului si este de tip candidat pentru a nu fi introdus acelasi nume de 2 ori.

Campul “id_dpt” apare pentru identificarea departamentului din care face parte utilizatorul respectiv.

Tabela “ IMPRUMUTURI” :

Contine informatii directe cu privire la cine, ce si cand a imprumutat.

De remarcat ca sunt folosite campurile de identificare pentru denumirile respective. Folosim acest mod de lucru deoarece campurile de identificare sunt mai scurte, mai rapid de indexat. Pentru numele unui CD, de exemplu vom folosi campul nume_item, tip caracter de lungime 30. O cheie primara pe acest camp este mult mai greoaie pentru aplicatie decat campul id_item, tip numeric de lungime 5 cu 0 zecimale. In plus schimarea numelui unui CD este mai simplu de realizat deoarece identificatorul ramane acelasi.

Tabela “TIPOBIECT”

De remarcat campul “capturare” de tip logic care se refera la faptul ca respectivului item ii poate fi capturata structura. De exemplu pentru CD –uri putem face capturarea structurii de directoare, in schimb pentu reviste nu putem face acest lucru.

Tabela “ITEMS”

Contine numele itemurilor din biblioteca : CD –uri, reviste.

Remarcam existanta campurilor :

luna, an care reprezinta luna si anul inscrise pe CD, de exemplu pentru CD –urile atasate revistelor CHIP, PC REPORT putem scrie luna si anul de editare.

data_a care reprezinta data de adaugare in baza de date ;

campul “label” reprezinta eticheta inscriptionata de fabrica pe CD, pentru posibilitatea de identificare a sa, fara posibilitatea unei erori

campul “imprumutat” de tip logic pentru informarea rapida daca e disponibil pentru a fi imprumutat

Tabela “ITEMS_DET”

Contine detalii cu privire la itemurile din biblioteca. Anume, pentru CD –uri contine ceea ce a fost capturat de pe ele : structura de fisiere sau simple informatii editate manual de catre utilizatori.

Mai contine si campul “observatii “ pentru notarea de observatii cu privire la detaliile respective.

Tabela “IDKEY”

Aceasta tabela are rol strict functional, si anume acela de a furniza numere de identificare pentru inregistrari. Pentru a putea crea inregistrari noi fara sa tinem cont de ceilalti utilizatori din retea e necesar sa putem lua numere de identificare care sa nu coincida cu cele luate de ceilalti din retea. De exemplu, in tabela “utilizatori” numarul de identificare cel mai mare este 152. Am creat o inregistrare noua. Numarul de identificare maxim devine 153. Daca nu facem salvarea imediata a inregistrarii atunci numarul de identificare maxim din tabela originala ramane tot 152. Daca cineva din retea creeaza o noua inregistrare in tabela “utilizatori “, nu stie ca eu am o noua inregistrare si poate da numarului de identificare tot valoarea 153. De aceea e necesara o tabela care sa poate fi actualizata imediat si care sa contina numarul de identificare maxim la care s-a ajuns in fiecare tabela.

Vederea “V_ARHIVA”

Din motive functionale s-a creat vederea “v_arhiva”. Este o vedere pentru tabela “arhiva” care s-a creat pentru a putea ordona inregistrarile din tabela “arhiva” dupa nume item sau nume utilizator.

Daca am fi lucrat direct cu tabela “arhiva”, ordonarea s-ar fi putut face dupa id_ut sau id_item. In aceste cazuri ordonarea dupa id_ut nu ar fi fost alfabetica, ci de fapt dupa id_ut.

Privire de detaliu asupra bazei de date

Pentru crearea identificatorilor din tabele se foloseste procedura “getid()” din “util.prg”.

S-au stabilit valori implicite acolo unde e necesar. De exemplu pentru data imprumutarii unui CD se da valoare implicita data si ora din momentul respectiv.

Pentru toate tabelele, cu exceptia items_det si arhiva s-a creat un camp de tip cheie primara care este utilizat in relatiile de integritate referentiala.

S-a urmarit protejarea datelor in cazul stergerii sau modificarii lor. De exemplu, nu se poate sterge un CD implicat intr-un imprumut. De asemenea, nu se poate adauga la imprumuturi un CD care nu exista in tabela “items”. Toate aceste conditii sunt indeplinite cu ajutorul relatiilor de integritate referentiala definite in baza de date. Aceste relatii au fost create cu ajutorul “Referential Integrity Builder”. Regulile stabilite pentru toate relatiile sunt de tipul:

CASCADA – pentru actualizare – la actualizarea inregistrarii parinte se actualizeaza si inregistrarile corespunzatoare din tabela fiu.

RESTRICT – pentru inserare – nu e permisa inserarea unei inregistrari in tabela fiu fara ca aceasta sa existe in tabela parinte

RESTRICT – pentru stergere – nu e permisa stergerea unei inregistrari in tabela parinte daca aceasta exista in tabela fiu.

Aplicatia mai cuprinde urmatoarele :

Programe

main.prg – programul principal in care se initializeaza aplicatia. Se executa configurari initiale si se creeaza obiectul de tip “aplicatie” definit in cele ce urmeaza la capitolul “Clase”

util.prg – contine functii si proceduri utilizate in cadrul aplicatiei

PROCEDURE get_id – extrage un nou identificator pentru tabele

FUNCTION encom(lobjname) – stabileste starea de activare a unui obiect din bara de instrumente

FUNCTION encomnew() – stabileste starea de activare a butonului “new” din bara de instrumente

FUNCTION encomdelete()- stabileste starea de activare a butonului “delete” din bara de instrumente

FUNCTION IsTag (tcTagName, tcAlias)- determina existenta unui tag (index) intr-un alias

FUNCTION FormIsObject() – determnina daca un formular exista si este de tip obiect

Function doerror(nerror,cmethod,nline) – functia de tratare a erorilor (in afara formularelor care trateaza intern erorile

FUNCTION OnShutdown() – functia care se executa daca se da shutdown in timpul rularii aplicatiei

FUNCTION fadir(ldirector) – functia care captureaza structura directoarelor de pe CD

Clase

baza.vcx – librarie de clase care cuprinde clase care se vor utiliza pentru crearea diverselor controale in formulare si nu numai.

plus.vcx

In cele ce urmeaza prezentam pe scurt codul celor 2 clase.

BAZA.VCX

**************************************************

*– Class: dbaseform (c:\lucru\proiecto\clase\baza.vcx)

De remarcat existenta urmatoarelor metode

*– Muta cursorul la inregistrarea urmatoare

PROCEDURE next

*– Muta cursorul la prima inregistrare

PROCEDURE first

*– Muta cursorul la ultima inregistrare

PROCEDURE last

*– Muta cursorul la inregistrarea anterioara

PROCEDURE prior

*– Salveaza modificarile in aliasul curent

PROCEDURE save

*– Sterge inregistrarea curenta

PROCEDURE delete

*–Anuleaza modificarile facute de la ultima salvare. Totodata anuleaza o inregistrare noua daca nu a fost salvata.

PROCEDURE restore

*– Apelarea metodei Refresh

PROCEDURE refreshform

*– Schimba modul “wait” pentru cursor in controalele de pe ecran.

PROCEDURE waitmode

*–Adauga numele formei la menul “Window” al aplicatiei..

PROCEDURE addtomenu

*– Sterge numele formei din menu

PROCEDURE removefrommenu

*– Afiseaza intrebare de salvare a modificarilor.

PROCEDURE asktosave

*– Pregateste pentru o noua inregistrare

PROCEDURE new

*– Actiunea de imprimare a unui raport

PROCEDURE imprima

*– Datele schimbate ?

PROCEDURE datachanged

*– Salveaza valoarea controlului curent

PROCEDURE writebuffer

PROCEDURE activarecimp

**************************************************

*– Class: dpageform (c:\lucru\proiecto\clase\baza.vcx)

PROCEDURE new

**************************************************

*– Class: dcheckbox (c:\lucru\proiecto\clase\baza.vcx)

**************************************************

*– Class: dcombobox (c:\lucru\proiecto\clase\baza.vcx)

**************************************************

*– Class: dcommand (c:\lucru\proiecto\clase\baza.vcx)

**************************************************

*– Class: deditbox (c:\lucru\proiecto\clase\baza.vcx)

**************************************************

*– Class: dgrid (c:\lucru\proiecto\clase\baza.vcx)

DEFINE CLASS dgrid AS grid

*– Nr. de cicluri la apasarea repetata a headerului.

PROTECTED cyclecount

cyclecount = 1

*– Coloana curenta.

PROTECTED crtcolumn

crtcolumn = "''"

Name = "dgrid"

*– Stabileste ordinea de afisare (index) parametrii: tag, numarcoloana

PROCEDURE setorder

lparameters tagname,col_name

this.setall("forecolor",RGB(0,0,0),"header")

this.cyclecount=this.cyclecount+1

if this.crtcolumn#col_name

this.cyclecount=2

endif

if this.cyclecount=4

this.cyclecount=1

endif

lname=EVAL('this.'+col_name)

do case

case this.cyclecount=1

set order to

lname.header1.forecolor=RGB(0,0,0)

case this.cyclecount=2

set order to tag &tagname ascending

lname.header1.forecolor=RGB(255,0,0)

case this.cyclecount=3

set order to tag &tagname descending

lname.header1.forecolor=RGB(0,0,255)

endcase

this.crtcolumn=col_name

thisform.refresh()

ENDPROC

ENDDEFINE

*– EndDefine: dgrid

**************************************************

*– Class: dlabel (c:\lucru\proiecto\clase\baza.vcx)

**************************************************

*– Class: dlistbox (c:\lucru\proiecto\clase\baza.vcx)

**************************************************

*– Class: doptiongroup (c:\lucru\proiecto\clase\baza.vcx)

**************************************************

*– Class: dtextbox (c:\lucru\proiecto\clase\baza.vcx)

**************************************************

*– Class: ingrid (c:\lucru\proiecto\clase\baza.vcx)

**************************************************

*– Class: standardform (c:\lucru\proiecto\clase\baza.vcx)

DEFINE CLASS standardform AS form

*– Toggles the wait cursor on and off for all controls on the screen.

PROCEDURE waitmode

*– Adds the caption of the form to the Window menu.

PROCEDURE addtomenu

*– Removes the caption of the form from the Window menu.

PROCEDURE removefrommenu

**************************************************

PLUS.VCX

**************************************************

*– Class: aplicatie (c:\lucru\proiecto\clase\plus.vcx)

**************************************************

*– Class: apptoolbar (c:\lucru\proiecto\clase\plus.vcx)

*– ParentClass: toolbar

DEFINE CLASS apptoolbar AS toolbar

**************************************************

*– Class: apptoolbarbutton (c:\lucru\proiecto\clase\plus.vcx)

**************************************************

*– Class: apptoolbarclock (c:\lucru\proiecto\clase\plus.vcx)

*– ParentClass: timer

DEFINE CLASS apptoolbarclock AS timer

**************************************************

*– Class: dformretval (c:\lucru\proiecto\clase\plus.vcx)

*– ParentClass: form

DEFINE CLASS dformretval AS form

**************************************************

*– Class: about (c:\lucru\proiecto\clase\plus.vcx)

*– ParentClass: dformretval (c:\lucru\proiecto\clase\plus.vcx)

DEFINE CLASS about AS dformretval

**************************************************

*– Class: dtoolbar (c:\lucru\proiecto\clase\plus.vcx)

*– ParentClass: toolbar

*– Saves the position of the toolbar to the INI file.

PROTECTED PROCEDURE savewindowpos

*– Restores the window's position from the INI file.

PROTECTED PROCEDURE restorewindowpos

PROCEDURE cmdprint.Click

PROCEDURE cmdfirst.Click

PROCEDURE cmdprior.Click

PROCEDURE cmdnext.Click

PROCEDURE cmdlast.Click

PROCEDURE cmdnew.Click

PROCEDURE cmdsave.Click

PROCEDURE cmdrestore.Click

PROCEDURE cmddelete.Click

PROCEDURE cmdclose.Click

**************************************************

*– Class: dtoolbarbutton (c:\lucru\proiecto\clase\plus.vcx)

**************************************************

*– Class: environment (c:\lucru\proiecto\clase\plus.vcx)

*– Setari specifice sesiunii private de date

PROCEDURE setspecial

Formulare

Formularele au fost create pe baza a una din urmatoarele 2 categorii de clase:

pe baza clasei de baza “form”

pe baza uneia din clasele de tip “form” din librariile “baza.vcx”,”plus.vcx”.

Acestea sunt :

“standardform” – tip standard

“dbaseform” – tip de baza pentru formulare cu una sau 2 tabele

“dpageform” – formular pentru tabele cu o singura tabela

“dformretval” – formular care returneaza o valoare

Majoritatea formularelor contin tabele. Au fost folosite zone tampon pentru inregistrari pe o inregistrare pentru tabela parinte sau pe toate inregistrarile pentru tabela fiu. Prin urmare, aplicatia este multi-user.

Formularele care tin evidenta cuprind 2 subpagini : in prima se face introducerea / modificarea unei inregistrari iar in a doua se vizualizeaza lista cu toate inregistrarile din care se alege cea dorita pentru modificare in subpagina 1.

imprumuturi – tabela principala cu imprumuturi

S-au folosit zone tampon de inregistrari astfel:

pe o inregistrare pentru tabelele “utilizatori”, “arhiva”.

pe toate inregistrarile pentru tabela “imprumuturi”.

Subpagina de actualizare cuprinde o lista cu itemurile din care putem alege unul pentru stabilirea unui imprumut. In dreapta sus avem un control de tip « combobox » cu utilizatorii, din care alegem pe cel care efectueaza imprumutul. In dreapta jos avem un control de tip « grid » in cu detaliile privitoare la imprumuturile efectuate de catre un utilizator. Butonul de deasupra gridului realizeaza functia de returnare a unui imprumut. El scoate inregistrarea din imprumuturi si o introduce ca inregistrare noua in tabela « arhiva ».

Adaugarea unui imprumut nou pentru utilizatorul curent se poate face in mai multe moduri :

prin folosirea butonului « New » din bara de instrumente

prin tragerea unui item din lista peste tabela de imprumuturi. Apare un meniu care ne intreaba daca dorim sa modificam inregistrarea curenta sau sa adaugam o inregistrare noua

prin click dreapta cu mouse-ul peste gridul cu imprumuturi apare un alt meniu din care putem alege sa introducem o inregistrare noua

Butonul de stergere din bara de instrumente sterge definitiv o inregistrare, fara sa o mai introduca in arhiva. A fost creat acest buton pentru cazul in care se introduce un imprumut, dar se face returnarea tot atunci din diverse motive. Ar fi neconcludenta o introducere in arhiva.

arhiva – arhivarea imprumuturilor returnate

Prin stergerea cu ajutorului butonului din dreapta jos se pot sterge definitiv inregistrarile din arhiva.

items – evidenta CD- urilor din biblioteca

S-au folosit zone tampon de inregistrari astfel:

pe o inregistrare pentru tabelele “items”.

pe toate inregistrarile pentru tabela “items_det”.

In subpagina de introducere/modificare avem, pe langa campurile necesare, un tabel cu inregistrarile din tabela “items_det” care cuprinde detaliile cu privire la un item : structura de fisiere a unui CD, articole dintr-o revista s.a..

Pentru capturarea structurii unui CD folosim butonul “Capturare structura” in care, cu ajutorul unei functii autoapelante, folosind functia “ADIR” aflam structura de directoare. Nu exista in Visual FoxPro o functie care prin simpla apelare sa faca acest lucru.

Butoanele “+” si “-“ adauga, respectiv sterge din tabela de detalii.

Pentru facilitarea stergerii tuturor inregistrarii am realizat formularul “mesaj” care foloseste la afisarea mesajului prin care se stabileste optiunea pentru stergerea uneia sau a mai multor inregistrari in items. Anticipam faptul ca tabela items_det va avea foarte multe inregistrari. Sa ne gandim la un CD, pe care putem avea sute sau mii de fisiere. De aceea, pentru o operare usoara si rapida, avem posibilitatea stergerii tuturor inregistrarilor din detalii corespunzatoare itemului curent.

Totodata, pentru stabilirea parametrilor la capturarea structurii CD –urilor am realizat formularul “mesaj_capt” in care se alege, dupa preferinta, daca se captureaza fisiere, directoare si daca da, pana la ce subramura.

4. departamente – evidenta departamentelor cu angajati

S-au folosit zone tampon de inregistrari pe o inregistrare pentru tabela “departamente”.

utilizatori – evidenta utilizatorilor care imprumuta

S-a folosit zona tampon de inregistrari pe o inregistrare pentru tabela “utilizatori”.

Pentru evidenta utilizatorilor, avem controlul de tip “combobox” care are “RowSource=departamente.nume_dpt” pentru a putea alege din lista de departamente pe cel caruia apartine utilizatorul respectiv.

Pentru adresa, fiind un camp de tip “memo” am folosit un control de tip “editbox”.

obiecte – evidenta tipuri de CD –uri

S-a folosit zona tampon de inregistrari pe o inregistrare pentru tabela “tipobiect”.

De remarcat casuta de validare « suporta captura » care, printr-un camp de tip logic stabileste daca obiectul respectiv suporta sau nu captura. Adica, daca, de exemplu, avem un CD, casuta va fi bifata, daca avem o revista nu va fi bifata, deoarece unei reviste nu-I putem captura structura de directoare. Aceasta proprietate va determina daca butonul « Capturare structura » din formularul « ITEMS » va fi activ sau nu.

status – afiseaza o forma de stare la intretinerea bazelor

intretin – formularul de la intretinerea bazelor.

E necesar ca, periodic, sa se dea « Intretinere baze » in primul rand pentru refacerea indecsilor. Daca un index este stricat, apar erori. Cu atat mai mult atunci cand, de exemplu, o lista nu e corect ordonata, dar nu numai atunci, e necesara o reindexare. La indexare, chiar daca un tabel sau baza de date sunt stricate, li se va reface structura deoarece programul de Intretinere Baze preia informatiile cu privire la structura bazei de date din tabela « data\dbcinfo.dbf ». De aceea trebuie ca aceasta tabela sa nu fie deteriorata sau stearsa.

 Meniuri

main – meniul principal al aplicatiei

drag – meniul care apare la modificare/adaugarea unei inregistrari in imprumuturi

sh_impr – meniu pentru lucrul cu inregistrarile in imprumuturi

Aplicatia foloseste 2 tipuri de bare de instrumente:

bara pentru controlul inregistrarilor la modificarea in formulare : pe baza clasei “dtoolbar”. Se poate naviga inainte si inapoi pe inregistrari, se poate adauga inregistrare noua, se poate sterge o inregistrare, se salveaza sau anuleaza modificarile.

bara pentru accesarea rapida a formularului “imprumuturi” – pe baza clasei “apptoolbar”

Ambele clase se afla in libraria “plus.vcx”.

Fisiere text

smartbox.h – contine constantele de preprocesare folosite in aplicatie

Pentru facilitarea scrierii codului s-au folosit constantele de preprocesare. Acestea, in general, incearca sa semnifice cat mai mult, functionalitatea constantelor respective.

Alte fisiere

Fisiere grafice de tip ‘.bmp’, ‘.ico’.

Explicarea functionarii aplicatiei

Programul principal la pornirea aplicatiei este main.prg. Acesta incepe cu directiva de preprocesare #INCLUDE « smartbox.h » care include constantele de preprocesare folosite in aplicatie.

Apoi este declarata procedura in caz de eroare, se fac configurari de mediu initiale si se creaza obiectul de tip “aplicatie” care este stocat in libraria de clase “plus.vcx”.

#INCLUDE "smartbox.h"

PUBLIC oApp

oApp = CREATEOBJECT("Aplicatie")

La crearea obiectului « aplicatie » se executa procedura « Init » in care se stabilesc parametrii de mediu prin crearea obiectului « oenvironment » din clasa « environment ». Se deschide baza de date aferenta aplicatiei si se inchid barele cu instrumente, daca acestea sunt.

Aplicatie.Init()

this.AddObject("oEnvironment", "Environment")

this.oEnvironment.Set()

OPEN DATABASE (this.BazaDeDate)

this.ReleaseToolBars()

Apoi se executa metoda « Do » a obiectului « aplicatie » care fusese apelata inca din main.prg. Se stabilesc proprietatile ecranului, anume: icon, culoarea desktopului, culoarea textului. Se adauga la ecran un obiect de tip imagine care va contine pictura « smartbox.bmp », adica sigla aplicatiei.

Aplicatie.Do()

_screen.lockscreen=.t.

_screen.caption = this.cMainWindCaption

_screen.icon = this.icon

_screen.backcolor=rgb(64,64,64)

_screen.forecolor=rgb(0,255,0)

_screen.addobject('poza','image')

_screen.poza.picture='SmartBox.bmp'

_screen.poza.backstyle=0

this.resize()

DO (this.mainmenu)

_screen.lockscreen=.f.

_screen.visible=.t.

this.gentoolbar=CREATEOBJECT('apptoolbar')

this.genToolBar.Show()

this.genToolBar.Refresh()

_screen.addobject('demon','apptoolbarclock',oapp.gentoolbar)

oapp.oenvironment.setspecial()

READ EVENTS

Tot aici se lanseaza si meniul principal al aplicatiei. Din acest moment se poate incepe lucrul efectiv in aplicatie.

Meniul principal contine submeniurile :

File cu :

Iesire

Intretinere baze – face reindexarea tabelelor.

Adauga ; Salveaza; Renunta; Sterge – activate in cadrul formularelor. Folosesc la controlul inregistrarilor. Dubleaza, practic, bara de intrumente “dtoolbar”.

Adauga pozitie; Sterge pozitie – adauga si respectiv sterge o inregistrare din tabela din formularul curent.

Print Setup – face configurarea imprimantei pentru rapoarte.

Iesire program – inchide aplicatia

Nomenclator – contine formularele de introducere a nomenclatoarelor de denumiri. Contine

Obiecte

Departamente

Utilizatori

Items

Operatii – contine formularele principale ale aplicatiei

Imprumuturi

Arhiva

Rapoarte

Cautare in detalii – formularul de cautare a unei expresii sau a unui fisier in detaliile cu privire la items (CD -uri)

Meniul mai cuprinde 4 submeniuri care nu tin direct de aplicatie:

Navigatie – pentru navigarea pe inregistrari in tabele

Utilities – pentru depanarea aplicatiei in caz de erori

Window – cuprinde ferestrele active la un moment dat

Help – contine ajutor referitor la aplicatie

Discutie asupra unor probleme aparute

I) Procedura FADIR()

Nu avem o functie in Visual FOX pentru capturarea intregii structuri a unui director. De aceea apelam la functia ADIR(). Aceasta functie are urmatoarea sintaxa :

LnReturnat= ADIR(Numesir [, StructuraFisiere [, Atribut]])

Unde

Numesir – reprezinta numele sirului care se creeaza si contine indormatiile despre fisiere / directoare. Are 4 coloane care reprezinta numele, marimea, data ultimei modificari, ora ultimei modificari si atributul fisierului.

StructuraFisiere – reprezinta directorul din care se culeg informatiile si, in cazul fisierelor, tipul de fisiere cautat. De exemplu, pentru fisiere de tip “.dbf” din directorul curent avem “*.dbf”.

Atribut – poate lua valorile D, H, S sau V. In functie de acesta functia poate returna una din urmatoarele:

Atribut= D – returneaza subdirectoarele si fiserele ce respecta criteriul din parametrul 2

S – returneaza fisierele sistem ce respecta criteriul din parametrul 2

H – returneaza fisierele ascunse ce respecta criteriul din parametrul 2

V – returneaza volumul drive-ului curent

Codul procedurii este urmatorul :

* parametrii initiali

*ldirector – directorul de capturat

*ldir -.T./.F. daca vrem/nu vrem capturarea numelor directoarelor

*ldirnivel – nivelul (subramura) pana la care se face capturare (in jos)

*lfis -.T./.F. daca vrem/nu vrem capturarea numelor fisierelor

*lAlias – aliasul bazei in care se adauga numele de fisiere si directoare

*lCamp – numele campului in care se introduc numele de fisiere si directoare

LPARAMETERS ldirector,ldir,ldirnivel,lfis,lAlias,lCamp

* variabile locale folosite

LOCAL lOlddefa, lnrfis, lnrdir, afisiere[1,1], adirector[1,1], lnewdir, i, ldirector, lSalvat, ltable

* daca numarul de parametri primiti de procedura e diferit de 6 dam mesaj si oprim procedura

if PCOUNT() # 6

=messagebox('Nr. de parametri incorect')

return

endif

* daca nu exista baza in care adaugam fisierele dam mesaj si oprim procedura

if !USED(lAlias)

=messagebox('Baza in care se adauga nu exista')

return

endif

* salvam directorul implicit

lSalvat=SYS(5)+SYS(2003)

* stabilim cam director implicit directorul pasat procedurii ca parametru

SET DEFA TO ADDBS(ldirector)

* capturam fisierele din director

lnrfis=ADIR(afisiere,ADDBS(ldirector)+'*.*')

* daca numarul de fisiere este nenul si parametrul care determina daca se captureaza fisiere este.T. atunci, pentru toate liniile din sir se insereaza in lAlias, campul lCamp, numele fisierelor

if lnrfis>0.AND. lfis

for i=1 to ALEN(afisiere,1))

INSERT INTO (lAlias) (&lCamp) VALUES ( LOWER(afisiere(i,1)) )

endfor

endif

* capturam subdirectoarele din director

lnrdir=ADIR(adirector,"",'D')

* daca parametrul care determina daca se captureaza directoare este.T. atunci, pentru toate liniile din sir se insereaza in lAlias, campul lCamp, numele directoarelor, fara inregistrarile”.” si “..” care apar la capturarea directoarelor

if ldir

for i=1 to ALEN(adirector,1))

if adirector(i,1)#'.'.AND. adirector(i,1)#'..'

INSERT INTO (lAlias) (&lCamp) VALUES (JUSTFNAME(adirector(i,1)))

endif

endfor

endif

* pentru directoarele din sir se reapeleaza functia ADIR(). Daca ldirnivel este natural pozitiv se paseaza ldirnivel decrementat cu o unitate. Altfel se paseaza la aceeasi marime.

for i=1 to lnrdir

if adirector(i,1)='.'.OR. adirector(i,1)='..'

LOOP

endif

if ldirnivel#-1

if ldirnivel<=1

exit

endif

=fadir(ADDBS(ldirector)+adirector(i,1),ldir,ldirnivel-1,lfis,lAlias,lCamp)

else

=fadir(ADDBS(ldirector)+adirector(i,1),ldir,ldirnivel,lfis,lAlias,lCamp)

endif

endfor

* se restabileste directorul implicit la cel initial

set defa to ADDBS(lSalvat)

*daca ldirnivel este diferit de –1 se incrementeaza cu 1 pentru a reveni la valoarea initiala

if ldirnivel#-1

ldirnivel=ldirnivel+1

endif

Aceasta este forma finala a codului.

O forma simplificata a codului ar putea fi :

definire parametri si variabile locale

salvarea directorului implicit intr-o variabila

apelare functie ADIR() pentru gasire fisiere

apelare functie ADIR() pentru gasire directoare

scanare a sirului de directoare gasit si reapelarea in acest moment a aceleiasi functii FADIR()

restabilirea directorului implicit la cel salvat initial

Se observa ca parametrul ldirnivel se decrementeaza pana ajunge la nivelul 0 cand procedura se incheie. Daca are valoarea initiala –1 atunci nu se mai ia in calcul si se captureaza intreaga structura.

II) Cautare in detalii

Avand in vedere ca dorim o cautare si in interiorul campului de detalii, dispunem de functia LOCATE, care, insa, nu este o solutie buna avand in vedere numarul relativ mare de inregistrari si marimea campului de detalii. De aceea apelam la functia SQL – SELECT care este un puternic motor de cautare si ofera si o bara de progres cu o foarte buna aproximare a timpului de cautare.

Pentru o situatie relevanta vom considera tabela “items_det” cu 50414 inregistrari. Daca folosim functia APPEND pentru a adauga alte 50414 inregistrari e nevoie de 46 secunde. In schimb, folosind functia SELECT … UNION e nevoie de doar 28 secunde.

Acest tabel se poate transpune in urmatorul grafic :

Asadar e necesar cu 64 % mai mult in cazul functiei APPEND.

Am folosit operatorul “%” pentru a cauta in interiorul campului. De exemplu, pentru a cauta expresia “e.r”, folosim astfel:

SELECT detaliu FROM itemd_det WHERE detaliu LIKE “%e.r%”.

Pentru inlocuirea unui singur caracter am folosit operatorul “?”. De exemplu, pentru a cauta expresia “e.r” incepand cu al doilea caracter, folosim astfel:

SELECT detaliu FROM items_det WHERE detaliu LIKE “?e.r%”.

Pentru cautarea expresiilor de tip fisier, am folosit tot operatorul “%”, care de fapt ia locul operatorului “*” in lucrul cu fisiere.

local llcase, lcVariabila, line1, line2, line3, ltable, cmdline, lTablename, i, nrcamp, cdetaliu, loldtalk

thisform.enabled=.f.

ltable=left('a'+sys(3),8)

cdetaliu=''

llcase=thisform.casesens.value

lcVariabila=allt(thisform.dtextbox1.value)

lcVariabila=iif(llcase,lcVariabila,lower(lcVariabila))

do case

case thisform.combo1.value=1 &&detalii

loldtalk=SET("TALK")

set talk on

set talk wind

select items_det.detaliu, items_det.id_item, imprumuturi.id_ut;

FROM items_det LEFT OUTER JOIN imprumuturi;

ON Items_det.id_item = Imprumuturi.id_item;

INTO CURSOR c0

set talk off

line1='select c0.detaliu, c0.id_item, c0.id_ut, utilizatori.nume_ut'+;

' FROM c0 LEFT OUTER JOIN imprumuturi'+;

' ON c0.id_item = Imprumuturi.id_item'

thisform.dgrid1.column1.header1.caption='Detaliu'

cdetaliu='detaliu'

endcase

do case

case thisform.option.value=1

line2= ' where '+iif(llcase,cdetaliu,'lower('+cdetaliu+')')+' like "%'+lcVariabila+'%"'

case thisform.option.value=2

line2= ' where '+iif(llcase,cdetaliu,'lower('+cdetaliu+')')+' like "'+lcVariabila+'%"'

case thisform.option.value=3

line2= ' where '+iif(llcase,cdetaliu,'lower('+cdetaliu+')')+' like "%'+lcVariabila+'"'

case thisform.option.value=4

lcVariabila=STRTRAN(lcVariabila,"?","_")

lcVariabila=STRTRAN(lcVariabila,"*","%")

line2= ' where '+iif(llcase,cdetaliu,'lower('+cdetaliu+')')+' like "'+lcVariabila+'"'

endcase

line3=' INTO CURSOR c1'

CmdLine=line1+line2+line3

set talk on

set talk wind

&cmdline

SELECT c1.*, items.nume_item;

FROM c1 LEFT JOIN items ON c1.id_item=items.id_item;

INTO TABLE (ltable)

set talk off

nrcamp=afields(campuri)

for i=1 to nrcamp

if INLIST(TYPE(campuri(i,1)),"C","M")

cmd='repl '+campuri(i,1)+' with "" all for ISNULL('+campuri(i,1)+')'

&cmd

endif

endfor

ltablename=DBF()

use

select c_gasite

lOldsafe=SET("SAFE")

set safe off

if thisform.adauginloc.value=1

zap

endif

set safe &lOldsafe

appe from (ltable)

if FILE(ltablename)

delete file (ltablename)

endif

set talk &loldtalk

thisform.enabled=.t.

wait window 'Ready ' nowait

thisform.dgrid1.refresh()

BIBLIOGRAFIE

1. Microsoft Press – Microsoft Visual FoxPro 6.0 – ghidul programatorului – editura TEORA

2. M. Bazian, J. Booth, J. Long, V. Miller, C. Silver, R. A. Byers – Totul despre Visual FoxPro 6 – editura TEORA

3. Michael D. Antonovich – Utilizare Visual FoxPro 3 – editura TEORA

4. Kevin Kline – SQL in a Nutshell : a Desktop Quick Reference – www.amazon.com

5. Menachem Bazian – Special Edition Using Visual FoxPro 6 – www.amazon.com

6. Savannah Brentnall, Ken Levy – Object Orientation in Visual FoxPro – www.amazon.com

Similar Posts