|
Løkker er lykken!
For...Next
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økkerEn 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.
Do…Loop løkkerFor…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.
While…Wend løkkerDen 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.
Andre løkkerDer 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.
- Tilbage til Programmering -
|