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

Løkker

Sveip for å vise menyen

Hver teknikk så langt har jobbet med én verdi om gangen. Løkker er måten du bruker samme logikk på mange verdier etter hverandre — fem produkter, fem hundre ordre, eller så mange rader som en tabell måtte inneholde — uten å måtte kopiere og lime inn samme kodeblokk om og om igjen.

For...Next

Gjentar en kodeblokk et fast, kjent antall ganger:

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økken starter i1, koden inni kjører én gang med den verdien, så økes i automatisk med 1 og hele blokken kjøres igjen — dette gjentas til i passerer 5, da stopper løkken og kjøringen fortsetter etter Next. Step endrer inkrementet: Step -1 teller nedover i stedet for standarden oppover med én, og Step 2 ville telt med to om gangen. Løkkevariabelen i er ikke spesiell syntaks — det er bare en vanlig Long-variabel som VBA oppdaterer for deg hver gang gjennom løkken.

For Each

Løkker gjennom hvert element i en samling direkte, uten at du trenger å vite hvor mange elementer det er eller holde styr på en teller selv:

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

Her tar cell verdien til hver enkelt celle i området B2:B6 etter tur, og du leser innholdet med .Value. Sammenlign dette med For...Next: med For...Next teller du gjennom tall og bruker det tallet til å slå opp noe; med For Each går du direkte gjennom elementene selv, noe som ofte er mer naturlig når du jobber med områder i regnearket.

Do While

Gjentar så lenge en betingelse er True — løkken vet ikke på forhånd hvor mange ganger den vil kjøre, noe som skiller seg 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 sjekker stock > 0 før hver eneste gjennomgang av løkken, inkludert den aller første. Følg det for hånd: 134 → 104 → 74 → 44 → 14, og så sjekkes betingelsen igjen — 14 er fortsatt større enn 0, så løkken kjører én gang til og lander på -16. Først da blir stock > 0 usann, og løkken stopper med stock på -16, ikke pent på 0 eller 14. Dette er verdt å følge nøye første gang, fordi det ofte fører til "off-by-one"-feil: en Do While-løkke fortsetter så lenge betingelsen stemmer i det øyeblikket den sjekkes, selv om handlingen inni løkken går forbi grensen du hadde sett for deg.

Do Until

Det finnes også Do Until, som er speilbildet av Do While — den gjentar mens en betingelse er False og stopper i det øyeblikket betingelsen blir True, altså motsatt vei. Hvilken som føles mest naturlig avhenger av hvordan du ville formulert forretningsregelen muntlig: "fortsett så lenge det er varer igjen" tilsier Do While; "fortsett til varene er tomme" tilsier Do Until — de kan gi identisk oppførsel, bare formulert fra hver sin retning.

Exit-setninger

Lar deg bryte ut av en løkke tidlig, før den naturlige sluttbetingelsen er nådd:

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

Denne løkken er satt opp til å telle helt til 100, men i det øyeblikket i når 10, stopper Exit For den — ingenting etter Exit For kjøres, og kjøringen hopper rett til linjen etter Next i. Dette er mønsteret du bruker for å søke gjennom en liste og stoppe så snart du har funnet det du leter etter, i stedet for å fortsette å sjekke resten av elementene unødvendig.

Sette det sammen

