Egyik kedves Olvasóm kérdése volt az ötletadója ennek a posztnak, ugyanis bár ő maga már jóval túllépett az alapokon, úgy gondoltam, egy ilyen jellegű megoldás kezdetleges kialakításának bemutatása mindenki számára hasznos lehet. Adott egy adatbázis, oszlopokkal, sorokkal, mindenféle adatokkal, mint a következő példa:
Ebben a posztban készíteni fogunk egy olyan userformot, amelynek a segítségével a felhasználónk roppant egyszerűen, akár már csak az első betű beírása után szűrni tud az adatbázis bármelyik oszlopában. Első lépésként a Developer ribbonfülünk Controls funkciójának Insert menüjéből szúrjunk be egy Command Buttont, amelyet aztán a jobb gombbal történt kattintás után formázzunk is meg, ahogy szeretnénk:
Ezután, még mindig Design Modeban, kattintsunk duplán erre a gombra, majd a megnyíló VBA-editorban a CommandButton1 Click eseményéhez rendeljünk hozzá egy UserForm2.Show utasítást (értelemszerűen a UserForm2 helyettesítendő az adott userform nevével), azaz a gombra való kattintással elindítjuk a keresést segítő userformot.
Ha már úgyis a VBA-editorban vagyunk, szépen menjünk az Insert menüpontra, ahonnan szúrjunk egy Userformot. Ha beszúrtuk, akkor a Toolbox segítségével (ha ezt nem látnánk úgy, ahogy a lenti képen, akkor a View menüben találjuk meg az indító parancsát) pakoljunk a formra legalább egy Listboxot és egy Textboxot, plusz célszerű esetleg valamiféle dizájnelemet vagy szöveget is rátenni:
Alapvetően a listboxunkat fogjuk a keresés eredményének megjelenítésére használni, a textboxban pedig gépelni fog a felhasználónk, úgyhogy a listboxot mindenképpen konfigurálnunk egy kicsit. Kattintsunk rá jobb gombbal, majd a Properties alatt formázgassuk meg, de a ColumnCount paramétert mindenképpen állítsuk annyira, ahány oszlopot akarunk kezelni:
Aztán nagyjából már csak a kód van hátra a Textboxunk mögött. Kattintsunk a mezőre jobb gombbal, majd View Code menüpont segítségével menjünk át a Textboxunk Change eseményéhez:
Tehát ez a kód akkor fog lefutni, ha bármi változás történik a szövegdobozunkban (ergó elkezdünk gépelni). Első lépésként töröljük ki a Listboxunk aktuális tartalmát. Az "me" parancsról már írtam itt korábban, ez mindig arra a "szülő" objektumra hivatkozik, amelyikben a kód benne van, jelen esetben tehát az "me" a userformot jelenti - azaz a userformunk Listbox1-éről beszélünk. Ezután definiáljunk egy i nevű változót, amely nagyjából a vizsgálandó sorokat jelenti, ezért lesz a következő sorunk egy For .. To..., ugyanis amennyiben elkezdünk gépelni, akkor a később következő kódrészeket meg fogjuk nézni az A oszlop összes (A:A), nem üres (CountA("A:A")) során, a headert leszámítva (For i = 2).
De egy újabb For ciklussal kell folytatnunk, hiszen soronként mind a három oszlopot meg kell vizsgálnunk, hiszen nem tudhatjuk, hogy a felhasználó az adatbázis három oszlopa közül melyikben keresne éppen. És hogy az így kialakult mátrix elemein milyen vizsgálatot is fogunk elvégezni?
Elsőként a Length névre keresztelt változóval vetessük fel a Textboxunkba írt szöveg karakterszámát. Ezután viszont jön a tényleges vizsgálat, a kód lelke, azaz ha (If) az adott munkalapunk előbb létrehozott mátrixának (minden sor minden oszlopát vizsgáljuk) aktuálisan vizsgált cellája (.Cells(i,f)) értékének (.Value) bal oldaláról levágunk annyi karaktert (Left), amennyit a felhasználó éppen beírt a textboxba és ez a levágott rész pontosan megegyezik a textboxba beírt szöveggel (és hát persze valami van a textboxban, ergó me.textbox1.text <> ""), akkor (Then) jön a képbe a Listbox AddItem metódusa, amelynek segítségével a listboxban megjelenített értékek listájához tudunk egy újabb értéket hozzáadni. Ezzel ugyanis szépen hozzáadjuk annak a sornak az első oszlopában szereplő értéket a listboxhoz, amely sorban a fenti vizsgálat egyezést talált bármelyik oszlopban.
A kód zárórészével pedig igazából már csak az előbb AddItemmel hozzáadott, első oszlopban szereplő érték mellé kell a második és harmadik oszlopban szereplő értékeket is beraknunk a Listboxba, amit pedig egy újabb For segítségével fogunk elérni, méghozzá úgy, hogy amennyiben a fenti vizsgálat talált egy egyezést, akkor még lesz egy, két lépésből álló ciklusunk (For m = 1 to 2), amelyben a listboxunk második és harmadik oszlopába betesszük az adott sor második és harmadik oszlopában szereplő értéket. Alapvetően ez így elég egyértelmű lenne, kivéve azt a mínusz egyest a listbox List tulajdonságában (ez utóbbi egyébként egy bizonyos elemet jelent a listboxban) szereplő listbox.listcount tulajdonság mögött, ami egyébként arra használatos, hogy megtudjuk egy listbox elemeinek számát. Szóval amit tudnunk kell erről az az, a ListCount mindig eggyel kezdi a számlálást az elemeknél, viszont a listbox nullánál kezdődik, ergó ez azt jelenti, hogy
.List(ListBox1.ListCount - 1, 1)
az első sorban és második oszlopban szereplő elemet fogja jelenteni, a -1,2 pedig a harmadikat.
És innentől kezdve már csak a For ciklusok kötelező Next elemeit kell betennünk és lezárhatjuk a szubrutint. Íme az eredmény: