Azzal nem árulok el nagy titkot, hogy Excelben a képletek is makrózhatók. Elég egyszer „megszenvedni” a korrekt formuláért, utána pedig ezt is automatizálhatjuk. Viszonylag könnyű belekeveredni: rögzítővel felveszünk egy képletet, és a kód jó eséllyel le is fut utána. De mi van mondjuk akkor, ha a VBA-ban megírt képletnek dinamikusnak kell lennie (a forrástartomány változása esetén is működjön)? Mikor kell .Formula-t és mikor .FormulaR1C1-et használni? Exceles vagy VBA-s függvényt alkalmazzunk?
Lássunk egy kis összegzést a témában.
VBA-ban a képletek beírása ugyebár angolul (azon belül is amerikai angol) történik.
Az összegzés összegzése:
I. Hivatkozási típusok (link)
II. Változók használata képletekben (link)
III. Excel és VBA képletek alkalmazása (link)
IV. Felhasználói függvény (UDF = User Defined Function) (link)
V. Képletek frissítése VBA-ban (link)
_
I. Hivatkozási típusok
A tartománynak (range) két fő tulajdonsága (property) VBA-ban van a képletek kapcsán:
1 .Formula
2 .FormulaR1C1
1 .Formula
– ez esetben konkrét képletet adunk meg, fix/bedrótozott hivatkozásokkal
– ún. A1-stílusú hivatkozás (mint Excelben, pl. A5-ös vagy C10:D25-ös tartomány)
– a makrórögzítő nem vesz fel ilyen megoldást (ugyanis a Formula helyett mindig a FormulaR1C1 változatot használja)
– egyetlen cellához adunk hozzá képletet
– lehet relatív vagy abszolút a hivatkozás a „$” jelektől függően – lásd a makrókban lévő kommenteket
Példa #1-01: képlet beírása egy cellába, FIX forrástartománnyal
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
Sub Sample01_FormulaProperty_FixedSourceRange_01() 'futtatás előtt: az A1-es és A2-es cellába írjunk be egy-egy számot 'itt RELATÍV hivatkozás van. Ha abszolút hivatkozás kell: a "$" jeleket be kell tenni a sor/oszlopazonosítók elé, 'mint Excelben, pl.: "=AVERAGE($A$1:$A$2)" Munka2.Select 'frissíteni Range("c1:d1").ClearContents 'alapállapot Range("c1").Formula = "=AVERAGE(A1:A2)" 'Exceles képlet: =ÁTLAG(A1:A2) Range("d1").Formula = "=IF(A1>A2,A1,"""")" 'Exceles képlet: =HA(A1>A2;A1;"") ->a képlet végén a ""-ből a makróban """" lesz End Sub |
Ha itt módosítani akarjuk pl. az ÁTLAG függvénynél a hivatkozott tartományt, azt itt kell átírni:
Ez akkor lehet macerás, ha a képlet többször is előfordul, ilyenkor minden egyes előfordulásnál meg kell ejteni a cserét (manuálisan vagy CTRL + H-val).
Példa #1-02: képlet beírása egy cellába, változóba berakott FIX forrástartománnyal
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
Sub Sample01_FormulaProperty_FixedSourceRange_02() Dim Tart As Range 'futtatás előtt: az A1-es és A2-es cellába írjunk be egy-egy számot 'ABSZOLÚT hivatkozás (Tart.Address értéke: $A$1:$A$5) Munka2.Select 'frissíteni Set Tart = Range("A1:A5") 'frissíteni Range("c1").ClearContents 'alapállapot 'Range("c1").Formula = "=AVERAGE(A1:A2)" Range("c1").Formula = "=AVERAGE(" & Tart.Address & ")" 'Exceles képlet, ha a Tart = Range("A1:A5"): =ÁTLAG($A$1:$A$5); 'Fontos: idézőjelek közt van minden, ami nem változó! End Sub |
Látható, hogy ebből:
1 |
"=AVERAGE(A1:A2)" |
Ez lett:
1 |
"=AVERAGE(" & Tart.Address & ")" |
Vagyis az „A1:A2”-t váltottuk ki a „Tart.Address”-szel. A „Tart.Address” előtti és után kódot pedig hozzáadtuk szövegként, ezért vannak „”-ek között.
Ha itt módosítani akarjuk pl. az ÁTLAG függvénynél a hivatkozott tartományt, azt csak egyszer kell átírni, ahol a „Tart” változóban megadtuk a tartományt:
Példa #2: képlet beírása egy cellába, változóba berakott DINAMIKUS forrástartománnyal
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
Sub Sample02_FormulaProperty_DynamicSourceRange() Dim Tart As Range 'futtatás előtt: az A1-es és A2-es cellába írjunk be egy-egy számot 'különbség a "Sample01_FormulaProperty_FixedSourceRange_02" kódhoz képest: a "Set Tart" kezdetű sor 'ABSZOLÚT hivatkozás (itt a Tart.Address értéke: $A$1:$A$10) Munka2.Select 'frissíteni Set Tart = Range("A1").CurrentRegion.Columns(1) 'frissíteni; ".Columns(1)" itt nem feltétlenül szükséges Range("c1").ClearContents 'alapállapot 'Range("c1").Formula = "=AVERAGE(A1:A2)" Range("c1").Formula = "=AVERAGE(" & Tart.Address & ")" 'Excel: ha az A1:A10 van kitöltve számokkal: '=ÁTLAG($A$1:$A$10) 'Fontos: idézőjelek közt van minden, ami nem változó! End Sub |
Itt tehát egyáltalán nem kell a kódban módosítani a hivatkozott tartományt a „CurrentRegion” miatt. Magyarán, ha az „A” oszlopban csökken/bővül a kitöltött cellák száma (és nincsenek üres cellák), ez a VBA kód akkor is helyesen fog működni, mégpedig változtatás nélkül.
.Formula két fő alkalmazása:
– VBA-ban beírjuk a képletet
– Excelből kimásoljuk a képletet, majd beillesztjük a makróba, és szükséges esetén módosítjuk. Azt, hogy miket kell(het) átírni, az alábbi példán keresztül szemléltetem:
2 .FormulaR1C1
– a makrórögzítő mindig a FormulaR1C1 változatot használja és különbséget tesz relatív és abszolút hivatkozás között
(Rögzítő indítása -> képletet beírni relatív/abszolút hivatkozással Excelben -> rögzítő leállítása).
– R1C1-nél az R és C jelentése: Row (Sor) és Column (Oszlop)
– R1C1 hivatkozás: sorok és oszlopok számával hivatkozunk egy cellára vagy tartományra.
Pl. a B3-as cella ugye alapból így néz ki:
Itt még B3-at látunk a cella címénél.
Excelben ideiglenesen állítsuk be az R1C1 (magyarul S1O1 azaz Sor-Oszlop) hivatkozást (pl. O365-ben):
Fájl menü -> Beállítások -> Képletek -> pipát betenni az „S1O1 hivatkozási stílus” elé -> OK:
Ezt követően Excelben az oszlopazonosítók is számok lesznek – vagyis kollégák ugratására is használható ez a beállítás 😊
Az iménti B3-as cella most már „S3O2”-ként szerepel (S3O2 angolul R3C2: a 3. sor és 2. oszlop metszéspontja):
Nézzük a hivatkozási típusokat a FormulaR1C1-nél:
2/1. Abszolút hivatkozás:
– korábban volt róla szó, pl. a B3-as (pontosabban $B$3) cella R1C1-es abszolút hivatkozása: R3C2
– ez a hivatkozás másolásnál/áthelyezésnél nem változik, marad R3C2
– itt az R és C után nincs [] (kapcsos zárójel)
2/2. Relatív hivatkozás:
– másolásnál/áthelyezésnél változik
– maradjunk a B3-as példánál -> ez így néz ki relatívan, ha pl. a E1-es-es cellából hivatkozunk rá: R[2]C[-3]
1 2 3 4 5 6 7 8 9 10 11 12 |
Sub Sample01_FormulaR1C1Property_01() 'Relatív hivatkozás Munka3.Select 'frissíteni Range("E1").ClearContents Range("E1").Select Range("E1").FormulaR1C1 = "=R[2]C[-3]" 'Exceles képlet: =B3 End Sub |
– látható, hogy a kapcsos zárójelekben adjuk meg, merre történjen a relatív elmozdulás
– itt az R[2]C[-3] jelentése: E1-es cellától mozduljon el 2 sort lefelé és 3 oszlopot balra
Elmozdulások:
– „R” utáni [ ]-ben pozitív szám: annyi sort mozduljon lefelé
– „R” utáni [ ]-ben negatív szám: annyi sort mozduljon felfelé
– „C” utáni [ ]-ben pozitív szám: annyi oszlopot mozduljon jobbra
– „C” utáni [ ]-ben negatív szám: annyi oszlopot mozduljon balra
– néhány további példa – itt a K15-ös cellából indulok ki:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
Sub Sample01_FormulaR1C1Property_02() 'Relatív hivatkozás Munka3.Select 'frissíteni 'makrót lépésenként érdemes futtatni Range("K15").ClearContents Range("K15").Select Range("K15").FormulaR1C1 = "=R[3]C[-6]" 'Exceles képlet: =E18 Range("K15").FormulaR1C1 = "=R[6]C" 'Exceles képlet: =K21 Range("K15").FormulaR1C1 = "=RC[6]" 'Exceles képlet: =Q15 Range("K15").FormulaR1C1 = "=R[-5]C[-2]" 'Exceles képlet: =I10 End Sub |
Az alábbi kép jobban szemlélteti az előző kód lényegét: a K15-ös cella az aktív és innen hivatkozunk négy különböző cellára (sárga színnel jelölve):
2/3. Vegyes hivatkozás:
– a hivatkozások tartalmaznak abszolút és relatív részeket
– a relatív részeknél az „R” vagy a „C” után [] (kapcsos zárójel) van
– ha a sor relatív hivatkozású, akkor az oszlop abszolút hivatkozású és fordítva:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
Sub Sample01_FormulaR1C1Property_03() 'Vegyes hivatkozás Munka3.Select 'frissíteni Range("H2:H3").ClearContents 'relatív hivatkozású sor (R[4]) , abszolút hivatkozású oszlop (C4) Range("H2").FormulaR1C1 = "=R[4]C4" 'Exceles képlet: =$D6 'abszolút hivatkozású sor (R5) , relatív hivatkozású oszlop (C[3]) Range("H3").FormulaR1C1 = "=R5C[3]" 'Exceles képlet: =K$5 End Sub |
_
II. Változók használata képletekben:
—————————————————————————————————————————————————————————-
Aranyszabály:
Konstans szöveget és a változót „&” jellel kell összefűzni.
Konstans szöveget ilyenkor “”-ek közé kell tenni.
Illusztrálva:
—————————————————————————————————————————————————————————-
1 .Formula-s hivatkozás:
– Példa #1: itt az “=AVERAGE(A1:A2)”-t rakjuk be a Keplet változóba:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
Sub Sample01_FormulaProperty_FixedSourceRange_03() Dim Keplet As String 'futtatás előtt: az A1-es és A2-es cellába írjunk be egy-egy számot 'változóval 'itt RELATÍV hivatkozás van. Ha abszolút hivatkozás kell: a "$" jeleket be kell tenni a sor/oszlopazonosítók elé, 'mint Excelben, pl.: "=AVERAGE($A$1:$A$2)" Munka2.Select 'frissíteni Range("c1").ClearContents 'alapállapot Keplet = "=AVERAGE(A1:A2)" Range("c1").Formula = Keplet 'Exceles képlet: =ÁTLAG(A1:A2) End Sub |
– Példa #2: a fentebb ismertetett „Sub Sample02_FormulaProperty_DynamicSourceRange” makró, ahol a Tart változó használtuk. Releváns sor:
1 |
Range("c1").Formula = "=AVERAGE(" & Tart.Address & ")" |
2 .FormulaR1C1-es hivatkozás:
Példa:
– megadunk egy range típusú változót (neve: Rng) és feltöltjük a hozzárendelt tartomány (itt: J1:J6) celláit FKERES képlettel
– az FKERES képlet Táblázat argumentuma dinamikus, amit szintén változóval (Szoveg néven) adunk meg
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
Sub Sample01_FormulaR1C1Property_05() Dim Rng As Range, Szoveg As String, LastRow As Long 'makrót lépésenként érdemes futtatni 'megadunk egy range típusú változót (neve: Rng) és feltöltjük a hozzárendelt tartomány(itt: J1:J6) celláit FKERES képlettel 'az FKERES képlet Táblázat argumentuma DINAMIKUS, ezért J6-os cellában is helyesen működik 'Makró lényege: '1. fix tartomány helyett az F1-es cella CurrentRegion-jét vesszük, így az F2:G11-es tartományból itt F2:G13 lesz '2. az F2:G13-as tartomány R1C1-es abszolút hivatkozása ugyebár R2C6:R13C7 '3. ebből az R2C6:R13C7-ből megkapjuk makróval az R és C utáni értékeket (2, 6, 13, 7) és tesszük be az egészet a Szoveg nevű változóba. 'Vagyis "R2C6:R13C7"-et kapunk, viszont dinamikusan: '"R" & ActiveCell.CurrentRegion.Rows(2).Row & "C" & ActiveCell.CurrentRegion.Columns(1).Column & ":R" & LastRow & "C" & ActiveCell.CurrentRegion.Columns(2).Column '4 végül az eredeti FKERES (VLOOKUP) R2C6:R13C7 részét kicseréljük a Szoveg változóra 'az 1. pont miatt lesz dinamikus az egész, vagyis ha mondjuk az 500. sorig tartana a tartomány, akkor 'az F1-es cella CurrentRegion-je ez lenne: F2:G500 Munka4.Select Set Rng = Range("J1:J6") Rng.ClearContents 'alapállapot Range("f1").Select 'ez a cella mindig a tartományon (CurrentRegion) belül legyen LastRow = ActiveCell.CurrentRegion.Cells(ActiveCell.CurrentRegion.Cells.Count).Row 'CurrentRegion utolsó sorszáma, itt: 13 'Ezt kapjuk meg és tesszük be a Szoveg változóba: "R2C6:R13C7" Szoveg = "R" & ActiveCell.CurrentRegion.Rows(2).Row & "C" & ActiveCell.CurrentRegion.Columns(1).Column & ":R" & LastRow & "C" & ActiveCell.CurrentRegion.Columns(2).Column 'előző makrónál ez volt a kód: 'Rng.FormulaR1C1 = "=VLOOKUP(RC[-1],R2C6:R11C7,2,0)" 'dinamikus kód: idézőjelek közt van minden, ami nem változó! Rng.FormulaR1C1 = "=VLOOKUP(RC[-1]," & Szoveg & ",2,0)" 'Exceles képlet a J1-es cellában: =FKERES(I1;$F$2:$G$13;2;0) End Sub |
_
III. Excel és VBA képletek alkalmazása:
1. Excel függvények meghívása VBA-ban (Excelben lévő és VBA-ban is használhatók): Application.WorksheetFunction
– a legtöbb Excelben használt képletet VBA-ban is alkalmazhatjuk, mégpedig az Application.WorksheetFunction segítségével
– ez az „Application” (vagyis itt az Excel) objektum eljárása (method)
Próbáljuk ki: VBA szerkesztőben írjuk be: Application.WorksheetFunction. -> a „.” Lenyomása után megkapjuk a súgónkat, mely függvények érhetők el:
– az alábbi kódban egy sima Szum függvényt használunk:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
Sub Formulas_Common_01() 'Exceles képletek, melyek VBA-ban is használhatók 'értéket adnak vissza Munka5.Select Range("E1").ClearContents 'alapállapot 'Range("E1").Formula = "=SUM(A1:C10)" 'Exceles cella tartalma itt: =SZUM(A1:C10) Range("E1").Value = Application.WorksheetFunction.Sum(Range("A1:C10")) 'Exceles cella tartalma: 2284 'Range("E1").Formula = Application.WorksheetFunction.Sum(Range("A1:C10")) 'Exceles cella tartalma itt is: 2284 End Sub |
– a fenti kód mindig értéket ad vissza, függetlenül attól, hogy a Range(“E1”) után „.Value”-t vagy „.Formula”-t alkalmazunk. Ha mégis képletet akarunk látni a cellában, akkor ekképp módosítsunk:
1 |
Range("E1").Formula = "=SUM(A1:C10)" |
– a cellában lévő képlet megjelenítéséről már volt szó fentebb, a kapcsoló makrók:
Sub Sample01_FormulaProperty_FixedSourceRange_01
Sub Sample01_FormulaProperty_FixedSourceRange_02
Sub Sample02_FormulaProperty_DynamicSourceRange
Sub Sample01_FormulaProperty_FixedSourceRange_03
– Application.WorksheetFunction-nel használható képleteket (methods) lásd itt.
Képletek listája az iménti linkről:
– bizonyos képleteknél az Application.WorksheetFunction-nél a WorksheetFunction elhagyható és akkor is működik, vagyis a VBA saját képletével is használható. Az előző kódnál ez így néz ki:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
Sub Formulas_Common_02() 'Exceles képletek, melyek VBA-ban is használhatók 'értéket adnak vissza 'Application.WorksheetFunction helyett csak Application Munka5.Select Range("E1").ClearContents 'alapállapot 'Range("E1").Value = Application.WorksheetFunction.Sum(Range("A1:C10")) 'Exceles cella tartalma: 2284 Range("E1").Value = Application.Sum(Range("A1:C10")) 'Exceles cella tartalma: 2284 End Sub |
Ha egy képlet VBA-ban és Excelben is elérhető: használd az utóbbit (Application.WorksheetFunction-ös változatot), mert a beépített Excel formulák gyorsabbak.
2. Excel-es függvények VBA-s változatai:
– vba kezdetűek (de a vba elhagyható) – pl.:
1 |
MsgBox VBA.LCase("HONAP") 'eredmény: honap |
vagy
1 |
MsgBox LCase("HONAP") 'eredmény: honap |
– bizonyos Excel függvényeket nem tudunk VBA-ban használni. Példának okáért ez a sor nem fog működni:
1 |
MsgBox Application.WorksheetFunction.today |
Hiába van Excelben TODAY (vagyis MA) függvény, ha a fenti kódot lefuttatjuk, hibát kapunk:
„Run-time error ’438’: Object doesn’t support this property or method”
– ebben a kivonatban látható, melyik Excel függvénynek mi a megfelelője VBA-ban (ez nem azt jelenti, hogy az alternatív képlet ugyanúgy számol vagy ugyanazt az eredményt hozza): – forrás
Nézzünk egy példát: ha az Excel előbb említett TODAY (MA) függvényét akarom VBA-ban, akkor az előbbi lista alapján a DATE-et kell alkalmaznom helyette, azaz:
1 |
MsgBox Date |
3.csak VBA-ban lévő függvények:
– itt nyilván van átfedés az előző (2.) ponttal
– vba kezdetűek (de a vba elhagyható): lásd példát a 2. pontnál
– link a teljes listához itt. A lényeg képként:
_
IV. Felhasználói függvény (UDF = User Defined Function)
Ha
– nem lenne számunkra megfelelő az Excelben elérhető csaknem 500 függvény (link) közül és/vagy
– nem tudjuk, hogy létezik egy vagy több olyan Excel függvény, mely megoldaná a problémánkat és/vagy
– van egy pöpec új függvény (pl. az O365-ben és Excel web-en elérhető XKERES), de az ügyfelek/kollégák egy része régebbi Excelen van – vagyis olyan megoldás kell, ami a korábbi verziókban is működik…
… akkor saját függvényeket is írhatunk VBA-val.
Egy-két keresetlen szó a felhasználói függvényekről:
– angoul UDF-nek (User Defined Function) hívjuk
– modulban tároljuk őket
– eljárás, mely értéket ad vissza. Vagyis olyan működő UDF-et nem tudunk írni, mely pl. a cella háttérszínét változtatja. Ez ugyanis hibára fut:
1 2 3 |
Function Cellaszin(Cella As Range, Cella2 As Range) If Cella.Value > 10 Then Cella2.Interior.Color = vbYellow '"#VALUE" hiba End Function |
– az eddig megszokott „Sub” helyett „Function”-nal kezdődik és „End Function”-nal végződik
– általában vannak bemeneti arguementumai, de nem mindig (Excelben sincs mindig argumentum, pl. a MA() függvénynél)
– önmagában nem futtatható
– VBA-ban meghívható egy másik eljárásból vagy közvetlenül használható Excelben (be kell gépelni az „=”-et és a függvény nevét, hasonlóan, mint ha Excelben mondjuk egy SZUM függvényt használnánk)
– ugyanúgy másolható a UDF-es képlet, mint a beépített Excel-es képlet
Nézzünk is pár példát:
1. Argumentum nélküli verzió, mely a Windows-os bejelentkezési felhasználónevet adja vissza
1 2 3 |
Function WindowsFelhasznaloiNev() As String WindowsFelhasznaloiNev = Environ("USERNAME") 'Windows-os bejelentkezési felhasználónevet adja vissza End Function |
Kis magyarázat:
2. Egy argumentumos változat.
2/1: annak ellenőrzése, hogy egy adott fájl létezik-e (ehhez meg kell adnunk a teljes elérési utat, mely tartalmazza a fájlnevet is):
1 2 3 4 5 6 7 8 9 |
Function FajlLetezik(FajlEleresiUt As String) As Boolean If Dir(FajlEleresiUt) = "" Then FajlLetezik = False Else FajlLetezik = True End If End Function |
Magyarázat:
2/2: cella megjegyzés kiíratás másik cellába.
Infó: Office 365-ben a korábban ismert „Megjegyzés” neve „Jegyzet, lásd a kapcsolódó posztomat itt.
Itt argumentumként objektum típusú változót (Cella) adtunk meg.
Kód:
1 2 3 |
Function CellaMegjegyzés(Cella As Range) As String CellaMegjegyzés = Cella.Comment.Text End Function |
Print screen:
3. Több argumentumos változat: kötelező + opcionális argumentum.
Számos Excel függvény tartalmaz opcionális paramétereket. Például az FKERES, ahol a „Tartományi_keresés”-t nem kötelező megadni (abból is látszik, hogy a megnevezés nem félkövérrel van írva):
Azzal viszont mindig legyünk tisztában, hogy ha az opcionálisnál nem adunk meg értéket, akkor mi fog történni/mi az alapértelmezett érték. Jelen esetben ha a „Tartományi_keresés”-t üresen hagyjuk, akkor az FKERES nem pontos, hanem közelítő egyezést hajt végre.
UDF-nél is tudunk ilyent hozzáadni. Néhány keresetlen szó az opcionális argumentumokról:
– ugyebár nem kötelező megadni a képlet beírásakor
– „Optional” kulcsszó után kell megadni a változó nevét, pl.:
1 |
Function Bla(A As Long, Optional B) |
– többet is megadhatunk, ám ezen paramétereknek mindig az utolsóknak kell lenniük a ()-ek között, pl.:
1 |
Function Bla(A As Long, Optional B, Optional C) |
– az „IsMissing” paranccsal tudjuk ellenőrizni, meg lett-e adva a nem kötelező rész
– megadható alapérték is neki, pl.:
1 |
Function Bla(A As Long, Optional B = 1) |
– deklarálásuknál lehetőleg semmilyen (akkor szintén variant lesz) vagy variant típust használjunk („IsMissing” parancs ugyanis ezeknél fog működni). Példák:
Nézzünk egy teljes példát:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
Function ArKalkulacio(Eladasi_ar As Double, Darabszam As Long, Optional Kedvezmeny) As Double Dim Van As Boolean If IsMissing(Kedvezmeny) Then Van = False Else Van = True If Van Then 'van Kedvezmeny megadva ArKalkulacio = Eladasi_ar * Darabszam * (1 - Kedvezmeny) Else 'nincs Kedvezmeny megadva ArKalkulacio = Eladasi_ar * Darabszam End If End Function |
Némi magyarázat:
Az előbbi kódban látszik, hogy az opcionális paraméter meglétét az „IsMissing” paranccsal ellenőrizzük. Ez akkor működik jól, ha az opcionális paraméter variant típusú, mint ahogy itt is, hiszen a „Kedvezmeny” után nem adtunk meg típust:
1 |
Optional Kedvezmeny |
4. UDF: hibakeresés (debugging):
A UDF ugye önmagában nem futtatható, vagyis hiába nyomkodjuk bőszen mondjuk az F8-at, nem tudjuk lépésről lépésre futtatani és megnézni mit művel vagy épp megkeresni a hiba okát. Módszerek debugging-ra/re:
4/1: MsgBox hozzáadása a UDF-hez: ugyanis az msgbox megjelenik, így ellenőrizhetjük pl. egy változó értékét -> példa:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
Function ArKalkulacio_02(Eladasi_ar As Double, Darabszam As Long, Optional Kedvezmeny) As Double Dim Van As Boolean '4/1. részhez (debugging UDF) If IsMissing(Kedvezmeny) Then Van = False Else Van = True MsgBox Kedvezmeny, , "" If Van Then 'van Kedvezmeny megadva ArKalkulacio_02 = Eladasi_ar * Darabszam * (1 - Kedvezmeny) Else 'nincs Kedvezmeny megadva ArKalkulacio_02 = Eladasi_ar * Darabszam End If End Function |
4/2: Hívjuk meg a UDF-et egy makróból (Sub procedure):
1 2 3 4 5 6 7 8 9 |
Sub UDF_meghivasa() '4/2. részhez (debugging UDF) Sheet3.Select '"UDF" lap Call ArKalkulacio_03(Range("B12").Value, Range("C12").Value, Range("D12").Value) End Sub |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
Function ArKalkulacio_03(Eladasi_ar As Double, Darabszam As Long, Optional Kedvezmeny) As Double Dim Van As Boolean '4/2. részhez (debugging UDF) If IsMissing(Kedvezmeny) Then Van = False Else Van = True If Van Then 'van Kedvezmeny megadva ArKalkulacio_03 = Eladasi_ar * Darabszam * (1 - Kedvezmeny) Else 'nincs Kedvezmeny megadva ArKalkulacio_03 = Eladasi_ar * Darabszam End If End Function |
Kezdjük el lépésenként (F8) futtatni a „Sub UDF_meghivasa” makrót. A „Call” rész után a futtatás átmegy a UDF-be, vagyis innen…
…Ide jutunk:
Innentől pedig F8-cal már végig lehet menni a kódon.
4/3: Töréspont (breakpoint) hozzáadása
Töréspont (breakpoint) hozzáadása a UDF-ben -> Excelben: szerkesztő mód (pl. F2-vel) a UDF cellájában -> Enter -> visszajutunk a VBA szerkesztőbe, ahol az adott sor ki van sárgítva -> most már F8-cal már végig lehet menni a kódon
Vagyis:
_
V. Képletek frissítése VBA-ban
Ha egy munkafüzet tele van komplex képletekkel (főleg olyanokkal, melyek indig újrakalkulálódnak) és makrót futtatunk: érdemes megfontolni a számolási beállításoknál a Manuális opciót.
Ez Excelben itt található: Képletek menü -> Számolási beállítások: 3 opcióból választhatunk
Ugyanez a 3 opció VBA-ban: Application.Calculation:
Az Application.Calculation-ben az Application magát az Excelt jelenti, vagyis ez a parancs nem egy adott tartományra/munkalapra/munkafüzetre, hanem az összes megnyitott munkafüzetre vonatkozik.
Ebből adódhatnak problémák, nézzünk is rá két példát:
1. A kalkulációs módot átállítjuk manuálisra (Excel menüből vagy VBA-ban) és nem rakjuk vissza automatikusra: a többi (megnyitott) munkafüzetben sem fogja újraszámolni a képleteket, melyből elég komoly félreértések, érték-eltérések stb. adódhatnak (kivéve, ha második harmadik stb példányt indítunk Excelben, de ebbe inkább most nem mennék bele).
2. Makróban a kód elején átállítjuk manuálisra és a végén vissza automatikusra, DE: a kód hibára fut, megáll és nem jut el addig, ahol visszaállítja automatikusra.
Ha az újraszámolást forszírozni akarjuk Excelben (összes megnyitott munkafüzetben), akkor ezt a parancsot használjuk:
1 |
Application.Calculate |
Vagy az Application el is hagyható:
1 |
Calculate |
Ezt egyébként nem csak applikáció (Excel) szintjén lehet alkalmazni, hanem munkalap (worksheet) és tartomány (range) szintjén is:
Azoknak, akik még mindig olvassák: remélem hasznos és érthető volt ez a bitangul hosszú poszt, mely a mai világban már-már felér egy kisebb epossszal 🙂
Inspiráció:
– https://www.automateexcel.com/vba/formula-formular1c1#VBA_Formula_Property
– https://www.automateexcel.com/vba/worksheet-functions-in-macro/
– https://docs.microsoft.com/en-us/office/vba/api/excel.worksheetfunction
– http://www.cpearson.com/excel/optionalargumentstoprocedures.aspx
– https://wellsr.com/vba/2020/excel/excel-vba-manual-calculation/