Løkker er lykken! 

For...Next
Do...Loop
While...Wend
Andre løkker

 

I sidste artikel omtalte jeg muligheden for at udføre kode, hvis givne betingelser var opfyldt, og anden kode, hvis de ikke var. Her skal vi se på en anden, hyppigt anvendt, kodestruktur, nemlig løkker. Løkker er simpelthen en mulighed for, at udføre en given mængde kode flere gange. Hvor mange gange afhænger af typen af løkke. Det kan fx være et bestemt antal gange. Dette håndteres med såkaldte For…Next løkker. Det er imidlertid ikke altid, det er muligt at forudsige, hvor mange gange en kode skal udføres. Så kan man i stedet anvende såkaldte Do…Loop løkker, der gennemløbes indtil en given betingelse er opfyldt/ikke er opfyldt.

Lige som tilfældet er med If og Select Case, kan også løkker indlejres, de kan kombineres indbyrdes og med If eller Select Case og med mange andre programmeringsfunktioner.

 

For…Next løkker

En For…Next løkke består af en start, en slutning og derimellem de kodelinjer, der skal udføres. Her er vist en simpel For…Next løkke.

 

    Dim i As Integer

    For i = 1 To 5

        MsgBox i

    Next

 

Løkken her, viser en meddelelsesboks, hvor der tælles op med en ad gangen, 1, 2, 3, 4, 5.

 

Som det fremgår indledes løkken med en For-sætning. Herefter følger en tællervariabel. Af gammel tradition kaldes denne ofte "i" uden nogen form for prefix, og uden at navnet er sigende for hvad, det er der tælles. Sådan skrev man allerede, da jeg lærte at programmere tilbage i slutningen af 1970'erne, og heller ikke dengang, var der nogen, der vidste hvorfor. Imidlertid kan man kalde tælleren præcis, hvad man vil, også noget sigende.

 

Vi fortæller nu, vor langt tælleren skal tælle, og derefter følger så koden, der skal udføres. For…Next løkken afsluttes med en Next-sætning. Her kan man skrive Next som i eksemplet, men man kan også skrive "Next Variabelnavn", i dette tilfælde Next i.

 

Det er altid muligt at forlade en For…Next løkke undervejs gennem udførelsen ved hjælp af en Exit For-sætning. Denne vil typisk bliver parret med noget betinget logik, fx

 

    For i = 1 To 5

        If MsgBox("Du er nu nået til " & i _

           & " Ønsker du at fortsætte?", vbYesNo + vbQuestion) = vbNo Then

           Exit For

        End If

    Next

 

Her er der mulighed for at vælge Ja eller Nej i meddelelsesboksen. Klikkes der Ja, fortsættes afspilningen, klikkes der Nej, afsluttes løkken. Efter en Exit For fortsætter koden med den første linje efter løkken. Hele koden kunne se sådan ud.

 

Sub Løkke()

    For i = 1 To 5

        If MsgBox("Du er nu nået til " & i _

           & " Ønsker du at fortsætte?", vbYesNo + vbQuestion) = vbNo Then

           Exit For

        End If

    Next

    MsgBox "Du har fuldført eller afsluttet løkken"

End Sub

 

Tælleren er det vigtigste ved For…Next løkker. I Do…Loop som vi skal se på senere, må man selv definere eventuelle tællere, og det kan medføre problemer, hvis man ikke er opmærksom. De problemer undgår man i For…Next løkker. I de fleste løkker tæller tælleren op med én ad gangen, men det er ikke altid nok. Det er derfor muligt at bestemme, hvor meget der skal tælles op ad gangen. Dette gøres ved at tilføje et Step ord til For sætningen. Jeg vender lige tilbage til det første eksempel:

 

    Dim i As Integer

    For i = 0 To 10 Step 2

        MsgBox i

    Next

 

Her tæller løkken op fra 0 til 10 med to ad gangen, altså 0, 2, 4, 6, 8, 10. Det er også muligt at tælle ned. I så fald skal tællerens øvre grænse skrives først, og Step-værdien skal være negativ, fx

 

    Dim i As Integer

    For i = 15 To 0 Step -3

        MsgBox i

    Next

 

Hvis tælleren ikke rammer præcis på den ønskede grænse, afslutttes loopet, ved den sidste tæller inden grænsen nås. Fx vil ovenstående kode vise en meddelelsesboks med 3 som sidste indhold, hvis For-sætningen i stedet var

 

    For i = 15 To 2 Step -3

 

Som jeg omtalte i indledningen kan For…Next løkker også indlejres. Dette kræver at der skal bruges to forskellige tæller-variabler.

 

Dim i As Integer

Dim h As Integer

 

