Az előző részben beígért példa előtt még meg kell ismerkednünk egy - két elengedhetetlenül fontos dologgal, amit majd fel fogunk használni a példaprogramban.

A Data Modul

A Data Modul egy speciális form amire szerkesztési időben rápakolhatjuk az adatelérési és egyéb nem vizuális komponenseket. A Data Modul futási időben nem jelenik meg. Létrehozni a File/New/DataModule menüben tudjuk. Segítségével az adatbázis-elérési komponenseket a különböző formoktól elkülönítve tudjuk tárolni, ezáltal megvalósul az adatelérési logika és a felhasználói felület elkülönítése.

Felhasznált adatmegjelenítési komponensek

Az adatmegjelenítési komponensekről már korábban volt szó, de részletes tárgyalásukra csak később kerül sor. Feladatuk az adatelérési komponensek által szolgáltatott adatok megjelenítése. Itt a részletezéstől eltekintve, most csak a példa programban felhasznált adatmegjelenítési komponensekről esik néhány szó.
 
 

DBGrid Adathalmaz rekordjainak táblázatos formában történő megjelenítésére szolgál. Számos property-je közül a DataSource a legfontosabb, ezt kell arra az adatforrás komponensre állítani, amely által szolgáltatott adatokat meg kívánjuk jeleníteni. Ez a következő két komponensre is vonatkozik.
DBNavigator Navigációs gombokat tartalmazó vizuális komponens, mellyel egy adathalmazban mozoghatunk, illetve lehetőségünk lesz új rekord felvételére, törlésére, rekord adatainak módosítása.
DBEdit Egy rekord egy mezőjének megjelenítésére, editálására szolgál. A DataSource tulajdonságban adjuk meg az adatforrást, a DataField property-ben pedig a mező nevét.
DBText Egy rekord egy mezőjének megjelenítésére szolgál. A DataSource tulajdonságban adjuk meg az adatforrást, a DataField propertyben pedig a mező nevét.

A Database Desktop

A Database Desktop egy Delphi-hez adott segédprogram, mellyel helyi adatbázistáblákat tallózhatunk, dBase vagy paradox táblákat hozhatunk létre, indexeket definiálhatunk, tábla struktúrát módosíthatunk stb.

Ezek után lássunk hozzá a példa programhoz, ami egy egyszerű telefonszám nyilvántartó program lesz. Egyszerűségéből adódóan mindössze egy táblán fog alapulni, így a táblák közötti relációkra nem ad példát, azt majd egy másik példaprogramon keresztül nézzük meg.

Először hozzuk létre az adatbázistáblát. Ehhez indítsuk el a Database Desktop-ot és itt válasszuk a New/Table menüpontot., ezen belől pedig a dBASE IV tábla formátumot. Az itt megjelenő ablakban tudjuk megadni a meződefiníciókat.

A következő mezőket hozzuk létre:
 

Field Name Type Size Dec
VEZ_NEV C 20  
KER_NEV C 20  
IRSZAM C 4  
VAROS C 20  
CÍM C 30  
TELEFON C 11  
EMAIL C 30  
EGYEB C 30  

Ezek után hozzuk létre az indexeket a következő mezőköz:
 

VEZ_NEV
KER_NEV
IRSZAM
VAROS
TELEFON

Ehhez nyomjuk meg a jobb felső részen, a lenyíló menü alatt lévő Define gombot (A lenyíló menü tartalma "Indexes" kell hogy legyen, ha nem az akkor állítsuk arra). Bejön egy új ablak, ahol a mezők közül ki lehet választani azt, amelyikhez indexet szeretnénk készíteni. Válasszunk ki egy mezőnevet (klikk a mezőn), majd nyomjunk OK gombot. Az ezután bejövő ablakban egy felajánlott nevet találunk az indexünknek, ez alapértelmezetten a mező neve. Ezt fogadjuk el. Ha minden indexszel készen vagyunk, mentsük el a táblánkat abba könyvtárba, ahova majd a programunkat is lementjük.

