A mai napon a VBA-ban lévő tömböket mutatom be. Maga a téma jóval összetettebb és terjedelmesebb, mint amit egy poszt elbírna, így egy általános ismertetés a célom, persze rengeteg gyakorlati példával.
I. Ismertető:
A tömb elemek csoportja vagy ha úgy tetszik, értékek sorozata.
Az elemek csoportjának közös neve van (ami a tömb neve).
A tömb is egyfajta változó, viszont a változókkal ellentétben nem csak egy, hanem több elemet is tud tárolni.
Az elemek adattípusa megegyezik.
Tömbök megadása:
Példa #1:
SzamTomb(99) – ez egy 100 elemből álló tömböt jelent (a számozás 0-től kezdődik és 99-ig tart, ezért 100). Az elemeknek később értéket kell adnunk – lásd lentebb. A tömb neve „SzamTomb”.
Példa #2:
HonapTomb(„Január”,”Február”,”Március”) – ez egy 3 elemből álló tömböt jelent, itt az értékek adottak (hónapok nevei). A számozás itt is 0-tól kezdődik: a 0. elem a Január, az 1. elem a Február és a 2.elem a Március. A tömb neve „HonapTomb”.
A tömb elemeire tudunk hivatkozni: tömb neve + indexszám alapján. Az előbb említett HonapTomb esetében így tudok hivatkozni a Januárra (ami a 0. eleme a tömbnek):
HonapTomb(0)
II: Tömbök deklarálása:
Deklarálás a Dim vagy a Public szóval – akárcsak a mezei változóknál. A tömb elemeinek típusát az „as” szóval adjuk meg.
Lássuk a korábbi példát, ami ugye 100 elemből áll:
SzamTomb(99)
Ennek a tömbnek a helyes deklarálása:
Dim Szamtomb(99) As Integer
Itt az elemek számozása tehát 0-tól kezdődik és 99-ig tart. Másik helyes deklarálási forma a 100 elemes tömbre:
Dim Szamtomb(0 To 99) As Integer
Itt már mi adtuk meg a kezdő indexszámot, a 0-t. Mi ennek az értelme? Hiszen, ha mindkettő ugyanazt jelenti…
Dim Szamtomb(99) As Integer
Dim Szamtomb(0 To 99) As Integer
… akkor a rövidebbet elég megjegyezni, nem? Azonban megadhatok olyan tömböt, melynek az elemei nem 0-tól kezdődnek, hanem mondjuk 5-től és nem 99-ig, hanem 9-ig tartanak:
Dim Szamtomb(5 To 9) As Integer
Vagyis az elemek első és utolsó sorszámát én döntöm el, így lett a
Dim Szamtomb(0 To 99) As Integer -ből
Dim Szamtomb(5 To 9) As Integer
Persze a „To” előtt lévő szám legyen kisebb, mint az utána levő, vagyis a következő kód hibát („Range has no values”) fog generálni:
Dim Szamtomb(20 To 9) As Integer
A fenti példáknál az „As Integer” azt jelenti, hogy a tömb elemei egész számok.
Ha szeretnénk, hogy egy tömb alapértelmezetten ne 0-tól, hanem 1-től kezdődjön, akkor a VBA modul legtetején az alábbi parancsot adjuk meg: „Option Base 1”
Ha az „Option Base 1”-et megadtuk, akkor a
Dim Szamtomb(99) As Integer
Számozása 1-gyel kezdődik, vagyis 99 elemből fog állni a 100 helyett.
Ha pedig nem akarjuk vagy nem tudjuk megadni a tömb elemeinek számát, ez a deklarálás is helyes, pl.:
Dim Napok()
Ilyenkor az elemeit így is megadhatjuk – lásd a lenti gyakorlatban:
Napok = Array(“Hétfő”, “Kedd”, “Szeda”, “Csütörtök”, “Péntek”, “Szombat”, “Vasárnap”)
III: Tömbök típusai: Egydimenziós és Többdimenziós
1. Egydimenziós
A fenti tömbök ún. egydimenziós tömbök. Ilyen tömbnek fogható fel egyébként Excelben egy oszlop vagy egy sor (és azok cellái).
Gyakorlat: a makrókat be tudod másolni egy sima modulba (üres munkafüzetben) és onnan lefuttatni.
Gyakorlat #1: adatok beolvasása tömbbe
A jól bevált módszer: adjuk meg a hét napjait változókkal, majd írassuk ki a napokat msgbox-ba:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
Sub Tomb03() Dim Nap1 As String, Nap2 As String, Nap3 As String, Nap4 As String, Nap5 As String, Nap6 As String, Nap7 As String Nap1 = "Hétfõ" Nap2 = "Kedd" Nap3 = "Szerda" Nap4 = "Csütörtök" Nap5 = "Péntek" Nap6 = "Szombat" Nap7 = "Vasárnap" MsgBox Nap1 MsgBox Nap2 MsgBox Nap3 MsgBox Nap4 MsgBox Nap5 MsgBox Nap6 MsgBox Nap7 End Sub |
Élelmesebbek észrevehették, hogy ebben az első kódban nincs is tömb😊
Ugyanezt oldjuk meg tömbbel: itt az elemeknek már értéket is adunk, a hét napjait: 0. elem a Hétfő, 1. elem a Kedd stb.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
Sub Tomb04() Dim Napok(0 To 6) As String '0 to 6: mert 0-tól 6-ig számolunk, hiszen 7 elembõl áll a tömb Napok(0) = "Hétfõ" Napok(1) = "Kedd" Napok(2) = "Szerda" Napok(3) = "Csütörtök" Napok(4) = "Péntek" Napok(5) = "Szombat" Napok(6) = "Vasárnap" MsgBox Napok(0) MsgBox Napok(1) MsgBox Napok(2) MsgBox Napok(3) MsgBox Napok(4) MsgBox Napok(5) MsgBox Napok(6) End Sub |
Hát nem lett sokkal rövidebb a kód, igaz? Szerencsére az indexszámok helyett feltölthetjük a tömbünket a hét napjaival. Ilyenkor a tömböt indexszám nélkül deklaráljuk: Dim Napok()
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
Sub Tomb05() Dim Napok() Napok = Array("Hétfõ", "Kedd", "Szerda", "Csütörtök", "Péntek", "Szombat", "Vasárnap") MsgBox Napok(0) MsgBox Napok(1) MsgBox Napok(2) MsgBox Napok(3) MsgBox Napok(4) MsgBox Napok(5) MsgBox Napok(6) End Sub |
Lehet ez tovább fokozni/egyszerűsíteni? Persze, hiszen a tömb elemein végigmehetünk, mondjuk egy
For – Next ciklussal:
1 2 3 4 5 6 7 8 9 10 11 |
Sub Tomb06() Dim Napok(), i As Long Napok = Array("Hétfõ", "Kedd", "Szerda", "Csütörtök", "Péntek", "Szombat", "Vasárnap") For i = LBound(Napok) To UBound(Napok) MsgBox Napok(i) Next i End Sub |
Látható – különösen a legelső makróhoz képest – hogy ez a megoldás jóval rövidebb, átláthatóbb és gyorsabban lefut.
Gyakorlat #2: tömb adatainak kiíratása munkalapra
Vegyük az alábbi tömböt:
Napok = Array(“Hétfő”, “Kedd”, “Szerda”, “Csütörtök”, “Péntek”, “Szombat”, “Vasárnap”)
Ennek az elemeit szeretnénk kiíratni egy tartományba, mondjuk a D oszlopba. A megoldás igen hasonló a fenti „Sub Tomb06” makróhoz:
1 2 3 4 5 6 7 8 9 10 11 |
Sub Tomb07() Dim Napok(), i As Long Napok = Array("Hétfõ", "Kedd", "Szerda", "Csütörtök", "Péntek", "Szombat", "Vasárnap") For i = LBound(Napok) To UBound(Napok) Worksheets("Sheet1").Cells(i + 1, 4) = Napok(i) Next i End Sub |
A különbség a cikluson belüli kód:
Worksheets(“Sheet1”).Cells(i + 1, 4) = Napok(i)
A ciklusnál az „i” kezdőértéke 0 vagyis az első körben az „i”-t 0-val helyettesíti be a kód:
Worksheets(“Sheet1”).Cells(0 + 1, 4) = Napok(0)
A cells(0+1,4) az első sort és 4. oszlopot jelent, magyarán a D1-es cellát. A Napok(0) pedig a Napok tömb 0. elemét jelenti, vagyis a Hétfőt. Azaz kezdetben a D1-es cellába kiíratjuk a Hétfőt.
A második körnél a ciklusban az „i” értéke 1-re változik, azaz:
Worksheets(“Sheet1”).Cells(1 + 1, 4) = Napok(1)
Vagyis itt már a D2-es cellába írjuk ki a Keddet. És így tovább.
2. Többdimenziós tömbök
A tömb ugyebár elemek csoportja. Ha több ilyen csoportot is tartalmaz, akkor beszélünk többdimenziós változatról.
A tömbök maximum 60 dimenziót tartalmazhatnak, de ne aggódjunk: a legtöbb embernek a 2-3 dimenziós változat bőven elegendő. Példa egy kétdimenziós tömb deklarálására:
Dim Napok_Teendok(1 To 7, 1 To 2)
A könnyebb megértés végett nézzük meg az alábbi tartományt:
A deklarálás megértéséhez gondoljunk egy mátrixra:
1 To 7 jelentése: sorok (1-től 7-ig): ez az első dimenzió
1 To 2 jelentése: oszlopok (A-tól B-ig vagyis 1-től 2-ig): ez a második dimenzió
Excelben is szoktunk ilyent, hiszen a cella egy sor és egy oszlop metszéspontja. Vagyis ha azt mondom: a 3. sor és 2. oszlop metszéspontja, akkor az a fenti kép alapján a B3-as cella lesz (melynek a tartalma a „Bevásárlás” szó).
Gyakorlat: a makrókat itt is be tudod másolni egy sima modulba (üres munkafüzetben) és onnan lefuttatni.
Gyakorlat #1: adatok beolvasása tartományból tömbbe
A „Napok_Teendok(1 To 7, 1 To 2)” tömb elemein is végigmehetünk ciklussal, pl. az első dimenzión, ami az „1 To 7” és amit így kell megadnunk:
(Napok_Teendok, 1) – lásd a mostani kódban:
1 2 3 4 5 6 7 8 9 |
Sub Tomb08() Dim Napok_Teendok(1 To 7, 1 To 2), i As Long For i = LBound(Napok_Teendok, 1) To UBound(Napok_Teendok, 1) MsgBox Napok_Teendok(i, 1) Next i End Sub |
A ciklusnál a „(Napok_Teendok, 1)”-nél tehát az 1 az első dimenziót jelenti, aminek értéke: 1-től 7-ig. Hasonlóképpen a második dimenziónál a „(Napok_Teendok, 1)” helyett a „(Napok_Teendok, 2)” lesz a korrekt.
Ezzel a kóddal egyetlen gond van: hogy a nagy nihilt kapjuk vissza az msgbox-ban, hiszen nincs értéke a tömb elemeinek.
Előbb a tömbhöz adjunk hozzá értékeket:
1 2 3 4 5 6 7 8 9 10 11 12 |
Sub Tomb09() Dim Napok_Teendok(1 To 7, 1 To 2) Dim i As Long, j As Long For i = LBound(Napok_Teendok, 1) To UBound(Napok_Teendok, 1) 'elsõ dimenzió: 1 To 7 For j = LBound(Napok_Teendok, 2) To UBound(Napok_Teendok, 2) 'második dimenzió: 1 To 2 Napok_Teendok(i, j) = Worksheets("Sheet1").Cells(i, j) 'értékhozzáadás Next j Next i End Sub |
Ellenőrzés: pl. a Napok_Teendok(1,1)-nek meg kell egyeznie a tartomány 1. sorának és 1. oszlopának cellájával, ami a „Hétfő”. Ha lépésenként futtatom a makrót, könnyedén tudom ellenőrizni:
Gyakorlat #2: tömb adatainak kiíratása munkalapra:
Most már kiírathatjuk a tömb elemeit. Az előző kód egy msgbox-os sorral kiegészítve:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
Sub Tomb09_02() Dim Napok_Teendok(1 To 7, 1 To 2) Dim i As Long, j As Long 'adatok beolvasása tömbbe és kiíratás: For i = LBound(Napok_Teendok, 1) To UBound(Napok_Teendok, 1) 'elsõ dimenzió: 1 To 7 For j = LBound(Napok_Teendok, 2) To UBound(Napok_Teendok, 2) 'második dimenzió: 1 To 2 Napok_Teendok(i, j) = Worksheets("Sheet1").Cells(i, j) 'beolvasás MsgBox Napok_Teendok(i, j) 'kiíratás Next j Next i End Sub |
És a non plus ultra, ami már-már vérlázítóan szemet gyönyörködtető: az előző makró még hatékonyabban:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
Sub Tomb09_03() Dim Napok_Teendok() Dim i As Long, j As Long Napok_Teendok = Worksheets("Sheet1").Range("a1").CurrentRegion.Value 'tartomány beolvasása tömbbe egy sorban megoldva! 'adatok beolvasása tömbbe és kiíratás: For i = LBound(Napok_Teendok, 1) To UBound(Napok_Teendok, 1) 'elsõ dimenzió: 1 To 7 For j = LBound(Napok_Teendok, 2) To UBound(Napok_Teendok, 2) 'második dimenzió: 1 To 2 MsgBox Napok_Teendok(i, j) 'kiíratás Next j Next i End Sub |
Ha még mindig olvasod a posztot, megérdemelsz egy kis pihenőt, illetve segítséget: az előző két makró összehasonlítva:
Két apró, ám lényeges különbség:
- Deklarálás: a jobb oldali kódnál nincs indexszám – sárga kiemelés
- A tömbbe történő beolvasás (avagy a tömb elemeinek feltöltése értékekkel) nem a cikluson belül van (bal oldali kép), hanem a cikluson kívül (jobb oldal) – lila kiemelés. Vagyis a „Sub Tomb09_03()”-nál egyszer olvassuk be az értékeket a tömbbe (egyetlen sorban!), ezzel pedig drasztikusan felgyorsulhat a kód futtatása. Egy tartomány (vagy akár táblázat) adatait ilyen egyszerű beolvasni egy tömbbe:
Napok_Teendok = Worksheets(“Sheet1”).Range(“a1”).CurrentRegion.Value
A fenti msgbox-os kiíratás – mi tagadás – nem annyira életszerű, illetve izgalmas. Írassuk ki a tömböt munkalapra (a Gyakorlat #2 amúgy is ezt ígérte). Ehhez kicsit megváltoztatjuk a beolvasott tömb elemeit, majd újra kiíratjuk, mégpedig az eredeti tartománytól három oszloppal arrébb:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
Sub Tomb10() Dim Napok_Teendok() Dim i As Long, j As Long Dim Tart As Range Set Tart = Worksheets("Sheet1").Range("a1").CurrentRegion 'tartomány megjegyzése Napok_Teendok = Tart.Value 'tartomány beolvasása tömbbe egy sorban megoldva! 'tömb értékeinek módosítása For i = LBound(Napok_Teendok, 1) To UBound(Napok_Teendok, 1) 'elsõ dimenzió: 1 To 7 For j = LBound(Napok_Teendok, 2) To UBound(Napok_Teendok, 2) 'második dimenzió: 1 To 2 Napok_Teendok(i, j) = Napok_Teendok(i, j) & "_" 'értékmódosítás: pl. a "Hétfõ"-bõl "Hétfõ_" lesz Next j Next i Tart.Offset(0, 3) = Napok_Teendok 'módosított tömb kiíratása tartományba egy sorban megoldva! End Sub |
Makró futtatása előtti és utáni állapot:
Egyelőre ennyit a tömbökről, remélem hasznosnak és érthetőnek találtad okfejtésemet.
Kérdésed, észrevételed van? Hívj vagy dobj egy emailt az xlmotyo@gmail.com-ra.