For i = 1 To 3

    For h = 1 To 3

        MsgBox "Den ydre løkke er i sit " & i _

            & ". gennemløb. Den indre i sit " & h _

            & ".", vbOKOnly + vbInformation

    Next h

Next i

 

Her gennemløbes den første løkke 3 gange. For hvert gennemløb, gennemløbes den indre løkke ligeledes tre gange. Det vil sige, at i den ovenstående kode vises meddelelsesboksen i alt 9 gange.

 

For…Next løkker kræver altså at koden ved hvor mange gange den skal gennemløbes. Det er ikke nødvendigvis det samme, som at programmøren også skal vide det, når han koder. Grænserne for tælleren kan sættes andre steder i koden. Fx

 

    Dim i As Integer

    Dim Antal As Integer

 

    Antal = InputBox("Hvor mange gange skal løkken køre?")

 

    For i = 1 To Antal

        MsgBox i

    Next

 

Og lige til sidst et praktisk eksempel på anvendelse af en For…Next løkke. Eksemplet findes også under småmakroer. Nedenstående er en funktion, der beregner tværsummen af et tal i en celle. Den udnytter to af de indbyggede funktioner, jeg nævnte i artiklen om Betinget Logik, nemlig Mid() og Len() foruden en ny funktion, CByte(). De to første er begge forklaret i ovenstående artikel. Disse to er såkaldte streng operatorer. CByte konverterer en værdi til et tal af datatypen Byte. Denne og mange andre indbyggede funktioner, vil jeg gennemgå yderligere i en senere artikel.

 

Function TSUM(ce As String) As Long

    Dim cif As Long

    For i = 1 To Len(ce)

        cif = cif + CByte(Mid(ce, i, 1))

    Next

    TSUM = cif

End Function

 

Funktionen modtager en celleværdi som input. Denne skal bestå af tal, men modtages som String. Derefter gennemløbes en løkke, fra 1 (første ciffer) til Len(ce), længden på tallet eller sidste ciffer. Antallet af gennemløb styres altså heraf tallets længde. For hvert gennemløb tildeles variablen cif værdien af det, den allerede er tillagt værdien af det næste ciffer. Til sidst er alle cifrene lagt sammen og vi har tværsummen.

 

- Til top -

Do…Loop løkker

For…Next løkker er nemme at håndtere. Do…Loop-løkker er noget besværlige, men til gengæld har de ikke den samme begrænsning om, at man skal kende antallet af gennemløb. Do…Loop løkker gennemløbes så længe, eller indtil en given betingelse er opfyldt. De omtales derfor også ofte som "betingede løkker". Af og til er betingelsen, at en tæller når en bestemt værdi, men da Do…Loop ikke har en tællefunktion, må man i givet fald konstruere den selv.

 

Risikoen ved Do…Loop er, at betingelsen, der styrer afslutningen af løkken, aldrig bliver opfyldt. I givet fald har vi en såkaldt "uendelig løkke", altså en løkke, der bliver ved med at køre i det uendelige. En uendelig løkke illustreres bedst med det gamle "leksikon opslag":

 

Uendelig løkke, se under Uendelig løkke.

 

Et eksempel på en uendelig løkke kunne være

 

Do Until i = 10

    a = a + 1

Loop

MsgBox a

 

Løkken køres igennem indtil tælleren i bliver 10. For hvert gennemløb opdateres en anden tæller, og når løkken er færdig vises resultatet af denne anden tæller i en meddelelsesboks. Problemet opstår fordi tælleren aldrig bliver 10. I Do…Loop opdateres en tæller ikke automatisk, og det betyder i dette tilfælde at i aldrig får en ny værdi, når løkken gennemkøres. En sådan uendelig løkke må afbrydes ved at trykke Ctrl+Break på tastaturet. Skal løkken virke rigtigt må man selv opdatere tælleren:

 

Do Until i = 10

    a = a + 1

    i = i + 1

Loop

MsgBox a

 

Af og til, er det nødvendigt at initialisere tælleren, altså at give den en startværdi. Det er vigtigt at dette sker inden løkken starter. Af til får man placeret initialiseringen inden for løkken, og så bliver denne også uendelig, fordi tælleren "resettes" for hvert gennemløb.

 

Do Until i = 10

    i = 2

    a = a + 1

    i = i + 1

Loop

MsgBox a

 

Rigtigt havde været

 

i = 2

Do Until i = 10

    a = a + 1

    i = i + 1

Loop

MsgBox a

 

Men nu til de forskellige former for Do…Loop løkker.

 

Der forekommer to typer af Do...Loop, nemlig Do While og Do Until. Som navnene antyder er forskellen, at den ene vil gennemløbe løkken så længe en betingelse er opfyldt, den anden vil gennemløbe løkken indtil betingelsen er opfyldt.

 

    Dim Tal As Byte

    Tal = 1

   

    Do Until Tal = 4

        MsgBox Tal

        Tal = Tal + 1

    Loop

 