Nos, miután megvagyunk a táblával, nekiállhatunk a program elkészítésének.

  • Kezdjünk egy új projectet (File/New Allplication), majd mentsük el abba a könyvtárba ahova phone.dbf-et mentettük. Mentsük el a projectet Phone néven, a unitot pedig Main néven.
  • Adjunk egy DataModul-t a projecthez (File/New/Data Module). A neve legyen DM, és mentsük le DMUnit néven.
  • Tegyünk egy Table és egy DataSource komponenst a DataModulra a következő beállításokkal:
Table
 
DataSource
Property Érték Property Érték
Name Phone AutoEdit False
TableName Phone.dbf DataSet Phone
Active True Name PhoneDS
    A Table komponensnél nem állítottuk be a DatabaseName tulajdonságot, így a program könyvtárában lévő táblákkal dolgozik. Ezért fontos, hogy a project és a táblánk egyazon könyvtárban legyenek.

    Az Active property True-ra váltásával már szerkesztési időben is láthatjuk egy adatbázistábla tartalmát. (illetve csak láthatnánk, ha nem lenne üres)

    A DataSource komponens DataSet tulajdonságában kell beállítani azt az adathalmazt, aminek tartalmát a DataSource majd szolgáltatni fogja. Jelen esetben ez a Phone, ami egyébként most nem is lehetne más, hiszen csak egy adathalmazunk van. Az AutoEdit False-ra állítása arra szolgál, hogy egy adatmegjelenítési komponenben csak akkor tudjunk editálni, ha először az adathalmazt dsEdit módba billentettük az Edit metódus segítségével. (AutoEdit=True esetén ez automatikusan megtörténik, ha egy adatbevitelre alkalmas adatmegjelenítési komponensben lenyomunk egy billentyűt)
     
     

  • Most jöhet a felhasználói felület kialakítása. Programunk egyetlen formból fog állni, amin egy PageControl komponens segítségével külön oldalakon jelenítjük meg a program különböző funkcióit. Ehhez a PageControl-on hozzunk létre három lapot. Az első lapon tallózhatunk ismerőseink telefonszámai között, a második lapon a részletes adatokat jeleníthetünk meg, a harmadikon pedig adatokat vihetünk fel. (Ennek megfelelően állítsuk be a Caption tulajdonságokat "Tallózás", "Részletes Adatok" és "Adatfelvitel" -re).
  • Készítsük el a tallózás felületét. Ehhez egy DBGrid, egy DBNavigator, két Edit, két ComboBox, két CheckBox, egy Bevel és néhány Label komponensre lesz szükség. Helyezzük el úgy a komponenseket, hogy egy a következő képen látható felületet kapjunk:
    Tehát a PageControl ezen lapján egy rácsban jelennek meg ismerőseink nevei és egyéb adatai. Az adatokat különböző szempontok szerint tudjuk sorba rendezni, mindig a rendezés szerinti mezőre tudunk keresni, illetve a beállított mezőt a beállított érték szerint tudjuk szűrni. Keresésnél lehetőség van rész-stringre is keresni.
  • Miután elkészült a komponensek elrendezése, a DBGrid és a DBNavigator DataSource tulajdonságát próbáljuk meg beállítani az adatforrásunkra, jelen esetben a PhoneDS-re. Mit veszünk észre? Az Object Ispectorban a DataSource property-ben nem tudunk kiválasztani adatforrást, pedig már létrehoztunk egyet az adatmodulon.


  • Pontosan azért nem látjuk az adatforrást, mert azt a DataModul-ra tettük. Ahhoz hogy el tudjuk érni a hőn áhított PhoneDS adatforrásunkat, mindössze a form unit-jának Implementation részébe be kell írnunk a Uses DMUnit; sort. Ezek után meg kell hogy jelenjen a DM.PhoneDS a lenyíló menüben. Tehát ha egy DataModul-on lévő adatforrást el akarunk érni egy másik form-ról, akkor először a form számára "láthatóvá" kell tennünk azt, a fentebb leírt módon.
  • A beállítás után azonnal meg kell hogy jelenjenek a mezőnevek a DBGrid-ben. (Ha a dbf-ünk tartalmazna adatokat, akkor azok is megjelennének) Láthatjuk, hogy a mezőnevek nem túl szépek egy igényes felhasználói felületre. Már korábban volt szó róla, hogy a Fields Edior-ral a mezők számos tulajdonsága beállítható. A Mezőszerkesztő behívásához a Table komponensen nyomjunk jobb gombot, majd válasszuk a Fields Editor menüt. Ez alapesetben teljesen üres. Hogy mégis megjelennek a mezők a DBGrid-ben az azért van, mert a Delphi ilyenkor automatikusan, dinamikus mezőket hoz létre. Ha azonban akár egy mezőt is felveszünk a mezőszerkesztőben, akkor un. prezisztens mezőket hozunk létre, ilyenkor eltűnnek a dinamikus mezők. Újabb jobb gombra (a mezőszerkesztőn belől) újabb menü jön be, itt az Add All Fields menüt választva megjelennek a mezők a mezőszerkesztőben. Ezután egy tetszőleges mezőt választva, annak tulajdonságait be tudjuk állítani. Minden mezőnek válasszunk valami szép, magyar megnevezést. (Ezt a DisplayLabel proprty-be írjuk). Az irányítószám és a telefonszám esetén az EditMask tulajdonságban megadhatjuk hogy csak számokat fogadjon el, illetve a telefonszámnál még a számokat elválasztó szeparátort is beállíthatunk. A Required property True-ra állításával azt érjük el, hogy annak a mezőnek ahol ez be van állítva mindenképpen értéket kell adnunk ha egy új rekordot viszünk fel, különben a rendszer nem engedi a rekord felvitelét. A VEZ_NEV, KER_NEV és TELEFON mezőknél állítsuk a Required tulajdonságot True-ra. Tehát minimálisan ez a három adat minden személyről be kell hogy kerüljön az adatbázisunkba, másképpen nem tudjuk felvinni egy adatát sem. Ha beállítottuk a DisplayLabel-eket, és visszatérünk a formunkra, akkor most már a DBGridben a DisplayLabel szerinti mezőnevek kell hogy szerepeljenek.


  •  
  • Készítsük el a sorba rendezést megvalósító részt.
    A táblánk mindig a bal oldali ComboBox-ban megjelenő tulajdonság szerinti rendezettségben jelenjen meg. Ehhez a ComboBox.Text property-je legyen Vezetéknév, a Table komponens IndexName property-je pedig VEZ_NEV. Ezek az apalértelmezett beállítások lesznek, tehát amíg a felhasználó nem állít be új rendezési sorrendet, a VEZ_NEV index szerinti sorrend lesz az alapértelmezett.

    A ComboBox Items tulajdonságát töltsük fel a következő értékekkel:
     

