Search  
Friday, February 10, 2012 ..:: Forum ::.. Register  Login
 Forum Minimize
Pentru a putea posta mesaje trebuie să vă înregistraţi.
Notă: Mesajele cu conţinut jignitor sau ilegal (inclusiv cereri de soft piratat) nu sunt acceptate şi vor fi şterse imediat .

Pentru a primi raspunsuri rapide si corecte, scrieti in mesaj ce intentionati sa faceti, ce mesaj de eroare primiti, in ce context si in urma caror actiuni. De asemenea, mentionati versiunea de FoxPro in care lucrati!
Dacă nu specificați versiunea, se consideră VFP 9.0 SP2.

SearchForum Home
  Visual FoxPro  Visual FoxPro in general  Atestat 2010...
 Atestat 2010
 
 1/21/2010 6:02:05 PM
User is offlineGooDy
194 posts
5th


Atestat 2010
 (N/A)
Salutare , ma numesc Marius si acesta este primul meu post aici . Sunt in clasa a XII si am primit lista cu subiectele pentru atestat . Initial am ales : Gestionarea unui magazin cu legume si fructe , dar m-am gandit mai bine si nu prea mi se pare ok aceasta alegere . Pot sa vin eu cu o tema si profa o va accepta sau nu . M-am gandit prima oara la un catalog virtual apoi la o biblioteca scolara .
Deci am de ales intre :
1. magazin legume fructe
2. catalog virtual
3. biblioteca scolara
Sincer as inclina spre biblioteca scolara . Ceea ce vreau si am nevoie sunt niste sfaturi si indrumari , NU doresc , ca cineva sa imi faca programul ( sunt constient ca nu o va face si nici nu doresc , vreau sa invat , ma atrage si imi place ) . Trebuie sa intelegeti ca stadiul meu este de : nici Basic nu cred ca se numeste , adica doar cateva chestii , niste date introduse , un programel de sortare  si cam atat ( Nu este vina mea , atata mi sa predat ) .

Am nevoie de un plan de bataie , m-am gandit la ceva de genu :  vine elevul si cere o carte :  disponibilitatea carti  [cate exemplare sunt disponibile, autori, unde], inregistreaza cartea pe numele lui  ) . In curand voi revenii cu un plan bine stabilit , poate pana atunci imi puteti da idei asupra planului , ce ar trebui si ce nu ar trebui sa contina programul meu , cat de greu credeti ca va fi pentru mine , si daca am ales bine tema sau ar trebui sa aleg altceva . Nu ma sperii de munca , de tutoriale , de citit , de practica ...vreau sa invat .

Cam atat deocamdata si sper sa fiti ingaduitori cu mine , multumesc mult !
 1/21/2010 7:55:39 PM
User is offlineGrigore Dolghin
3521 posts
www.class-software.eu
1st






Re: Atestat 2010
 (Romania)

Bun. Imi place atitudinea. Da-i bataie cu planul ala si cand esti gata vino cu el incoa'. (Apropo, planul ala se numeste analiza de sistem.) Cel mai probabil o sa suporte niste modificari cand il vom citi, si inca niste modificari cand te vei apuca efectiv de lucru. Dar inceputul e bun.

Astept ;)


Grigore Dolghin
Visual FoxPro MVP 2006 - 2010
Class Software
My blog
 1/21/2010 9:08:04 PM
User is offlineGooDy
194 posts
5th


Re: Atestat 2010
 (N/A)
Am revenit cu o analiza de sistem ( multumesc pentru pont ) . Multumesc pentru raspuns ( nu stiu cum sa iti spun , Grigore - admin ? sau un alt nickname ? )

Dupa ideiile mele arata cam asa :

3 baze de date :
a- Elev : Nume | Prenume | CNP ( nu stiu sigur daca este necesar CNP-ul avand in vedere ca este o biblioteca scolara ) | Clasa | Data
b- Carte : Autor | Titlu | Volum | Bucati ( nr cartilor din biblioteca )
c- Biblioteca : Sector ( A , B , C ( ma gandeam ca sectoarele sa fie initialele autorilor , Nichita Stanescu sectorul N , Marin Preda sectorul M ...etc ) ) | Rand (1,2,3,4...) | Corp (1,2,3,4.... dulapul cu nr ... din randu x ) | Raft ( 1,2,3,4)

Cam la asta m-am gandit eu .
Ma gandeam si la partea grafica/interfata .... sa fie un ecran cu 3 optiuni/butoane : Cauta carte | Introdu o carte | Vizualizare ( aici se vor afisa cartile imprumutate )
Cauta carte -> o continuare cu un camp unde se va introduce numele carti cautate , aici se va afisa daca este disponibila cartea si se va afisa detaliile ( Sector , corp , rand ...etc ) cu 2 butoane -> Continua & Iesire ... la apasarea Continua se va deschide o pagina unde se vor introduce datele elevului si un buton Finish unde se vor stoca datele intr-o baza de date care va putea fi accesata ulterior .
Intro o carte -> campuri de introducere ( Autor , Titlu , Volum ) , introducere in baza de date existenta : carte
Vizualizare -> afisarea cartilor imprumutate cu optiuni de sortare .

Cam asa m-am gandit eu ... ceva pareri asupra analizei mele ?... am gresit undeva sau am uitat sa adaug cate ceva . Va rog sa imi atrageti atentia ...sau poate cineva are alta analiza asupra subiectului meu .

Multumesc si numai bine !
 1/22/2010 12:08:37 AM
User is offlineedyshor
1450 posts
1st




Re: Atestat 2010
 (N/A)
Probabil vrei sa le dai si cateva atribute: tip subiect (fictiune, clasici, stiinte, enciclopedii, romante, etc.), cum se imprumuta (doar sala de lectura, imprumut acasa pentru o perioada de 1 sapt, 2 sapt) - asta poate depinde de cantitatea disponibila si de valoarea cartilor, (daca vrei poti tine cont si de perioada in care se imprumuta cel mai des - examene, vacante, iarna, vara, etc), se poate imprumuta selectiv in functie de "calitatea" clientului (atibute ale clientului: vechime abonament, cata grija are de carti, daca le aduce la timp sau dupa termen, elev/student, etc). just a little brainstorming, hope it helps :)
 1/22/2010 10:47:02 AM
User is offlineDaniel Buduru
2141 posts
1st




Re: Atestat 2010
 (N/A)
Cum te-ai gandit sa inregistrezi imprumutul si returnarea cartilor?

Daniel Buduru
 1/22/2010 9:29:45 PM
User is offlineGooDy
194 posts
5th


Re: Atestat 2010
 (N/A)
M-am gandit ca atunci cand bibliotecara a gasit cartea respectiva , sa dea un click si sa apara un formular : nume prenume | clasa | cartea | perioada etc ...iar aceste date vor fii stocate intr-o BD care va fii accesata ulterior de bibliotecara pentru a vedea situatia imprumuturilor . Ma gandeam la ceva simplu .... returnarea se va inregistra in Perioada din formularul respectiv .

Multumesc edyshor pentru ajutor , mai astept si alte pareri si voi revenii cu o analiza mai bine schitata si +| - cateva lucruri .

Numai bine ,
 1/23/2010 2:18:57 AM
User is offlineDaniel Buduru
2141 posts
1st




Re: Atestat 2010
 (N/A)
Planul de bataie, cum i-ai zis tu, sau analiza de sistem, dupa cum ti-a zis Grig, inseamna - in mare - definirea cerintelor aplicatiei si identificarea datelor necesare pentru a raspunde acestor cerinte.
Cerintele aplicatiei sunt, de obicei, definite de beneficiar. In acest caz insa, va trebui sa definesti tu cerintele aplicatiei, deci sa te pui in locul beneficiarului.

Pornesti de aici: la ce intrebari (interogari) trebuie sa raspunda aceasta aplicatie?
Am sa pun eu cateva din ele, ca sa-ti faci o idee:

- Ce carti se gasesc in biblioteca?
- Ce carti sunt imprumutate?
- Cand ar trebui sa revina un exemplar imprumutat dintr-un anume titlu?
- Care sunt cititorii care au depasit termenul de predare?
- Cititorul x are vreo restrictie la imprumutul unei carti?
- Titlul x are vreo restrictie la imprumut?
- Cum poate fi gasit cititorul care nu a mai restituit cartea?
- Ce valoare au cartile nerestituite de catre cititorul x?
- Ce valoare au toate cartile din gestiunea bibliotecii?
- Ce valoare au cartile care sunt imprumutate la data de?
- Ce carti se gasesc in numar insuficient de exemplare (sunt cerute dar toate exemplarele sunt imprumutate)?
- Ce carti se gasesc in genul x?
- Ce carti de autorul x se gasesc in biblioteca?
- Cate carti se imprumuta pe o perioada de timp?
- De cate ori a fost imprumutat titul x?
- Ce titluri se cer si nu exista in biblioteca?
- Unde gasesc in biblioteca titlul x?
- Exemplarul n al cartii x este deteriorat. Se poate identifica ultimul cititor care a imprumutat acest exemplar?
- Rezultatul interogarii (oricare dintre cele din lista asta) va fi doar afisat sau va trebui si imprimat?
.....

Pentru a raspunde fiecarei intrebari e nevoie de anumite informatii. Unele dintre aceste informatii sunt specifice obiectului (cartii),  altele locului de depozitare, altele tranzactiei (imprumutul) si altele clientului (cititorului.)
Nici o informatie nu trebuie sa fie stocata doar pentru simplul fapt ca exista si poate fi identificata, ci numai prin prisma utilitatii ei in aplicatie.
Daca ai face o aplicatie pentru uzul unei edituri, ar trebui sa raspunzi la alte intrebari - cine detine copyright-ul, cine a facut tehnoredactarea, ce coli de tipar s-au folosit, si altele, informatii care se gasesc in carte, dar care, pentru biblioteca, nu sunt utile.
Pe de alta parte, formatul volumului se poate dovedi util daca vrei sa gestionezi si depozitarea pe rafturi ...


In urmatoarea etapa a analizei vei identifica aceste informatii, de unde pot fi obtinute, carui obiect ii sunt caracteristice si cum anume vor fi stocate ele.
Trebuie sa te asiguri ca poti identifica in mod unic fiecare entitate - carte, autor, cititor, tranzactie (imprumut/restituire).

Pana aici nu e nevoie sa stii vreun limbaj de programare ...

Dupa ce ai parcurs aceste etape, se ajunge la proiectarea bazei de date. Baza de date trebuie sa poata raspunde la toate interogarile definite in prima etapa.
In faza asta este util sa stii ceva despre structurarea datelor. Daca stii ce este o cheie primara si o ccheie straina, e bine. Daca inca nu stii, trebuie sa te documentezi inainte de a trece mai departe.

Apoi treci la interfata utilizator. Interfata trebuie sa permita atat intretinerea datelor (introducere, modificare, stergere) cat si interogarea bazei de date.

La o aplicatie bine structurata, baza de date si interfata sunt independente. Nu in sensul ca fiecare poate lucra singura, ci in sensul ca interfata nu este conditionata de baza de date, si nici baza de date de designul interfetei.
Baza de date poate fi vfp nativa, access, mssql, mysql, firebird, ...  Fiecare are particularitatile ei, dar datele si relatiile dintre ele sunt aceleasi.

Pentru partea de design a interfetei, inca nu ai nevoie sa stii vreun limbaj de programare. Trebuie doar sa stii ce vrei sa faci. Poti desena si cu creionul pe hartie cum vrei sa arate fiecare form si  ce sa contina fiecare menu. Abia aici vine "sa dea un click si sa apara un formular : nume prenume | clasa | cartea | perioada etc ".  Inspira-te din aplicatiile cu care lucrezi, windows, office, internet explorer ...

Dupa ce ai definit si designul intefetei, poti trece la cod. Abia acum trebuie sa te hotarasti la un limbaj de programare, cel in care vei face interfata.
Odata ajuns in faza asta vei fi in urmatoarea situatie: vei sti ce anume vrei sa faci, dar nu prea bine cum anume sa faci. Dar e simplu sa afli cum, daca stii ce vrei...

Poate sa ti se para complicat, dar in realitate nu este asa.


Daniel Buduru
 1/23/2010 6:02:40 PM
User is offlineoviciandrus
761 posts
www.comptech.ro
1st




Re: Atestat 2010
 (N/A)

Salut!

Pe de alta parte ma trebuie ţinut cont că: omul pleaca de la zero şi mai are maxim trei luni la dispoziţie, proiectul este pur didactic, adică nu va fi folosit niciodată pe bune într-o bibliotecă şi, după câte îmi dau seama, acolo la şcoala nu are de la cine învăţa .... Dacă scopul final este trecerea atestatului, proiectul trebuie privit mai simplist (se poate lua 10 şi cu rezolvarea ecuaţiei de gradul II). În acest caz, propun următorul set minimal de cerinţe:

- să se poată înregistra intrarea unei cărţi noi în bibliotecă: data, cartea, număr de exemplare achiziţionat

- să se poată înregistra împrumutul unei cărţi la un elev: data, cartea, elevul

- să se poată înregistra restituirea unei cărţi: data, elevul, cartea

Să vedem dacă absolventul ne spune de ce tabele are nevoie ca să memoreze informaţiile asta şi ce liste, statistici, etc îşi imaginează plecând de la aceste date.

 

 1/24/2010 1:52:39 PM
User is offlineGooDy
194 posts
5th


Re: Atestat 2010
 (N/A)
In primul rand vreau sa va multumesc tuturor pentru interesul si timpul acordat .
Este adevarat ca va fii ceva strict pentru scoala , chiar daca stiu ca atestatul va fii trecut cu brio , nu vreau sa ma duc acolo cu un atestat cumparat de pe diverse site-uri sau ceva gata facut . Vreau sa fiu o idee mai sus fata de colegii mei si ceva din munca mea , chiar daca voi muncii de 2-3 ori la el , stiu ca voi gresii si o voi lua de la capat , asta este , sunt dispus sa o fac .

Pentru inceput as dorii sa vad programul facut , ceva basic , iar apoi ii voi adauga diverse chestii extra ( stiu ca nu se face asa ceva , stiu ca asta va insemna chiar sa rescriu totul de la inceput , dar sunt dispus sa o fac , asa consider eu ca mai invat ) .

asa ca m-am gandit la :

- inregistrarea unei carti in biblioteca
- inregistrarea unui abonament
- inregistrarea unui imprumut
- cautarea unui abonament
- cautarea unei carti

Pentru acestea as avea nevoie de urmatoarele tabele :

Biblioteca -> Sector | Rand | Corp | Raft
Carte -> Autor | Titlu | Volum | Bucati | Pret
Imprumut -> Abonament | Carte | Data imprumut | Data restituire
Abonament -> Numar | Nume | Clasa

Ce parere aveti ? . am gresit undeva ?.. ar mai trebui sa adaug ceva ? ...sa incep sa ma apuc ? sau am omis cate ceva .

Multumesc inca odata !
 1/24/2010 5:00:55 PM
User is offlineoviciandrus
761 posts
www.comptech.ro
1st




Re: Atestat 2010
 (N/A)
Salut!

OK. Ţi-ai stabilit tabelele. Acuma trebuie să le umplem cu date pentru exemplificări concrete.

BIBLIOTECA

| Sector | Rand | Corp | Raft |
===================
| A | 1 | XYZ | L1 |
........

etc

Stabileste la fiecare tabelă vreo 10 înregistrări de exemplu ca să putem continua.
 1/24/2010 5:56:58 PM
User is offlinecostin_mentor
483 posts
www.accessoft.ro
2nd




Re: Atestat 2010
 (N/A) Modified By costin_mentor  on 1/24/2010 5:59:06 PM)
1. legatura dintre biblioteca si carte ?
2. fiecare tabela trebuie sa aiba un camp care sa identifice in mod unic o inregistrare , adica acea cheie primara.
3. eventual o tabela persoane , si tabela abonament sa aiba un camp persoanaid .
 1/24/2010 7:50:09 PM