Denne løkke køres igen indtil betingelsen Tal = 4 er opfyldt. Hvis man afprøver koden vil man se, at det sidste tal, der vises i meddelelsesboksen er 3. Dette skyldes testen for, hvilken værdi "Tal" har udføres inden løkken gennemløbes og næste gang løkken skal gennemløbes er "Tal" 4, og så udføres løkken ikke. Skulle den have vist fire også, kunne vi i stedet for "=" have brugt ">". Så ville løkken først være blevet afbrudt, når Tal blev 5 og 4 ville blive vist i meddelelsesboksen.

 

Havde vi i stedet brugt en Do While løkke, kunne den have set således ud

 

    Do While Tal < 4

        MsgBox Tal

        Tal = Tal + 1

    Loop

 

Her køres løkken igennem, så længe Tal er mindre end 4. Det største tal, der vises er 3. Ville vi have vist 4-tallet også, skulle vi have sagt

 

    Do While Tal < 5

 

Løkken udføres kun til det øjeblik, betingelsen ikke længere er opfyldt.

 

Forestil dig et øjeblik denne løkke:

 

    Tal = 4

    Do While Tal < 4

        MsgBox Tal

        Tal = Tal + 1

    Loop

 

Den vil aldrig blive udført, da Tal jo allerede er 4. Ønsker man, at en løkke skal gennemløbes mindst én gang, uanset om betingelsen er opfyldt, kan man flytte betingelsen ned i slutningen af løkken

 

    Tal = 4

    Do

        MsgBox Tal

        Tal = Tal + 1

    Loop While Tal < 4

 

Så testes der først efter at løkken er kørt igennem første gang. Denne metode kan bruges både sammen med While og Until løkker.

 

Do-Løkker kan naturligvis kombineres med andre funktioner, så som fx betinget logik. Dette kan være interessant, hvis man skal teste på et bestemt svar i en inputboks, og genvise denne indtil svaret er korrekt:

 

Sub Inddata()

 

    Dim varValid As Variant

    varValid = InputBox("Indtast et tal mellem 1 og 10")

   

    If varValid = "" Then Exit Sub

 

    Do Until IsNumeric(varValid) And varValid >= 1 And varValid <= 10

        varValid = InputBox("Indtast et tal mellem 1 og 10")

        If varValid = "" Then Exit Sub

    Loop

   

    MsgBox varValid & " er godkendt", vbOKOnly + vbInformation

 

End Sub

 

Koden her anmoder om indtastning af et tal mellem 1 og 10. Det indtastede anbringes i en variabel af typen variant. Dette skyldes, at hvis variablen erklæres som tal, vil koden fejle, hvis der tastes en tekst. Først testes på, om der klikkes Annuller. I så fald forlades proceduren. Derefter køres en løkke, der bliver ved med at vise inputboksen indtil den indtastede værdi er et tal mellem 1 og 10 eller der klikkes på Annuller. Bemærk at sætningen

 

If varValid = "" Then Exit Sub

 

gentages inde i løkken. Det skyldes, at ellers vil inputboksen også blive genvist, selv om man klikker på Annuller, efter at være kommet ind i løkken.

 

Også Do…Loop kan forlades "i utide" under anvendelse af Exit Do, fx hvis en bestemt betingelse er opfyldt/ikke er opfyldt. Ved Exit Do genoptages koden i første linje efter løkken.

 

- Til top -

 

While…Wend løkker

Den sidste form for løkker, som jeg vil nævne i denne omgang er de såkaldte While…Wend løkker. Det er en slags reduceret Do While løkke, og mange programmører betragter den som værende "gammeldags". Den kan dog være nem, og forholdsvis overskuelig at gå til.

 

Se fx denne kode:

 

Sub WhileWend()

    Dim intTaeller As Integer

    intTaeller = 1

 

    While intTaeller < 10

        MsgBox intTaeller

        intTaeller = intTaeller + 1

    Wend

 

End Sub

 

Vær opmærksom på, at While…Wend løkker ikke kan forlades i utide. Der er ingen Exit While kommando.

 

- Til top -

Andre løkker

Der findes endnu en type løkker, nemlig de såkaldte For…Each…Next løkker. De hænger sammen med VBA's håndtering af objekter, og er derfor måske i virkeligheden de mest anvendte løkker overhovedet. Disse vil jeg beskrive nærmere i den næste artikel, som netop kommer til at handle om objekter.

 

- Til top -

- Tilbage til Programmering -
- Tilbage til makroer -
- Tilbage til Excel -