Variabler, konstanter og argumenter og andre begreber

Moduler
Variabler
Statiske variabler
Tabel- eller arrayvariabler
Navngivning
Konstanter
Rækkevidde
Argumenter

Moduler
Al kode i Excel skal "gemmes" et sted. Det sker i såkaldte moduler. Disse moduler ligger inde i Excel projektmapperne. For at en makro skal kunne afspilles, skal den projektmappe, som indeholder modulet med koden, være åben. I modsat fald kan Excel ikke finde makroen.

Kode kan altså ligge i den projektmappe, hvor koden skal anvendes, men kan også ligge i en anden projektmappe, bare denne er åben, når makroen skal bruges. Skal en kode kun anvendes i en enkelt projektmappe, er det bedst at gemme koden i et modul i denne projektmappe, skal den kunne anvendes bredt, kan man gemme den andre steder. Noget kode skal ligge i helt bestemte moduler for at virke; det vender jeg tilbage til senere. Skal koden bruges på flere forskellige pcer, kan den med fordel lægges i et såkaldt "tilføjelsesprogram"; også dette vender jeg til i en senere artikel. De eksempler vi har arbejdet med indtil videre, og også skal se på i de kommende artikler, er primært beregnet på at skulle anvendes i en bestemt projektmappe, og derfor gemmer vi koden i et modul i denne.

For at åbne et modul, skal du have en projektmappe åben. Nu kan du så  vælge Funktioner - Makroer - Visual Basic Editor. Så åbnes editoren. Indsæt et modul ved at vælger Insert - Module. Husk at vælge Module, ikke Class Module, som ligner et almindeligt modul, men bruges til noget andet. Alternativt kan du bare trykke Alt+F11, mens du står i et regneark. Indspiller du en makro i "Denne projektmappe" oprettes modulet automatisk.

- Til top -

Variabler
Når man programmerer i VBA, har de procedurer man arbejder med, ofte brug for at gemme informationer i kortere eller længere tid. Til at gemme sådanne informationer, kan man anvende såkaldte variabler - eller hvis informationen ikke skal ændres, konstanter. Variabler har altså en værdi, som kan ændres under udførelse af koden.

Sub Variabler()
    a = 3
    b = 4
    MsgBox a * b
End Sub

I denne kode er a og b variabler. Msgbox'en viser resultatet af de to variabler ganget med hinanden. For at det skal virke, skal a og b tildeles en værdi, og det gøres i linjerne a = 3 og b = 4. Tildeles variablerne ingen værdi, vil makroen fejle.

Imidlertid er ovenstående ikke en god måde at bruge variabler på. Vi fortæller ikke VBA noget om, hvad variablerne skal bruges til/hvad de skal indeholde. Det betyder, at Excel selv bestemmer, og det giver typisk et spild af god arbejdshukommelse. I stedet bør man "erklære" sine variable. Dette gøres med en såkaldt Dim-sætning. Ved hjælp af denne kan man fortælle, hvad der skal kunne gemmes i en given variabel.

Sub NyVariabel()
    Dim a As Byte
    Dim B As Byte

    a = 3
    B = 4
    MsgBox a * B
End Sub

I denne sub fortæller vi VBA at variablerne a og b, hver må indeholde talværdier, der kan repræsenteres af én byte information. Det betyder i praksis at variablerne kan indeholde hele tal mellem 0 og 255, og det er nok i dette tilfælde. Skal en variabel indeholde større tal, tal med decimaler, tekster osv., vælger man i stedet andre datatyper (som det kaldes). Se her for en oversigt over de datatyper, der kan anvendes i VBA, og hvilke definitioner, der gælder for de enkelte typer.

Husk, at det gælder om, at vælge datatyper, der er så små som muligt, men store nok til at indeholde det, de skal bruges til. Se nærmere på denne kode, som gør det samme som ovenstående, blot anbringes resultatet i en ny variabel, inden det vises i meddelelsesboksen:

Sub NyVariabel()
    Dim a As Byte
    Dim b As Byte
    Dim Resultat As Byte

    a = 3
    b = 4

    Resultat = a * b
    MsgBox a * b
End Sub

Koden vil virke upåklageligt indtil resultatet af regnestykket bliver større end 255. Så kan dette nemlig ikke rummes i en byte og man vil få en "overflow" fejl.

Sub NyVariabel()
    Dim a As Byte
    Dim b As Byte
    Dim Resultat As Byte

    a = 30
    b = 40

    Resultat = a * b
    MsgBox a * b