User is offlineGooDy
194 posts
5th


Re: Atestat 2010
 (N/A)
Multumesc ,

corect ,
1- se pare ca am uitat sa fac legatura intre cele doua .
2- ai putea sa imi explici mai multe despre cheie primara sau un articol / tutorial ar fii ideal
3- acel camp : persoanaid , eu m-am gandit sa fie : NrAbonament din exemplele mele .
revenim :

Biblioteca -> CarteaNr | Sector | Rand | Corp | Raft
Carte -> NrCarte | Autor | Titlu | Volum | Bucati | Pret
Imprumut -> NrAbonament | NrCarte | Data imprumut | Data restituire
Abonament -> NrAbonament | Nume | Clasa


exemplele ar fii asa :

Biblioteca -> 01 | A | 1 | C1 | R1
Carte -> 01 | Alin Rus | Primavara | 1 | 23 | 15
Imprumut -> 01 | 01 | 10/10/09 | 10/11/09
Abonament -> 01 | Ion Marin | X- A


Biblioteca -> 23 | B | 1 | C1 | R1
Carte -> 23 | Barbu Stefanescu | Vara | 1 |  10 | 12
Imprumut -> 05 | 23 | 10/10/09 | 10/11/09
Abonament -> 05 | Marinescu Alin | X- A


.....

ce parere aveti ?

Multumesc !
 1/24/2010 8:22:32 PM
User is offlineoviciandrus
761 posts
www.comptech.ro
1st




Re: Atestat 2010
 (N/A)
Ai zis că vrei să realizezi următoarele funcţionalităţi:

F1. inregistrarea unei carti in biblioteca
F2. inregistrarea unui abonament
F3. inregistrarea unui imprumut
F4. cautarea unui abonament
F5. cautarea unei carti

Le luăm pe rând. Ne concentrăm pe F1. inregistrarea unei carti in biblioteca. Uităm pe moment de celelalte. Ce scenariu îţi imaginezi? Ce trebe să bage bibliotecara în calculator?
 1/24/2010 8:33:04 PM
User is offlineGooDy
194 posts
5th


Re: Atestat 2010
 (N/A)
Scenariu imaginat de mine ....
buton in meniul programului :  Adauga carte
tanti apasa , si ii apare un formular , aici trebuie sa completeze :

CarteaNr: 03
Autor : Craciunescu Mihai
Titlu : Vara
Volum : 1
Stoc : 12
Pret : 15

( date ce vor completa tabela Carte )

dupa aceea un buton Continua , unde la apasarea lui se va afisa alt formular ce va completa datele din tabela biblioteca :

CarteaNr : 03
Sector :  C
Rand : 2
Corp : C4
Raft : R1

Unde CarteaNr  , vor fii gasite detaliile in tabela : Carte ( cu toate detaliile aferente ) , Sectorul va fii dupa numele autorului ( in acest caz un autor care incepe cu litera C , Craciunescu Mihai )  Rand - Corp - Raft vor fii aleatoriu , in realitate vor fii datele exacte unde exista un loc liber pentru carte .

 1/24/2010 9:05:23 PM
User is offlineDaniel Buduru
2141 posts
1st




Re: Atestat 2010
 (N/A)
Informatiile din tabela Biblioteca sunt utile, dar tabela nu. Fiecarei inregistrari din tabela Biblioteca ii corespunde o inregistrare in tabela Carti.
In acest caz, e suficient sa adaugi campurile respective in tabela Carti.

Campul CarteaNr este ceea ce se numeste un identificator, un cod care identifica in mod unic o inregistrare. In tabela de carti nu poti avea acelasi cod (CarteNr) de mai multe ori, ci o singura data. Acest camp poate fi cheia primara pentru tabela Carti.
Campul CarteNr se regaseste si in tabela imprumuturi, dar acolo acelasi cod poate aparea de mai multe ori. Campul CarteNr din tabela Carti se numeste cheie straina (foreign key), si asigura legatura dintre tabela Carti si Tabela Imprumuturi.
In programare se prefera numirea acestor campuri cu ID + numele tabelei: IDCarte. In acest mod se regasesc mai repede cheile primare cand te uiti la structura unei tabele.

Daca vrei sa elimini informatii redundante - informatii care se repeta identic in mai multe inregistrari - ai putea face o tabela de autori, pe care sa o referi in tabela carti.


Daniel Buduru
 1/25/2010 10:20:27 AM
User is offlineoviciandrus
761 posts
www.comptech.ro
1st




Re: Atestat 2010
 (Romania) Modified By oviciandrus  on 1/25/2010 10:50:26 AM)
Inseamnă că vei avea un tabel cam aşa, după ce se înregistrează câteva cărţi succesiv.
IDCarteAutorTitluVolumStocPretSectorRandCorpRaft
00001Mihai EminescuPoezii1157.5A1P7A11
00002Ion CreangaAmintiri din copilarie1620.2A1P7A12
00003Mihail EminescuPoezii (1)1208.5B2P6A25
00004I. CreangaPovestea bostanului11018.25B2P6A26
00005M. EminescuPoezii1208.5B2P6A25


Oare vei putea să răspunzi la întrebări de genul? Căte exemplare de Ion Creangă sunt? Câte volume Poezii de Eminescu sunt? Ce zici? Ce părere ai?
 1/25/2010 6:06:50 PM
User is offlineGooDy
194 posts
5th


Re: Atestat 2010
 (N/A)
Am inteles daniel , voi urma sfatul tau si voi adopta noua structura..
Da , exact asa va arata tabela mea ...

cate exemplare de Ion Creanga ?

daca voi face un INPUT si voi atribui valoarea unei variabile , apo voi face un BROWSE dupa Autor = variabila ,  asa imi va afisa toate cartile cu autorul care este introdus de la tastatura ... corect ?

imi cer scuze daca voi spune prostii , dar asta este ceea ce am invatat si incerc sa fac cat mai bine posibil , voi accepta cu mare placere atata sfaturi cat si critici .

Numai bine ,
 1/25/2010 7:39:00 PM
User is offlineDaniel Buduru
2141 posts
1st




Re: Atestat 2010
 (N/A)
Poti folosi si comenzi SQL in proiect, sau exista o interdictie din partea profesorului in acest sens?
O interogare SQL e mai eficienta decat un filtru pus pe tabela, mai ales daca sunt implicate date din mai multe tabela.
Daca poti folosi sql, interogarea ar fi cam asa:

Select * From carti Where autor='Creanga'

Dupa cum vezi, filtrul (clauza Where) e acelasi ca si in cazul cand ai face un Browse.

Dar, in ambele variante, vor aparea ceva probleme:
- Daca autorul in tabela carti este Ion Creanga si nu Creanga Ion?
- Daca la diferite carti de acelasi autor numele autorului este scris diferit? Ca in exemplul de mai sus.
- Daca utilizatorul scrie creanga sau CREANGA?
In aceste cazuri nu vei obtine toate cartile acestui autor. Poate niciuna.
Intrebarea va trebui sa fie pusa un pic altfel pentru a gasi toate cartile lui Creanga, indiferent cum ar fi scris numele.
Dar, daca mai pui o tabela de autori si te legi in tabela carti de idautor, in loc de numele complet al autorului, vei realiza doua lucruri:
- eviti variatiile de scriere a numelui
- reduci lungimea inregistrarii din tabela carti, cu efecte favorabile asupra performantei (desi, in momenul de fata, performanta este ultimul lucru care te intereseaza :))

Dupa ce termini cu structurile, inainte de a trece la program, ar fi bine sa testezi toate interogarile. In acest fel iti vei da seama din timp daca trebuie sa mai umbli la structuri, fara sa fi nevoie sa modifici in programele deja facute.
Cand vei ajunge in aceasta faza, se vor clarifica si problemele legate de filtrare.


Daniel Buduru
 1/25/2010 8:05:19 PM
User is offlineoviciandrus
761 posts
www.comptech.ro
1st




Re: Atestat 2010
 (N/A)
Păi eu zic că, dacă bagi de la tastatură Ion Creangă, ies numa 6 exemplare. Dacă bagi I. Creangă, rezultă 10 exemplare. În bibliotecă sunt, de fapt, 16 exemplare de Ion Creangă.
 1/25/2010 8:35:11 PM
User is offlineDaniel Buduru
2141 posts
1st




Re: Atestat 2010
 (N/A)
Daca in conditia de filtru se pune ATC('creanga',autor)>0 setul rezultat va cuorinde toate inregistrarile care contin "Creanga" in autor, indiferent daca este scris cu litere mici sau mari si indiferent daca este scris I. Creanga, Ion Creanga sau Creanga I.



Daniel Buduru
 1/25/2010 9:01:26 PM
User is offlineGooDy
194 posts
5th


Re: Atestat 2010
 (N/A)
ok....deci ceea ce ma sfatuiti este sa mai fac o tabela separata Autori , unde vor fii introdusi autorii . Tabela va avea : IdAutor | Nume . Iar in tabela carti voi folosii in loc de Autor => IdAutor .
 1/25/2010 10:55:17 PM
User is offlineDaniel Buduru
2141 posts
1st




Re: Atestat 2010
 (N/A)
Ar fi bine.  Cel putin asa s-ar face pentru o baza de date reala.
Iti este de folos o documentatie in limba engleza?


Daniel Buduru
 1/26/2010 7:47:31 AM
User is offlineGooDy
194 posts
5th


Re: Atestat 2010
 (N/A)
da , ar fii ideala .

Multumesc !
 1/26/2010 11:12:19 AM
User is offlineDaniel Buduru
2141 posts
1st




Re: Atestat 2010
 (N/A) Modified By Daniel Buduru  on 1/26/2010 11:34:09 AM)
Aici e un articol care trateaza un aspect al structurarii unei baze de date, scris intr-o forma accesibila:

http://www.island-data.com/downloads/papers/normalization.pdf

Ar fi bine sa incerci sa-l parcurgi pe tot, chiar daca nu poti intelege totul de la inceput. In special, citeste paragraful Normalized Design: Pros and Cons, te va ajuta sa te decizi daca citesti si restul sau nu.

Mai ai aici 3 articole pe care n-ar strica deloc sa le citesti. Am sa pun la fiecare sumarul, ca sa-ti faci o idee despre ce contin:

http://www.jamesbooth.com/buffering1.htm, http://www.jamesbooth.com/buffering2.htm

"We can do this the hard way or we can do this the easy way." Data buffering is the easy way, once you understand how it works. It takes less code to accomplish the same results as the FoxPro 2.x methodology and it allows for the exploitation of the data binding capabilities of the VFP controls. There are a lot of choices related to data buffering. A careful examination of each of these choices will go along way in simplifying making the decisions.

http://www.jamesbooth.com/uidesign.htm

User interface design is more an art than a science.  There are guidelines that can be used but the final resulting interface design depends on many unrelated issues. Issues like system requirements, user preferences, speed of data entry, existing interfaces, intuitiveness, aesthetics, system performance requirements, and others.
In this session we divided user interface designs into three categories, Process Centric, Data Centric, and Goal Centric. Applications were divided into two categories, Sovereign and Transient. To design an effective user interface the application must be classified into the appropriate category and then the interface style should be identified.  Only after you know these requirements can you begin to design an effective user interface.


Nu sunt mari, aproape sigur nu le vei intelege in totalitate, dar asa iti poti face cat de cat o idee despre proiectarea unei aplicatii.
Desigur ca vei alege o solutie pe care sa o poti realiza fara probleme in timpul de care dispui.
E bine insa ca atunci cand alegi o varianta, sa stii intre ce si ce ai ales, ce avantaje si ce dezavantaje are fiecare.
Daca ai 2-3 luni pentru a finaliza proiectul, cateva zile pentru documentare nu te vor intarzia, ci te vor ajuta sa castigi timp.

Daniel Buduru
 1/30/2010 3:11:01 PM
User is offlineGooDy
194 posts
5th


Re: Atestat 2010
 (N/A)
In primul rand vreau sa imi cer scuze pentru ca nu am mai spus nimic , dar am fost ocupat cu scoala , cu mediile etc si am cititi acele ghid-uri date de daniel . Multumesc mult .

Ce am inteles eu de acolo :
- o tabela sa contina un camp care sa fie un identificator unic si bineinteles inregistrarile sa se refere strict la ceea ce reprezinta tabela.
- eliminate campurile inutile
- evitate tabelele care fuzioneaza'
- creearea si implementarea , sunt diferite . Creeaza structura in primul rand si apoi pune in aplicare , asta va scutii timp .
asta este un mic rezumat la ceea ce am inteles din acele mici tutoriale .Acum incerc sa revin cu noi tabele , si sper ca de data aceasta sa fie cat mai aproape de finalizare .

Autori -> IDautori | Nume
Carte -> IDcarte | IDautori | Titlu | Volum | Stoc | Pret | Sector | Rand | Corp | Raft
Abonament -> IDabonat | Nume | Clasa
Imprumut -> IDimprumut | IDabonat | IDcarte | Dimprumut | Dreturn

ce parere aveti ?

Multumesc !
 1/30/2010 5:49:30 PM
User is offlineDaniel Buduru
2141 posts
1st




Re: Atestat 2010
 (N/A) Modified By Daniel Buduru  on 1/30/2010 5:53:01 PM)
E bine daca ai citit articolele.

Si tabelele sunt aproape de final. Mai sunt cateva detalii:
- Cum vei inregistra o carte care are, sa zicem, 3 volume?
- Cum vei inregistra imprumutul volumului 2 din acea carte?
- Cum vei afla daca o carte este disponibila pentru a fi imprumutata?
Nu ma refer la cum anume vei face interfata si cum se va opera, ci la inregistrarile din baza de date.
- In tabela imprumut ar trebui sa ai un camp termen, in care sa se inregistreze termenul de restituire al cartii.

Trebuie sa incepi sa definesti si campurile, ca tip si dimensiune.

Ar fi bine sa creezi un proiect, sa creezi in el o baza de date, iar tabelele tale sa fie atasate acelei baze de date.
Proiectul iti tine la un loc toate elementele, tabele, programe, formuri, menu-uri, clase, etc.
Baza de date iti permite sa pui in tabele cheile primare si straine si sa ai nume de campuri mai mari de 10 caractere, si nu numai atat.
In baza de date vei putea vedea si legaturile dintre tabele.

Ramane deschisa intrebarea daca poti folosi comenzi SQL in aplicatie.

Daniel Buduru
 1/30/2010 6:20:49 PM
User is offlineGooDy
194 posts
5th


Re: Atestat 2010
 (N/A)
ok... la primele 2 chiar nu stiu , asa ca voi renunta la Volum din tabela carte .
la 3 , o functie : if stoc > 0 then ....... , asta ma gandesc ca ar fii o solutie ...cred !
la 4 , Dimprumut este data in care se face imprumutul si Dreturn  este data la care ar trebui sa se returneze cartea . Crezi ca mai este necesar inca un camp ?

voi incepe creearea lor ... implicit a proiectului .
Voi putea raspunde la aceasta intrebare in decursul a 1-2 zile ( sper ) .

Multumesc !
 1/30/2010 10:55:34 PM
User is offlineDaniel Buduru
2141 posts
1st




Re: Atestat 2010
 (N/A)
Referitor la volum, ai doua posibilitati:
- inregistrezi fiecare volum ca fiind o carte. Ex: Poezii Vol. I, Poezii Vol II - asta fiind varianta pentru care ai optat)
- ar trebui sa ai inca un id pentru volum, idcarte fiind acelasi pentru toate volumele - te complici inutil, se imprumuta volum cu volum

