LABORATORUL NR. 6 Proceduri si functii utilizator Procedura reprezinta un grup de instructiuni ce primeste de la programul apelant un grup de parametri, realizeaza anumite prelucrari, dupa care revine in programul apelant. O procedura definita de utlizator nu poate intra in alcatuirea unei expresii ca operand, fiind analoaga comenzilor standard din Visual FoxPro. (1) PROCEDURE ProcedureName Commands [RETURN [eExpression ]] ENDPROC Functia utilizator (UDF = User Defined Function) reprezinta un grup de instructiuni care primeste un set de parametri de la programul apelant si ii returneaza acestuia o valoare ca rezultat al prelucrarilor parametrilor transmisi. O UDF poate intra in componenta unei expresii ca operand, analog functiilor standard din Visual FoxPro. (2)
FUNCTION FunctionName Commands [RETURN [eExpression]] ENDFUNC Visual FoxPro permite specificarea unui fisier de proceduri si/sau UDF cu comanda: SET PROCEDURE TO [FileName1 [, FileName2, ...]] [ADDITIVE] astfel incat acestea sunt apelabile de oriunde. Specificarea unui alt nume de fisier de proceduri inchide automat pe cel vechi. Numai un singur fisier de acest tip poate fi activ la un moment dat. Pentru a inchide fisierul curent de proceduri fara a deschide unul nou, se da comanda fara argument. SET PROCEDURE TO Avantajul acestor fisiere este ca aduna toate rutinele intr-un singur loc, apelul lor facandu-se mult mai rapid decat in cazul unor fisiere program separate. Ordinea de cautare a unei proceduri de catre Visual FoxPro este: - programul curent in executie - fisierul de proceduri indicat in SET PROCEDURE - cauta un fisier program independent in directorul curent in ordinea: .EXE (executabil), .APP (aplicatie), .FXP (compilat), .PRG (sursa) - cauta un fisier program independent in calea Visual FoxPro de directoare stabilita cu SET PATH TO <lista directoare> Apelul unei proceduri se face cu: DO ProgramName1 | ProcedureName [IN ProgramName2] [WITH ParameterList] iar a unei UDF cu o simpla atribuire = FuncName() Daca nu intereseaza valoarea returnata se poate scrie: =FuncName(). Exemplu: Se creaza o clasa de obiecte numita "Hello" si se adauga o fubctie metoda numita "SayHello", care intoarce sirul "Hello World" care va fi afisat de functia sistem MESSAGEBOX. Nota: Definitia clasei este plasata dupa codul programului care instantiaza obiectul. Local oHello 1
oHello=CREATEOBJECT("Hello") =MESSAGEBOX(oHello.SayHello(),48) RELEASE oHello * Codul de definire a clasei DEFINE CLASS Hello AS CUSTOM FUNCTION SayHello RETURN "Hello World" ENDFUNC ENDDEFINE Variabile locale si globale. Transferul parametrilor. Intr-un modul de program pot fi referite doua tipuri de variabile: globale si locale. Variabilele globale (publice) pot fi accesate si modificate in orice modul de executie , de pe un nivel inferior, egal sau superior nivelului modulului curent. Variabilele globale se definesc cu instructiunile: PUBLIC VarList Efect: Declara si creaza variabilele globale din VarList. PUBLIC [ARRAY] ArrayName1(nRows1 [, nColumns1]) [, ArrayName2(nRows2 [, nColumns2])] ... Efect: Declara si creaza masivele globale din ArrayName i. Variabilele locale (private) pot fi accesate numai in modulul curent sau in cele aflate pe un nivel inferior modulului curent. PRIVATE VarList -sauPRIVATE ALL [LIKE Skeleton | EXCEPT Skeleton] Efect: Declara ca private variabilele din VarList (nu le creaza !) Exemplu: SET TALK OFF val1 = 10 val2 = 15 DO down ? val1, val2 && Afisaza 10, 100 PROCEDURE down PRIVATE val1 val1 = 50 val2 = 100 ? ' Val1 Val2' ? val1, val2 RETURN ENDPROC
&& Afisaza 50, 100
Transferul parametrilor. Procedurile si functiile pot primi maxim 24 parametri de la apelant. Parametrii pot fi trimisi in doua moduri:
2
- prin valoare (eventuala modificare a variabilei in subprogram nu afecteaza valoarea acesteia in programul apelant); - prin referinta (variabila transmisa este afectata de eventualele modificari aduse in subprogram). Transmiterea parametrilor la un subprogram se desfasoara in modul urmator: 1. se stabilesc variabilele care se vor transmite subprogramului ca parametri, intr-o ordine stabilita de programator la conceperea programului; 2. se stabileste un set de variabile locale subprogramului, care vor prelua valorile variabilelor transmise ca parametri de la programul apelant; 3. corespondenta dintre variabilele transmise din programul apelant si cele locale ale subprogramului se face prin pozitia in doua liste si anume: -lista cu parametrii de apel ai subprogramului si, - respectiv, lista variabilelor locale, specificata prin comanda PARAMETERS; 4. in modulul apelat se lucreaza cu variabilele locale respective; 5. daca tipul transmisiei este prin referinta, la sfarsitul executarii subprogramului, continutul variabilelor este trecut in variabilele corespunzatoare transmise ca parametri; 6. daca avem o transmisie prin valoare, aceasta ultima copiere nu mai are loc, deci in acest caz variabilele de apelare nu vor mai fi actualizate cu noile valori ale variabilelor locale corespunzatoare. In ceea ce priveste metoda folosita la transmisia parametrilor, avem urmatoarele reguli: - la programe parametrii se transmit implicit prin referinta; - la proceduri si functii se foloseste implicit metoda transmiterii parametrilor prin valoare. Pentru a schimba metoda implicita de transmitere a parametrilor la proceduri si functii se poate folosi comanda SET UDFPARMS cu sintaxa urmatoare: SET UDFPARMS TO VALUE | REFERENCE Obs. : Daca in lista argumentelor reale este un camp al unui tabel (deci nu o variabila de memorie !!) acesta este intotdeauna transmis prin valoare !! Exemplu.: Se ilustreaza diferenta dintre transferul parametrilor prin valoare si prin referinta: *** Transferul parametrilor prin valoare *** CLEAR SET TALK OFF WAIT 'Apasati o tasta pentru transfer prin valoare' WINDOW SET UDFPARMS TO VALUE STORE 1 TO gnX *** Valoarea variabilei gnX este neschimbata *** @ 2,2 SAY 'UDF value: ' + STR(plusone(gnX)) @ 4,2 SAY 'Value of gnX: ' + STR(gnX) *** Transferul parametrului prin referinta *** WAIT 'Apasati o tasta pentru transfer prin referinta' WINDOW CLEAR SET UDFPARMS TO REFERENCE STORE 1 TO gnX *** Valoarea variabilei gnX se schimba *** @ 2,2 SAY 'UDF value: ' + STR(plusone(gnX)) @ 4,2 SAY 'Value of X: ' + STR(gnX) SET UDFPARMS TO VALUE
3
FUNCTION plusone PARAMETER gnZ gnZ = gnZ + 1 RETURN gnZ ENDFUNC Pentru a forta transmiterea unui parametru prin valoare, la apelul unei functii acesta se include intre paranteze rotunde, iar pentru fortarea transmiterii prin referinta, acesta va fi precedat de caracterul '@'. La fel se poate transfera un masiv (matrice). Obs.: O variabila definita oriunde in program, devine globala pentru toate procedurile din program apelate dupa definire, care o folosesc.
Pozitionarea intr-o baza de date. a) Pozitionarea absoluta. GO [RECORD] nRecordNumber [IN nWorkArea | IN cTableAlias] -sauGO TOP | BOTTOM [IN nWorkArea | IN cTableAlias] -sauGOTO [RECORD] nRecordNumber [IN nWorkArea | IN cTableAlias] -sauGOTO TOP | BOTTOM [IN nWorkArea | IN cTableAlias] Efect: Permite pozitionarea pointer-ului pe un anumit articol precizat prin numarul de ordine determinat de valoarea <expN>, la Inceputul sau la sfarsitul fisierului din zona de lucru specificata. Obs.: - BOTTOM permite pozitionarea la sfarsitul tabelului; - TOP permite pozitionarea la inceputul tabelului; - RECORD nRecordNumber permite pozitionarea pe articolul cu numarul de ordine <expN> in tabel; - IN nWorkArea| IN cTableAlias permite realizarea pozitionarii in fisierul din zona de lucru precizata . Exemplu: CLOSE DATABASES OPEN DATABASE Parteneri USE oferte && Deschide tabelul Oferte GO BOTTOM ? RECNO('oferte') GO TOP ? RECNO( ) && Afisaza 1 GO 5 ? RECNO( ) && Afisaza 5 b) Pozitionarea relativa. SKIP [nRecords] [IN nWorkArea | cTableAlias]
4
Efect: Permite pozitionarea pointer-ului pe un anumit articol precizat prin nRecords, relativ la pozitia curenta, in fisierul din zona de lucru specificata. Obs.: - daca nRecords >0 atunci pozitionarea se face cu nRecords articole dupa cel curent; daca nRecords <0 atunci pozitionarea se face cu nRecords articole inaintea celui curent. Exemplu: CLOSE DATABASES OPEN DATABASE Parteneri USE Clienti CLEAR SKIP 4 IN 'clienti' ? RECNO('clienti') && Afisaza 5 GO BOTTOM SKIP -5 ? RECNO( )
c) Cautarea secventiala LOCATE FOR lExpression1 [Scope] [WHILE] [NOOPTIMIZE] Efect: Permite pozitionarea pointer-ului pe primul articol care indeplineste conditiile din filtru. Obs.: - daca nu exista un articol care sa indeplineasca conditiile din filtru, pointerul de inregistrare se pozitioneaza pe sfarsit de fisier, EOF() are valoarea .T. si FOUND() are valoarea .F.. - optiunea NOOPTIMIZE inhiba mecanismul de optimizare RUSHMORE; - cautarea se poate face numai in fisierul din zona de lucru curenta. CONTINUE Efect: Permite pozitionarea pointer-ului pe urmatorul articol care indeplineste conditiile precizate prin filtrul instructiunii LOCATE anterioare. Nu are efect daca nu s-a executat in prealabil o instructiune LOCATE. d) Cautare indexata. SEEK eExpression [ORDER nIndexNumber | IDXIndexFileName | [TAG] TagName [OF CDXFileName] [ASCENDING | DESCENDING]] [IN nWorkArea | cTableAlias] Efect: Permite pozitionarea pointerului pe primul articol care are cheia egala cu eExpression din sintaxa. Pentru folosirea acestei instructiuni, tabelul trebuie sa fie indexat. SEEK(eExpression [, nWorkArea | cTableAlias [, nIndexNumber | cIDXIndexFileName | cTagName]]) Efect: Permite pozitionarea pointerului pe primul articol care are cheia egala cu eExpression in zona de lucru curenta sau in cea specificata. Functia intoarce .T. daca s-a incheiat cautarea cu succes si .F. in caz contrar. Tabelul trebuie sa fie indexat. Obs.:
- functia SEEK este mai puternica decat instructiunea SEEK deoarece permite cautarea si in alta zona de lucru decat cea curenta si permite determinarea rezultatului cautarii.
5
Activare rutine de servici. (1) ON ERROR [Command] Efect: Permite specificarea unei comenzi Visual FoxPro care se va activa in cazul aparitiei unei erori. In general, se foloseste DO ,pentru a putea defini o procedura complexa de tratare a erorilor. Obs.: - instructiunea ON ERROR fara parametru dezectiveaza instructiunea ON ERROR definita anterior. Exemplu: ON ERROR DO errhand WITH ; ERROR( ), MESSAGE( ), MESSAGE(1), PROGRAM( ), LINENO( ) *** The next line should cause an error *** USE nodatabase ON ERROR && restore system error handler PROCEDURE errhand PARAMETER merror, mess, mess1, mprog, mlineno CLEAR ? 'Error number: ' + LTRIM(STR(merror)) ? 'Error message: ' + mess ? 'Line of code with error: ' + mess1 ? 'Line number of error: ' + LTRIM(STR(mlineno)) ? 'Program with error: ' + mprog (2) ON ESCAPE [Command] Efect: Permite definirea unei comenzi care se va activa in cazul apasarii tastei ESC. De obicei, se foloseste DO pentru definirea o procedura complexa de tratare a intreruperii cu ESC. Obs.: - instructiunea fara parametru dezactiveaza comanda ON ESCAPE definita anterior; - instructiunea Command din sintaxa se activeaza daca mecanismul ESCAPE este activat cu SET ESCAPE ON Exemplu: SET ESCAPE ON ON ESCAPE DO stopit WAIT WINDOW 'Press ESC to stop loop' NOWAIT glMoreLoop = .T. DO WHILE glMoreLoop ENDDO RETURN PROCEDURE stopit glMoreLoop = .F. RETURN (3) ON KEY [LABEL KeyLabelName] [Command] Efect: Permite definirea unei instructiuni Visul FoxPro care se va activa in cazul apasarii tastei precizate prin nume 6
Obs.: - ON KEY fara parametru dezactiveaza instructiunea similara definita anterior. Exemplu: Urmatorul exemplu afisaza un mesaj cand este apasata o tasta sageata. CLEAR PUBLIC msg msg = "Press F9 to " + ; "restore default key definition." ON KEY LABEL RIGHTARROW Wait Window "Right Arrow " + msg NOWAIT ON KEY LABEL LEFTARROW Wait Window "Left Arrow " + msg NOWAIT ON KEY LABEL UPARROW Wait Window "Up Arrow " + msg NOWAIT ON KEY LABEL DNARROW Wait Window "Down Arrow " + msg NOWAIT * Se apasa F9 pentru a sterge asignarile ON KEY LABEL ON KEY LABEL F9 ON KEY Asignarea etichetelor pentru taste in Visual FoxPro Tasta ↑ ↓ HOME END PAGE UP PAGE DOWN DEL BACKSPACE SPACEBAR INS TAB SHIFT+TAB ENTER F1 to F12 CTRL+F1 to CTRL+F12 SHIFT+F1 to SHIFT+F12 ALT+F1 to ALT+F12 ALT+0 to ALT+9 ALT+A to ALT+Z CTRL+LEFT ARROW CTRL+RIGHT ARROW CTRL+HOME CTRL+END CTRL+PAGE UP CTRL+PAGE DOWN CTRL+A TO CTRL+Z
Valoarea parametrului KeyLabelName LEFTARROW RIGHTARROW UPARROW DNARROW HOME END PGUP PGDN DEL BACKSPACE SPACEBAR INS TAB BACKTAB ENTER F1, F2, F3 ... CTRL+F1, CTRL+F2 ... SHIFT+F1, SHIFT+F2 ... ALT+F1, ALT+F2, ALT+F3 ... ALT+0, ALT+1, ALT+2 ... ALT+A, ALT+B, ALT+C ... CTRL+LEFTARROW CTRL+RIGHTARROW CTRL+HOME CTRL+END CTRL+PGUP CTRL+PGDN CTRL+A, CTRL+B, CTRL+C ... 7
CTRL+0 RIGHT MOUSE BUTTON LEFT MOUSE BUTTON MOUSE BUTTON ESC
CTRL+0 RIGHTMOUSE LEFTMOUSE MOUSE ESC
Exemplu.
USE agenti ON KEY LABE ENTER DO Editez ON KEY LABE SPACEBAR DO Acces ON KEY LABE ALT+L DO penal ON KEY LABE ALT+C DO cfact ………. ON KEY LABE ENTER ON KEY LABE SPACEBAR ON KEY LABE ALT+L ON KEY LABE ALT+C PROCEDURE penal SET CENTURY ON ON KEY LABE F1 DO help DO penalizari ON KEY LABE ESC KEYB '{CTRL+W}' ON KEY LABE ALT+P DO Tiparesc REPO FORM (m.rapcale+'penal'); NOEJ; NOCO; TO penal MODI FILE penal.txt ON KEY LABE ESC ON KEY LABE ALT+P RETU PROC tiparesc ON ERRO DO erori WITH 2000,"CHR(27)+'@'+CHR(27)+'M'+CHR(15)" *** Initalizare,condensat,12 CPI ???CHR(27)+'@'+CHR(27)+'M'+CHR(15) IF PRIN() actiune='COPY '+ 'penal.txt'+' PRN >NUL' !&actiune ENDI ON ERRO DO erori WITH ERRO(),MESS(),PROG(),LINE() RETU PROC penalizari * se calculeaza sumele care constituie penalizare **** RETURN
8