End Sub

ville således ikke kunne lade sig gøre, da 30 * 40 = 1200. I stedet kunne man vælge at erklære Resultat som Heltal med erklæringen

Dim Resultat as Integer

men dette er heller ikke nok på grund af den måde VBA regner på. Mindst én af de to andre variabler, skal også være stor nok til et rumme resultatet. En rigtig variabelerklæring kunne derfor se således ud:

Dim a As Long
Dim b As Byte
Dim Resultat As Long

Ved at erklære sine variabler på forhånd, reserverer man på forhånd plads i hukommelsen, og VBA sørger så for, at der holdes kontrol med, om variablens datatype er overholdt. Erklærer man ikke sine variabler selv, tildeler VBA dem automatisk datatypen Variant, og den er temmelig hukommelseskrævende. Det samme gælder, hvis man erklærer sine variabler uden datatype, altså fx

Dim Resultat

Variant-datatypen kan indeholde stort set alting. Derfor afsættes der temmelig meget plads til denne datatype. Man kan selverklære variabler som Variant, men det gør man normalt kun, hvis man ikke på forhånd ved, hvad variablen kan komme til at indeholde.

Det er muligt at erklære flere variabler på samme linje, fx:

Dim a As Byte, b As Byte, Resultat As Byte

er således OK. Derimod er erklæringer af typen:

Dim a, b, Resultat As Byte

som man ofte ser, ikke OK, da det faktisk kun er den sidste variabel på linjen, der tildeles en datatype. Datatypen skal altså specificeres for hver enkelt variabel for sig. Hvis du vil være sikker på ikke at glemme at erklære dine variabler, kan du skrive sætningen

Option Explicit

i begyndelsen af dine moduler. Det vil betyde, at variabler kun kan bruges, hvis de er erklæret på forhånd. I modsat fald vil VBA give fejl.

- Til top -

Statiske variabler
En lokal variabel "beholder" sin værdi så længe koden kører. Når proceduren er overstået, vender variablen tilbage til sit udgangspunkt så at sige.

Se på følgende kode:

Sub NyVariabel()
    Dim Taeller As Integer
    Taeller = Taeller + 1
    MsgBox Taeller
End Sub

Den giver resultatet 1 i en meddelelsesboks, og det bliver den ved med, hver gang proceduren afspilles. Imidlertid har man af og til brug for at en variabel beholder (husker) sin værdi indtil næste gang koden afspilles. Det kan gøres ved at ændre erklæringen af variablen, så koden ser ud som følger:

Sub NyVariabel()
    Static Taeller As Integer
    Taeller = Taeller + 1
    MsgBox Taeller
End Sub

Udtrykket Static i stedet for Dim betyder. at vi har nu erklæret variablen som statisk og det betyder igen netop, at den husker den sidste værdi, den havde, når proceduren afspilles igen  indtil programmet afsluttes, fx ved at lukke projektmappen. I ovenstående tilfælde vil meddelelsesboksen kontinuert tælle op, hver gang koden afspilles.

- Til top -

Tabel- eller arrayvariabler
En datatabel eller et array er i virkeligheden et antal variabler med samme datatype som har et fælles navn. Man skelner så mellem de enkelte variabler (elementer i tabellen) med et tal, et såkaldt indekstal. Erklærer man fx en variabel:

Dim Varer(4) As String

har man oprettet en datatabel som kan indeholde 5 varenavne (5 fordi det første indekstal normalt er 0 med mindre man selv specifcerer noget andet i koden). Man kan nu tildele værdi til et enkelt element i tabellen ved fx at skrive

Varer(0) = "Stålsøm"

Datatabeller kan defineres i flere dimensioner

Dim Varer(2, 2) As String

betyder at datatabellen erklæres med  "rækker" og tre "kolonner". Endelig kan en datatabel erklæres uden størrelse,

Dim Varer() As String.

Så kan koden senere selv sætte størrelsen gennem en såkaldt ReDim, fx

ReDim Varer(5).

Denne sætning kan så gentages efter behov.

ReDim Varer (8)

ændrer størrelsen på datatabellen, men samtidigt "sletter" den de informationer, der allerede er gemt i den. Det kan man så løse ved i stedet at skrive

ReDim Preserve Varer(8)

Så bevares indholdet, der allerede er gemt i datatabellen.

NB! Værdier i datatabeller tildeles ofte gennem såkaldte programløkker. Dette beskrives nærmere i en kommende artikel.