Stocul nu-ti este clar. stoc>0 poate fi o conditie de filtru, dar cine intretine stocul?
Trebuie sa ai un camp in care sa tii numarul de exemplare inregistrate in biblioteca, respectiv cele din raft + cele imprumutate, si altul cudoar exemplarele din raft, care pot fi imprumutate (stoc curent).
Stocul, cum i-ai spus tu, reprezinta exemplarele din raft.
Acest stoc trebuie actualizat dupa imprumuturi si returnari: se scad exemplarele imprumutate si se adauga exemplarele returnate.
Va trebui sa te gandesti cum vei face practic actualizarea stocului, la nivel de tabele, nu de interfata.

Nu este suficient un singur camp pentru returnare. Ai nevoie atat de termenul la care trebuie returnata cartea, cat si de data efectiva la care s-a returnat.
Daca nu evidentiezi data returnarii nu poti sti daca o carte a fost sau nu returnata.
O biblioteca poate penaliza intarzierea la returnare - fie printr-o taxa, fie prin suspendarea abonatului o anumita perioada, de ex. nu poate imprumuta alta carte decat peste o saptamana. Cartea nereturnata dupa un anumit interval se considera pierduta si se cere achitarea ei - de unde necesitatea pretului.

Care ar etapele urmatoare:
Dupa ce creezi tabelele vor trebui indexate si create relatiile dintre ele.
Relatiile vor asigura "integritatea referentiala". Iti explic foarte sumar in ce consta asta:
In tabela carti, in loc de numele autorului, ai un idautor.
- Daca introduci o inregistrare in tabela carti iar autorul cartii respectiva nu exista in tabela autori, creezi o inregistrare "orfana", campul idautor va fi nul.
- Daca ai una sau mai multe carti de acelasi autor si stergi autorul, cartile vor ramane "orfane"
In baza de date se stabileste o relatie intre carti si autori, pe idautor, care va impiedica adaugarea unei inregistrari in carti daca nu exista idautor in autori si va impiedica stergerea unei inregistrari din autori daca acel idautor exista in tabela carti..
Baza de date va face automat aceste verificari si nu va permite alterarea inregistrarilor.
Altfel, ar trebui sa scrii cod  care sa faca aceste verificari inainte de adaugare, modificare, stergere.

Apoi populezi tabelele cu cateva inregistrari in fiecare, dupa cum ti-a indicat Ovidiu.
Pe tabelele populate, vei pune la punct algoritmii pentru cautare, filtrare, etc. De scris si probat codul pe care-l vei folosi in aplicatie in acest scop.
In aceasta faza s-ar putea sa fie necesar sa mai faci ceva modificari in tabele.

Dupa asta, vei avea baza de date pusa la punct si poti trece la interfata.

Daniel Buduru
 1/31/2010 10:43:41 AM
User is offlineGooDy
194 posts
5th


Re: Atestat 2010
 (N/A)
Am inteles partea cu volumul . Multumesc !
Partea cu stocul . Ma gandeam sa fac o tabela separata STOC -> stocT | stocP ... unde stocT = stocul total de carti si stocP=numarul de carti prezent in biblioteca. Dar nu imi vine deloc in cap cum voi face actualizarea .
Partea cu returnarea . Am mai adaugat la tabela Imprumut-> Dneed ... am acum Dimprumut= data cand sa imprumutat | Dreturn=data cand sa returnat | Dneed=data cand ar trebui returnata cartea
 1/31/2010 12:47:29 PM
User is offlineDaniel Buduru
2141 posts
1st




Re: Atestat 2010
 (N/A)
In mod normal, ar fi utilizata o tabela de stoc curent, asa cum te-ai gandit. Ea s-ar utiliza numai pentru a reduce frecventa actualizarilor pe tabela carti.
In cazul de fata, nu e strict necesara o tabela separata, poti tine foarte bine stocul in tabela carti, cu cele doua campuri, in unul total exemplare, in celalalt exemplare disponibile.
Oricare ar fi solutia, tabela separata sau campuri in tabela carti, actualizarea trebuie facuta. Vom ajunge la asta in faza stabilire si testare a codului de actualizare si interogare a bazei de date.

Exista mai multe reguli pentru atribuirea de nume campurilor si variabilelor, scopul lor fiind acela de a da nume sugestive, care sa permita sa urmaresti usor codul si structura.
Ar fi ceva mai clar daca acele campuri cu date s-ar numi DtImprumut, Termen, DtReturnare, dar se poate si asa cum le-ai numit deja, totul e sa-ti fie mereu clar ce se introduce in fiecare.




Daniel Buduru
 1/31/2010 2:28:51 PM
User is offlineGooDy
194 posts
5th


Re: Atestat 2010
 (N/A)
Am inteles , vreau sa iti multumesc pentru ajutorul acordat pana acum si apreciez timpul pierdut pentru explicatii si ajutor . ( poate daca esti din Buc intr-o zi as putea sa ma revansez , macar cu o bere - 2 -5 :D )

Am facut proiectul in VFP , baza de date si implicit tabelele care arata asa :

Autori -> IDautor | Nume
Carte -> IDcarte | IDautor | Titlu | Volum | Tstoc | Dstoc | Pret | Sector | Rand | Corp | Raft
Abonament -> IDabonat | Nume | Clasa
Imprumut -> IDimprumut | IDabonat | IDcarte | DTimprumut | DTtermen | DTreturnare
(DTimprumut-data imprumutului | DTtermen- data termen | DTreturnare- data la care sa returnat cartea)

Am creeat tabelele , urmatorul pas ar fii popularea tabelelor . Am citit ca ar trebui sa stabilesc cheile primare , asta nu ar trebui sa o fac inainte de a popula tabelele ? . Partea urata este ca aici se termina firul , nu am invatat ce urmeaza , cum se face si in ce mod . Am luat 2 carti/tutoriale  Baze de date in VFP si Manual VFP , si am incercat sa le citesc , nu prea am inteles mare lucru fara un model , voi mai parcurge din nou pentru o aprofundare mai completa .

Multumesc !
 1/31/2010 3:44:44 PM
User is offlineGrigore Dolghin
3521 posts
www.class-software.eu
1st






Re: Atestat 2010
 (N/A)
Cheia primara a unui tabel este un camp cu o caracteristica speciala: valoarea lui este generata de sistem (in general crescatoare), odata alocat un numar nu se mai modifica si nu se mai realoca nimanui, niciodata, chiar daca inregistrarea respectiva este stearsa (si in felul asta obtii 'gauri' in sirul ala crescator, dar nu te deranjeaza), aceasta valoare nu este afisata utilizatorului si (foarte important) nu are sens in contextul businessului tratat de aplicatie. Altfel spus, desi intr-o lista de angajati CNP-ul ar putea fi cheie primara, NU E. Se face un camp separat in care se numeroteaza inregistrarile alea, de la 1 la cat o fi. La fel pentru codul de client, ISBN-ul cartii, etc etc etc. Rolul cheii primare este sa identifice INREGISTRAREA DIN TABELA, nu entitatea stocata in inregistrarea respectiva. Motivul este urmatorul: Valorile unice pertinente in businessul aplicatiei sunt introduse de oameni. Care pot gresi, ca de-aia-s oameni. Si daca le dai voie sa modifice valoarea cheii primare n-o s-o mai gasesti cand vrei sa actualizezi inregistrarea. Ca sa nu mai vorbim de faptul ca modificarea contravine regulii expuse in prima fraza.

Daca folosesti VFP9 poti seta un camp de tip Integer AutoInc drept cheie primara. Acesta se va popula cu valori pe masura ce adaugi inregistrari.

Grigore Dolghin
Visual FoxPro MVP 2006 - 2010
Class Software
My blog
 1/31/2010 3:54:21 PM
User is offlineDaniel Buduru
2141 posts
1st




Re: Atestat 2010
 (N/A)
Daca ai creat tabelele in dbc, poti pune cheile primare si relatiile intre tabele.
Mai intai, ce este o "cheie", fie ea primara sau nu?
Bazele de date folosesc un mecanism pentru regasirea mai rapida a informatiei.
Sa zicem ca ai tabela de carti, completata cu vreo 1000 de titluri.
Completarea s-a facut in ordinea naturala, cand a venit fiecare carte, deci inregistrarile nu sunt ordonate in vreun fel.
Acum vrei sa cauti o carte anume. Cum faci?
Singurul mod in care o poti face este sa iei pe rand fiecare inregistrare si sa vezi daca titulul corespunde cu ceea ce cauti.
E o procedura extrem de consumatoare de timp.
Dar, daca ai face un index alfabetic, in care sa treci titlul si numarul inregistrarii la care se gaseste el, cautarea e mult mai rapida. Daca mai faci si un index al indexului, un fel de cuprins, in care sa pui fiecare litera si pagina din index la care se gaseste, cauti mai intai aici prima litera, te duci apoi la pagina respectiva, apoi parcurgi indexul pana gasesti titlul cautat, iei de acolo numarul inregistrarii, mergi in tabela carti si te duci direct la inregistrarea cautata.
Asta ar fi foarte simplificat si foarte pe scurt modul in care functioneaza un index.
Intr-o baza de date poti fi creati indecsi. Expresia care este stocata in index se numeste "cheie de indexare". De ex, LEFT(NUME,10)+LEFT(PRENUME,10) (unde nume si prenume ar nume de campuri).
"Cheia primara" este expresia folosita pentru indexul primar. Un index primar este un index in care fiecare valoare este unica. Daca se incearca introducerea unei valori duplicate, baza de date o refuza si nu permite salvarea inregistrarii.
Intr-o tabela poate exista o singura cheie primara. Dar pot fi definite si alte chei unice, care insa vor fi numite "candidate" (candidate la cheie primara).

Sa luam tabela autori.
Campul Nume ar trebui sa aiba valori unice, sa nu ai doua inregistrari cu acelasi nume. Dar se poate intampla ca doi autori sa aiba nume identice, diferentierea facandu-se printr-o initiala,, un al treilea nume, sau altfel. Cert e ca e nevoie de intreg numele pentru a  fi sigur de unicitate.
Campul Nume va avea o lungime de 30-60 caractere. Sa zicem 60. Daca acest camp ar fi cheie primara, ar insemna ca in tabela Carte sa ai un camp la fel de mare, ar fi ca si cand ai scrie autorul cu numele intreg la fecare carte.
Pentru simplificare, nu am luat in discutie cartiel scrise de un colectiv de autori :).  Daca apare aceasta situatie, va fi creat grupul de autori ca si un autor unic, dar ar fi mai adecvat pentru nume un camp de tip memo.
Deci, daca incercam sa folosim datele stocate pentru cheia unica, ne lovim de ceva probleme. Prima dintre ele, cea aratata mai sus, e dimensiunea cheii. A doua, este legata de modul de generare al cheii.
Pentru a evidentia asta, sa nu uitam la tabela Imprumut:
Fiecare imprumut este unic, dar un abonat poate imprumuta o carte de mai multe ori. Deci, avem nevoie de abonat, carte si data imprumutului pentru a genera o cheie unica. Si in acest caz, din concatenarea cheilor IDcarte, IDAbonat si DTimprumut rezulta o cheie lunga. Se poate folosi, dar un index cu aceasta cheie va avea aproape accesi dimensiune cu tabela.
Mai luam in considerare inca un aspect.
Sa zicema ca la inregistrarea unui autor s-a tastat gresit numele. S-a generat cheia primara cu acest nume si ai fost deja folosita la un numar de carti. Daca vrem sa corectam numele autorului, se va modifica cheia primara. In acest caz, fie facem acea modificare in totata tabela Carte, unde a fost referita acea cheie, fie nu permitem modificarea si mergem inainte cu un nume scris gresit.
Din cele expuse mai sus se vede ca nu e indicat sa folosim datele utilizator din tabele pentru cheile primare. Unicitatea lor va fi validata prin chei candidat, dar nu sunt indicate pentru cheia primara.
Ce folosim atunci?
Se pot folosi campuri numerice cu valori crescatoare, care arata ca un numar curent (asta si sunt la generarea lor), sau chei generate cu un algoritm care asigura unicitatea cheii. O astfel de cheie este GUID, Globally Unique Identifier, dar nu intram acum in detalii.
Daca folosesti VFP9 si ai pus tabelele in baza de date, poti folosi un camp numeric, pe care baza de date il fa incrementa automat. Acest camp este de tip AUTOINC.
Ar trebui ca IDAutor, IDCarte, IDAbonat, IDImprumut sa fie de tip interger AUTOINC.

Cum faci asta?
Editezi structura tabelei (Modi Stru, sau direct din project manager). La campul IDAutor pui tipul Integer(Autoinc), apoi bifexi indexul.
Treci apoi la Indexes, vei gasi deja completat un rand cu Name IDAutor, Type Regular si Expression IDAutor. Aici modifici Type in Primary.

Faci asta la toate tabelele.
Apoi mai discutam.




Daniel Buduru
 1/31/2010 3:55:15 PM
User is offlineDaniel Buduru
2141 posts
1st




Re: Atestat 2010
 (N/A)
Vad ca Grig ti-a raspuns deja la intrebare, in timp ce scriam

Daniel Buduru
 1/31/2010 6:24:46 PM
User is offlineGrigore Dolghin
3521 posts
www.class-software.eu
1st






Re: Atestat 2010
 (N/A)
...and great minds think alike.

Grigore Dolghin
Visual FoxPro MVP 2006 - 2010
Class Software
My blog
 1/31/2010 9:06:29 PM
User is offlineGooDy
194 posts
5th


Re: Atestat 2010
 (N/A)
Multumesc pentru raspunsuri . In exemplul de fata , cheile primare vor fii : IDautor | IDcarte | IDimprumut | IDabonat fiecare corespunzand tabelei sale respectiv Autori | Carte | Imprumut | Abonament
Din pacate folosesc VFP 6.0 , deci voi introduce aceste valori numerice ( crescatoare ) manual .

Tabelele le-am facut asa :

Autori : idautor | numeric | 10 | 0 | Ascending
            nume | character | 50 | 0 |      |

Carte : idcarte | numeric | 10 | 0 | Ascending
           idautor | numeric | 3 | 0 |         |
           titlu | character | 60 | 0 |         |
           volum | numeric | 3 | 0 |         |
           tstoc | numeric | 10 | 0 |         |
           dstoc | numeric | 10 | 0 |         |
           pret | numeric | 10 | 2 |         |
           sector | numeric | 3 | 0 |         |
           rand | numeric | 3 | 0 |         |
           corp | character | 3 | 0 |         |
           raft | character | 3 | 0 |         |
Abonament :   idabonat | numeric | 10 | 0 |  Ascending|
                      nume | character | 40 | 0 |         |
                      clasa | character | 10 | 0 |         |
Imprumut :    idimprumut | numeric | 10 | 0 |Ascending   |
                     idabonat | numeric | 10 | 0 |         |
                     idcarte | numeric | 10 | 0 |         |
                      dimprumut | date | 8 | 0 |         |
                     dtermen | date | 8 | 0 |         |
                     dreturnare | date | 8 | 0 |         |
 1/31/2010 9:19:23 PM
User is offlineDaniel Buduru
2141 posts
1st




Re: Atestat 2010
 (N/A) Modified By Daniel Buduru  on 1/31/2010 9:32:13 PM)
Daca nu ma insel, in VFP6 exista campul de tip integer.
Ar fi mai indicat ca toate campurile ID sa fie de tip integer.
Introducerea manuala a cheii primare nu e deloc recomandabila. Pentru asta se face un program.

Aici gasesti functia utilizata pentru cheile primare  in aplicatia exemplu din vfp6, "Tastrade".
http://support.microsoft.com/kb/136921
Se lucreaza cu o tabela separata care tine, pentru fiecare tabela din dbc, urmatoarea cheie primara.
Functia newid('tabela') returneaza urmatoarea cheie primara pentru tabela 'tabela'.
Uita-te putin pe cod, nu ma astept sa intelegi ce este cu lock-urile, sigur nu vi s-a predat asa ceva, dar iti poti face o idee.
Vom relua cu siguranta aceasta discutie.

Daniel Buduru
 2/1/2010 4:33:19 PM
User is offlineGooDy
194 posts
5th


Re: Atestat 2010
 (N/A)
