Notice: This page requires JavaScript to function properly.
Please enable JavaScript in your browser settings or update your browser.
Oppiskele Silmukat | VBA Fundamentals
Excel VBA Liiketoiminnan Automaatioon

Silmukat

Pyyhkäise näyttääksesi valikon

Kaikki tähän asti esitellyt tekniikat ovat käsitelleet vain yhtä arvoa kerrallaan. Silmukat mahdollistavat saman logiikan soveltamisen useaan arvoon peräkkäin — viiteen tuotteeseen, viiteensataan tilaukseen tai niin moneen riviin kuin taulukossa sattuu olemaan — ilman, että samaa koodilohkoa tarvitsee kopioida uudelleen ja uudelleen.

For...Next

Toistaa koodilohkon ennalta määrätyn, tunnetun määrän kertoja:

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

Ensimmäisessä silmukassa i alkaa arvosta 1, koodin sisällä oleva lohko suoritetaan kerran tällä arvolla, sitten i kasvaa automaattisesti arvolla 1 ja koko lohko suoritetaan uudelleen — toistuen kunnes i ylittää arvon 5, jolloin silmukka yksinkertaisesti päättyy ja suoritus jatkuu Next i jälkeen. Step muuttaa kasvatusväliä: Step -1 laskee alaspäin oletusarvoisen ylöspäin kasvattamisen sijaan, ja Step 2 laskisi kahden välein. Silmukkamuuttuja i ei ole erityinen syntaksi — se on tavallinen Long-tyyppinen muuttuja, jota VBA päivittää puolestasi jokaisella kierroksella.

For Each

Käy läpi kokoelman jokaisen alkion suoraan, ilman että sinun tarvitse tietää montako alkiota on tai hallita laskuria itse:

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

Tässä cell saa vuorollaan jokaisen yksittäisen solun alueelta B2:B6, ja voit lukea sen sisällön .Value-ominaisuudella. Vertaa tätä For...Next-silmukkaan: For...Next-rakenteessa lasketaan numeroita ja käytetään sitä numeroa jonkin hakemiseen; For Each-rakenteessa käydään suoraan läpi itse alkiot, mikä on luonnollisempaa, kun työskennellään taulukkoalueiden kanssa.

Do While

Toistaa niin kauan kuin ehto pysyy True — silmukka ei tiedä etukäteen, montako kertaa se suoritetaan, mikä erottaa sen For...Next-rakenteesta:

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 tarkistaa stock > 0 ennen jokaista silmukan kierrosta, mukaan lukien ensimmäinen. Seuraa käsin: 134 → 104 → 74 → 44 → 14, ja sitten ehto tarkistetaan uudelleen — 14 on yhä suurempi kuin 0, joten silmukka suoritetaan vielä kerran, jolloin päädytään arvoon -16. Vasta silloin stock > 0 palauttaa arvon False ja silmukka päättyy, jolloin stock on -16, ei tasan 0 tai 14. Tämä kannattaa käydä tarkasti läpi ensimmäisellä kerralla, sillä kyseessä on yleinen "off-by-one"-virheen lähde: Do While-silmukka jatkuu niin kauan kuin ehto pitää paikkansa tarkistushetkellä, vaikka silmukan sisäinen toiminto ylittäisi rajan, jonka olit ajatellut.

Do Until

On myös Do Until, joka on Do While-rakenteen peilikuva — se toistaa niin kauan kuin ehto on False ja päättyy heti, kun ehto muuttuu True:ksi, toisin kuin edellisessä. Kumpi tuntuu luonnollisemmalta riippuu siitä, miten liiketoimintasäännön muotoilisi ääneen: "jatka niin kauan kuin varastoa on" viittaa Do While-rakenteeseen; "jatka kunnes varasto loppuu" viittaa Do Until-rakenteeseen — molemmat voivat tuottaa saman lopputuloksen, mutta eri näkökulmasta ilmaistuna.

Exit-lauseet

Mahdollistavat silmukasta poistumisen ennen sen luonnollista päättymisehtoa:

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

Tämä silmukka on asetettu laskemaan sataan asti, mutta heti kun i saavuttaa arvon 10, Exit For pysäyttää sen — mitään Exit For-kohdan jälkeen ei suoriteta, ja suoritus hyppää suoraan Next i-rivin jälkeiseen kohtaan. Tätä kaavaa käytetään esimerkiksi listan läpikäyntiin ja pysähtymiseen heti, kun haluttu asia löytyy, sen sijaan että tarkistettaisiin turhaan kaikki loputkin alkiot.

Yhdistäminen käytäntöön

