Notice: This page requires JavaScript to function properly.
Please enable JavaScript in your browser settings or update your browser.
Lära Loopar | VBA-Grunder
Excel VBA för affärsautomatisering

Loopar

Svep för att visa menyn

Varje teknik hittills har arbetat med ett värde i taget. Slingor (loops) är hur du tillämpar samma logik på många värden i rad — fem produkter, femhundra ordrar, hur många rader en tabell än råkar innehålla — utan att behöva kopiera och klistra in samma kodblock om och om igen.

For...Next

Upprepar ett kodblock ett fast, känt antal gånger:

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örsta loopen börjar i1, koden inuti körs en gång med det värdet, sedan ökar i automatiskt med 1 och hela blocket körs igen — detta upprepas tills i passerar 5, då loopen helt enkelt slutar och exekveringen fortsätter efter Next. Step ändrar steglängden: Step -1 räknar nedåt istället för standardvärdet uppåt med ett, och Step 2 skulle räkna med två steg. Loopvariabeln i är inte någon speciell syntax — det är bara en vanlig Long-variabel som VBA uppdaterar åt dig varje gång loopen körs.

For Each

Loopar över varje objekt i en samling direkt, utan att du behöver veta hur många objekt det finns eller hantera en räknare själv:

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

Här antar cell varje enskild cell i området B2:B6 i tur och ordning, och du läser vad som finns i den med .Value. Jämför detta med For...Next: med For...Next räknar du genom siffror och använder det numret för att slå upp något; med For Each går du direkt igenom objekten själva, vilket känns mer naturligt när du arbetar med kalkylbladsområden.

Do While

Upprepar så länge ett villkor är True — loopen vet inte i förväg hur många gånger den kommer att köras, vilket skiljer sig från 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 kontrollerar stock > 0 före varje varv genom loopen, inklusive det allra första. Följ det för hand: 134 → 104 → 74 → 44 → 14, och sedan kontrolleras villkoret igen — 14 är fortfarande större än 0, så loopen körs en gång till och landar på -16. Först då blir stock > 0 falskt, och loopen stannar med stock på -16, inte exakt på 0 eller 14. Detta är värt att följa noggrant första gången, eftersom det är en vanlig källa till "off-by-one"-överraskningar: en Do While-loop fortsätter så länge villkoret gäller i det ögonblick det kontrolleras, även om åtgärden inuti loopen går förbi den gräns du hade tänkt dig.

Do Until

Det finns också Do Until, som är spegelbilden av Do While — den upprepar medan ett villkor är False och stannar i samma ögonblick som villkoret blir True, istället för tvärtom. Vilken som känns mest naturlig beror på hur du skulle formulera affärsregeln högt: "fortsätt medan lager finns kvar" antyder Do While; "fortsätt tills lagret tar slut" antyder Do Until — de kan ge identiskt beteende, bara uttryckt från motsatta håll.

Exit-satser

Låter dig bryta ut ur en loop i förtid, innan dess naturliga slutvillkor är uppfyllt:

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

Denna loop är inställd på att räkna hela vägen till 100, men i samma ögonblick som i når 10 stoppar Exit For den direkt — inget efter Exit For körs, och exekveringen hoppar direkt till raden efter Next i. Detta är mönstret du använder för att söka igenom en lista och sluta så snart du hittat det du letar efter, istället för att i onödan fortsätta kontrollera varje återstående objekt.

Sätta ihop det