Am modificat toate campurile ID sa fie integer .

M-am uitat pe acel exemplu , dar sa fiu sincer , nu am priceput nimic , nu am mai vazut si nu am mai facut asa ceva . Am incercat sa o iau de la un capat , dar nush daca am inteles ceva :

ce sunt aceste tcAlias | lcAlias | lcID | lc0ldReprocess | ln0ldArea


stiu ca voi devenit stresant si enervant , dar de aici in colo numai stiu nimic , nu am facut nicioadata . Nu stiu de unde vin si unde trebuiesc puse fiecare :( .

Numai bine  !
 2/1/2010 4:56:52 PM
User is offlineDaniel Buduru
2141 posts
1st




Re: Atestat 2010
 (N/A) Modified By Daniel Buduru  on 2/1/2010 5:12:01 PM)
Nu ma asteptam la prea mult, dar ...
tcAlias | lcAlias | lcID | lc0ldReprocess | ln0ldArea sunt variabile.

Inainte de a trece le cod, sa vedem cam ce stii din programarea in VFP.
Zici ca este un proiect pentru atestat. Eu nu sunt la curent cu ce se face in scoala, spune-mi te rog care este denumirea completa a acestui atestat?
Ai facut vreun program in VFP?
Ce anume s-a predat din VFP si la ce nivel ar trebui sa cunosti acest limbaj conform programei?
Intereseaza mai mult ce ar trebui sa stii decat ce stii acum.

In acest moment, doua lucruri sunt evidente:
- nu prea stii suficient cat sa scrii codul;
- nu poti invata tot limbajul VFP in cateva zile
Asa ca trebuie sa determinam ce anume trebuie totusi sa inveti din VFP.

Daniel Buduru
 2/1/2010 5:21:39 PM
User is offlineGrigore Dolghin
3521 posts
www.class-software.eu
1st






Re: Atestat 2010
 (N/A)
Nu esti enervant, dimpotriva. Hai sa-ti zic ce e cu codul ala.

Pentru ca nu ai autoinc in vfp6 si inregistrarile alea trebuie numerotate crescator printr-o metoda oarecare, ai de ales intre doua variante.
1. Verifici care e cel mai mare numar existent in tabela, iar inregistrarea noua capata in campul id valoarea aia + 1. Select Max(Id) As MaxId From tabela Into Cursor crsMax iti intoarce valoarea maxima existenta.
2. Apelezi la solutia pe care ti-a dat-o Daniel.

Varianta 1 merge bine in regim monoutilizator. Cand ai doi sau mai multi useri care lucreaza simultan lucrurile se complica foarte tare in sensul ca in anumite situatii pot primi acelasi numar, desi nu ar trebui. Tinand cont ca in cazul tau particular programul este monouser ai putea sa o folosesti fara grija.

Varianta 2 foloseste o tabela intermediara (in exemplul dat de Daniel se numeste "setup") in care tine valorile maxime din fiecare tabela cu date. Cand un user are nevoie de un id nou pentru o tabela, inregistrarea din Setup corespunzatoare tabelei respective este blocata, se extrage un id nou, se incrementeaza valoarea de acolo si apoi se deblocheaza. In felul asta, daca doi utilizatori vor numere, unul dintre ei il va astepta pe celalat si apoi va primi urmatorul numar.

Structural, codul din exemplu este impartit in urmatoarele sectiuni:

1. Parametri si variabile locale:
 FUNCTION NewID(tcAlias) && se primeste un alias (deci o apelezi cu x = NewId("nume_tabela")
LOCAL lcAlias, ; && astea-s declaratii de variabile. Pot sa lipseasca, da' nu-i frumos.
lcID, ;
lcOldReprocess, ;
lnOldArea

lnOldArea = SELECT() && lnOldArea va memora zona de lucru curenta, pentru ca ulterior
&& programul va selecta alta tabela si trebuie sa se mute inapoi
&& pe zona initiala inainte de a se inchide. Tot din categoria
&& "nu-i frumos sa schimbi zona de lucru necontrolat."

IF PARAMETERS() < 1 && PARAMETERS() intoarce numarul de parametri primiti in functie.
lcAlias = UPPER(ALIAS()) && daca nu s-a primit nici unul, programul va considera
&& ca se cere un id nou pentru tabela selectata in prealabil.
ELSE
lcAlias = UPPER(tcAlias) && in caz contrar se va folosi tabela specificata ca parametru.
ENDIF
&& oricum ar fi, numele tabelei e stocat in variabila lcAlias, fiindca ne trebuie mai jos.

lcID = ""
lcOldReprocess = SET('REPROCESS') && programul va modifica valoarea lui Set Reprocess.
&& ca sa-l poata reconsitui la terminare trebuie sa memoreze cat era.
2. Programul propriu-zis:

     *-- Lock until user presses Esc
SET REPROCESS TO AUTOMATIC && chestia asta determina foxul sa incerce la nesfarsit blocarea
&& unei inregistrari atunci cand se incearca blocarea. Alternativele
&& sunt "incearca un numar prestabilit de secunde" sau "incearca de un
&& numar prestabilit de ori". Nu se pot folosi aici - rutina asta trebuie
&& ori sa blocheze si sa-si faca treaba, ori sa nu blocheze si sa iasa.

IF !USED("SETUP")
USE tastrade!setup IN 0 && daca tabela "setup" nu e deschisa, o deschide intr-o zona de lucru noua ...
ENDIF
SELECT setup && ... si o selecteaza.

IF SEEK(lcAlias, "setup", "key_name") && cauta numele tabelei (din variabila lcAlias). Functia SEEK()
&& cauta numele tabelei in campul key_name si, daca gaseste, se duce
&& pe inregistrarea aia. Daca nu, ajunge pe EOF() si returneaza .F.,
&& deci tot ce e in IF nu se executa deloc. ALtfel spus, daca trimiti
&& balarii ca parametru, nu se executa nimic.
IF RLOCK() && Incearca blocarea inregistrarii gasite. Din cauza lui SET REPROCESS AUTOMATIC de mai sus,
&& programul va intepeni aici pana cand a) blocheaza inregistrarea sau b) userul apasa Esc.
&& Dat fiind ca programul asta dureaza extrem de putin, sansele sa ajungi sa dai Esc sunt infime.
lcID = setup.value && se ia valoarea urmatoare a id-ului tabelei specificate ca parametru intr-o variabila.
REPLACE setup.value WITH ;
STR(VAL(ALLT(lcID)) + 1, LEN(setup.value)) && apoi se incrementeaza valoarea aia, ca sa fie disponibila la urmatorul apel al functiei.
UNLOCK && deblocheaza tabela
ENDIF
ENDIF
3. Clean-up code

    SELECT (lnOldArea) && selecteaza zona de lucru selectata initial
SET REPROCESS TO lcOldReprocess && reconstituie SET REPROCESS

RETURN lcID && returneaza id-ul.

Functia asta se apeleaza cam asa:
Select Carti
Append Blank
Replace Id With NewId("carti")

In tabela SETUP (pe care trebuie sa o ai si tu - copiaz-o din Tastrade - asta e in folderul FoxPro) trebuie sa ai o inregistrare care contine "Carti" in campul Key_Name, altfel SEEK() n-o s-o gaseasca. La fel pentru toate tabelele la care vrei sa ai campul asta autoincrementabil.

Grigore Dolghin
Visual FoxPro MVP 2006 - 2010
Class Software
My blog
 2/1/2010 6:11:41 PM
User is offlineDaniel Buduru
2141 posts
1st




Re: Atestat 2010
 (N/A)
Pana ne lamurim cu nivelul VFP, hai sa continuam asa cum am facut si cu structurile: fara sa ne referim la cod, ci numai la algoritm.
In informatica, algoritmul este metoda efectiva de rezolvare a unei probleme.
Grig ti-a dat deja un exemplu de algoritm cand a explicat prima metoda pentru alocarea id-ului numeric.
Am sa-ti mai dau un exemplu, apoi vei continua in acelasi mod.

Problema: Inregistram o carte noua.
Cel care face inregistrarea va trebui sa poata furniza urmatoarele informatii:
- titlul cartii
- autorul
- pretul unui exemplar
- numarul de exemplare care intra in biblioteca
- locul in care va fi depozitata in biblioteca (sectorul, randul, raftul...)
Primele doua informatii (titlul si autorul) pot fi gasite chiar in carte.
Urmatoarele doua, pretul si numarul de exemplare, se regasesc pe documentul de achizitionare (nir, factura ...)
Ultima, locatia, va fi stabilita de catre bibliotecar.
Acum, la inregistrarea cartii, avem nevoie de idautor
Deci, va fi nevoie sa cautam autorul dupa nume in tabela de autori si sa obtinem id-ul sau.
Aici avem doua situatii:
- autorul se gaseste deja in baza de date
- autorul nu a fost inca introdus in baza de date.
In primul caz, odata gasit numele autorului, notam idautor si il folosim la inregistrarea cartii.
Daca autorul nu se gaseste in baza de date, trebuie adaugat. In acest caz, vom apela algoritmul pentru inregistrarea autorului (algoritm pe care nu l-am definit inca)
Daca avem toate aceste date, suntem gata de inregistrare.
Inainte de a inregistra cartea, trebuie sa verificam daca nu este cumva deja inregistrata in baza de date.
Pentru asta, cautam titlul si idautor in baza de date.
Daca gasim o inregistrare cu acelasi titlu si idautor, inseamna ca s-au mai aprovizionat un numar de exemplare din acel volum.
In acest caz, vom actualiza stocul. Noul stoc va fi egal cu vechiul stoc+numarul de exemplare care rezulta din documente.
Daca nu gasim o inregistrare cu acelasi titlu si idautor, vom crea noua inregistrare.
Vom avea nevoie de noul IDCarte, pe care il vom obtine apeland algoritmul de generare al unui nou id pentru tabela carti.
Acum putem crea inregistrarea in tabela carti.

Tema este sa descrii in acelasi mod inregistrarea unui abonament, imprumutul unei carti si restituirea ei.



Daniel Buduru
 2/2/2010 4:21:35 PM
User is offlineGooDy
194 posts
5th


Re: Atestat 2010
 (N/A)
Nivelul meu de VFP ....hmm

Baze de date : Definitii si exemple
Modul de lucru in VFP : Interactiv si programat
Comenzi ( Create | Modify Structure | Delete )
Tipuri de date 1
Configurarea mediului VFP
Tipuri de date 2 : functii pentru tip numeric
                                                    caracter
                                                   logic
                                                   gestionarea timpului
Creearea variabilelor
Ordonare date VFP
Programare structurata
Instructiuni de control in VFP

cam atat .

Tema mea :

Inregistrarea unui abonament :
Bibliotecara trebui sa stie Numele si clasa elevului , date ce vor fii furnizate de acesta .
Se cauta in baza de date daca exista cineva cu acest nume , daca nu exista se trece la inregistrarea unui nou abonament pe acest nume .
Se obtine IDabonat prin apelarea algoritmului , iar Numele si Clasa vor fii introduse de la tastatura .
Daca exista cineva cu acel nume , se noteaza IDabonat si se trece la inregistrarea imprumutului .

Inregistrarea unui imprumut :
Se cauta IDabonat celui care se prezinta sau se creeaza un abonament nou . Se cauta cartea ceruta de elev in tabela carte si se noteaza IDcarte , IDimprumut se obtine prin apelarea altgoritmului . Se introduce de bibliotecara Data imprumutului |  Data cand ar trebui restituita .

Restituire unei carti , hmm aici ma lovesc de ceva nou ... Ma gandeam ca se va face un meniu unde va scrie ceva de genul Restituire . Aici va trebui introdus IDimprumut care va fii furnizat de elev , care a primit acest ID in momentul in care a imprumutat cartea . Dupa ce sa introdus IDimprumut se merge mai departe si se afiseaza imprumutul : IDimprumut | IDabonat |IDcarte |Dimprumut | Dreturn ( acesta este lasat necompletat sau este 00/00/00 ) | Dneed . Se introduce data din momentul restituiri cartii si se va face verificarea daca Dreturn <Dneed atunci totul este OK . Daca este mai mare atunci se trece la penalizari .
 2/2/2010 5:43:40 PM
User is offlineDaniel Buduru
2141 posts
1st




Re: Atestat 2010
 (N/A)
In programare in general si in VFP in special, un lucru se poate face in mai multe moduri.
VFP este mai special intrucat, ajuns la versiunea 9 si la capatul vietii ca MSVFP, inca poate rula cod scris in dbase II, care dateaza de la sfarsitul anilor '70.
Asta a fost si bine si rau pentru vfp, bine pentru ca nu a necesitat rescrierea aplicatiilor, rau pentru ca, dupa 40 de ani, se folosesc inca metodele destul de rudimentare ale dbase II, in loc de a fi folosite noile posibilitati, cu performante net superioare, introduse in versiunile Visual FoxPro.
Din acest motiv e bine sa stim cum va fi evaluata aplicatia.
Cand trecem la implementarea codului, vom analiza cele doua stiluri de programare - procedurala si orientata obiect - si vom vedea care din ele se potriveste mai bine aplicatiei tale.

Tema sta destul de bine.
Dupa un mic retus, vom trece la transpunerea algoritmilor in cod.

Sa clarificam restituirea.
Abonatul nu trebuie sa tina minte un id sau altceva legat de imprumut, ci doar numarul abonamentului, dar nu e obligatoriu.
El vine si aduce cartea, isi da numarul de abonament, daca il stie, daca nu, numele. Se cauta fie abonamentul, fie numele.
Daca nu se gaseste abonatul nici dupa nume, fie a imprumutat cartea fara sa fie inregistrat, fie e cartea imprumutata de alta persoana.
Se cauta cartea dupa titlu, se obtine idcarte, se cauta imprumuturile dupa idcarte nereturnate inca.
- Comentariu -
Daca am fi tinut si evidenta pe exemplar de carte, am fi stiut cine a imprumutat exemplarul respectiv si s-ar fi putut verifica daca este aceeasi persoana.
Pentru a tine evidenta pe exemplar, ar fi fost necesar ca la inregistrarea cartii pe fiecare exemplar sa se noteze numarul exemplarului, iar in tabela de imprumut sa existe un camp pentru nr. exemplar
Nu e strict necesar, dar nici complicat.
Tine insa de personalul care utilizeaza aplicatia, la fel ca si asezarea cartii intr-o anume locatie (sector, rand, raft ...)
--------
Se cauta imprumutul dupa idabonat, idcarte
Daca nu se gaseste, nu s-a operat inregistrarea imprumutului ....
Daca se gaseste, se inscrie data returnarii

Trebuie sa ai in vedere intotdeuna situatiile in care cautarile nu returneaza nici un rezultat, si sa decizi de la inceput ce va face aplicatia in acea situatie.
Fie se cere interventia utilizatorului, fie se executa o anumita procedura.
Asta face parte din tratarea erorilor. Tratarea erorilor nu se refera, de obicei, la erori de cod - ele ar trebui sa fie gasite si remediate in timpul testarii, in cea mai mare parte - ci la situatia in care nu sunt indeplinite anumite conditii pentru functionarea aplicatiei. Situatiile prezentate mai sus fac parte din aceasta categorie.

Acum vom trece la transpunerea algoritmilor in cod.
E momentul sa facem o precizare cu privire la modul de lucru al aplicatiei:  va fi o aplicatie mono utilizator.

Vom incepe cu functia care trebuie sa returneze noul ID pentru fiecare tabela.
Fiind aplicatie monouser, se poate adopta fara probleme prima varianta expusa de Grig.
Va trebui sa scrii o functie care sa primeasca drept parametru numele tabelei si sa returneze urmatorul ID.
Va trebui sa gasesti cel mai mare id din tabela respectiva si sa-l incrementezi.
Grig ti-a dat si comanda cu care se poate face asta cel mai simplu.