Alle teknikkene fra dette kapittelet — variabler, operatorer, funksjoner, betinget logikk og nå løkker — kombineres i prosedyren dette kapittelet har bygget opp mot:

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
Gjennomgang linje for linje
expand arrow
  • Dim products(1 To 5) As String og de to lignende linjene under erklærer arrayer — hver av dem er en nummerert rad med fem bokser i stedet for én boks, så products(1) er navnet på det første produktet, products(2) det andre, og så videre;
  • De fem linjene som bruker kolon (:) mellom setningene, samler flere tildelinger på én linje kun for lesbarhet her — products(1) = "Laptop Stand": stockLevels(1) = 58: reorderLevels(1) = 20 er nøyaktig det samme som å skrive dem som tre separate linjer;
  • For i = 1 To 5 ... Next i går gjennom alle fem produktene ett om gangen, og bruker i både som løkketeller og som indeks i hver array;
  • Select Case stockLevels(i) kjører samme områdebaserte avgjørelse fra seksjon 2.4, men nå mot ekte array-data i stedet for et enkelt hardkodet tall;
  • Case Is <= reorderLevels(i) fanger opp ethvert produkt der lageret har falt til eller under sitt eget bestillingsnivå — merk at reorderLevels(i) selv er en variabel, ikke et fast tall, så hvert produkt vurderes mot sin egen terskel i stedet for én felles terskel for alle;
  • alertMessage = alertMessage & ... & vbNewLine bygger opp en voksende streng én linje om gangen — vbNewLine er en innebygd konstant som legger inn linjeskift, slik at hvert flagget produkt vises på egen linje i den endelige meldingen;
  • Den siste If alertMessage = "" Then-sjekken avgjør hvilken av de to MsgBox-variantene brukeren faktisk ser — en tom streng betyr at løkken aldri fant noe som burde flagges.

Kjør dette, og du skal se at Monitor Arm blir flagget som "følg nøye med" (18 enheter mot et bestillingsnivå på 10) — gå gjennom løkken manuelt for i = 4 hvis du vil bekrefte nøyaktig hvorfor det er den eneste som fanges opp av den andre Case og ikke den første. Denne prosedyren bruker matriser, en løkke, en Select Case og strengbygging, alt som jobber sammen. Dette er faktisk nær produksjonsklar logikk allerede, bare kjørt mot eksempeldata skrevet direkte inn i koden i stedet for et ekte regneark.

Oppgave

  1. Kopier CheckStockLevels inn i arbeidsboken din og kjør den. Bekreft at meldingen samsvarer med skjermbildet.
  2. Endre lagerbeholdningen for Wireless Mouse til 25 og kjør på nytt — den skal nå også vises som "følg nøye med".
  3. Legg til en Do While-løkke under som simulerer salg av 15 enheter Laptop Stand om gangen til lageret faller til 20 eller lavere, og skriv ut løpende total til Immediate Window etter hvert salg.
  4. Utfordring: skriv om For i = 1 To 5-løkka ved å bruke For Each over en Variant-matrise i stedet — fungerer logikken fortsatt?
Tips
expand arrow

2. Endre lagerbeholdningen for Wireless Mouse

  • Finn linjen som setter opp dataene for Wireless Mouse: products(2) = "Wireless Mouse": stockLevels(2) = 134: reorderLevels(2) = 30.
  • Du trenger bare å endre det midterste tallet (134) til 25 — la produktnavnet og bestillingsnivået være uendret.
  • Før du kjører det, regn ut for hånd hvilken Case som skal fange det: er 25 ≤ 30 (bestillingsnivået)? Sammenlign dette spesielt med linjen Case Is <= reorderLevels(i), ikke den andre.

3. Simulere partisalgs med Do While

  • Du trenger en variabel for å holde styr på løpende lager for Laptop Stand — start den med samme verdi som allerede står i stockLevels(1) (58), slik at du ikke skriver inn et nytt tall som kan komme ut av synk med resten av makroen.
  • Løkkens betingelse skal sjekke om lageret fortsatt er over 20 — i det øyeblikket den sjekker og finner lageret på 20 eller lavere, skal den stoppe.
  • Trekk fra 15 én gang per gjennomgang, og skriv ut den nye verdien rett etter at du har trukket fra — ikke før — slik at hvert utskrevne tall gjenspeiler et fullført salg.
  • Gå gjennom det på papir først: 58 → 43 → 28 → 13. Merk at den siste verdien faller under 20 i stedet for å lande nøyaktig på det — dette er samme Do While-overskridelsesatferd som løkkediagrammet tidligere i kapitlet viste, ikke en feil.
Løsning
expand arrow

Punkt 2 — inne i CheckStockLevels, endre bare ett tall:

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

Kjør Sub på nytt.

Punkt 3 — legg til dette under eksisterende kode, fortsatt inne 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
Alt var klart?

Hvordan kan vi forbedre det?

Takk for tilbakemeldingene dine!

Seksjon 2. Kapittel 5

Spør AI

expand

Spør AI

ChatGPT