Alla tekniker från detta kapitel — variabler, operatorer, funktioner, villkorslogik och nu slingor — kombineras i proceduren som detta kapitel har byggt upp 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
Gå igenom det rad för rad
expand arrow
  • Dim products(1 To 5) As String och de två liknande raderna under deklarerar arrayer — var och en är en numrerad rad med fem rutor istället för en enda ruta, så products(1) är namnet på den första produkten, products(2) den andra, och så vidare;
  • De fem raderna som använder kolon (:) mellan satser packar flera tilldelningar på en rad enbart för läsbarhet här — products(1) = "Laptop Stand": stockLevels(1) = 58: reorderLevels(1) = 20 är exakt likvärdigt med att skriva dessa som tre separata rader;
  • For i = 1 To 5 ... Next i går igenom alla fem produkter en i taget, där i används både som loopräknare och som index i varje array;
  • Select Case stockLevels(i) kör samma intervallbaserade beslut från avsnitt 2.4 igen, men nu mot verklig arraydata istället för ett enda hårdkodat tal;
  • Case Is <= reorderLevels(i) fångar alla produkter vars lager har fallit till eller under sin egen beställningsnivå — observera att reorderLevels(i) i sig är en variabel, inte ett fast tal, så varje produkt bedöms mot sin egen tröskel istället för en gemensam tröskel för alla;
  • alertMessage = alertMessage & ... & vbNewLine bygger upp en växande sträng rad för rad — vbNewLine är en inbyggd konstant som infogar en radbrytning, så varje flaggad produkt visas på en egen rad i det slutliga meddelandet;
  • Den sista If alertMessage = "" Then-kontrollen avgör vilken av de två MsgBox-varianterna användaren faktiskt ser — en tom sträng betyder att loopen aldrig hittade något värt att flagga.

Kör detta så ska du se att Monitor Arm flaggas som "watch closely" (18 enheter mot en beställningsnivå på 10) — gå igenom loopen manuellt för i = 4 om du vill bekräfta exakt varför det är den enda som fångas av det andra Case och inte det första. Denna procedur använder arrayer, en loop, en Select Case och strängbyggnad, allt samverkar. Det är faktiskt nära produktionskvalitet redan, bara att det körs mot exempeldata som skrivits direkt i koden istället för ett riktigt kalkylblad.

Uppgift

  1. Kopiera CheckStockLevels till din arbetsbok och kör den. Bekräfta att meddelandet matchar skärmdumpen.
  2. Ändra Wireless Mouse lager till 25 och kör igen — den ska nu också visas som "watch closely".
  3. Lägg till en Do While-loop under som simulerar försäljning av 15 enheter Laptop Stand åt gången tills lagret sjunker till 20 eller lägre, och skriv ut det löpande totalen till Immediate Window efter varje försäljning.
  4. Utmaning: skriv om loopen For i = 1 To 5 med For Each över en Variant-array istället — fungerar logiken fortfarande?
Tips
expand arrow

2. Ändra lagersaldot för Wireless Mouse

  • Hitta raden som sätter upp data för Wireless Mouse: products(2) = "Wireless Mouse": stockLevels(2) = 134: reorderLevels(2) = 30.
  • Du behöver bara ändra det mittersta numret (134) till 25 — lämna produktnamnet och beställningsnivån oförändrade.
  • Innan du kör, räkna ut för hand vilket Case som ska fånga det: är 25 ≤ 30 (beställningsnivån)? Jämför det mot raden Case Is <= reorderLevels(i) specifikt, inte den andra.

3. Simulera partiförsäljning med Do While

  • Du behöver en variabel för att hålla det löpande lagersaldot för Laptop Stand — börja på samma värde som redan finns i stockLevels(1) (58), så att du inte skriver in ett nytt tal som kan hamna ur synk med resten av makrot.
  • Loopens villkor ska kontrollera om lagret fortfarande är över 20 — så fort det kontrollerar och hittar lagret på 20 eller lägre ska den stanna.
  • Subtrahera 15 en gång per varv, och skriv ut det nya värdet direkt efter subtraktionen — inte före — så att varje utskrivet tal speglar en genomförd försäljning.
  • Följ det på papper först: 58 → 43 → 28 → 13. Notera att det sista värdet går under 20 istället för att landa exakt på det — det är samma Do While-överskjutningsbeteende som kapitlets loopdiagram visade tidigare, inte ett fel.
Lösning
expand arrow

Punkt 2 — inuti CheckStockLevels, ändra bara ett tal:

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

Kör Sub igen.

Punkt 3 — lägg till detta under befintlig kod, fortfarande inuti CheckStockLevels (före 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 allt tydligt?

Hur kan vi förbättra det?

Tack för dina kommentarer!

Avsnitt 2. Kapitel 5

Fråga AI

expand

Fråga AI

ChatGPT

Fråga vad du vill eller prova någon av de föreslagna frågorna för att starta vårt samtal

Avsnitt 2. Kapitel 5
some-alt