- Til top -

Navngivning
For at gøre det nemmere at se, om jeg bruger mine variabelnavne korrekt, plejer jeg at anføre dem med et stort bogstav, fx "Resultat" i stedet for "resultat". Det har den fordel, at man kan skrive dem med småt, når man skriver sin kode. Excel sørger så for, selv at rette til stort, hvis variabelnavnet findes. På den måde kan man sikre at man ikke kommer til at bruger variabler, der ikke er erklærede.

Variabelnavne skal begynde med et bogstav og kan indeholde bogstaver, tal og enkelte specialtegn. Der er dog mange specialtegn, der IKKE kan anvendes, så i stedet for at huske, hvilke der kan, og hvilke der ikke kan, er det nemmere helt at undgå dem. En undtagelse kan dog være underscore (understregning), der kan bruges i stedet for mellemrum, som ikke er tilladte. Et navn kan være op til 255 tegn langt. Lyder dette bekendt? Så er det nok fordi, det er de samme regler som gælder for navngivning af rutiner (procedurer), se fx her.

Nogle bruger at sætte et prefix (en forstavelse) foran variabelnavne, der så fortæller, hvilken datatype  variablen er erklæret med, fx bytResultat for at fortælle at variablen har datatypen byte. Det kan gøre det nemmere for andre senere at skulle overtage vedligeholdelse og videreudvikling af koden. Der er flere navngivningsstandarder, man kan vælge mellem, eller man kan udvikle sin egen. Hvad man skriver er ikke så vigtigt, bare man er konsekvent. I linket til oversigten over datatyper, kan du også se, hvad jeg plejer at bruge som prefix til forskellige datatyper. Nogle programmører sætter også enten yderligere et prefix eller et suffix (endelse) på deres navne, for at vise, variablernes rækkevidde, se nedenfor.

Det er også en rigtig god idé at give sine variable sigende navne. fx bytFoersteTal og bytAndetTal i stedet for bare a og b. På den måde gør man klart for andre læsere af koden, hvad det er variablerne bør indeholde. Det er noget nemmere at læse og forstå

strNavn = strFornavn & " " & strEfternavn

end det er at forstå, hvad der sker i

a = b & " " & c

NB! &-tegnet sammenkæder tekststrenge.

På den anden side skal man også passe på, at de navne man anvender ikke bliver for lange, for så bliver de besværlige sig at skrive, når man skal bruge dem i sin kode. Fx er

strNavnPaaMinFaetterPaaMorsSidesAeldsteSoensHustru

ikke særligt praktisk, hvis det skal skriver 50 gange i et program. Så også her gælder det om at kende begrænsningens kunst. Navngivning gælder såvel for variabler som konstanter og argumenter.

- Til top -

Konstanter
Konstanter har samme funktion som variabler, nemlig at fungere som "opbevaringssteder" for data. I modsætning til variabler ændres konstanters værdi imidlertid ikke, når koden udføres, men bevarer som navnet antyder sin værdi. Variabler har derimod en værdi, som kan ændres under udførelse af koden:

intResultat = intResultat + 1

I dette eksempel ændres indholdet af intResultat, når koden afvikles. Det kan en konstant ikke. Her erklæres konstanten, og samtidigt tildeles den en værdi. For at erklære en konstant anvendes udtrykket Const, fx

Const sngMomssats as Single = 0.25

Hvorfor nu have besværet med at erklære konstanter, hvis de alligevel ikke kan ændres? Igebn er svaret, at det grø det meget nemmere at læse og forstå koden. Og i øvrigt også at rette i den. Forestil dig en kode, hvor du 50 gange undervejs skal gange noget med 0,25, fx

Moms1 = sngKoebsPris1 * 0.25
Moms2 = sngKoebspris2 * 0.25
osv.

For det første er nemmere at forstå

Moms1 = sngKoebspris1 * sngMomssats

end ovenstående, og for det andet skal vi nu kun rette momssatsen et enkelt sted i koden, nemlig der hvor konstanten erklæres uanset hvor mange steder den anvendes, og dermed overser vi ingen af dem.

NB! Vær opmærksom på at decimaltegnet altid er punktum (.) i forbindelse med VBA programmering.

- Til top -

Rækkevidde
Alle variabler såvel som konstanter har en såkaldt rækkevidde (scope) på engelsk. Rækkevidden fortæller noget om, hvor variablerne/konstanterne kan anvendes. Dette hænger så igen sammen med, hvordan erklæringerne sker.