Spør om hva du vil, eller prøv ett av de foreslåtte spørsmålene for å starte chatten vår

Løkker

Hver teknikk så langt har jobbet med én verdi om gangen. Løkker er måten du bruker samme logikk på mange verdier etter hverandre — fem produkter, fem hundre ordre, eller så mange rader som en tabell måtte inneholde — uten å måtte kopiere og lime inn samme kodeblokk om og om igjen.

For...Next

Gjentar en kodeblokk et fast, kjent antall ganger:

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økken starter i1, koden inni kjører én gang med den verdien, så økes i automatisk med 1 og hele blokken kjøres igjen — dette gjentas til i passerer 5, da stopper løkken og kjøringen fortsetter etter Next. Step endrer inkrementet: Step -1 teller nedover i stedet for standarden oppover med én, og Step 2 ville telt med to om gangen. Løkkevariabelen i er ikke spesiell syntaks — det er bare en vanlig Long-variabel som VBA oppdaterer for deg hver gang gjennom løkken.

For Each

Løkker gjennom hvert element i en samling direkte, uten at du trenger å vite hvor mange elementer det er eller holde styr på en teller selv:

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

Her tar cell verdien til hver enkelt celle i området B2:B6 etter tur, og du leser innholdet med .Value. Sammenlign dette med For...Next: med For...Next teller du gjennom tall og bruker det tallet til å slå opp noe; med For Each går du direkte gjennom elementene selv, noe som ofte er mer naturlig når du jobber med områder i regnearket.

Do While

Gjentar så lenge en betingelse er True — løkken vet ikke på forhånd hvor mange ganger den vil kjøre, noe som skiller seg 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 sjekker stock > 0 før hver eneste gjennomgang av løkken, inkludert den aller første. Følg det for hånd: 134 → 104 → 74 → 44 → 14, og så sjekkes betingelsen igjen — 14 er fortsatt større enn 0, så løkken kjører én gang til og lander på -16. Først da blir stock > 0 usann, og løkken stopper med stock på -16, ikke pent på 0 eller 14. Dette er verdt å følge nøye første gang, fordi det ofte fører til "off-by-one"-feil: en Do While-løkke fortsetter så lenge betingelsen stemmer i det øyeblikket den sjekkes, selv om handlingen inni løkken går forbi grensen du hadde sett for deg.

Do Until

Det finnes også Do Until, som er speilbildet av Do While — den gjentar mens en betingelse er False og stopper i det øyeblikket betingelsen blir True, altså motsatt vei. Hvilken som føles mest naturlig avhenger av hvordan du ville formulert forretningsregelen muntlig: "fortsett så lenge det er varer igjen" tilsier Do While; "fortsett til varene er tomme" tilsier Do Until — de kan gi identisk oppførsel, bare formulert fra hver sin retning.

Exit-setninger

Lar deg bryte ut av en løkke tidlig, før den naturlige sluttbetingelsen er nådd:

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

Denne løkken er satt opp til å telle helt til 100, men i det øyeblikket i når 10, stopper Exit For den — ingenting etter Exit For kjøres, og kjøringen hopper rett til linjen etter Next i. Dette er mønsteret du bruker for å søke gjennom en liste og stoppe så snart du har funnet det du leter etter, i stedet for å fortsette å sjekke resten av elementene unødvendig.

Sette det sammen