Ce ar mai trebui sa stii inainte de a scrie codul:
In tabelele DBF inregistrarile sterse (deleted) nu sunt sterse fizic, ci doar se marcheaza pentru stergere.
Pentru asta exista un camp, care nu se vede in structura, in care se face aceasta marcare.
Inregistrarile sterse (marcate ca sterse) se vad in continuare in tabela. In browse, apare un dreptunghi negru in stanga randului.
Comanda SET DELETED ON pune un filtru pe fiecare tabela (nici acest filtru nu se vede, dar asa lucreaza)
SET DELETED ON e echivalent cu SET FILTER TO DELETED()=.T.
De ce am adus asta in discutie?
Sa zicem ca am sters ultima inregistrare introdus in tabela carti, cea care are cel mai mare ID
Cand se cauta cel mai mare iD, aceasta inregistrare nu va fi luata in calcul, iar cel mai mare id existent va fi al inregistrarii precedente.
Noul id = cel mai mare id gasit +1, va fi egal cu ID-ul ultimei inregistrari, cea stearsa.
In acest caz vei avea o cheie primara duplicata - indexul tine cont si de inregistrarile sterese, de vreme  ce ele pot fi rechemate cu RECALL - si nu va fi acceptata in tabela.
Pentru a evita asta, trebuie sa faci SET DELETED OFF inainte de a cauta cel mai mare ID, iar dupa cautare sa refaci starea lui SET DELETED asa cum era ea inainte de cautare.
Functia trebuie sa lase contextul asa cum l-a gasit.

Incepe, si vom discuta apoi codul pe care il vei scrie.

Daniel Buduru
 2/2/2010 7:02:18 PM
User is offlineGooDy
194 posts
5th


Re: Atestat 2010
 (N/A)
Stiu ca voi scrie o prostie cat mine de mare , dar singurele programe facute la scoala au fost :

use magazin
set talk off
scan
replace prettotal with prettotal * nrproduse
endscan
browse

dupa , executam DO  xxxx
si gata programu .

eu m-am gandit ca functia ar arata cam asa :

SELECT Max(IDautor) as  MaxID FROM autori INTO CURSOR
REPLACE IDautor with MaxID + 1

dar ma gandesc ca de fiecare data va inlocui in toata tabela IDautor cu MaxID+1 si nu va face nimic .

Multumesc !
 2/2/2010 9:10:29 PM
User is offlineDaniel Buduru
2141 posts
1st




Re: Atestat 2010
 (N/A) Modified By Daniel Buduru  on 2/2/2010 10:49:56 PM)
Sa o luam mai de la inceput.
Ce este de fapt o functie?
alfa=PI()/8
X=COS(alfa)
PI() este functie care returneaza valoarea lui pi. Nu primeste nici un argument, intrucat valoarea lui pi nu depinde nimic.
COS() este tot o functie, care primeste ca argument unghiul (alfa) si returneaza valoarea cosinusului acestui unghi.
O functie utilizator (UDF, User Defined Function) este un program care poate primi date si care returneaza un rezultat.

Functia Newid trebuie sa primeasca drept parametru numele tabelei pentru care vrei sa obtii noul id si sa returneze noul id pentru acea tabela.
Nu trebuie sa il scrie in tabela, pentru ca nu mai lucram cu o tabela separata.
Hai sa vedem cum ar arata functia:

FUNCTION newid
LPARAMATERS tcTableName, tcFieldName           &&LPARAMETERS spune ca variabilele care urmeaza sunt parametrii primiti de functie
                                                                                &&tcTableName este numele tabelei; tc inseamna parametru (t) de tip caracter (c). Notatia asta este conventionala, pentru claritate, si nu este obligatorie
                                                                                &&tcFieldName este numele campului in care este stocat ID-ul
*In continuare verificam parametrii primiti
*Ei trebuie sa fie de tip caracter si sa aiba o valoare
*Desi se poate face verificarea intr-o singura expresie, in scop didactic, pentru claritate, verificam separat fiecare parametru
IF EMPTY(tcTableName) OR VARTYPE(tcTableName])<>"C"                               &&EMPTY(parametru) returneaza .T. daca paranetrul este gol, adica daca e "", sau 0 sau .F., in functie de tipul parametrului
                                                                                                                                &&VARTYPE(parametru) returneaza "C" daca parametru e de tip caracter, pentru restul valorilor returnate vezi in help

         MESSAGEBOX("NewID: nume tabela invalid"+TRANSFORM(tcTableName)) &&Atentionare pentru programator, nu ar trebui ca functia sa fie apelata cu parametru incorect
         RETURN .null.                                                                                                &&returneaza .NULL., pentru ca valoarea sa nu poata fi folosita mai departe
ENDIF                                                                                                                     &&daca avem un parametru invalid, nu avem de ce rula codul mai departe

IF EMPTY
(tcNumeCamp) OR VARTYPE(tcFieldName)<>"C" 
         MESSAGEBOX("NewID: nume camp invalid"+TRANSFORM(tcNumeCamp))
         RETURN .null.                                                                                               
ENDIF 

*Aici  am putea sa verificam existenta tabelei primita ca parametru, dar nu e cazul acum. Functia va fi apelata doar din program, iar acolo vei avea grija

*Intrucat interogarea tabelei va schimba zona de lucru si setarea lui SET DELETED, memoram valorile curente

LOCAL
lnArea, lcSetDeleted       &&LOCAL inseamna ca variabilele lnArea si lcSetDeleted sunt locale, asta insemnand ca nu vor interfera cu alte variabile cu acelasi nume definite in alte proceduri

lnArea=SELECT()                       &&lnArea memoreaza zona curenta
lcSetSeleted=SET("DELETED")   &&lcsetDeleted memoreaza starea lui SET DELETED
SET DELETED OFF                   &&Anulam filtrarea inregistrarilor marcate pentru stergere

* Cautam inregistrarea cu cel mai mare ID
* Declaram locale variabilele in care vom pune ultimul id si noul id

LOCAL lnLastId, lnNewId

*Vom folosi o facilitate a VFP, substitutia de nume, pentru a construi comanda sql

SELECT MAX((tcFieldName)) AS lastid FROM (tcTableName) INTO CURSOR crsid     && (tcFieldName) va fi inlocuit cu valoarea din variabila tcFieldName. Parantezele fac parte din sintaxa.

*Dupa aceasta comanda, se va selecta automat cursorul crsid
*Daca tabela tcTableName nu are inregistrari, cursorul crsid nu va contine nici o inregistrare

lnLastID=crsid.lastId  
lnNewID=IIF(EMPTY(lnlastID),0,lnlastID)+1 &&Daca lnlastid e gol, se va lua 0, altfel va lua valoarea lui lnlastid

*Acum avem noul ID, trebuie doar sa facem curat si sa punem lucrurile asa cum le-am gasit
USE IN (SELECT('crsid'))  &&Aceasta comanda va inchide cursorul crsid si nu va da o eroare daca acest cursor nu exista

*Reselectam zona

SELECT (lnArea)

*Refacem setarea lui SET DELETED asa cum era inainte

IF lcSetDeleted='ON'      &&nu stim daca era ON sau OFF, punem SET DELETED ON numai daca era asa cand a fosr apelata functia
   SET DELETED ON
ENDIF
*Se poate face si cu macrosubstitutie:
*SET DELETED &lcSetDeleted
*eu insa prefer forma cu IF

*Am refacut contextul, asa ca putem returna valoarea

RETURN lnNewID
ENDFUNC           &&ENDFUNC nu e obligatoriu in general, dar sunt situatii cand trebuie pus, cum ar fi in cazul unei functii in DBC. Spune doar ca s-a terrminat codul functiei

Ei, cam asa ar arata codul functiei newid.
Sa vedem cum procedam in continuare.


Daniel Buduru
 2/2/2010 9:20:46 PM
User is offlineDaniel Buduru
2141 posts
1st




Re: Atestat 2010
 (N/A)
De ce timp dispui pentru acest proiect?
Cand trebuie sa fie gata si cam cate ore in total poti aloca pentru el?



Daniel Buduru
 2/2/2010 9:36:24 PM
User is offlineGooDy
194 posts
5th


Re: Atestat 2010
 (N/A)
Proiectul trebuie sa fie gata pana in Mai . Sa zic 3-5 ore / zi
 2/2/2010 9:56:57 PM
User is offlineDaniel Buduru
2141 posts
1st




Re: Atestat 2010
 (N/A)
Timp ar fi, dar trebuie organizat.
Trebuie sa studiezi cate ceva, tema de proiect, asa cum e descrisa, presupune un nivel de cunostinte mai mare decat ai acum, chiar daca asta nu e din vina ta.
Te-am intrebat de vreo doua ori de sql si nu degeaba. In situatia de fata, e mult mai usor sa intelegi cum se lucreaza cu comenzi sql decat cu comenzi xbase (scan, replace ...)
As zice sa incepi deja cu SQL.
Citeste in help tot ce e la SELECT - SQL Command si intra pe toate link-urile
SELECT - SQL Command - FROM Clause
SELECT - SQL Command - WITH Clause
SELECT - SQL Command - WHERE Clause

SELECT - SQL Command - GROUP BY Clause

SELECT - SQL Command - HAVING Clause

SELECT - SQL Command - UNION Clause

SELECT - SQL Command - ORDER BY Clause

SELECT - SQL Command - INTO or TO Clause

SELECT - SQL Command - Additional Display Options

A
i acolo si ceva exemple

Apoi vezi INSERT - SQL Command si DELETE - SQL Command

Cand esti gata cu asta, adauga cateva inregistrari in tabela autori folosind comanda INSERT INTO ....


Daniel Buduru
 2/2/2010 10:06:44 PM
User is offlineGooDy
194 posts
5th


Re: Atestat 2010
 (N/A)
FUNCTION newid
LPARAMATERS tcautori, tcidautor      
IF EMPTY(tcautori) OR VARTYPE(tcautori])<>"C"                        
          
MESSAGEBOX("NewID: nume tabela invalid"+TRANSFORM(tcautori))
         RETURN .null.                                                                                            
ENDIF                                                                                                                   

IF EMPTY
(tcidautor) OR VARTYPE(tcidautori)<>"C" 
         MESSAGEBOX("NewID: nume camp invalid"+TRANSFORM(tcidautori))
         RETURN .null.                                                                                               
ENDIF 
LOCAL lnArea, lcSetDeleted     
lnArea=SELECT()                 
lcSetSeleted=SET("DELETED")  
SET DELETED OFF                 
LOCAL lnLastId, lnNewId
SELECT MAX((tcidautor)) AS lastid FROM (tcautori) INTO CURSOR crsid   
lnLastID=crsid.lastId  
lnNewID=IIF(EMPTY(lnlastID),0,lnlastID)+1
USE IN (SELECT(crsid))
SELECT (lnArea)
IF lcSetDeleted='ON'      
SET DELETED ON

ENDIF
 RETURN lnNewID
ENDFUNC          

cam asa ar trebui sa arate functia mea , bineinteles nu am facut mai nimic , inlocuind doar unde mi sa aratat . Este greu avand in vedere ca am 4 ani de liceu de pomana , invatand Pascal in scarba , adica cateva instructiuni in 3 ani , scrii 5 pagini pentru a rezolva o minoritate . Si acum ,, invata " VFP , nici macar invatat .
 2/2/2010 10:14:06 PM
User is offlineDaniel Buduru
2141 posts
1st




Re: Atestat 2010
 (N/A)

Nu trebuie sa inlocuiesti nimic. Functia este valabila pentru orice tabela, schimbi doar parametrii la apelare
Salveaza functia intr-un prg, pe care il botezi NewID.prg.
Apoi comentezi linia FUNCTION newid cu o steluta pusa in fata.
Va rata asa:
*FUNCTION newid
Apoi apelezi functia
Ex:
? NewID('autori','idautor')
? NewID('carti','idcarte')
? NewID('abonament','idabonament')
?NewID('imprumut','idimprumut')
Toate ar trebui sa returneze 1, daca nu ai nici o inregistrare in tabele.
Nu trebuie scrisa o functie pentru fiecare tabela.







Daniel Buduru
 2/2/2010 10:16:07 PM
User is offlineDaniel Buduru
2141 posts
1st




Re: Atestat 2010
 (N/A)
Intra un pic pe sql si spune-mi cum ti se pare si daca helpul e suficient de explicit.

Daniel Buduru
 2/3/2010 9:43:35 AM
User is offlineGooDy
194 posts
5th


Re: Atestat 2010
 (N/A)
Am facut cum ai spus cu functia si la apelare imi da : No PARAMETER statemen is found.

Nu inteleg despre ce help vorbesti , la mine F1 nu functioneaa , iar cand dau la meniu HELP sunt active doar : Microsoft on the Web & About Microsoft VisualFoxPro .

Multumesc !
 2/3/2010 10:16:58 AM
User is offlineRomeo
495 posts
2nd


Re: Atestat 2010
 (N/A)
Daca nu-ti merge Help-ul, mergi in C:\Microsoft Visual FoxPro 9 (sau in c:\Program Files\Microsoft Visual FoxPro 9 sau unde ai foxul) si cauta fisierul dv_foxhelp.chm
Apoi executa 2 clik pe el. In finali fa-i un shourtcut pe desktopul calculatorului.

test
 2/3/2010 10:48:34 AM
User is offlineRomeo
495 posts
2nd


Mai exista link-ul Grig ?
 (N/A)
Acum vreo 2-3 ani Grig tineai un blog, in care descriai vizita din America.
Acolo parca era o diagrama sql-server cu baza de date pe care ai modelat-o si pe baza careia ai refacut programul; parca erau si ceva comentarii.
Cred ca lui Marius i-ar fi foarte util sa vada un exemplu de baza de date proiectata profesional - chiar daca este in sql-server. Cand va avea mai mult timp va descarca sql-server express si va aprofunda.


 Grigore Dolghin wrote
Cheia primara a unui tabel este un camp cu o caracteristica speciala: valoarea lui este generata de sistem (in general crescatoare), odata alocat un numar nu se mai modifica si nu se mai realoca nimanui, niciodata, chiar daca inregistrarea respectiva este stearsa (si in felul asta obtii 'gauri' in sirul ala crescator, dar nu te deranjeaza), aceasta valoare nu este afisata utilizatorului si (foarte important) nu are sens in contextul businessului tratat de aplicatie. Altfel spus, desi intr-o lista de angajati CNP-ul ar putea fi cheie primara, NU E. Se face un camp separat in care se numeroteaza inregistrarile alea, de la 1 la cat o fi. La fel pentru codul de client, ISBN-ul cartii, etc etc etc. Rolul cheii primare este sa identifice INREGISTRAREA DIN TABELA, nu entitatea stocata in inregistrarea respectiva. Motivul este urmatorul: Valorile unice pertinente in businessul aplicatiei sunt introduse de oameni. Care pot gresi, ca de-aia-s oameni. Si daca le dai voie sa modifice valoarea cheii primare n-o s-o mai gasesti cand vrei sa actualizezi inregistrarea. Ca sa nu mai vorbim de faptul ca modificarea contravine regulii expuse in prima fraza.

Daca folosesti VFP9 poti seta un camp de tip Integer AutoInc drept cheie primara. Acesta se va popula cu valori pe masura ce adaugi inregistrari.

test
 2/3/2010 11:05:53 AM
User is offlineGooDy
194 posts
5th


Re: Mai exista link-ul Grig ?
 (N/A)
Mi-am luat VFP9 ...acum nu stiu ce sa  zic , sa continui pe VFP6 sau pe 9 .Daca as continua pe 9 nu ar mai fii nevoie de aceea functie , dar ati muncit cu mine 2-3 zile sa imi explicati , nu ar fii deloc corect .
 2/3/2010 12:56:36 PM
User is offlineDaniel Buduru
2141 posts
1st




Re: Mai exista link-ul Grig ?
 (N/A) Modified By Daniel Buduru  on 2/3/2010 12:56:54 PM)
