Poenta je da napraviš recordset koji sadrži samo one podatke koje želiš da obrišeš i onda jednostavno prođeš kroz taj recordset i brišeš redom, umesto da otvaraš kompletan recordset, pa onda u petlji proveravaš uslov kao što ti radiš. Prvo što je to mnogo sporije, a drugo, što je sklono greškama, kao što si već primetio. To je posebno uočljivo u tvom primeru gde koristiš bindovani textbox za upoređivanje uslova, jer da bi se taj textbox apdejtovao tekućim redom, ipak je potrebno neko vreme, koje se povećava kako ima više podataka u bazi, a petlja neće da čeka da se taj textbox apdejtuje, nego će da piči po svom. Upravo to je i najverovatniji razlog zašto dobijaš grešku kada imaš više podataka, jer se petlja izvršava jako brzo i u nekom trenutku textbox ne uspe da se apdejtuje na vreme i onda dobijaš pogrešnu vrednost u promenljivoj datum, što dovodi do toga da uslov bude ispunjen čak i kada on nije ispunjen ili ne postoji red tamo gde ti je trenutno pokazivač, a ti pokušavaš da obrišeš taj red. Dakle, to su i osnovna dva problema u tvom kodu, može da se desi da obrišeš podatak koji nisi hteo da obrišeš, a drugo može da se desi da pokušaš da obrišeš prazan red što dovodi do greške.
U mom primeru, prvo se otvara recordset koji sadrži samo one podatke koje želiš da obrišeš (u konkretnom slučaju sve redove gde je datum manji ili jednako 12.02.2010). Time se osiguravaš da neće biti obrisan neki podatak koji ne želiš da bude obrisan, jer se neće ni naći u recordset-u. Zatim, pokrećeš petlju koja prvo odabira prvi postojeći red u otvorenom recordset-u. Zašto prvi ? Bez nekog posebnog razloga. Možeš da staviš i da ide na poslednji (samo umesto MoveFirst, staviš MoveLast). Poenta ovoga je da se osiguraš da će se pokazivač nalaziti iznad nekog podatka kada pokušaš brisanje. Naime, kada obrišeš neki podatak, ispod pokazivača ostaje prazan red i ako pokušaš da ga obrišeš dobićeš grešku. Ti si to pokušao da rešiš sa MoveNext, što takođe može da radi, ali MoveNext može dovesti pokazivač na EOF (to je ono što ide posle poslednjeg podatka u recortdset-u), čak i kada još uvek ima podataka u recordset-u koje želiš da obrišeš i onda se može desiti da izađeš iz petlje, a nisi pobrisao sve što si želeo. U stvari, ima i za to rešenje, proveravaš i EOF i BOF (to je ono što ide pre prvog podatka u recordset-u) i ako su oba True, onda nema više podataka u recordset-u, ali to samo bespotrebno komplikuje stvari. Sa MoveFirst ili MoveLast se osiguravaš da će pokazivač uvek biti iznad nekog podatka, sve dok ima podataka u recordset-u i onda kada očitaš EOF, znaš da su svi podaci u recordset-u obrisani. Linija If Adodc1.Recordset.EOF Then Exit Do služi upravo za to, kada se detektuje EOF, čak i posle pozivanja MoveFirst, to znači da nema više podataka u zadatom recordset-u i napuštamo petlju.
Da uprostimo, ono tvoje će u dosta slučajeva da radi, ali je problem što ideš kroz petlju "kao muva bez glave" da se tako izrazim, bez ikakvih provera, pa tako ako se zvezde poklope (tj. textbox uspe da se apdejtuje na vreme), sve će biti uredu, međutim ako apdejt izostane, a petlja nastavi da radi, može se desiti da se obriše nešto što nisi želeo ili da se pokuša brisanje praznog reda i to će naravno javiti grešku, što se tebi i dešava čim imaš više redova. U mom primeru postoji više mera zaštite. Prvo je kreiranje recordseta koji sadrži samo podatke koje zaista želimo da obrišemo čime se eliminiše mogućnost da se obriše neki podatak koji nismo hteli da obrišemo. Drugo, koristimo MoveFirst pre brisanja što eliminiše mogućnost da se u trenutku brisanja pokazivač nađe iznad praznog podatka, tj. reda. I treće, proveravamo EOF, što nam omogućava da pre nego što napustimo petlju budemo sigurni da smo obrisali sve podatke koje smo želeli da obrišemo. Naravno, ja ti i dalje predlažem da se baciš na detaljnije proučavanje rada sa bazama (imaš dosta tutorijala po netu, ali i na ovom forumu) i da ovakve stvari rešavaš korišćenjem query-ja, pa bi u konkretnom slučaju sve završio jednim SQL upitom tipa
Code:
DELETE * FROM ImeTabele WHERE datum <= #2/12/2010#
jer je to em mnogo brže, em će raditi i ako nemaš nijedan podatak koji ispunjava uslov, em se ne bakćeš sa petljama.
Kod programiranja je inače jako bitno izbeći (koliko god je to moguće) situaciju da tok izvršavanja neke procedure zavisi od rasporeda zvezda i time dovede do nepredviđenih rezultata, pa samim tim i raznoraznih grešaka. Zato je potrebno u kodu imati razne provere, a pre tih provera, koliko god je to moguće, eliminisati sve ono što može dovesti do problema, kao što smo u konkretnom slučaju pre bilo kakvih provera, eliminisali iz recordset-a sve redove koje ne želimo da obrišemo. Recimo, banalan primer, u programiranju se često se javlja potreba da se saberu vrednosti dva ili više polja (na primer iz textboxa). Neki bi to uradili ovako
Code:
rezultat = Text1.Text + Text2.Text
MsgBox rezultat
što će samo po sebi dati ispravan rezultat u nekim slučajevima, ali pošto nema nikakvih dodatnih provera, vrlo lako može doći do raznoraznih grešaka, prvo zato što nismo definisali tip podatka za promenljivu rezultat, a drugo zato što je Text svojstvo Textbox-a ipak string tipa, pa je moguće upisati svašta, pa se može dobiti Type Mismatch i slično. Dakle, mnogo je bolje uraditi ovako
Code:
Dim rezultat As Long 'ako se radi o celobrojnoj vrednosti naravno
rezultat = Val(Text1.Text) + Val(Text2.Text)
MsgBox rezultat
što će u svakom slučaju vratiti neku vrednost bez izbacivanja greške. Međutim, opet može doći do neželjenih rezultata, jer ako neko upiše u Textbox "t654" gde je slovo t greškom zakačeno prilikom unosa, Val će vrednost tog textbox-a konvertovati u 0, pa će se dobiti pogrešan rezultat, a ako onaj ko je to unosio nije pazio i primetio to na vreme, može doći do kasnijih problema, zavisno već od toga za šta se dobijeni rezultat upotrebljava. Pa tako, ne bi bilo loše uvesti dodatne provere da li je uneta vrednost numeričkog tipa.
Code:
Dim rezultat As Long 'ako se radi o celobrojnoj vrednosti naravno
If IsNumeric(Text1.Text) And IsNumeric(Text2.Text) Then
rezultat = Val(Text1.Text) + Val(Text2.Text)
Else
Msgbox "Jedna od vrednosti koju ste uneli nije numerickog tipa.", vbCritical, "Greska"
Exit Sub
End If
MsgBox rezultat
Sve ovo su provere, a naravno, najbolja solucija jeste potpuno eliminisati, tj. zabraniti unos nenumeričkih podataka u textbox, što se može postići korišćenjem KeyPress event-a i setovanjem KeyAscii na 0 ukoliko se ne radi o numeričkoj vrednosti, no nećemo se sada baviti time (ukoliko nekome treba, ostavljao sam negde na forumu kod i za to).
U svakom slučaju, izvinjavam se ako sam udavio sa ovim tekstom, ali eto, možda nekom koristi :)
[Ovu poruku je menjao Marko_L dana 22.03.2010. u 08:09 GMT+1]
-Odracuonogakomijedrpiorazmaknicu.
-Ne rxdi mi txstxturx, kxd god hocu dx
ukucxm "x" onx ukucx "x".
-Ko kaaz e da ja neuummem da kuuca
m.
-Piše "Insert disk 3", a jedva sam i ova
dva ugurao u drajv
-Postoje samo dve osobe kojima
verujem, jedna sam ja, a druga nisi ti