Notice: This page requires JavaScript to function properly.
Please enable JavaScript in your browser settings or update your browser.
Lære Løkker | VBA-Grundlæggende
Excel VBA til Forretningsautomatisering

Løkker

Stryg for at vise menuen

Alle teknikker hidtil har arbejdet med én værdi ad gangen. Løkker er måden, hvorpå du anvender den samme logik på mange værdier i træk — fem produkter, fem hundrede ordrer, eller hvor mange rækker en tabel nu end måtte indeholde — uden at skulle kopiere og indsætte den samme kodeblok igen og igen.

For...Next

Gentager en kodeblok et fast, kendt antal gange:

Dim i As Long
For i = 1 To 5
    Debug.Print "Row " & i
Next i
 
' Step lets you skip or count backward
For i = 10 To 1 Step -1
    Debug.Print i
Next i

I den første løkke starter i ved 1, koden indeni kører én gang med den værdi, derefter øges i automatisk med 1, og hele blokken kører igen — dette gentages, indtil i overstiger 5, hvorefter løkken stopper, og eksekveringen fortsætter efter Next. Step ændrer inkrementet: Step -1 tæller nedad i stedet for standarden, som er opad med 1, og Step 2 ville tælle med to ad gangen. Løkkevariablen i er ikke speciel syntaks — det er blot en almindelig Long-variabel, som VBA opdaterer for dig hver gang løkken kører.

For Each

Går direkte igennem hvert element i en samling, uden at du behøver vide, hvor mange elementer der er, eller selv styre en tæller:

Dim cell As Range
For Each cell In ThisWorkbook.Worksheets("Products").Range("B2:B6")
    Debug.Print cell.Value
Next cell

Her får cell hver enkelt celle i området B2:B6 efter tur, og du læser indholdet med .Value. Sammenlign dette med For...Next: med For...Next tæller du gennem tal og bruger det tal til at slå noget op; med For Each går du direkte gennem elementerne selv, hvilket ofte læses mere naturligt, når du arbejder med regnearksområder.

Do While

Gentager så længe en betingelse forbliver True — løkken ved ikke på forhånd, hvor mange gange den vil køre, hvilket adskiller sig fra For...Next:

Dim stock As Integer
stock = 134
Do While stock > 0
    stock = stock - 30    ' simulate selling in batches of 30
Loop
Debug.Print stock   ' whatever's left after the loop stops

VBA tjekker stock > 0 før hvert eneste gennemløb af løkken, også første gang. Følg det manuelt: 134 → 104 → 74 → 44 → 14, og så tjekkes betingelsen igen — 14 er stadig større end 0, så løkken kører én gang mere og lander på -16. Først da bliver stock > 0 falsk, og løkken stopper med stock på -16, ikke pænt på 0 eller 14. Dette er værd at gennemgå nøje første gang, da det ofte fører til off-by-one-fejl: en Do While-løkke fortsætter, så længe betingelsen holder i det øjeblik, den tjekkes, selv hvis handlingen indeni løkken går forbi den grænse, du havde tænkt dig.

Do Until

Der findes også Do Until, som er spejlbilledet af Do While — den gentager, mens en betingelse er False, og stopper i det øjeblik, betingelsen bliver True, i stedet for omvendt. Hvilken der læses mest naturligt, afhænger af, hvordan du ville formulere forretningsreglen mundtligt: "fortsæt mens der er lager" antyder Do While; "fortsæt indtil lageret er opbrugt" antyder Do Until — de kan give identisk adfærd, blot formuleret fra hver sin retning.

Exit Statements

Lader dig bryde ud af en løkke før dens naturlige slutbetingelse er nået:

For i = 1 To 100
    If i = 10 Then Exit For   ' stop the loop immediately
    Debug.Print i
Next i

Denne løkke er sat op til at tælle hele vejen til 100, men i det øjeblik i når 10, stopper Exit For den — intet efter Exit For køres, og eksekveringen hopper direkte til linjen efter Next i. Dette mønster bruges til at søge gennem en liste og stoppe, så snart du har fundet det, du leder efter, i stedet for unødigt at fortsætte gennem alle resterende elementer.

Samlet anvendelse

Alle teknikker fra dette kapitel — variabler, operatorer, funktioner, betinget logik og nu løkker — kombineres i proceduren, som dette kapitel har bygget op til:

Option Explicit
 
Sub CheckStockLevels()
 
    ' Sample data standing in for the Products table
    Dim products(1 To 5) As String
    Dim stockLevels(1 To 5) As Integer
    Dim reorderLevels(1 To 5) As Integer
    Dim i As Long
    Dim alertMessage As String
 
    products(1) = "Laptop Stand": stockLevels(1) = 58: reorderLevels(1) = 20
    products(2) = "Wireless Mouse": stockLevels(2) = 134: reorderLevels(2) = 30
    products(3) = "USB-C Hub": stockLevels(3) = 44: reorderLevels(3) = 15
    products(4) = "Monitor Arm": stockLevels(4) = 18: reorderLevels(4) = 10
    products(5) = "Keyboard": stockLevels(5) = 61: reorderLevels(5) = 20
 
    alertMessage = ""
 
    For i = 1 To 5
        Select Case stockLevels(i)
            Case Is <= reorderLevels(i)
                alertMessage = alertMessage & products(i) & _
                    " — REORDER NOW" & vbNewLine
            Case Is <= reorderLevels(i) + 10
                alertMessage = alertMessage & products(i) & _
                    " — watch closely" & vbNewLine
        End Select
    Next i
 
    If alertMessage = "" Then
        MsgBox "All products are adequately stocked."
    Else
        MsgBox "Stock Alerts:" & vbNewLine & alertMessage
    End If