Treci pe vfp9, crede-ma ca efortul e mai mare, cel putin pentru mine, sa-mi amintesc ce functii si comenzi erau disponibile in VFP6.
Tot ce ai de facut este sa modifici structurile si sa treci toate campurile ID pe integer(autoinc).
SQL?

Daniel Buduru
 2/3/2010 1:09:34 PM
User is offlineDaniel Buduru
2141 posts
1st




Re: Atestat 2010
 (N/A)
 GooDy wrote
Am facut cum ai spus cu functia si la apelare imi da : No PARAMETER statemen is found.

Nu inteleg despre ce help vorbesti , la mine F1 nu functioneaa , iar cand dau la meniu HELP sunt active doar : Microsoft on the Web & About Microsoft VisualFoxPro .

Multumesc !


Functia am scris-o direct aici, si inerent am mai tastat gresit. Pe prima line e LPARAMATERS in loc de LPARAMETERS, undeva mi-a ramans un tcNumeCamp, pe care l-am schimbat ulterior in tcFieldName, si am mai introdus o condtitie pentru campul id null
Aici e forma corectata

FUNCTION newid
LPARAMETERS tcTableName, tcFieldName           &&LPARAMETERS spune ca variabilele care urmeaza sunt parametrii primiti de functie
                                                                                &&tcTableName este numele tabelei; tc inseamna parametru (t) de tip caracter (c). Notatia asta este conventionala, pentru claritate, si nu este obligatorie
                                                                                &&tcFieldName este numele campului in care este stocat ID-ul
*In continuare verificam parametrii primiti
*Ei trebuie sa fie de tip caracter si sa aiba o valoare
*Desi se poate face verificarea intr-o singura expresie, in scop didactic, pentru claritate, verificam separat fiecare parametru
IF EMPTY(tcTableName) OR VARTYPE(tcTableName)<>"C"                               &&EMPTY(parametru) returneaza .T. daca paranetrul este gol, adica daca e "", sau 0 sau .F., in functie de tipul parametrului
                                                                                                                                &&VARTYPE(parametru) returneaza "C" daca parametru e de tip caracter, pentru restul valorilor returnate vezi in help
         MESSAGEBOX("NewID: nume tabela invalid"+TRANSFORM(tcTableName)) &&Atentionare pentru programator, nu ar trebui ca functia sa fie apelata cu parametru incorect
         RETURN .null.                                                                                                &&returneaza .NULL., pentru ca valoarea sa nu poata fi folosita mai departe
ENDIF                                                                                                                     &&daca avem un parametru invalid, nu avem de ce rula codul mai departe

IF EMPTY(tcFieldName) OR VARTYPE(tcFieldName)<>"C" 
         MESSAGEBOX("NewID: nume camp invalid"+TRANSFORM(tcNumeCamp))
         RETURN .null.                                                                                               
ENDIF 

*Aici  am putea sa verificam existenta tabelei primita ca parametru, dar nu e cazul acum. Functia va fi apelata doar din program, iar acolo vei avea grija

*Intrucat interogarea tabelei va schimba zona de lucru si setarea lui SET DELETED, memoram valorile curente

LOCAL lnArea, lcSetDeleted       &&LOCAL inseamna ca variabilele lnArea si lcSetDeleted sunt locale, asta insemnand ca nu vor interfera cu alte variabile cu acelasi nume definite in alte proceduri

lnArea=SELECT()                       &&lnArea memoreaza zona curenta
lcSetDeleted=SET("DELETED")   &&lcsetDeleted memoreaza starea lui SET DELETED
SET DELETED OFF                   &&Anulam filtrarea inregistrarilor marcate pentru stergere

* Cautam inregistrarea cu cel mai mare ID
* Declaram locale variabilele in care vom pune ultimul id si noul id

LOCAL lnLastId, lnNewId

*Vom folosi o facilitate a VFP, substitutia de nume, pentru a construi comanda sql

SELECT MAX((tcFieldName)) AS lastid FROM (tcTableName) INTO CURSOR crsid     && (tcFieldName) va fi inlocuit cu valoarea din variabila tcFieldName. Parantezele fac parte din sintaxa.

*Dupa aceasta comanda, se va selecta automat cursorul crsid
*Daca tabela tcTableName nu are inregistrari, cursorul crsid nu va contine nici o inregistrare

lnLastID=crsid.lastId  
lnNewID=IIF(EMPTY(nvl(lnlastID,0)),0,lnlastID)+1 &&Daca lnlastid e gol, se va lua 0, altfel va lua valoarea lui lnlastid

*Acum avem noul ID, trebuie doar sa facem curat si sa punem lucrurile asa cum le-am gasit
USE IN (SELECT('crsid'))  &&Aceasta comanda va inchide cursorul crsid si nu va da o eroare daca acest cursor nu exista

*Reselectam zona
SELECT (lnArea)

*Refacem setarea lui SET DELETED asa cum era inainte
IF lcSetDeleted='ON'      &&nu stim daca era ON sau OFF, punem SET DELETED ON numai daca era asa cand a fosr apelata functia
   SET DELETED ON
ENDIF


Daniel Buduru
 2/3/2010 1:15:55 PM
User is offlineDaniel Buduru
2141 posts
1st




Re: Atestat 2010
 (N/A)
Aici ai documentatia online pentru comenzile SQL din VFP9

SELECT - SQL
http://msdn.microsoft.com/en-us/library/h09t6a82%28VS.80%29.aspx

INSERT - SQL
http://msdn.microsoft.com/en-us/library/h54fa37c%28VS.80%29.aspx

UPDATE - SQL
http://msdn.microsoft.com/en-us/library/8hwekas8%28VS.80%29.aspx

DELETE -SQL
http://msdn.microsoft.com/en-us/library/6kt4x6zx%28VS.80%29.aspx

Daniel Buduru
 2/4/2010 9:56:25 AM
User is offlineGooDy
194 posts
5th


Re: Atestat 2010
 (N/A)
Am citit toate aceste informatii si zic eu ca am inteles cate ceva .
 2/4/2010 10:31:08 AM
User is offlineDaniel Buduru
2141 posts
1st




Re: Atestat 2010
 (N/A)
Atunci sa trecem la ceva exercitii.
Mai intai sa populam tabelele cu cateva inregistrari, altfel nu avem pe ce testa.
Ia vreo 10 carti din biblioteca si incarca-le.
Vei da comenzile din fereastra de comenzi. Am sa-ti dau eu comenzile pentru insert, pe celelalte le vei scrie singur

Mai intai, incarci autorul. Nu mai stiu exact ce nume de tabele si campuri au ramas la final, le pui tu pe cele pe care le ai acolo

na="Numele Autorului"
INSERT INTO autori (nume) VALUES (na)

* Acum trebuie sa regasim idautor, pentru ca nu-l stim, il pune automat campul autoinc
* Functia GETAUTOINC() returneaza ultima valoare generata de un camp autoinc intr-o sesiune de date (datasession)
* Vezi in help mai multe

nIDAutor=GETAUTOINC()

* Incarcam cartea:

tc="Titlul cartii"
npu=pretul cartii
nex=numarul de exemplare
INSERT INTO carti (idautor, titlu, pret, exemplare) VALUES (nIDautor, tc, npu, nex)

Reperti asta pentru fiecare carte

Apoi scrii cateva comenzi sql:
- selectezi cartile cu un anumit titlu, sa zicem titlul celei de-a doua carte introdusa
- afli cate carti si cate exemplare sunt in biblioteca in total, nu pe fiecare carte.

Daca ai dificultati, intreaba.


Daniel Buduru
 2/5/2010 12:10:48 PM
User is offlineGooDy
194 posts
5th


Re: Atestat 2010
 (N/A)
am populat tabelele cu INSERT , este destul de usor daca stii despre ce este vorba . Am inteles cum se face .
Am facut si prima cerinta :

SELECT titlu;
   FROM carte ;
   WHERE idcarte=2

si m-am mai jucat pe acolo , sa selectez cate ceva , pentru a vedea cum functioneza .

La al 2-lea am ceva probleme , nu stiu cum sa calculez , stiu sa selectez stocul total dar nu stiu cum sa le calculez .
 2/5/2010 12:18:30 PM
User is offlineDaniel Buduru
2141 posts
1st




Re: Atestat 2010
 (N/A) Modified By Daniel Buduru  on 2/5/2010 5:55:08 PM)
Tema era sa selectezi cartea dupa titlu, nu dupa ID.
Incearca si vei vedea dece.

Vezi functiie SUM(), COUNT(), MAX(), MIN(), AVG() in SELECT - SQL

SELECT COUNT(*) as total_carti, SUM(stoct) as total_exemplare FROM carti

Acum alta tema, scurt:
Selecteaza idCarte, titlu, autor (numele autorului, nu idautor) din carti si autori.

Vezi JOIN inSELECT SQL
http://msdn.microsoft.com/en-us/library/f4saeycb(VS.80).aspx


Daniel Buduru
 2/12/2010 8:54:40 PM
User is offlineGooDy
194 posts
5th


Re: Atestat 2010
 (N/A)
Imi cer mii de scuze pentru inactivitate , dar dupa cum presupun ca stiti , luni voi avea de sustinut proba orala la romana ...timpul meu sa concentrat mai mult pe aceasta proba . Dupa ce se va termina , voi revenii in forta pentru a recupera timpul pierdut .

Multumesc si sper sa ma intelegeti !
 2/13/2010 5:23:12 PM
User is offlineDaniel Buduru
2141 posts
1st




Re: Atestat 2010
 (N/A)
Bafta !

Daniel Buduru
 2/18/2010 12:16:42 AM
User is offlineGooDy
194 posts
5th


Re: Atestat 2010
 (N/A)
Am revenit hotarat pe treaba . Proba orala la romana s-a incheiat cu bine , am obtinut  calificativul Experimentat :D .

prima sarcina , selectarea dupa titlu :

SELECT titlu,idcarte,dstoc;
from carte;
WHERE titlu="Morometii"

functioneaza , dar , daca pun "morometii" , numai functioneaza .

La a 3-a tema am facut ceva de genul dar imi da urmatoarea eroare :

IDAUTOR is not unique and must be qualified .

SELECT idautor, nume , titlu ;
   FROM carte AS TAlias1 ;
   INNER JOIN autori AS TAlias2 ;
      ON TAlias1.idautor = TAlias2.idautor ;
      

Numai bine ,
 2/18/2010 12:42:01 AM
User is offlineDaniel Buduru
2141 posts
1st




Re: Atestat 2010
 (N/A) Modified By Daniel Buduru  on 2/18/2010 1:15:12 AM)
Experimentat, desigur, doar o vorbesti din frageda pruncie

Deci ai vazut ca nu e chiar simplu sa pui un filtru dupa un text ...

lcString='Morometii'

SELECT titlu, carte, dstoc ;
   FROM carte ;
   WHERE UPPER(lcString)$UPPER(titlu)

Sau

SELECT titlu, carte, dstoc ;
   FROM carte ;
   WHERE ATC(lcString,titlu)>0

Functia ATC(sir_cautat, Sir_in_care_se_cauta) returneaza pozitia in care sirul cautat se gaseste in sirul de cautat, indiferent daca este scris cu majuscule sau minuscule (case insensitive).
Functa AT() face acelasi lucru, dar este case sensitive, nu va gasi 'morometii' in 'Morometii'

Sau

SELECT titlu, carte, dstoc ;
   FROM carte ;
   WHERE titlu LIKE '%'+lcString+'%'

In acest caz '%' folosit cu operatorul LIKE are functia de "wildcard", inocuieste orice sir de caractere.


Va mai apare o problema, si anume diacriticele ...
Se poate scrie Morometii sau Moromeţii.
Dar vom lasa asta la sfarsit, daca va mai fi timp si vei mai avea chef :)

IDAutor apare in ambele tabele, trebuie sa precizezi din care tabela vrei sa fie luat campul:

SELECT car.idautor, nume , titlu ;
   FROM carte car ;
   INNER JOIN autori aut ;
      ON car.idautor = aut.idautor ;
  ORDER BY nume, titlu

E corect cum ai scris aliasul, dar neeconomic cand ai de scris mult cod :)
De asemenea, e mai usor de urmarit codul daca aliasul e o prescurtare a numelui fisierului.

Acum sa aflam cate titluri de Creanga exista in biblioteca.


Daniel Buduru
 2/18/2010 1:46:10 AM
User is offlineDaniel Buduru
2141 posts
1st




Re: Atestat 2010
 (N/A)
Si inca o tema.
La introducerea unui autor sau a unei carti va trebui sa verificam daca autorul sau cartea exista deja in baza de date.
Dupa cum am vazut deja de la cautarea unui titlu dintr-un singur cuvant, lucrurile nu sunt chiar atat de simple.
Avem un singur camp de nume pentru autor, care contine numele complet (ume si prenume).
Numele poate fi scrie fie ca Nume Prenume, fie ca Prenume Nume (Creanga Ion sau Ion Creanga).
Daca verificam numele intreg, si cautam Creanga Ion, nu il vom gasi pe Ion Creanga, cel care exista deja in baza de date, si vom crea un alt autor, cu un alt ID.
La fel, daca in titlul unei carti operatorul introduce doua spatii, titlul nu va fi gasit.
Solutia este cautarea fiecarui cuvant din nume sau din titlu.
Apar doua probleme:
- sa extragem fiecare cuvant dintr-un sir
- sa cream expresia de filtru cu aceste cuvinte, al caror numar este variabil.
Sunt aproape sigur ca nu ati ajuns sa studiati functiile necesare, asa ca am sa le indic:
GETWORDCOUNT(sir, delimitatori) - intoarce numarul cuvintelor din sir delimitate de doi dintre delimitaori (delimitatorii impliciti sunt spatiu, virgula, punct)
GETWORDNUM(sir, index, delimitatori) intoarce cuvantul cu numarul index din sir delimitat de doi delimitatori
FOR ... NEXT 

Vezi in help aceste functii si comenzi si scrie o secventa  de cod care sa extraga cuvintele si-un sir si sa construiasca o clauza WHERE cu aceste cuvinte:

WHERE ATC(cuvant1, titlu)>0 AND ATC(cuvant2, titlu)>0 AND ...





Daniel Buduru
 2/19/2010 12:19:42 AM
User is offlineedyshor
1450 posts
1st




Re: Atestat 2010
 (N/A)
daca-mi permiteti o mica insertie...
doresc sa amintesc ca in sintaxa sql se pot folosi functii proprii, iar pentru acest exemplu foarte utila ar fi o functie care sa verifice daca un sir reprezinta un cuvant intr-o expresie, ignorandu-se case-ul si chiar diacrticele.
functia se poate folosi in 'Where' si trebuie sa intoarca .T./.F. - iar selectul devine usor de citit, mai ales daca se doreste cautarea mai multor cuvinte sau in mai multe expresii.
 2/19/2010 2:10:09 AM
User is offlineDaniel Buduru
2141 posts
1st




Re: Atestat 2010
 (N/A) Modified By Daniel Buduru  on 2/19/2010 2:10:53 AM)
De acord cu functia, dar nu sunt de acord cu ea pusa in select.
Avand in vedere frecventa interogarilor, eu prefer utilizarea unui camp in tabela care sa contina textul procesat astfel - uppercase, cu diacriticele eliminate - si indexat.
Sirul de cautat se proceseaza in acelasi mod, inainte de cautare. In acest mod, in anumite conditii, interogarea poate fi chiar optimimizabila Rushmore.

Insa, in aceasta etapa, trebuie sa ne limitam la functionalitatea minim necesara, avand in vedere de la ce nivel pornim si timpul ramas.
Intentia este de a acumula cunostintele necesare pentru a face interogarea, inserarea si actualizarea bazei de date prin comenzi sql si de a scrie rutinele necesare pentru aceasta inainte de a trece partea de interfata.



Daniel Buduru
 2/23/2010 4:20:10 PM
User is offlineGooDy
194 posts
5th


Re: Atestat 2010
 (N/A)
