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
- 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) = 20on täsmälleen sama kuin kirjoittaisi nämä kolme eri riville; For i = 1 To 5 ... Next ikä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 & ... & vbNewLinerakentaa kasvavaa merkkijonoa rivi kerrallaan —vbNewLineon 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 kahdestaMsgBox-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ä
- Kopioi
CheckStockLevelstyökirjaasi ja suorita se. Varmista, että viesti vastaa kuvakaappausta. - Muuta Wireless Mouse -tuotteen varastomääräksi 25 ja suorita uudelleen — sen pitäisi nyt näkyä myös "watch closely" -merkinnällä.
- 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. - Haaste: kirjoita
For i = 1 To 5-silmukka uudelleen käyttämälläFor Each-rakennetta Variant-taulukon yli — toimiiko logiikka edelleen?
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) arvoon25— 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 riviinCase 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.
Kohta 2 — CheckStockLevels-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
Kiitos palautteestasi!
Kysy tekoälyä
Kysy tekoälyä
Kysy mitä tahansa tai kokeile jotakin ehdotetuista kysymyksistä aloittaaksesi keskustelumme