Såfremt en variabel erklæres inde i en rutine, som i de ovenstående eksempler, fx

Sub Variabler()
    Dim sngResultat As Single

kan den pågældende variabel kun ses af den pågældende rutine/procedure. Sådanne variable kaldes "lokale variable". En anden procedure vil ikke kende disse, og kan derfor ikke anvende dem.

Man kan imidlertid erklære sine variabler i begyndelsen af hvert modul, i den såkaldte "General" sektion af modulet (General er den del, der kommer før den første procedure. Har man erklæret variabler her, adskilles sektionen fra proceduresektioner ved hjælp af en vandret streg.

Variabler og konstanter, der erklæres i den generelle sektion kendes af, og kan anvendes af alle procedurer, der befinder sig i samme modul. Sådanne variabler kaldes "modulvariable".

Endlig kan man definere såkaldte "globale variable", også kaldet  Public variable. Disse variable kan anvendes af alle procedurer i et givent program, uanset hvilket modul,  de befinder sig i. Det betyder, at de er fleksible, men betyder også at de indlæses, når programmet indlæses og optager hukommelsesplads indtil programmet er helt færdigt og afsluttes - uanset om variablerne anvendes eller ej. Globale variable og konstanter erklæres også i den generelle sektion, men i stedet for ordet Dim anvendes Public, fx:

Public sngVarepris As Single
Public Const Brugernavn as String = "Jan Kronsell"

Argumenter
Argumenter er også en slags variabler, men i modsætning til andre variabler sættes de ikke undervejs. Til gengæld overføres de til proceduren, når denne kaldes. Argumenter anvendes oftest i forbindelse med funktionsprocedurer, man kan også anvendes i forbindelse med Subrutiner (makroer).

Argumenter erklæres ikke på samme måde som andre variabler, men erklæres ved at angive deres navn i forbindelse med den parentes, der står efter procedurenavnet. Fra den almindelige brug af Excel, kender du fx funktionen SUM(), som fx kan se ud som følger =SUM(A1:A5). A1:A5 er værdien af et argument, som er defineret for funktionen.

Ser vi på denne funktion

Function Engelsk(cel As Range)
    Engelsk = Range(cel.Address).Formula
End Function

er "cel" et argument for funktionen Engelsk(). Når funktionen bruges kan den fx kaldes med =Engelsk(A1), og vil returnere den engelske version af den formel, der står i celle A1. Også selve funktionen kan erklæres med en datatype, fx

Function Engelsk(cel As Range) As String
    Engelsk = Range(cel.Address).Formula
End Function

På den måde bliver den "sidste" variabel, der har navn som funktionen erklæret med funktionens datatype. En funktion kan have adskillige argumenter, der erklæres hver for sig.

Function DelNavn(Cel As String, del As Byte) As String

har to argumenter. Cel, der er er en tekststreng, og Del som er en Byte. Hele funktionen er erklæret som en tekststreng. Argumenter kan være obligatoriske eller valgfri. Det kender man fx fra den indbyggede funktion YDELSE(), hvor de to sidste argumenter er valgfri. Valgfri argumenter skal ALTID stå til sidst. De defineres med ordet Optional, fx

Function Salgspris(Pris As Long, Fortjeneste As Single, Optional Momssats As Single) As Double

Udfyldes et valgfrit argument ikke, bør koden "vide, hvad den skal gøre". Der bør altså lægges et check ind, der undersøger om det valgfri argument er udfyldt eller ej, og så gør noget forskelligt, afhængig af om argumentet er udfyldt eller ej.

Det kan fx gøres sådan

Function Salgspris(Pris As Long, Fortjeneste As Single, Optional Momssats As Variant) As Double
    If IsMissing(Momssats) Then
        Momssats = 0.25
    End If
    Salgspris = Pris + Pris * (Fortjeneste / 100)
    Salgspris = Salgspris * (1 + Momssats)
End Function

Læg mærke til, at jeg undtagelsesvis har defineret et argument som Variant, selv om jeg ved, at den kun vil kunne komme til at indeholde tal. Det skyldes at alle taldatatyperne automatisk tildeles værdien 0, hvis de ikke tildeles en anden værdi. Havde jeg erklæret Momssats som fx Single (for at give plads til decimalerne), ville den ikke blive "missing" selv om jeg ikke udfyldte den, da den i så fald ville have værdien 0.

- Til top -
- Tilbage til Programmering -
- Tilbage til makroer -
- Tilbage til Excel -