Din pacate am o problema mare , nu reusesc sa execut nici tema 1 nici tema 2 :( .
Chiar nu inteleg ce nu imi iese . La prima tema stiu sa selectez dupa autor dar nu imi iese sa afisez cate rezultate imi afiseaza . La a 2-a tema , scuzati-ma dar nu am inteles si reusit nimic .

Imi cer scuze , dar chiar nu ma prind unde este buba :(
 2/23/2010 5:02:23 PM
User is offlineDaniel Buduru
2141 posts
1st




Re: Atestat 2010
 (N/A) Modified By Daniel Buduru  on 2/23/2010 5:03:45 PM)
Tema 1 era sa afli cate titluri de Creanga sunt in biblioteca.
Tema 2, sa scrii un algoritm care sa extraga toate cuvintele dintr-un sir.

Mai intai, tema 1.
Ce inseamna sa afli cate titluri de Creanga sunt in biblioteca? Pai, sa numeri cate carti ale unui autor se gasesc in tabela carti.
In SQL se pot folosi functii - COUNT(), SUM(), MAX(), MIN(), AVG() si altele - care fac respectivele calcule pe setul de inregistrari selectat prin filtru (clauza WHERE)
COUNT() tocami asta face, numara cate inregistrari se gasesc in set.
Mai intai insa, trebuie sa extragem din toate cartile doar pe cele al caror autor este Creanga.
Pentru asta, mai intai trebuei sa aflam IDautor, apoi sa selectam cartiel cu acest idautor, air apoi sa numaram cate carti sunt.

Primul filtru:
Vom primi cumva numele autorului, pe care-l vom pune intr-o variabila, apoi vom lucra cu variabila.
lcAutor="Creanga"
Vrem sa gasim lcAutor oricum ar fi scris numele, asa ca vom converti sirul in majuscule.
lcAutor=UPPER(lcAutor)
Dar vrem sa eliminam si eventualele spatii din fata sau de la sfrsitul numelui
lcAutor=ALLTRIM(lcAutor)
Apoi selectam inregistrarile care contin lcAutor in campul nume

SELECT IDautor FROM autori WHERE lcAutor$UPPER(Nume)      &&Operatorul $ folosit aici inseamna "lcAutor este inclus in UPPER(Nume)"

Avem un set de inregistrari care contin "Creanga" in numele autorului.
Ar trebui sa fie o singura inregistrare, daca sunt mai multe inseamna ca numele nu unic si ne mai trebuie inca un cuvant (sau mai multe) pentru a-l identifica in mod unic.
Trecem acum peste acest aspect, il vom relua mai tarziu.

Acum trebuie sa selectam un set de inregistrari din carti, care sa aiba idautor acelasi cu setul pe care tocmai l-am obtinut.
Pentru asta, punem conditia ca IDAutor din tabela carti sa se gaseasca in setul pe care l-am selectat mai inainte din autori.

SELECT * FROM carti WHERE idautor IN (SELECT IDautor FROM autori WHERE lcAutor$UPPER(Nume) )

Acum avem un set de inregistrari din tabela carti al caror autor contine "Creanga" in nume.
Tema insa era accea de a numara cate carti ale autorului avem in biblioteca.
Pentru asta, vom folosi functia COUNT.

SELECT COUNT(*) as Carti FROM carti WHERE idautor IN (SELECT IDautor FROM autori WHERE lcAutor$UPPER(Nume) )

Comanda sql select mai are o clauza, INTO, care permite specificarea unei destinatii pentru respectiva comanda.  Daca nu se specifica aceasta clauza, automat se creeaza un cursor cu aliasul Query, cursor care este afisat direct in Browse. Urmatoarea comanda SELECT fara INTO va suprascrie acest cursor.

SELECT COUNT(*) as Carti FROM carti WHERE idautor IN (SELECT IDautor FROM autori WHERE lcAutor$UPPER(Nume) ) INTO CURSOR crsCount
Va crea un cursor cu aliasul "crscount".

SELECT COUNT(*) as Carti FROM carti WHERE idautor IN (SELECT IDautor FROM autori WHERE lcAutor$UPPER(Nume) ) INTO ARRAY aCount
Va crea un vector aCount, cu atatea coloane cate campuri ar avea cursorul creat si atatae linii cate inregistrari ar avea acel cursor.

Mai tarziu, vom folosi comenzile SELECT numai cu clauza INTO.


Daniel Buduru
 2/23/2010 5:24:41 PM
User is offlineDaniel Buduru
2141 posts
1st




Re: Atestat 2010
 (N/A)
Tema 2, sa scrii un algoritm care sa extraga toate cuvintele dintr-un sir.
Functia GETWORDCOUNT(sir) returneaza numarul cuvintelor din sir.
Functia GETWORDNUM(sir, x) returneaza cuvantul numarul x din sir
"?" pus in fata unei variabile sau a unei functii afiseaza variabila sau rezultatul functiei.


lcText="Ion Luca Caragiale"

? GETWORDCOUNT(lcText)

FOR lni=1 TO GETWORDCOUNT(lcText)
? GETWORDNUM(lcText,lni)
NEXT

Ca sa cautam dupa fiecare cuvant din lcText in autori, trebuie sa scriem o clauza WHERE cam asa:

... WHERE cuvant1$UPPER(nume) AND cuvant2 $UPPER(nume) AND cuvant3$UPPER(nume)

Dar nu stim cate cuvinte va introduce utilizatorul, deci va trebui sa construim clauza WHERE in mod dinamic

lcWhere='WHERE '
lnCuvinte=
GETWORDCOUNT(lctext)
FOR lni=1 TO lnCuvinte
    lcCuvant=GETWORDNUM(lctext,lni)
    lcWhere=lcWhere+"UPPER("+lcWord+")$UPPER(nume) "
   *** Aici trebuie sa punem AND, dar numai daca nu este ultimul cuvant din sir
   IF lni< lnCuvinte
      lcWhere=lcWhere+" AND "
  ENDIF
ENDFOR

? lcWhere
lcSQL="SELECT * FROM autori "+lcWhere
? lcSQL
&lcSQL

Asta era tema 2.
Problema este accea ca, la un singur post pe saptamana, nu va fi timp pentru mai nimic, si vei recurge la atestatul "de gata".



Daniel Buduru
 2/23/2010 7:05:43 PM
User is offlineGooDy
194 posts
5th


Re: Atestat 2010
 (N/A)
k , am inteles toate explicatiile , multumesc mult . Am avut unele probleme si de aceea nu am putut sa fiu activ , sper sa nu se mai repete .
La a 2-a problema :
FOR Ini=1 to getwordcount(lctext)

( imi spune : statements is not allowed in interactive mode ) ...banueies ca este problema ca acolo apare INI , este o variabila care nu a fost declarata inainte ...corect ?
 2/23/2010 7:21:59 PM
User is offlineDaniel Buduru
2141 posts
1st




Re: Atestat 2010
 (N/A) Modified By Daniel Buduru  on 2/23/2010 7:27:03 PM)
In VFP nu este obligatoriu ca variabilele sa fie declarate inainte de utilizare.
Doar in cazul in vare se doreste ca variabila sa aiba o alta vizibilitate decat cea implicita - de ex., PUBLIC sau PRIVATE.
"statement is not allowed in interactive mode" se refera la FOR ...
Copiaza tooata bucla FOR (cele 3 randuri, de la FOR la ENDFOR sau NEXT, inclusiv), apoi click-dreapta, selectezi "Execute selection"
Sau, mai simplu si mai comod, deschizi un prg nou (fie din File, New, Program, fie din Command cu Modi Comm) apoi copiezi toate comenzile acolo.
Nu e nevoie sa salvezi programul, selectezi totul cu Ctrl+A, iar click-dreapta, Execute Selection

Iar variabila este lnI (l=local, n=numeric, I este un contor), si nu INI ...
Este un mod de a numi variabilele astfel incat sa poti identifica vizibilitatea si tipul variabilei.

Daniel Buduru
 2/24/2010 10:06:19 PM
User is offlineGooDy
194 posts
5th


Re: Atestat 2010
 (N/A)
am inteles , am crezut ca este ca la Pascal unde se declarau toate variabilele.
 2/24/2010 10:33:56 PM
User is offlineDaniel Buduru
2141 posts
1st




Re: Atestat 2010
 (N/A)
OK.
Pune aici structura fiecarei tabele - nume camp, tip, lungime, zecimale (unde e ste cazul)- pentru ca nu mai stiu la ce nume de campuri ai ramas.

Urmatoarea tema:
Alege o carte dintre cele pe care le-ai introdus in tabela carti.
Obtine id-ul acelei carti folosind o comanda SELECT SQL.
Folosind comanda SQL UPDATE sa actualizezi numarul de exemplare existente in biblioteca pentru acea carte, presupunand ca s-au imprumutat trei exemplare.



Daniel Buduru
 2/25/2010 5:07:31 PM
User is offlineGooDy
194 posts
5th


Re: Atestat 2010
 (N/A)
In sfarsit vin si eu cu o tema ( zic eu ) rezolvata ... functioneaza :

n='morometii'
UPDATE carte;
SET dstoc=dstoc-3;
from carte;
WHERE UPPER(n)$UPPER(titlu)

aici este structura tabelelor :
Abonament : idabonat (autoinc | 4 | 0 )
                     nume ( character | 60 | 0 )
                     clasa ( character | 10 | 0 )

Autori : idautor ( autoinc | 4 | 0 )
             nume ( character | 60 | 0 )

Carte : idcarte ( autoinc | 4 | 0 )
            idautor ( integer | 4 | 0 )
           titlu ( character | 40 | 0 )
           volum ( numeric | 10 | 0 )
           tstoc ( numeric | 10 | 0  )
           dstoc ( numeric | 10 | 0  )
            pret ( numeric | 10 | 2  )
            sector ( character | 10 | 0 )
            rand ( numeric | 10 | 0  )
           corp ( character | 10 | 0 )
           raft ( character | 10 | 0 )

Imprumut : idimprumut ( autoinc | 4 | 0 )
                  idabonat ( integer | 4 | 0 )
                  idcarte ( integer | 4 | 0 )
                  dimprumut ( date | 8 | 0 )
                  dtermen ( date | 8 | 0 )
                  dreturnare ( date | 8 | 0 )
                 

 2/25/2010 8:37:33 PM
User is offlineDaniel Buduru
2141 posts
1st




Re: Atestat 2010
 (N/A)
Intr-adevar e rezolvata, chiar daca nu intocmai cum era tema. Sintaxa este corecta, si face actualizarea.
In tema era sa obtii mai intai id-ul cartii, apoi sa faci actualizarea folosind acel id.
Ce importanta are cum faci actualizarea?
Din punct de vedere al comenzii de actualizare, nici una.
Din punct de vedere al filtrului, mare.
Ce s-ar intampla daca in carti ai "Morometii Vol. I", "Morometii Vol.II" ?
Comanda de actualizare va modifica stocul ambelor carti, desi au ID-uri diferite.
Ce se schimba daca obtin mai intai ID-ul?
Verific cate inregistrari returneaza comanda SELECT IDCarte FROM carti WHERE UPPER(n)$UPPER(titlu) INTO CURSOR crsCarte
? RECC('crsCarte')
Daca avem 0 inregistrari, cartea nu exista.
Daca avem mai mult de 1 inregistrare, numele nu este unic si trebuie inca un cuvant in conditia de filtru. Acum poti sa constati pentru ce este necesar codul acela pentru crearea unei clauze where.
Putem actualiza stocul abia cand avem un singur IDCarte.

Sa vedem unde ne aflam acum.
Avem definite structurile de date.
Nu avem inca definite cheile de legatura intre tabele, va trebui sa o facem.
Stim sa selectam o inregistrare dupa o conditie.
Stim sa selectam informatii din doua tabele si sa le afisam intr-un singur cursor.
Stim sa inseram inregistrari intr-o tabela.
Stim sa actualizam inregistrari intr-o tabela.
Stim sa numaram cate inregistrari satisfac o anumita conditie.
Stim sa generam o comanda sql in cod.

Cu ce stim pana acum, putem deja lucra cu baza de date.
Pe parcurs, vom mai adauga cate ceva la acest set de comenzi.

Acum sa incepem ceva teste cu interfata.
Ar fi bine sa ai 5-10 inregistrari in fiecare tabela, ca sa putem vedea ceva concret.

Vom incepe cu actualizarea tabelei Autori

Mai intai, sa discutam un pic despre interfata utilizator.
Interfata trebuie sa ne permita cautarea unui autor, introducerea unui autor nou si modificarea datelor deja introduse.

Cum ar trebui sa fie o interfata prietenoasa?
Un textbox in care operatorul tasteaza numele autorului, apoi un buton de cautare?
Cine cauta un fisier folosind Search File, unde sa-i dea numele si locatia in care sa fie cautat?
Cine cauta un contact in address book tastand numele?
Cu rare exceptii, se folosesc listele, fie din folder explorer, fie din contacts.
Iar atunci cand trebuie inserat undeva, tot selectie din lista facem. Daor daca nu am gasit nimic in lista, cream un fisier, folder sau contact nou.

VFP are 3 controale native care pot afisa inregistrarile dintr-o tabela. Listbox, Combobox si Grid.
Putem afisa lista autorilor din baza de date, putem filtra pe litera de inceput a numelui, putem cauta incremental un autor in lista.
Si asta doar din mouse, fara a fi necesara tastarea. Cam asa cum ne sunt puse la dispozitie informatiile in windows.

Pentru inceput, vom deschide o forma.
Vom plasa pe o lista si un textbox.
Lista in stanga, textbox-ul la dreapta ei.
Salvam forma cu numele frmAutori.
Daca ai dificultati, intreaba.


Daniel Buduru
 2/25/2010 9:24:38 PM
User is offlineGooDy
194 posts
5th


Re: Atestat 2010
 (N/A)
Tabelele sunt populate cu inregistrari .

Nu am mai lucrat pana acum cu interfete deci sper ca nu zic o prostie .

Din Project Manager , am ales Documents apo Form., new form , Din forms controls am ales ->  List Box ( lista din stanga ) apoi Textbox ( cel din dreapta ) iar sub el un command button .
 2/25/2010 10:17:06 PM
User is offlineDaniel Buduru
2141 posts
1st




Re: Atestat 2010
 (N/A)
E bine.
Nu umblam inca la dimensiuni si aranjare, vrem doar un model care sa functioneze.
Acum, vom face ca acest form sa aiba o sesiune de date privata.
Asta inseamna ca tabelele deschide de acest form nu vro interfera cu aceleasi tabela deschise de un alt form.
Deschide fereastra de Properties pentr form.
Click dreapta pe form, apoi alegi properties.
In Properties, defileaza pana la Datasession
Pui Datasession=2 - Private.
Revii la form, iar click dreapta, alegi Data Environment
Se va deschide o fereastra cu titlul Data Environment - frmAutori.
Data Environment este un obiect, care poate fi asociat unui form, si care se ocupa de deschiderea si inchiderea tabelelor.
Vom pune aici tabela autori, pe care o vrem deschisa in form.
Click dreapta in acea fereastra, Add.
Se deschide fereastra de selectie tabela.
Alegi tabela Autori, apoi inchizi fereastra Data Environment.


Acum avem nevoie de comanda SQL pentru selectarea nume si idautor din autori, ordonat dupa nume.
Acum o pun eu, la celelalte formuri vei scrie singur comanda.

SELECT nume, idautor FROM autori ORDER BY nume INTO CURSOR crsList1

Click dreapta pe List1, Properties
Mergi la RowSource.  Aici punem comanda pe care tocmai am scris-o.

RowSource="SELECT nume, idautor FROM autori ORDER BY nume INTO CURSOR crsList1"
Row SourceType=3 - SQL Statement

Ce am facut pana acum? Row Source inseamna sursa liniilor din lista. Liniile din lista vor contine campurile cursorului crsList1, generat de comanda SQL.
II mai indicam listei ca liniile sunt resultatul unei comenzi sql prin RowSourceType.
Acum trebuie sa mai stabilim cate coloane va avea lista.