Vezetéknév
Keresztnév
Irányítószám
Város
Telefon
    Ezek azok a mezők, amelyek szerint még rendezni lehet a táblát.
    A ComboBox OnChange eseményébe írjuk a következő kis kódot:
procedure TmainForm.ComboBox1Change(Sender: Tobject);begin   case ComboBox1.Itemindex of     0: DM.Phone.IndexName:='VEZ_NEV';     1: DM.Phone.IndexName:='KER_NEV';     2: DM.Phone.IndexName:='IRSZAM';     4: DM.Phone.IndexName:='VAROS';     5: DM.Phone.IndexName:='TELEFON';  end;   ComboBox3.ItemIndex:=ComboBox1.ItemIndex; end;
    Ennek hatására a kiválasztott érték szerint lesz indexelve a tábla, így a sorrend is ilyen lesz.
    (A ComboBox3 egy másik lapon lévő lenyíló menü, így a két ComboBox tartalma együtt változik)
     
     
  • Keresés

  • A keresendő szöveget egy egyszerű Edit komponensbe kell beírni. A keresés akkor indul, ha Entert nyomunk, ezért a kis kereső kódunkat a komponens OnKeyDown eseményébe írjuk.
    Procedure TmainForm.Edit1KeyDown(Sender: Tobject; var Key: Word;   Shift: TshiftState); begin If Key = VK_RETURN Then    If not CheckBox1.Checked Then      Begin      If DM.Phone.FindKey([Edit1.Text]) Then         Edit1.SelectAll      End    Else      Begin      DM.Phone.FindNearest([Edit1.Text]);      Edit1.SelectAll;      End; end;

    A FindKey, az aktuális Index szerinti mezőben keres a megadott értékre, a FindNearest szintén az aktuális index szerinti mezőben hozzávetőleges keresést valósít meg. A CheckBox1-el állítjuk be hogy csak pontos találatot fogadjon el (FindKey), vagy szótöredékre is keressen (FindNearest). Találat esetén az Edit-be beírt szöveget kijelöltté tesszük, így ha újabb szóra akarunk keresni, nem kell először kitörölni a beírt tartalmat, hanem egyből tudjuk írni a következő keresési feltételt.

  • Szűrés

  • A szűrés segítségével a megjelenített adatok számát szűkíthetjük le adott feltétel szerint. Pl. csak a pécsi haverokat jelenítjük meg, vagy pl. csak azokat akiknek Szabó a vezetékneve.

    A ComboBox tulajdonságait ugyanúgy állítsuk be ahogy a keresésnél, majd a Szűrést aktiváló CheckBox OnClick eseményjellemzőjébe írjuk be:

    procedure TmainForm.CheckBox2Click(Sender: Tobject); begin With DM.Phone do Begin Case ComboBox2.ItemIndex of    -1: Filter:='VEZ_NEV='''+Edit2.text+'''';    0: Filter:='VEZ_NEV='''+Edit2.text+'''';    1: Filter:='KER_NEV='''+Edit2.text+'''';    2: Filter:='IRSZAM='''+Edit2.text+'''';    3: Filter:='VAROS='''+Edit2.text+'''';    4: Filter:='TELEFON='''+Edit2.text+''''; End; Filtered:=CheckBox2.Checked; End; end;

    A szűrési feltételt a Table komponens Filter property-ébe kell beírni, és a Filtered property True-ra állításával aktiválhatjuk a szűrést. Látható, hogy a ComboBox által kiválasztott mező-t tesszük egyenlővé az Edit2 komponensbe beírt értékkel, és ez lesz a szűrési feltételünk. Tehát ha pl. a Város-t választjuk, és az Edit komponensbe beírjuk hogy Budapest és a Szűrést bekapcsoljuk, akkor csak a Budapesti személyek jelennek meg a rácsban.

  • Most következhet a "Részletes Adatok " lap elkészítése. Ehhez helyezzük el a képen látható komponenseket a képen látható elrendezésben a PageControl második lapján.

  •  

     


     
  • A Név,Cím stb. kiírása Label komponenssel történik, a mezők megjelenítésére DBText-et használunk, a keresendő szöveget egy egyszerű Edit komponensbe írjuk, a keresési adat kiválasztására pedig egy ComboBox komponens szolgál. A keresés-t ugyanúgy valósítjuk meg, mint a "Tallózás"-nál. Ami újdonság ezen a lapon az a név és cím megjelenítése, ugyanis ezekhez számított mezőket (Calculated Fields) használunk. Számított mezőket a Fields Editor-ban tudunk létrehozni. A mezőszerkesztőn jobb gombot nyomva, most válasszuk a New Fields menüt. A bejövő ablakban a Fields Properties részben be kell állítani a számított mezőnk nevét (Name), típusát (Type) és a méretét (Size). A mező típusa (Field Type) számított, vagyis Calculated. Két számított mezőt hozunk létre, az egyik a vezeték és keresztnévből összeállítja a teljes nevet, a másik pedig az irányítószámból, a városból és az utcából összerakja a teljes címet. A mezők adatait következő két táblázat tartalmazza:
    Az első számított mező paraméterei
Field Properties
Name Nev
Type String
Size 41
 
Field Type Calculated
    A második számított mező paraméterei
Field Properties
Name Lakhely
Type String
Size 56
 
Field Type Calculated
    Nos, ezzel létrehoztuk a két számított mezőt, de ez még kevés ahhoz hogy egy adott rekord esetén ezekben a mezőkben megjelenjen a várt érték. Ez csak akkor történik meg, ha a Table komponens (Phone) OnCalcFields eseményjellemzőjébe beírjuk a mező értékét előállító kódot. Jelen esetben:
    procedure TDM.PhoneCalcFields(DataSet: TDataSet); begin With Phone do Begin FieldByName('Nev').AsString:=   FieldByName('VEZ_NEV').AsString +' '+ FieldByName('KER_NEV').AsString; FieldByName('Lakhely').AsString:= FieldByName('IRSZAM').AsString +' '+    FieldByName('VAROS').AsString +', '+FieldByName('CIM').AsString; End; end;

    Ezzel el is készültek a számított mezőink.

    A mezők értékének megjelenítésére a DBText komponenst használjuk. A DataSource Property-t állítsuk a DM.PhoneDS adatforrásunkra, a DataField property-be pedig az éppen megjeleníteni kívánt mező-t kell beállítani.

  • Lássuk az "Adatfelvitel" fület.
    Itt lehet új adatokat felvinni, illetve meglévőket módosítani. Adatbevitelre a DBEdit vizuális adatmegjelenítési komponenst használjuk. Helyezzük el a megfelelő komponenseket a képen látható formában:

    A DBEdit DataSource tulajdonságát állítsuk a DM.PhoneDS-re, a DataField property-t pedig arra a mezőre, amelyet meg szeretnénk jeleníteni. Ha már lennének adatok a táblában akkor ennyi beállítás után rögtön megjelenne az aktuális rekord és az adott mező értéke a DBEdit komponensben.

    Kódoljuk le a az adatfelvitelt és a módosítást. Az "Új elem" gomb OnClick eseményjellemzőjébe írjuk be következő kódot:

    procedure TMainForm.Button2Click(Sender: TObject); begin   DBEdit1.SetFocus;   DM.Phone.Append; end;
    DBEdit1.SetFocus mindössze annyit csinál, hogy a DBEdit1 komponensre állítja a fókuszt, bárhol is volt eddig, hiszen valószínűleg sorban akarjuk majd felvinni az adatokat.

    Az Append metódus hatására vált az adathalmaz dsInsert állapotba és létrehoz egy új üres rekordot, melynek mezőit a DBEdit komponensek segítségével fel tudjuk tölteni adatokkal. Az új rekordot a Post metódus segítségével tudjuk elmenteni, vagy a Cancel metódussal érvényteleníteni a létrehozásának szándékát.

    Tehát az "OK" gomb OnClick eseményjellemzőjében hívjuk meg a Post metódust, a "Mégsem" gomb lenyomására pedig a Cancel metódust.

    Az "OK" gomb OnClick eseményjellemzőjébe ez kerül:

    procedure TMainForm.Button4Click(Sender: TObject); begin   If DM.Phone.State in [dsEdit,dsInsert] Then   DM.Phone.Post; end;

    Először megvizsgáljuk, hogy az adathlamaz dsEdit vagy dsInsert állapotban van-e, és ha igen akkor meghívjuk a Post metódust. Hogyha ezt a vizsgálatot nem végeznénk el akkor hibaüzenetet kapnánk minden olyan esetben mikor úgy hívjuk meg a Post metódust, hogy az adathalmaz nincs a szerkesztési állapotok egyikében sem.

    A "Mégsem " gomb OnClick eseményjellemzője pedig így alakul:

    procedure TMainForm.Button3Click(Sender: TObject); begin   DM.Phone.Cancel; end;

    Már csak a "Módosítás" gomb van hátra, amire rákattintva az Edit metódust kell meghívni a következő formában:

    procedure TMainForm.Button1Click(Sender: TObject); begin   DBEdit1.SetFocus;   DM.Phone.Edit; end;

    Még a DataModul-unk OnCreate eseményjellemzőjébe írjuk be a következő kódot, a Table komponens Active proprty-ét állítsuk False-ra ha nem az, és ezzel el is készült a kis telefonszám nyilvántartó programunk.

    procedure TDM.DMCreate(Sender: TObject); begin   Phone.IndexName:='VEZ_NEV';   Phone.Open;   Phone.First; end;

    Ebben a kis programrészletben beállítjuk a VEZ_NEV-et indexnek, megnyitjuk a táblát és az első rekordra ugrunk.

Még korábban beállítottuk néhány mezőre a Reguired jellemzőt, tehát új rekord felvitelekor kötelezővé tettük, hogy ezen mezők tartalmazzanak adatot, különben az adatfelvitel meghiúsul és hibaüzenetet kapunk. Ez a hibaüzenet jelen esetben a BDE saját üzenete, de lehetőségünk van a hibák feldolgozására és pl. saját hibaüzenetek kiírására is. Hogy ezt hogyan is lehet megvalósítani azt majd egy későbbi példaprogramban fogjuk megnézni.

A letölthetô az elmondottakra a forráskód, és a telefonkönyv fordított változata, az EXE!