Excel nyilvántartórendszer készítése 4. gyakorlat - 5. gyakorlat Készítette: Debreceni Bálint
Szükséges és felhasznált ismeretek Excel VBA ismeretek Excel osztály modulok (Class module) ismeret Excel eseménykezelők használata Excel fájlkezelés VBA és Worksheet függvények használata
1. feladat Készítsünk egy egyszerű menetrend nyilvántartót, amely eleget tesz a következő alfeladatoknak! a.
b.
Tudja tárolni a következő menetrendi adatokat: Indulási hely, Érkezési hely, Indulási idő (óra:perc formátumban), Rendszám, Menetidő (óra:perc formátumban). Ezt egy ‘menetrend’ munkalapon tárolja (az oszlopok az előbb említett mezők, és minden menetrendi adatot leíró rekord egy-egy sor Egy másik munkalapon (neve legyen ‘kezelo_felulet’). Itt egy rekordot lehet hozzáadni az előző munkalaphoz. Legyenek szövegmezők az egyes mezőknek és egy gomb, amelynek hatására az előző munkalap végére hozzáfűzödik az itt megadott adatokból készült rekord!
1. feladat c. Egészítse ki a programot úgy, hogy a formon érték ellenőrzést végzünk. Ha a mezők nem üresek, az időtartamok óra:perc formában adottak, a rendszám megfelelő formátúmú (3betű kötőjel 3szám) akkor adódjon csak hozzá a menetrend munkalaphoz az új rekord. Ha valami hibás formátumban van, a színe legyen piros. Ha elkezdünk bele gépelni, akkor álljon vissza feketére. d.Valósítsa meg, hogy ha a menetrend táblán kijelölünk egy sort (minden oszlopot benne ami a menetrendet érinti), akkor a másik munkalapon (‘kezelo_felulet’) lévő formba a kijelölt sor adati másolódjanak be és a gomb szövege változzon “Módosítás”-ra. Ha itt módosítunk valamit, akkor a nyomógomb lenyomására módosuljanak a menetrendben. Ha nincs kijelölve sor, akkor a formok álljanak vissza üres értékre és a gomb felirata is változzon vissza. A módosítás is csak akkor mehet végbe, ha a formátumok rendben vannak!
1. feladat e. Valósítsa meg, hogy mind a módosítás, mind a hozzáadás csak a b. és d. pontba leírtakkal legyen megvalósítható. Azaz a menetrend munkalapon ne lehessen kézzel új sort bevinni és valamelyik sort kézzel átírni, csak formon keresztül a beszúrást, illetve kijelöléssel és formon keresztül a módosítást!
Megoldás Mivel a class modulokat is szeretnénk használni, a legjobban úgy tehetjük ezt meg, hogy a menetrend munkalap kezelésére szolgáló eljárásainkat, függvényinek osztály modulokba szervezzük. Így a menetrend, és menetrendek class.
Az a. feladatrész megoldása
Menetrend class modul elkészítése A “Fejlesztőeszközök” fülre kattintás után kattintsuk a “Visual Basic”re.
Menetrend class modul elkészítése Ezután a bal oldali részen kattintsuk jobb klikkel a Microsoft Excel Objects-re, a felugró menüből válasszk ki az Insertet, majd ott a Class Module.
Menetrend class module létrehozás Az elnevezés úgy törtnénik, hogy a létrejövő classt (Class1 néven jön létre) kijelöljük (belekattintunk), a felső menüsorban a View menüpontban a Property Windows-t válasszuk ki, majd a felugró eszköztárban a Name mellé írjuk be, hogy menetrend.
Menetrend class module elkészítése menetrend modul-ra kattintva készíthetjük el az osztályunk belsejét. Tartalmazhat: konstruktor, destruktorhoz hasonló szerkezeteket, property-ket, mezőket (adattag),és tagfüggvényeket. A mezők Private hatáskörűek lesznek, a beállításukra és lekérdezésükre Propertyket definiálunk. Adattagok úgy definiálhatunk VBA-ban, mint a változókat. Private mezonev As Tipus
Menetrend class module elkészítése Get property: A Property Get kulcsszóval történik, és egy a mögöttes mező típusa a visszatérési érték típusa, tehát úgy kell definálni, mintha egy függvényt definiálnánk, annyi kivétellel, hogy Function kulcsszó helyett Property Get van Private valtozonev As típus Public/Private Property Get Propertyneve() As Visszatérési_típus Propertyneve=valtozonev End Property
Menetrend class module elkészítése Let property: A Property Let kulcsszóval történik a definiálása, olyan mintha egy egyparaméteres sub eljárást definiálnánk szerkezetileg (használat során mutatkozik meg a különbség, mert nem olyan szintaktikával használjuk), annyi hogy Sub helyett Property szerepel. Private valtozonev As típus Public/Private Property Let Propertyneve(Value As típus) valtozonev=Value End Property Nyilván, a valtozonev ha van Get és Let property-nk, csak egyszer definiáljuk, itt az általános szerkezet jobb kiemelése érdekében tüntettem fel Get és Let előtt is.
Menetrend class module elkészítése Szükségünk van mIndulas, mErkezes, mIndulasIdo, mMenetido, mRendszam mezőkre (m az elnevezések elején a mező szóból van, természetesen tetszőleges lehet) és ezekhez lekérdező (Get) és beállító (Let) property. Ezek a következőképpen alakulnak. A Visual Basic ablakunkban a Class module-t lenyitva a menetrend-re duplán kattintva bejön a felület, ahova az osztály kódját írhatjuk. Ide egyenlőre a következőket írjuk.
menetrend class module kódja
Menetrend class module kódja
menetrendek class module A menetrend rekordot leíró osztályunkat az előbb elkészítettük. A menetrend rekordok a ‘menetrend’ munkalapon lesznek elhelyeze. Most szükségünk lenne egy olyan osztályra, ami a menetrend rekordokat beszúrja a ‘menetrend’ munkalapra. Mivel az az elvárásunk, hogy az új beszúrt menetrendi adatokat mindig a táblázat végéhez fűzzük, beszúráskor le kell kérdeznünk az utolsó még nem üres indexet, majd így egyet hozzáadva megkapjuk , hogy hanyadik sorba kell beszúrnuk az új rekordot. Az, hogy adott sorban melyik oszlopba melyik adat megy a rekordból, az meg az elrendezéstől függ.
menetrendek class module A korábban leírt módszerrel létrehozzunk class module-t, majd elnevezzük ‘menetrendek’-nek. Egyenlőre egy HozzaAd metódust írunk, aminek paramétere egy menetrend rekord, és a ‘menetrend’ munkalap-hoz beszúrja a menetrend adatait (ezeket a property-jei segítségével kérdezzük le) A kód a következőképpen alakul:
menetrendek class module
menetrendek class module Egy adott oszlop utolsó nemüres celláját úgy kapjuk meg (utolsoIndex), hogy megkeressük a legutolsó cellát (ezt a Rows.Count adja meg, így fejből nem kell tudni, hány cella lehetséges az Excelben egy oszlopban), és ennek a végétől megkeressük azt a cellát, ami nem üres (End(xlUp)), és lekérdezzük, hogy ez hanyadik sorban van (Row). Mivel nekünk ezután kell majd beszúrni adatot, a kapott értéket 1-el növeljük (utolsoIndex + 1) Hasonló meggondolások alapján egy adott sor utolsó nemüres oszlopa is megkapható) Mivel sokszor hivatkozuk a menetrend munkalap-ra, ezért ezt külön változóba (menetredSheet) tároljuk, hogy szebb és átláthatóbb legyen a kifejezés
menetrendek class module példányosítása Mivel osztályokban gondolkozunk, valahol ezt a menetrendek osztályt példányosítani kell, hiszen addig nem tudjuk használni. A kérdés az, hogy hol kellene példányosítani. Lehetne minden használat előtt (tehát minden űrlapkitöltés után esetünkben), de elég lenne egyszer példányosítani, és az alkalmazás futása során ezt a példányt használni. Lehetőségek: minden használat előtt megnézni, hogy van -e példányosítva, és ha nincs, megtesszük az alkalmazás (Excel munkafüzet betöltésekor) példányosítani, és ezt a példányt használni a továbbiakban
menetrendek class module A második opciót válasszuk most. A kérdés, hogy lehet elérni, hogy a munkafüzet megnyitódásakor (xlsx fájlunk megnyitásakor) lefusson általunk megírt VBA kód? Eseménykezeléssel lehet megoldani.
Eseménykezelés Excel-ben Az esemény valami, ami megtörténhet Excel-ben. Például: egy Workbook-ot megnyitunk/bezárunk, egy munkafüzetet aktiválunk/deaktiválunk. Adatot beütünk egy cellába vagy módosítjuk egy cella tartalmát, munkafüzetet elmentjük. Egy objektumra kattintunk (pl. gombra), bizonyos billentyűkombinációkat leütünk, bizonyos nap van, hiba történik stb.., ezek mind-mind események és még lehetne sorolni. Legtöbbször ezekhez az eseményekhez nem igazán kell nyúlni. De előfordul, hogy olyan dolgokat kell leprogramoznunk, amik ezeknek az eseményeknek a bekövetkezésével kapcsolatos: „ha az ügyfél bezárja a munkafüzetet, egy fájlba írjuk ki mennyi ideig volt megnyitva, hogy tudjuk hogy mennyit dolgozzon” stb..
Eseménykezelés Excel-ben Technikailag: A VBA-ban sok módja van, hogy egy VBA sub eljárást (procedure-t, amit Sub és End Sub segítségével definiálunk) lefutassunk. Egyik útja, hogy egyszerűen meghívjuk. Van azonban másik mód is: automatikusan fusson le. Pontosabban a következőre gondolunk: lehet olyan eljárást írni, ami valamely esemény hatására (pl. munkafüzetet megnyitjuk, bezárjuk stb..) hajtódjon végre.
Eseménykezelés Excel-ben Eseménykezelőt szükséges tehát írni. (event handler) Szerkezete: Private Sub Eseményheztartozóobjektum_Esemény(paraméterek (ezek le vannak írva dokumentációba, melyik eseményhez milyen paramétereket kapunk) ‘esemény bekövetkezéskor lefutó kódrész End Sub Eseményheztartozóobjektum: amin az adott esemény kiváltódását figyeljük. Pl. Worksheet, Workbook stb.. Paraméterek: esemény kiváltódásával kapcsolatos információk (melyik tartomány váltotta ki pl.)
Eseménykezelés VBA-ban Feltünhet, hogy az eseményhez tartozó objektum nem utal pontos helyre. Pl. ha Worksheet-el kezdődik, honnan tudja a VBA, hogy melyik Worksheet-ről (munkalapról) van szó. A válasz egyszerű, onnan, hogy ezeket az eseményeket Excel objektumok (Worksheet, Workbook) esetén a hozzájuk tartozó Visual Basic felületen definiáljuk a Visual Basic editor-ban. Gomboknál ott láttuk, hogy ott úgy működik az eseménykezelés, hogy az “eseményheztartozóobjektum” az a gombnak a Name property-ben megadott neve (pl. mikor létrejön, akkor commandbutton1_Click, de ha átírjuk pl. katt-ra a Name-t akkor katt_Click stb..
Workbook-hoz esemény készítése Visual Basic editorba VBAProject-en belül a Microsot Excel Objects-et nyissuk le, ott válasszk ki a ThisWorkbook-ot és kattintsunk is rá duplán
Workbookhoz esemény készítése Az ő VB felületére már jöhetnek az eseménykezelő sub-ok. De nem kell az események nevét fejből megjegyezni. A bejövő VB felületen felül látunk két legördülő listát (alapesetbe egyiken a (General) van kijelölve, a másikon pedig a Declarations)).
Workbook-hoz esemény készítése A (General)-nál választhatjuk ki, melyik objektumra szeretnénk eseményt. Mi most a Workbook-ra szeretnénk. A másik listába pedig, hogy melyik eseményre szeretnénk írni eseménykezelőt. Ott most az Open-t választjuk (alapból ez is kerül kiválasztásra). Látható hogy sokféle esemény van, és amire szeretnénk kezelőt írni, itt kiválasszk, ő elkészíti a Sub vázát. Dokumentációból meg utánanézhetünk, hogy a paraméter adott eseményekhez mit tartalmaz. Esetünkben a Workbook Open eseménykezelője nem kap paramétert.
Workbook-hoz esemény készítése
Workbook-hoz esemény készítése Kipróbálásképp: Tegyünk ebbe a Workbook_Open nevű sub-ba egy MsgBox “Elindult a munka!” kódot. Zárjuk be az Excelt, majd nyissuk meg újra ezt a munkafüzetünket. Ha még nem mentettük el, ügyeljünk, hogy makróbarát formába (xlsm) mentsük!
Workbook-hoz esemény készítése
Workbook-hoz esemény készítése Persze, nekünk most nem ez az utasítás kell bele. Visszatérve a témához, itt fogjuk a menetrendek osztályt példányosítani. A másik dolog amit meg kell oldani, hogy valahogy úgy deklarálni az objektumot, hogy az a többi modulból is elérhető legyen. Ilyen változót úgy kell deklarálni VBA-ban, hogy: az adott modulban minden függvényt, eljárást megelőzően szükséges deklarálni. Public kulcsszóval szükséges ellátni Értéket adni ennek a változónak úgy foguk adni, hogy a Workbook_Open en belül a Set kulcsszóval (ugyanis objektumok értékadásánál az értékadást a Set kulcsszónak meg kell előznie)
Workbook-hoz esemény készítése De a menetrendek osztályunkat még nem tudjuk így deklarálni. A class modul beállításainál a menetrend class modulnál az Instancing-ot állítsuk Private-ról, PublicNotCreateable-re. Ezt a menetrend osztállyal is tegyük meg.
Workbook-hoz esemény készítése Menjünk vissza a ThisWorkbook modulra, és a benne lévő kód nézzen ki a következőképpen:
Workbook-hoz esemény készítése menetrendGyujtemeny Public, így elérhető más modulokból is (tehát ha kész az a modul ami az űrlap feldolgozását végző kódot tartalmazza, ezen keresztül be fogja tudni szúrni az űrlap adatait. Változó deklarálásakor a következő dián lévő kulcsszavakat használhatjuk a változó hatókörének meghatározásához A menetrendGyujtemeny más modulból a ThisWorkbook.menetrendGyujtemeny hivatkozással használható. (Mivel a ThisWorkbook modulban deklaráltuk, definiáltuk.)
Változók hatásköre VBA-ban Hatáskör
Kulcsszó
csak eljárás szintű (azaz Sub és Function-ben)
Dim vagy Static utasítással kell az adott eljárásban deklarálni a változót.
csak modulszintű
Dim vagy Private utasítással kell a modulban az első Sub vagy Function előtt deklarálni a változót, és akkor az adott modulban az összes eljárásban és függvényben használható
minden procedúra minden modulban
Public utasítással kell deklarálni egy modulban az első procedúra vagy függvény előtt a modulban
Workbook-hoz esemény készítése A Workbook_Open eljárásban hozzuk létre a megfelelő példányt.
Kezelő felület elkészítése Nevezzük át az erre szánt munkalapot ‘kezelo_felulet’-nek. Korábbi példában megfigyelhettük, hogy a munkalapra lehet a nevével hivatkozni, tehát erre a munkalapra Worksheets(“kezelo_felulet”)-el hivatkoznánk.
Kezelő felület elkészítése Az Excel Fejlesztőeszközök fülön a Beszúrás-t lenyitva az elérhető ActiveX vezérlőkből rakjuk most össze a formunkat (későbbi diákban megismermünk a felület összerakására egy másik módot is). Amikor ilyen módon rakjuk össze a formunkat, a Tervező négyzet legyen bekapcsolva! Amikor a formunkat próbáljuk ki, akkor legyen kikapcsolva!
Kezelő felület elkészítése Amikor kirakunk egy formot, rajta jobb klikkel a “Tulajdonságok”-ra kattintva megjelenik egy táblázat. Itt a form tulajdonságai láthatók. A Name tulajdonság határozza meg azt a nevet, amivel VBA kódban erre a vezérlővel hivatkozhatunk. (Ezeket úgy kell használni, mint a Property-ket, de ezt látni fogjuk). A Value propertyvel kérdezhetjük majd le az adott vezérlőbe beírt értéket. Az Indulási hely bevitelére hozzunk létre Textbox-ot. A neve legyen IndulasiHely. Ennek lépései részletesebben.
Kezelő felület létrehozása 1. 2.
ActiveX vezérlőkből válasszk ki a TextBox-t Ha rajta hagyjuk kiválasztáskor a kurzort , megjelenik hogy Szövegmező. Erre kell kattintani és készíteni egyet. Kiválasztás után megváltozik az egérkurzor. Ahova helyezni akarjuk a szövegmezőt, a táblázatban oda belekattintunk és húzzuk a megfelelő méretig.
Kezelő felület létrehozása 3. A létrejött szövegmezőbe kattintsuk egyet (ne duplán). Jobb klikkel a “Tulajdonságok” ra kattintva a nevét írjuk át “IndulasiHely”-re (Name property)
Kezelőfelület létrehozása A többi elem létrehozását az űrlapnak nem részletezzük így, ugyanezek a lépései. A neveket rögzítsük: Indulási hely (IndulasiHely), Érkezési hely (ErkezesiHely), Rendszám (Rendszam), Menetidő (MenetIdo), Indulási idő (IndulasiIdo) A form aljára tegyünk egy gombot (ezt is ActiveX vezérlőkből), a neve legyen BeszurGomb, a felirata (Caption property) pedig “Beszúrás” Az én esetemben a form így néz ki végső állapotában a “kezelo_felulet” munkalapon
Kezelő felület létrehozása
Adatok beszúrása a kezelőfelületről Kattintsunk a form végén elhelyezett gombra duplán. Ekkor generálódik hozzá egy Sub (az ehhez a munkalaphoz tartozó modulban),amivel a gombra kattintáskor meghatározhatjuk, hogy mi történjen. (Ha a Tervező mód be van jelölve)
Adatok beszúrása a kezelőfelületről A gombra kattintás eseménykezelőjét a következővel kell kitölteni. Létre kell hozunk egy menetrend objektumot. Ennek a propertyjeit az egyes űrlap elemeink Value propertyjeivel megkapott értékekkel beállítjuk, majd a menetrendGyujtemeny HozzaAd metódusát meghívva ezzel a menetrend objektummal a ‘menetrendek’ formhoz hozzáadódik amit az űrlapon kitölöttünk. Mivel a HozzaAd egy Sub ezért zárójelezés nélkül hívjuk majd meg. A menetrendGyujtemeny-re az őt deklaráló/definiáló modullal együtt hivatkozunk. Tehát ThisWorkbook.menetrendGyujtemeny.
Adatok beszúrása a kezelőfelületről A kód a következőképpen alakul
Adatok beszúrása a kezelőfelületről A példányosításnál a deklarálást és definiálást végezhetjük egy lépésben is Dim objektumneve As New objektumtípusa De a korábban használt forma is jó természetesen, ott azért nem ezt használtuk, mert a deklarálás és definiálásnak külön kellett megtörténnie. A másik forma ismétlésképp Dim objektumneve As objektumtípusa Set objektumneve = New objektumtípusa Látható, hogy a formok neve elérhető minden modulban, ahogy a Name propertyjükben megadtuk. Az értéküket a Value property-n keresztül lekértük , és a menetrendRekord megfelelő propertyjének értékül adtuk
Adatok beszúrása a kezelőfelületről Miután beállítottuk a menetrend objektumunk minden elemét, a ThisWorkbook modulból a menetrendGyujtemeny objektumon HozzaAd metódust meghívjuk az előbb feltöltött menetrend objektummal. ThisWorkbook.menetrendGyujtemeny.HozzaAd menetrendRekord
Alkalmazás kipróbálása Eddigi alkalmázusnk kipróbálásához lépjünk ki a munkafüzetünkből majd indítsuk újra (zárjuk be az excel-t majd nyissuk meg a nyilvántartó rendszerüket). De ha Workbook_Open után megírása után megtettük, akkor nem biztos, hogy szükséges, de biztos, ami biztos. Töltsük ki a formunkat mintaadatokkal, majd a Beszúr gomb lenyomása után ha mindent jól csináltunk, a menetrend munkalapon megjelennek a formnál megadott adatok. Természetesen ha megint Beszúrunk, a következő ezután fog megjelenni.
Alkalmazás kipróbálása
Alkalmazás kipróbálása
Bemenő adatok ellenőrzése A következő feladatunk az volt, hogy a bemenő adatokat ellenőrizzük. A következő megkötéseket definiáltuk: “mezők nem üresek, az időtartamok óra:perc formában adottak, a rendszám megfelelő formátúmú (3betű kötőjel 3szám)” Excelben erre többféle megoldás létezik. Lehetne, hogy a beszúráskor a Value értékeken VBA kóddal végeznénk az ellenőrzéseket. Lehetne akár, hogy a menetrend osztály Let propertyjeibe. Lehetne hogy a menetrendek osztály HozzaAd metódusába. Lehetne akár nem VBA megoldással is, mégpedig az Excel : Adatok fül, Adatok érvényesítse rész
Bemenő adatok ellenőrzése Az Excel Adatérvényesítéses megoldás a következőképp működne. A beszúrási folyamat továbbra is úgy nézne ki, ahogy. Az ellenrőzés akkor hajtódna végre, amikor a ‘menetrend’ munkalapra írunk. Ugyanis itt lenne rögzítve az adat érvényesítés, és ha nem megfelelő adatot írunk ide (vagy a form alapján ír ide a program) akkor hibát kapnánk, és nem íródna be az érték. Probléma, ami miatt most nem tudjuk haszálni: szöveg-re nehéz lenne formátumkövetelményt megadni. Például rendszám esetén: három betűvel kezdődjön, utána kötőjel, utána szám. Szabályos kifejezéseket képletekben alapból nem tudunk használni.
Rendszám formátum ellenőrzése Az ellenőrzést hajtsuk végre a gomb lenyomása utána. Rendszám formátumának ellenőrzése: Asc(betű): betű ASCII kódja (ezzel ellenőrizni tudjuk, hogy nagy betű-e, illetve szám-e). Valami nagy betű: 65≤Asc(karakter)≤90 Valami szám: IsNumeric(karakter). De lehetne ezt is ASCII kód alapján Szöveget VBA-ba (legalábbis az én Excel verzióm, 2010) így tudunk indexeli: Mid(szoveg, index, 1) : szöveg indexedik karakterét adja vissza
Rendszám formátum ellenőrzése
Rendszám formátum ellenőrzése Ez a kód ugyanoda kerül, mint ahol a Beszúr gomb eseménykezelője van. Lényegében bejárja a stringünket (VBA-ban 1től indexelünk). Ha 1. és 3. karakterek között járunk, akkor azt kell nézni hogy nagybetű-e, ha a 4. karakter, akkor azt kell nézni, hogy kötőjel-e.
Az 5. karaktertől a 7.ik meg azt, hogy szám áll-e ott. Ha IsRendszam igazzal (True) tér vissza, akkor a paraméterül kapott érték helyes rendszám formátum
Idő formátum ellenőrzése Lehetséges módszer: mivel óra:perc formátum az elvárt, a beadott string-et : mentén feldaraboljuk. Ha nem 2 darab elemre esik szét, akkor alapból rossz a formátum. Ha 2 darabra esik szét, akkor meg kell nézni, hogy 2 számra esik-e szét, és ha számok is, meg kell vizsgálni, hogy az első tag 0 és 23 közé esik, a második pedig 0 és 59 közé-e. Ha nem, akkor nem jó a formátum Feldaraboláshoz a Split VBA string függvényt használjuk. Ennek első paramétere, hogy mit szeretnénk feldarabolni, második, hogy mi mentén, harmadk pedig, hogy max. hány darab részre essen szét (esetünkben 2). Ha nincs benne :, akkor nem daraboljuk szét, mert biztos hogy nem idő. InStr(kezdőpozíció, miben, mit): mit pozíciójával tér vissza mibe, ha nincs akkor 0
Idő formátum ellenőrzése
Időformátum ellenőrzése Vigyázzunk, mert tömböknél az indexelés (pl. Mid-nél említettük, hogy 1-től kezdjük) 0-tól kezdődik. Következő pontunk a településnevek ellenőrzése. Egyszerűség kedvéért itt csak azt vizsgáljuk, hogy ne legyen üres.
Kitűztük még célul, hogy ahol hibáztunk a bemenetnél, ott legyen piros a szöveg, amíg nem írunk bele újból. A ForeColor property-nek vbRed-et adva a szöveg piros lesz. Az összes szövegmező Change eseményét felülírjuk és itt meg vbBlack-re állítjuk, mert kitűztük, hogy ha beleírunk, legyen újra fekete.
Formátum ellenőrzés összegzés A nyomógomb eseményének belseje tehát átszerveződik.
Formátum ellenőrzés összegzése
Tesztelés
Kezelés és módosítás felületen keresztül Következő feladatuk az volt, hogy: “d.Valósítsa meg, hogy ha a menetrend táblán kijelölünk egy sort (minden oszlopot benne ami a menetrendet érinti), akkor a másik munkalapon (‘kezelo_felulet’) lévő formba a kijelölt sor adati másolódjanak be és a gomb szövege változzon “Módosítás”-ra. Ha itt módosítunk valamit, akkor a nyomógomb lenyomására módosuljanak a menetrendben. Ha nincs kijelölve sor, akkor a formok álljanak vissza üres értékre és a gomb felirata is változzon vissza. A módosítás is csak akkor mehet végbe, ha a formátumok rendben vannak!”
Kezelés és módosítás felületen keresztül Első körben a menetrendek osztályban vezessünk be egy olyan metódust, ami paraméterül kap egy sorszámot és egy menetrend objektumot, és a “menetrend” munkalap adott sorszámú sorát módosítja a menetrend objektum adataival. A metódus végez egy érték ellenőrzést, hogy az index nem-e esik ki az aktuális sorindex tartományból. Vezessünk be továbbá egy olyan metódust, ami az éppen kijelölt rekord sorinexét adja vissza. Nyílván csak teljes sor kijelölése esetén. Továbbá egy metódust, ami index alapján visszaadja a menetrend objektumot
menetrendek class module bővítése
menetrendek class module bővítése
menetrendek class module bővítése Fontos megjegyezni, hogy ha objektummal térünk vissza, a Set értékadás akkor is vonatkozik Set függvényneve = visszatérésiobjektum Az aktuális kijelölt menetrend rekord sorindexénél annyit kell megvizsgálni, hogy egy sort és 5 oszlopot jelöltünk-e ki. Kijelölt cellatartományra a Selection objektumon keresztül hivatkozhatunk. Fontos, hogy előtte aktiváljuk azt a worksheet-et, amin a kijelölt tartomány érdekel minket (Worksheet objektum Activate metódus)
menetrendek class module bővítése
Kijelölés alapján form feltöltése Mikor a kezelo_felulet munkalapot megnyitjuk, meg kell történnie egy ellenőrzésnek, hogy a menetrend munkalapon van-e menetrend rekord kijelölés. Erről könnyen meggyőzödhetünk, hisz csak a ThisWorkbook. menetrendGyujtemeny.KijeloltMenetrend hívást kell kiadnunk a kezelo_felulet munkalap argumentummal. Az argumentum azért szükséges, mert amíg azt nézi a metódus, hogy a menetrend munkalapon milyen a kijelölt terült, aktívnak kell lenni. Ezt az Activate hívás biztosítja. Ilyenkor azonban átugrik az Excel arra a munkalapra, amire az Activate hívást kiadjuk (mivel ez a célja). Így ha paraméterül megkapja, hogy melyik munkalapról történt a metódushívás, akkor miután a kijelölt területet megvizsgálta a menetrend munkalapon, vissza tud ugrani arra munkalapra, ahonan kiadtuk (paraméterként kapott Worksheet objektumon meghívja az Activate-et
Kijelölés alapján form kitöltése Hozzunk létre a kezelo_felulet munkalapon egy Worksheet objektumra vonatkozó Activate eseményhez tartozó eseménykezelőt (a korábban leírt eljárások alapján) Ennek a kódja a következőképpen fog kinézni: Lekérdezi, hogy van e kijelölt menetrend rekord a menetrend munkalapon. Ilyenkor azonban az előbb leírtak alapján erre a kezelo_felulet-re ki lesz adva a metódusban egy Activate hívás. Ilyenkor ez az Activate eseménykezelő lefutna, majd megint lefutna stb.. Ennek elkerülése végett fenntartunk egy logikai változót, ami azt jelzi, hogy az Activate esemény VBA kód adta-e ki, vagy felhasználó. Ha VBA kód, akkor ne fusson le.
Kijelölés alapján form kitöltése Ha van kijelölt rekord, akkor a menetrendek osztály GetMenetrend metódusát meghívjuk a kijelölt rekord indexével és a form értékeit a GetMenetrend által visszaadott menetrend objektum adataival feltöltjük, és a gomb feliratát “Módosítás”-ra állítjuk. Ügyeljünk arra, hogy az idő adatokat a Format paranccsal “hh:mm” formátumra hozzuk, hogy biztosan ebbe a formátumba legyen. (Nem megfelelő cellaformázás miatt előfordulhat, hogy hiába óra:perc formába van a menetrend munkalapon, itt nem úgy lesz
Kijelölés alapjá form kitöltése Ha nincs kijelölt rekord, a form mezőit üres string-re állítjuk éa a gomb feliratát “Beszúrás”-ra visszaállítjuk.A gomb eseménykezelőjébe vizsgáljuk, hogy a gomb felirata kattintáskor éppen mi. Ha “Módosítás” akkor a menetrendek osztály Modosit metódusát hívjuk meg a kijelölt menetrend rekord indexével és a form adataiból képzett menetrend objektumot átadva neki
Kijelölés alapján form kitöltése
Kijelölés alapján form kitöltése BeszurGomb Click korábban megírt eseménykezelőjének vége módosítva
Kijelölés alapján form kitöltése tesztelés
Kijelölés alapján form kitöltése tesztelés
Kezelőfelület használatának kikényszerítése Elérkeztünk utolsó kitűzött célunkhoz “e. Valósítsa meg, hogy mind a módosítás, mind a hozzáadás csak a b. és d. pontba leírtakkal legyen megvalósítható. Azaz a menetrend munkalapon ne lehessen kézzel új sort bevinni és valamelyik sort kézzel átírni, csak formon keresztül a beszúrást, illetve kijelöléssel és formon keresztül a módosítást!” Megvalósítás: a menetrend munkalaphoz egy Worksheet-re vonatkozó olyan eseménykezelőt kell létrehozni, ami ha valamelyik cellába beleírunk akkor ha átírtuk az értékét, írja ki , hogy csak a kezelőfelülettel lehet módosítani és írja visssza a régi értéket. Továbbá, ha a menetrend adatokon kívűlre kattintunk, akkor írja ki üzenetablakban, hogy “Nem használt tartomány!”
Kezelőfelület használatának kikényszerítése Itt is szükséges figyelni, hogy az eseményt a VBA program vagy a felhasználó váltja ki, hisz a VBA kód a felület kitöltése után módosít a menetrend munkalapon, ami szintén kiváltaná az eseményt ami szintén… Két eseményhez kell eseménykezelőt rendelnünk: SelectionChange: mielőtt valamelyik cellába beleír a felhasználó, nyílván belemegy a cellába, azaz kijelöli. Ilyenkor beállítjuk, hogy nem VBA kód váltja ki az eseményt (programIrjaBe = false). Lementjük, mi volt a cellába, hogy szükség esetén erre az adatra visszaállítható legyen, ha belegépelünk valamit. Change: tartalomváltozást figyel. Ha a SelectionChange érzékelésekor elmentett adathoz képest változás van, visszaírjuk. Dobjuk fel üzentablakot ekkor, hogy csak a felületen keresztül lehetséges a módosítás.
Kezelőfelület használatának kikényszerítése Egyszerűség végett csak egy cella módosítását figyeljük. A menetrend munkalap modul elején vezzüsk be a következőket:
A programIrjaBe jelzi, hogy program-e (True) vagy felhasználó módosít. regiertek változó azt jelzi, hogy mi volt a kijelöléskor (módosítás előtt) a cellatartam
Kezelőfelület használatának kikényszerítése
Kezelőfelület használatának kikényszerítése Target(1,1) el kijelölések közül az első cellát jelenti (említettük hogy az egyszerűség kedvéért csak egy cellával foglalkozunk) Ha felhasználó próbálja átírni és ténylegesen átírt (nem csak véletlenül) belekattintott, akkor feldobunk egy üzenetet és visszaírjuk az eredeti értéket. Ezt a Change eseményhez rendelt eseménykezelő csinálja
Kezelőfelület használatának kikényszerítése Amikor írunk a menetrend munkalapra, előtte a programIrjaBe változót igazra kell állítani. A modellünkben ez két helyen történik meg (menetrendek osztály). A programIrjaBe esetünkben a Munka1 nevű modulban található, így Munka1.programIrjaBe kifejezéssel hivatkozhatunk erre a logikai változóra Következő dián látható, hogy a menetrendek osztály két metódusát egy-egy sorral kiegészítetttük, mégpedig a Munka1.programIrjaBe = True - ra.
Kezelőfelület használatának kikényszerítése
Kezelőfelület használatának kikényszerítése teszt
GNA-876 -ot megpróbltam GNA-875 re átírni