ColumnCount=2
ColumnWidths=300,0

Vom avea doua coloane - campurile nume si idautor; Prima coloana va avea o latime de 300 de pixeli, a doua coloana va avea latimea 0 - nu vrem sa afiseze idautor.

Vrem ca lista sa returneze valoarea lui IDautor. IDautor este al doilea camp din cursor. Punem

BoundColumn=2

Salvam forma si o rulam.





Daniel Buduru
 2/26/2010 4:34:01 PM
User is offlineGooDy
194 posts
5th


Re: Atestat 2010
 (N/A)
Am facut totul exact cum ai spus si mi-a iesit bine , in aceea lista mi-au aparut toti autorii din tabela autori :)
 2/26/2010 8:28:49 PM
User is offlineDaniel Buduru
2141 posts
1st




Re: Atestat 2010
 (N/A)
N-a fost chiar complicat, nu? :)
Sa continuam.
Ce facem cu textbox-ul?
Pai, ar trebui sa punem in el numele autorului.
Si asta, ori de cate ori ne deplasam in lista.
Pentru asta, ar trebui sa stim cumva cand utilizatorul s-a deplasat in lista si sa actualizam informatia din textbox.

Am sa incerc sa explic cele doua metode prin care se poate face acest lucru printr-o analogie:
Sa zicem ca astepti sa vina un cunoscut la tine. Cand vine, trebuie sa-i deschizi usa.
Ai doua alternative:
- te duci la usa din minut in minut, sa vezi daca a venit.
- astepti pana suna la sonerie, sau bate in usa, sau te striga de afara.
Prima metoda se numeste programare "polling" - interogarea periodica pentru a sesiza schimbarea unei stari.
A doua metoda se numeste programare "event based" - bazata pe evenimente.
In cazul acesta, evenimentul este ajungerea cunoscutului in fata usii. Cand se produce evenimentul, cunoscutul tau il semnaleaza.
Continuand analogia, cunoscutul este, din punct de vedere al programarii, un obiect (desi aici se va obiecta imediat ca nu e obiect, ci fiinta ...).
Acest obiect anunta cand se produc diverse evenimente. Penntru asta, fiecare eveniment are atasata o metoda care se executa atunci cand se produce respectivul eveniment. Acea metoda se numeste "event", desi nu ea este evenimentul.
Daca te uiti in fereastra Properties, sus are un sir de tab-uri - All, Data, Methods, Layout, Others si Favorites.
In All se vad toate proprietatile, evenimentele si metodele obiectului, iar in celelalte sunt filtrate pe categorii.
In Data apar proprietatile legate de procesarea datelor, in Methods - metodele si evenimentele, in Others - proprietatile si metodele definite de utilizator.
Evenimentele se recunosc usor dupa pictograma cu un fulger galben.

Revenind la listbox, ne trebuie evenimentul declansat de modificarea valorii listei, ca urmare a deplasarii in lista.
Aceste se numeste InteractiveChange, si se regaseste si la alte obiecte.
Vrem sa afisam, in textbox, numele autorului.
Pentru asta vom pune cod in InteractiveChange:
Atentie! Este doar pentru intelegerea functionarii, NU VOM PROCEDA ASA IN CONTINUARE.
Click dreapta pe lista, alegi Code
Se deschide o fereastra care are sus doua combobox-uri: Object - in care apare List1, si Procedure, in care apare, probabil, AddItem.
Alegi din acest combobox InteractiveChange.
Apoi scrii in fereastra:

Thisform.Text1.value=THIS.List(This.ListIndex,1)

Salvezi formul si il rulezi.

Am sa mai postez ceva in seara asta, avand in vedere ca nu voi mai avea acces la net pana duminica seara :)


Daniel Buduru
 2/26/2010 9:13:45 PM
User is offlineGooDy
194 posts
5th


Re: Atestat 2010
 (N/A)
Am inteles explicatia , am executat form-ul si functioneaza perfect .

Iti multumesc enorm pentru bataia de cap si pentru explicatiile tale .
 2/26/2010 10:53:05 PM
User is offlineDaniel Buduru
2141 posts
1st




Re: Atestat 2010
 (N/A) Modified By Daniel Buduru  on 3/1/2010 6:58:32 PM)
Ok. Continuam.
Spuneam ca e doar un exemplu pentru utilizarea evenimentului, si ca nu vom proceda asa in continuare.
Ce nu e in regula cu acel cod?
Doua lucruri:
- Afisam o valoare intr-un textbox folosind proprietatea value in loc de ControlSource doar daca nu avem alta solutie - iar aici avem.
- Obiectul List1 trebuie sa stie cine este si unde se gaseste obiectul Text1 si ce proprietati are.
Aceasta metoda de programare se numeste "tight coopling" - cuplare stransa.
O alta metoda de programare este "loose coopling" - cuplare slaba.
Avantajele principale ale celei de-a doua metode sunt portabilitatea codului si derivarea obiectelor.
Portabilitatea codului inseamna reutilizarea aceluiasi cod in diferite situatii, fara modificari.
Derivarea insemna crearea unui obiect care mosteneste toate proprietatile si metodele unui obiect parinte, si care poate capata proprietati si functii noi.
Am sa mai revin asupra acestor definitii sumare.
Ce inseamna asta din punctul de vedere al aplicatiei noastre?
Daca dorim ca si celelalte actualizari - carti, abonati - sa le facem in acelasi mod ca si autorii, atunci avem interesul ca acest cod sa poata fi refolosit.
Cum se poate face un cod reutilizabil?
Codul poate fi reutilizat daca nu foloseste nume proprii.
Un exemplu: un profesor care cunoaste toti elevii din clasa poate spune "Marius, adu lucrarea", in timp ce un profesor nou, care nu stie pe nimeni pe nume, poate rezolva problema astfel: "Elevul din stanga, banca a doua, randul de la geam, adu lucrarea".
Sa incercam sa cream un astfel de cod.
Mai intai, vom adauga niste proprietati si metode formului nostru.
Le vom adauga din designer.
Deschidem forma. In menu trebuie sa apara un pad numit Form. Deschidem acel menu si alegem "New Method"
Se deschide o forma, in care dai numele metodei: OnListChange. Apoi salvezi.
Modificam codul din  evenimentul List1.InteractiveChange
Stergem linia de cod existenta acolo.
Apoi punem urmatoarea linie:
Thisform.OnListChange

Pentru ca tot esti in editorul de cod, vom pune un cod si in metoda OnListChange a formului.
Din comboboxul Object (cea din stanga) selectezi formul. E prima inregistrare.
La procedura selectezi Init. Asigura-te ca esti in form.init.
Aici vom pune urmatorul cod:

* Adaugam formei o proprietate in care vom tine valoarea listei.
Thisform.AddProperty("ListValue",0)
* Apoi ii spunem listei sa puna valoarea in acea proprietate:
Thisform.List1.ControlSource="thisform.ListValue"
* Pozitionam lista pe prima inregistrare
Thisform.List1.listIndex=1

Apoi adaugam cod in metoda OnListChange
O cauti in combo Procedure (va fi probabil scrisa onlistchange si se va gasi la coada listei).
Aici vom pune urmatorul cod:

SELECT nume, idautor FROM autori Where idautor=(thisform.ListValue) INTO CURSOR crsautor
Thisform.text1.ControlSource="crsautor.nume"
Thisform.Text1.Refresh

Ce am rezolvat cu asta?
Pentru acest form, nu mare lucru. Pentru reutilizare, mult.
Observam ca doar formul stie de cele doua obiecte, List1 si text1.
Avem cod specific tabelei cu care lucram intr-o singura metoda a formului.
Tabela si campurile ei mai sunt numite doar in proprietatile obiectului List1, proprietati care pot fi modificate oricand, chiar si in timpul rularii.

Textboxul isi ia valoarea din campul specificat in ControlSource, si o afiseaza la refresh.

Pentru o tabela la care completam un singur camp (celalalt este autoincrement) nu pare a prezenta vreun avantaj.
Mai ales partea cu selectul din metoda OnListChange.
In realitate, nu se foloseste un astfel de cursor, ci un cursor actualizabil, obtinut fie cu un view, fie cu un cursoradapter.
Vom reveni asupra acestei probleme.

Cred ca formul nu arata deloc bine cu acel fond gri-ej.
Sa-i schimbam culoarea
Punem in Properties, la form, Backcolor=191,214,251

Inchidem, salvam formul si rulam.


Mai departe, trebuie sa stabilim cum anume vom face adaugarea, modificarea, eventuala abandonare a adaugarii sau modificarii si salvarea.
Cum te gandesti sa arate?



Daniel Buduru
 2/26/2010 11:44:53 PM
User is offlineGooDy
194 posts
5th


Re: Atestat 2010
 (N/A)
am o mica problema , cand dau run imi apare : proprety control source is not found .

:(
 2/27/2010 12:19:03 AM
User is offlineDaniel Buduru
2141 posts
1st




Re: Atestat 2010
 (N/A)
Am scris totul direct aici si n-am verificat nimic.
Hai sa invatam sa depanam.
Cand apare fereastra de eroare, are un buton  Suspend.
Click pe suspend.
Din menu, Tools, selectezi Debugger.
Se va deschide fereastra debugger-ului.
In fereastra de sus din debuger, Trace, vei vedea codul rulat si un pointer pe inregistrarea care a produs eroarea.

Dupa mesajul de eroare, obiectul nu are proprietatea control source.
E fie o eroare de tastare, fie altceva.

Vezi in fereastra Trace in ce obiect si ce procedura a aparut eroarea.
Spune-mi obiectul, procedura si comanda care a produs eroarea.

Daniel Buduru
 2/27/2010 12:26:26 AM
User is offlineDaniel Buduru
2141 posts
1st




Re: Atestat 2010
 (N/A)
Am gasit eroarea, eu am gresit.
In form.init am zis:
Thisform.ControlSource="thisform.ListID" - si nu e corect

Inlocuieste linia cu asta:
Thisform.List1.ControlSource="thisform.ListValue"

Daniel Buduru
 3/1/2010 4:22:01 PM
User is offlineGooDy
194 posts
5th


Re: Atestat 2010
 (N/A)
tot nu functioneaza , de data aceasta spune :

error with list1 - value : data type mystake

... in form1.init linia 2 : Thisform.List1.ControlSource="thisform.ListValue"

 3/1/2010 4:34:44 PM
User is offlineDaniel Buduru
2141 posts
1st




Re: Atestat 2010
 (N/A)
Da, cand am creat proprietatea formului ListValue am initializat-o cu "", deci caracter, iar idautor e numeric
In form.init inlocuieste linia
Thisform.AddProperty("ListValue,'')
cu
Thisform.AddProperty("ListValue,0)

Ruleaza din nou


Daniel Buduru
 3/1/2010 6:20:41 PM
User is offlineGooDy
194 posts
5th


Re: Atestat 2010
 (N/A)
daca scriu :
Thisform.AddProperty("ListValue,0)  -> eroare : Unrecognized comand verb
Thisform.AddProperty("ListValue,0") -> eroare : Incorect proprety name
 3/1/2010 6:28:04 PM
User is offlineDaniel Buduru
2141 posts
1st




Re: Atestat 2010
 (N/A)
Eu am gresit, dar mai uita-te si tu in help la sintaxa.

Thisform.AddProperty("ListValue",0)


ListValue e caracter, numele proprietatii, si trebuie delimitat cu ghilimele simple, sau duble, sau []


Daniel Buduru
 3/1/2010 6:52:11 PM
User is offlineGooDy
194 posts
5th


Re: Atestat 2010
 (N/A)
Acum imi zice : property listindex is not found .

am adaugat si eu : Thisform.AddProperty("Listindex",0)

ruleaza , dar nu ruleaza corect , imi arata alt nume nu cel pe care il selectez .

am incercat si : Thisform.list1.Index=1  , dar tot nu functioneaza
 3/1/2010 6:54:29 PM
User is offlineDaniel Buduru
2141 posts
1st




Re: Atestat 2010
 (N/A)
deschide formul, click dreapta pe lista, properties,
mergi la BoundTo
BoundTo = .T.


Daniel Buduru
 3/1/2010 6:57:16 PM
User is offlineDaniel Buduru
2141 posts
1st




Re: Atestat 2010
 (N/A)
E am scris codul direct aici, nu l-am verificat.
E inerent sa imi mai scape diverse lucruri. Problema e intervalul mare intre sesiuni.
Am sa ma mai uit pe cod sa vad unde am pus listindex si dece.


Daniel Buduru
 3/1/2010 6:59:14 PM
User is offlineDaniel Buduru
2141 posts
1st




Re: Atestat 2010
 (N/A)
Pune in init

Thisform.List1.listIndex=1

Acolo unde era thisform.listindex

Daniel Buduru
 3/1/2010 7:27:33 PM
User is offlineGooDy
194 posts
5th


Re: Atestat 2010
 (N/A)
functioneaza , numai da eroare dar tot imi afiseaza aiurea.
 3/1/2010 8:06:28 PM
User is offlineDaniel Buduru
2141 posts
1st




Re: Atestat 2010
 (N/A)
Ai pus BoundTo=.T.?
Cred ca nu.
Pune in Form Init, la sfarsit:

Thisform.list1.BoundTo=.t.


Daniel Buduru
 3/1/2010 8:10:37 PM
User is offlineGooDy
194 posts
5th


Re: Atestat 2010
 (N/A)
era pus ....dar am pus si in cod ....si tot asa imi afiseaza ....imi afiseaza ultimul nume selectat .

ex : apas mihai eminescu  si dupaia ion creanga ...cand apas pe creanga imi afiseaza mihai eminescu ....daca apas apoi pe marin preda imi afiseaza pe creanga ....s.a.m.d

am incercat cu : Thisform.List1.listIndex=0 ...dar tot asa afiseaza
 3/1/2010 8:23:52 PM
User is offlineDaniel Buduru
2141 posts
1st




Re: Atestat 2010
 (N/A) Modified By Daniel Buduru  on 3/1/2010 8:25:56 PM)
Thisform.List1.ListIndex=1 pus in init activeaza prima linie din lista.
Acum afiseaza numele cu o pozitie in urma fata de linia selectata.
Nu am avut intentia, cand m-am oprit cu codul acolo si am zis sa rulezi, sa fie completa, ci numai sa nu fie erori in cod.
Era destul de tarziu si a trebuit sa inchei.
Erorile s-au rezolvat, am sa reiau codul mai tarziu.

Cum stai cu raspunsul la intrebare?

Daniel Buduru
 3/1/2010 8:46:32 PM
User is offlineDaniel Buduru
2141 posts
1st




Re: Atestat 2010
 (N/A) Modified By Daniel Buduru  on 3/1/2010 11:05:43 PM)
Am pus codul din Form.OnListChange  doar ca sa am ceva acolo.
Nu vom folosi acel cod.
Sa explic ce se intampla si de unde vine decalajul:

Listbox.List(nRow, nCol)  returneaza elementul nCol, de pe linai nRow a listei.

Thisform.Text1.value=Thisform.List1.List(Thisform.ListIndex,1)  &&afiseaza in text1 coloana  de pe linia ListIndex a listei.

Comanda este corecta. De unde apare decalajul?

Cand se produce evenimentul InteractiveChange, ListIndex , care este numarul liniei curente din lista, are inca valoarea liniei precedente.
Abia dupa ce se incheie InteractiveChange, listindex ia noua valoare.
Din acest motiv, nu vom folosi acest tip de cod in continuare.
Codul pe care-l vom avea in OnListChange e mai complex, si tine de modul in care vom face actualizarea bazei de date.


Daniel Buduru
  Visual FoxPro  Visual FoxPro in general  Atestat 2010...

Search  Forum Home         

 Google Ads Minimize

    

Copyright 2002-2010 Profox   Terms Of Use  Privacy Statement