Kaikki tämän luvun tekniikat — muuttujat, operaattorit, funktiot, ehtolauseet ja nyt silmukat — yhdistyvät menettelyssä, jota tämä luku on rakentanut:

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
Rivikohtainen läpikäynti
expand arrow
  • Dim products(1 To 5) As String ja kaksi seuraavaa riviä määrittelevät taulukot — jokainen on viiden laatikon numeroitu rivi yhden laatikon sijaan, joten products(1) on ensimmäisen tuotteen nimi, products(2) toisen ja niin edelleen;
  • Viisi riviä, joissa käytetään kaksoispistettä (:) lauseiden välissä, mahdollistavat useiden sijoitusten tekemisen yhdellä rivillä pelkästään luettavuuden vuoksi — products(1) = "Laptop Stand": stockLevels(1) = 58: reorderLevels(1) = 20 on täsmälleen sama kuin kirjoittaisi nämä kolme eri riville;
  • For i = 1 To 5 ... Next i käy läpi kaikki viisi tuotetta yksi kerrallaan, käyttäen i:tä sekä silmukan laskurina että taulukon indeksinä;
  • Select Case stockLevels(i) suorittaa saman alueeseen perustuvan päätöksen kuin kohdassa 2.4, mutta nyt oikeaa taulukkodataa vastaan yhden kovakoodatun luvun sijaan;
  • Case Is <= reorderLevels(i) poimii kaikki tuotteet, joiden varasto on laskenut oman tilausrajan tasolle tai sen alle — huomaa, että reorderLevels(i) on itsessään muuttuja, ei kiinteä luku, joten jokainen tuote arvioidaan oman raja-arvonsa mukaan, ei yhden yhteisen rajan mukaan;
  • alertMessage = alertMessage & ... & vbNewLine rakentaa kasvavaa merkkijonoa rivi kerrallaan — vbNewLine on sisäänrakennettu vakio, joka lisää rivinvaihdon, joten jokainen merkitty tuote näkyy omalla rivillään lopullisessa viestissä;
  • Lopullinen If alertMessage = "" Then -tarkistus määrittää, kumman kahdesta MsgBox-vaihtoehdosta käyttäjä näkee — tyhjä merkkijono tarkoittaa, ettei silmukka löytänyt mitään huomautettavaa.

Suorita tämä, ja sinun pitäisi nähdä Monitor Arm merkittynä "watch closely" (18 yksikköä, kun uudelleentilaustaso on 10) — käy silmukka läpi käsin kohdassa i = 4, jos haluat varmistaa, miksi juuri tämä on ainoa, jonka toinen Case poimii eikä ensimmäinen. Tämä proseduuri käyttää taulukoita, silmukkaa, Select Case -rakennetta ja merkkijonon muodostamista, kaikki yhdessä. Tämä on jo hyvin lähellä tuotantotasoista logiikkaa, vaikka se käyttääkin esimerkkidataa, joka on kirjoitettu suoraan koodiin eikä oikeaan laskentataulukkoon.

Tehtävä

  1. Kopioi CheckStockLevels työkirjaasi ja suorita se. Varmista, että viesti vastaa kuvakaappausta.
  2. Muuta Wireless Mouse -tuotteen varastomääräksi 25 ja suorita uudelleen — sen pitäisi nyt näkyä myös "watch closely" -merkinnällä.
  3. Lisää alle Do While -silmukka, joka simuloi 15 kappaleen erissä tapahtuvaa Laptop Stand -tuotteen myyntiä, kunnes varasto laskee 20:een tai sen alle, tulostaen kokonaissumman Immediate Window -ikkunaan jokaisen myynnin jälkeen.
  4. Haaste: kirjoita For i = 1 To 5 -silmukka uudelleen käyttämällä For Each -rakennetta Variant-taulukon yli — toimiiko logiikka edelleen?
Vihje
expand arrow

2. Langattoman hiiren varaston muuttaminen

  • Etsi rivi, jossa määritellään langattoman hiiren tiedot: products(2) = "Wireless Mouse": stockLevels(2) = 134: reorderLevels(2) = 30.
  • Sinun tarvitsee muuttaa vain keskimmäinen numero (134) arvoon 25 — jätä tuotteen nimi ja tilausraja ennalleen.
  • Ennen suorittamista selvitä käsin, minkä Case-ehdon pitäisi ottaa tämän tapauksen: onko 25 ≤ 30 (tilausraja)? Vertaa tätä erityisesti riviin Case Is <= reorderLevels(i), ei toiseen ehtoon.

3. Erämyynnin simulointi Do While -silmukalla

  • Tarvitset muuttujan, joka säilyttää Laptop Standin varastosaldon — aloita samalla arvolla, joka on jo stockLevels(1)-muuttujassa (58), jotta et kirjoita uutta arvoa, joka voisi poiketa makron muista tiedoista.
  • Silmukan ehdon tulee tarkistaa, onko varasto yli 20 — heti kun tarkistus löytää varaston olevan 20 tai vähemmän, silmukka pysähtyy.
  • Vähennä 15 joka kierroksella ja tulosta uusi arvo heti vähennyksen jälkeen — ei ennen — jotta jokainen tulostettu luku vastaa toteutunutta myyntiä.
  • Kokeile paperilla: 58 → 43 → 28 → 13. Huomaa, että viimeinen arvo menee alle 20:n eikä pysähdy tasan siihen — tämä on sama Do While -ylilyöntikäytös, jonka luvun silmukkakaavio aiemmin esitteli, eikä kyseessä ole virhe.
Ratkaisu
expand arrow

Kohta 2CheckStockLevels-aliohjelmassa muuta vain yksi numero:

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

Suorita Sub uudelleen.

Kohta 3 — lisää tämä olemassa olevan koodin alle, edelleen CheckStockLevels-aliohjelmassa (ennen End Sub -riviä):

    ' --- 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
Oliko kaikki selvää?

Miten voimme parantaa sitä?

Kiitos palautteestasi!

Osio 2. Luku 5

Kysy tekoälyä

expand

Kysy tekoälyä

ChatGPT

Kysy mitä tahansa tai kokeile jotakin ehdotetuista kysymyksistä aloittaaksesi keskustelumme

Osio 2. Luku 5
some-alt