End Sub
Gennemgang linje for linje
expand arrow
  • Dim products(1 To 5) As String og de to tilsvarende linjer nedenunder erklærer arrays — hver især en nummereret række af fem bokse i stedet for én boks, så products(1) er navnet på det første produkt, products(2) det andet osv.;
  • De fem linjer med kolon (:) mellem sætninger samler flere tildelinger på én linje udelukkende for læsbarhed — products(1) = "Laptop Stand": stockLevels(1) = 58: reorderLevels(1) = 20 svarer præcis til at skrive dem som tre separate linjer;
  • For i = 1 To 5 ... Next i går igennem alle fem produkter ét ad gangen, hvor i bruges både som løkketæller og som indeks i hvert array;
  • Select Case stockLevels(i) gentager den samme intervalbaserede beslutning fra afsnit 2.4, men nu mod rigtige arraydata i stedet for et enkelt hårdkodet tal;
  • Case Is <= reorderLevels(i) fanger ethvert produkt, hvis lager er faldet til eller under dets egen genbestillingsniveau — bemærk, at reorderLevels(i) selv er en variabel, ikke et fast tal, så hvert produkt vurderes mod sin egen grænse i stedet for én fælles grænse;
  • alertMessage = alertMessage & ... & vbNewLine opbygger en voksende tekststreng én linje ad gangen — vbNewLine er en indbygget konstant, der indsætter et linjeskift, så hvert markeret produkt vises på sin egen linje i den endelige besked;
  • Den afsluttende If alertMessage = "" Then-kontrol afgør, hvilken af de to MsgBox-varianter brugeren faktisk ser — en tom streng betyder, at løkken aldrig fandt noget, der skulle markeres.

Kør dette, og du bør se Monitor Arm markeret som "watch closely" (18 enheder mod et genbestillingsniveau på 10) — gennemgå løkken manuelt for i = 4, hvis du vil bekræfte præcis, hvorfor det kun er denne, der fanges af det andet Case og ikke det første. Denne procedure bruger arrays, en løkke, en Select Case og strengopbygning, som alle arbejder sammen. Det er allerede tæt på produktionsklar logik, blot kørt mod eksempeldata indtastet direkte i koden i stedet for et rigtigt regneark.

Opgave

  1. Kopiér CheckStockLevels ind i din projektmappe og kør den. Bekræft, at beskeden matcher skærmbilledet.
  2. Ændr Wireless Mouse's lager til 25 og kør igen — den bør nu også vises som "watch closely".
  3. Tilføj en Do While-løkke nedenunder, der simulerer salg af 15 enheder Laptop Stand ad gangen, indtil lageret falder til 20 eller derunder, og udskriv det løbende total til Immediate Window efter hvert salg.
  4. Udfordring: omskriv For i = 1 To 5-løkke ved at bruge For Each over et Variant-array i stedet — virker logikken stadig?
Tip
expand arrow

2. Ændring af lagerbeholdningen for Wireless Mouse

  • Find linjen, der opsætter data for Wireless Mouse: products(2) = "Wireless Mouse": stockLevels(2) = 134: reorderLevels(2) = 30.
  • Du skal kun ændre det midterste tal (134) til 25 — lad produktnavnet og genbestillingsniveauet være uændret.
  • Inden du kører det, gennemgå manuelt, hvilken Case der skal fange det: er 25 ≤ 30 (genbestillingsniveauet)? Sammenlign det specifikt med linjen Case Is <= reorderLevels(i), ikke den anden.

3. Simulering af partisalgs med Do While

  • Du skal bruge en variabel til at holde styr på Laptop Stand's løbende lager — start den med den samme værdi, der allerede står i stockLevels(1) (58), så du ikke indtaster et nyt tal, der kan komme ud af sync med resten af makroen.
  • Løkkens betingelse skal kontrollere, om lageret stadig er over 20 — i det øjeblik den tjekker og finder lageret på 20 eller derunder, skal den stoppe.
  • Træk 15 fra én gang pr. gennemløb, og udskriv den nye værdi lige efter fratrækningen — ikke før — så hvert udskrevet tal afspejler et gennemført salg.
  • Gennemgå det på papir først: 58 → 43 → 28 → 13. Bemærk, at den sidste værdi falder under 20 i stedet for at lande præcis på det — det er den samme Do While overskridelsesadfærd, som kapitlets løkkediagram tidligere har gennemgået, ikke en fejl.
Løsning
expand arrow

Punkt 2 — inde i CheckStockLevels, skal du blot ændre ét tal:

products(2) = "Wireless Mouse": stockLevels(2) = 25: reorderLevels(2) = 30

Kør Sub igen.

Punkt 3 — tilføj dette under den eksisterende kode, stadig inde i CheckStockLevels (før End Sub):

    ' --- Simulate selling Laptop Stand in batches of 15 ---
    Dim laptopStandStock As Integer
    laptopStandStock = stockLevels(1)

    Do While laptopStandStock > 20
        laptopStandStock = laptopStandStock - 15
        Debug.Print laptopStandStock
    Loop
Var alt klart?

Hvordan kan vi forbedre det?

Tak for dine kommentarer!

Sektion 2. Kapitel 5

Spørg AI

expand

Spørg AI

ChatGPT

Spørg om hvad som helst eller prøv et af de foreslåede spørgsmål for at starte vores chat

Sektion 2. Kapitel 5
some-alt