Alle teknikkene fra dette kapittelet — variabler, operatorer, funksjoner, betinget logikk og nå løkker — kombineres i prosedyren dette kapittelet har bygget opp mot:

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
Gjennomgang linje for linje
expand arrow
  • Dim products(1 To 5) As String og de to lignende linjene under erklærer arrayer — hver av dem er en nummerert rad med fem bokser i stedet for én boks, så products(1) er navnet på det første produktet, products(2) det andre, og så videre;
  • De fem linjene som bruker kolon (:) mellom setningene, samler flere tildelinger på én linje kun for lesbarhet her — products(1) = "Laptop Stand": stockLevels(1) = 58: reorderLevels(1) = 20 er nøyaktig det samme som å skrive dem som tre separate linjer;
  • For i = 1 To 5 ... Next i går gjennom alle fem produktene ett om gangen, og bruker i både som løkketeller og som indeks i hver array;
  • Select Case stockLevels(i) kjører samme områdebaserte avgjørelse fra seksjon 2.4, men nå mot ekte array-data i stedet for et enkelt hardkodet tall;
  • Case Is <= reorderLevels(i) fanger opp ethvert produkt der lageret har falt til eller under sitt eget bestillingsnivå — merk at reorderLevels(i) selv er en variabel, ikke et fast tall, så hvert produkt vurderes mot sin egen terskel i stedet for én felles terskel for alle;
  • alertMessage = alertMessage & ... & vbNewLine bygger opp en voksende streng én linje om gangen — vbNewLine er en innebygd konstant som legger inn linjeskift, slik at hvert flagget produkt vises på egen linje i den endelige meldingen;
  • Den siste If alertMessage = "" Then-sjekken avgjør hvilken av de to MsgBox-variantene brukeren faktisk ser — en tom streng betyr at løkken aldri fant noe som burde flagges.

Kjør dette, og du skal se at Monitor Arm blir flagget som "følg nøye med" (18 enheter mot et bestillingsnivå på 10) — gå gjennom løkken manuelt for i = 4 hvis du vil bekrefte nøyaktig hvorfor det er den eneste som fanges opp av den andre Case og ikke den første. Denne prosedyren bruker matriser, en løkke, en Select Case og strengbygging, alt som jobber sammen. Dette er faktisk nær produksjonsklar logikk allerede, bare kjørt mot eksempeldata skrevet direkte inn i koden i stedet for et ekte regneark.

Oppgave

  1. Kopier CheckStockLevels inn i arbeidsboken din og kjør den. Bekreft at meldingen samsvarer med skjermbildet.
  2. Endre lagerbeholdningen for Wireless Mouse til 25 og kjør på nytt — den skal nå også vises som "følg nøye med".
  3. Legg til en Do While-løkke under som simulerer salg av 15 enheter Laptop Stand om gangen til lageret faller til 20 eller lavere, og skriv ut løpende total til Immediate Window etter hvert salg.
  4. Utfordring: skriv om For i = 1 To 5-løkka ved å bruke For Each over en Variant-matrise i stedet — fungerer logikken fortsatt?
Tips
expand arrow

2. Endre lagerbeholdningen for Wireless Mouse

  • Finn linjen som setter opp dataene for Wireless Mouse: products(2) = "Wireless Mouse": stockLevels(2) = 134: reorderLevels(2) = 30.
  • Du trenger bare å endre det midterste tallet (134) til 25 — la produktnavnet og bestillingsnivået være uendret.
  • Før du kjører det, regn ut for hånd hvilken Case som skal fange det: er 25 ≤ 30 (bestillingsnivået)? Sammenlign dette spesielt med linjen Case Is <= reorderLevels(i), ikke den andre.

3. Simulere partisalgs med Do While

  • Du trenger en variabel for å holde styr på løpende lager for Laptop Stand — start den med samme verdi som allerede står i stockLevels(1) (58), slik at du ikke skriver inn et nytt tall som kan komme ut av synk med resten av makroen.
  • Løkkens betingelse skal sjekke om lageret fortsatt er over 20 — i det øyeblikket den sjekker og finner lageret på 20 eller lavere, skal den stoppe.
  • Trekk fra 15 én gang per gjennomgang, og skriv ut den nye verdien rett etter at du har trukket fra — ikke før — slik at hvert utskrevne tall gjenspeiler et fullført salg.
  • Gå gjennom det på papir først: 58 → 43 → 28 → 13. Merk at den siste verdien faller under 20 i stedet for å lande nøyaktig på det — dette er samme Do While-overskridelsesatferd som løkkediagrammet tidligere i kapitlet viste, ikke en feil.
Løsning
expand arrow

Punkt 2 — inne i CheckStockLevels, endre bare ett tall:

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

Kjør Sub på nytt.

Punkt 3 — legg til dette under eksisterende kode, fortsatt inne 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
Alt var klart?

Hvordan kan vi forbedre det?

Takk for tilbakemeldingene dine!

Seksjon 2. Kapittel 5
some-alt