本篇介紹 Excel VBA 的迴圈使用方式,並提供實用的範例程式碼。
迴圈控制是各種程式語言都會有的基本功能,他的作用是可以讓電腦重複執行某一段類似的動作,在運用得當的情況下,可以幫助使用者快速處理大料的資料,既省時又省力。
在 Excel VBA 中的迴圈主要可分為
For Loop
、For Each
與 Do Loop
這幾種,不同的迴圈適用於不同類型的問題,以下是各種 VBA 迴圈的語法教學。
For Loop
迴圈
For Loop
迴圈主要用於已知重複次數的問題,也就是在執行迴圈之前,就已經事先知道要迭代幾次。
運算內容
Next 迭代變數
在 For Loop
迴圈執行時,迭代變數會從開始值
不斷遞增至結束值
,每次遞增時都會執行一次運算內容
。以下是一個計算從 1
到 10
總和的範例:
Dim i, s As Integer s = 0 For i = 1 To 10 s = s + i Next i MsgBox "s = " & s
以這個例子來說 i
就是迭代變數,在 For Loop
迴圈第一次執行時,i
這個變數會被設定為 1
,然後執行 s = s + i
,接著讓 i
遞增為 2
,再執行一次 s = s + i
,以此類推,直到 i
遞增到 10
並執行完該次迭代之後,才會跳出 For Loop
迴圈。整個程式執行完之後,就會把 1
到 10
的總和算出來:
Exit For
中斷迴圈
For Loop
迴圈在正常的狀況下會一直執行,直到迭代變數遞增至結束值
為止,如果想要中途跳出迴圈,可以加上 Exit For
來中斷迴圈:
Dim i, s As Integer s = 0 For i = 1 To 10 s = s + i If i >= 4 Then Exit For ' 中斷迴圈 End If Next i MsgBox "s = " & s
在這個範例中,我們在 For Loop
迴圈當中加入了一個 If Then
條件判斷式,當 i
大於或等於 4
的時候,就跳出迴圈,所以最後我們會得到從 1
加到 4
的總和:
For Each
迴圈
For Each
迴圈是 For Loop
迴圈的另外一種精簡寫法,兩者功能差不多,只是在某些狀況下使用 For Each
迴圈會比較方便。
一般若要使用 For Loop
迴圈對陣列中的每個元素逐一處理時,必須明確指定開始與結束的索引值,再以索引值取出陣列中的元素做進一步的運算,而 For Each
迴圈則是可以自動將陣列中的元素逐一取出,放進迴圈的迭代變數中處理,這樣的寫法會比 For Loop
更精簡。
運算內容
Next 迭代變數
這是使用 For Each
迴圈找出目前 Excel 中所有工作表的範例程式:
Dim wSheet As Worksheet For Each wSheet In Worksheets MsgBox "找到工作表: " & wSheet.Name Next wSheet
這個 For Each
迴圈會將 Worksheets
中的每一個元素逐一取出,儲存在 wSheet
變數中,並且執行迭代的內容。這個例子會將 Excel 中的每一張工作表取出來,呼叫 MsgBox
輸出每一張工作表的名子,也就是說 Excel 中的工作表有幾張,這個迴圈就會執行幾次。
Do Loop
迴圈
Do Loop
迴圈可以重複執行某一段程式碼,直到指定的條件判斷式成立或是不成立的時候,才停止迴圈的執行,而這類的迴圈有好幾種不同的型式,使用者可以依照需求選擇適合的寫法。
Do While Loop
迴圈
Do While Loop
迴圈可以在每一次迭代時,檢查一個指定的條件判斷式,如果成立的話(判斷為 True
)就會繼續執行,而如果條件不成立(判斷為 False
)的話,就會中止迴圈。
運算內容
Loop
以下是一個使用 Do While Loop
迴圈計算 1
到 10
總和的範例。
Dim i, s As Integer s = 0 i = 1 Do While i <= 10 s = s + i i = i + 1 Loop MsgBox "s = " & s
在這個例子中,一開始先初始化兩個變數,s
變數用於儲存總和值,而 i
則是用於每次迭代的變數,迴圈執行時會先判斷 i
是否小於或等於 10
,如果條件成立則執行迴圈的內容,一直重複執行直到 i
大於 10
為止,所以最後得到的 s
就是 1
到 10
的加總數值。
While
的條件判斷式也可以放在迴圈結尾處,這樣的話迴圈在執行時就會先執行第一次的迭代,執行完第一次之後才判斷是否要繼續執行下一次的迭代,如果條件成立則繼續執行,若不成立就立刻中止迴圈,這樣的寫法只是檢查條件判斷式的時機不同,觀念上大同小異。
運算內容
Loop While 條件判斷式
以下是一個簡單的範例。
Dim i, s As Integer s = 0 i = 1 Do s = s + i i = i + 1 Loop While i <= 10 MsgBox "s = " & s
Do Until Loop
迴圈
Do Until Loop
迴圈與 Do While Loop
迴圈在條件的判斷上剛好相反,Do Until Loop
迴圈會在指定條件不成立(判斷為 False
)時繼續執行,當判斷條件成立時(判斷為 True
)則終止迴圈。
運算內容
Loop
以下是一個 Do Until Loop
迴圈的範例程式碼。
Dim i, s As Integer s = 0 i = 1 Do Until i > 10 s = s + i i = i + 1 Loop MsgBox "s = " & s
Do Until Loop
迴圈也可以將條件判斷式放在迴圈的最後面,這跟上面 Do While Loop
迴圈也很類似。
運算內容
Loop Until 條件判斷式
以下是一個簡單的範例。
Dim i, s As Integer s = 0 i = 1 Do s = s + i i = i + 1 Loop Until i > 10 MsgBox "s = " & s
Exit Do
中斷迴圈
如果要在 Do Loop
迴圈執行到一半時終止迴圈的執行,可以在迴圈中加入 Exit Do
,以下是一個範例:
Dim i, s As Integer s = 0 i = 1 Do Until i > 10 s = s + i i = i + 1 If i > 4 Then Exit Do ' 中斷迴圈 End If Loop MsgBox "s = " & s
在這個例子中,我們在迴圈之中加入一個 If
判斷式,讓程式在 i
大於 4
的時候就執行 Exit Do
跳出迴圈,所以這個程式最後所得到的結果就是從 1
到 4
的總和。
應用範例
迭代 Excel 工作表
此範例示範如何結合 For Loop
迴圈與 Cells
函數(Cells
函數的用法請參考活頁簿、工作表與儲存格),自動迭代處理 Excel 工作表內的資料:
Dim i, j As Integer For i = 1 To 3 For j = 1 To 3 MsgBox ("(" & i & "," & j & ") = " & Cells(i, j)) Next j Next i
更多關於 VBA 的教學文章,請參考 VBA 程式設計。
參考資料:ExcelFunctions.net、Excel VBA Programming、tutorialspoint、Excel Easy、stackoverflow
Chen
VBA的各個教學的寫得淺顯易懂
幫助很大
希望大大有空還可以繼續寫更深入的教學文章
謝謝!
G. T. Wang
感謝您的支持,VBA 的教學我目前正在寫,有新文章就會放上來。
Learning_VBA
過年期間想要自學VBA 您的文章對初學者幫助很大 謝謝
Lai
您好,看您教的VBA貼文,讓我學到很多
非常感謝您
而我有一個迴圈的問題想請問您
假如:
SUB TRY()
DIM W,S,X AS INTEGER
W=0
FOR S= O TO 10
X=W+S
IF S>=4 THEN
EXIT FOR
END IF
NEXT S
MSGBOX “X=” & X
END SUB
1.為何X跑出的結果卻是4
2.上述的解釋不是:
[算X=W+S的迴圈,當S大於等於4時跳出終止迴圈嗎?]
3.大於等於4(>=4)不就只要為4或大於是就終止迴圈,所以不是應該只有加1+2+3=6嗎?為何答案為10?
4.想請問一下,為何把上述的X=W+S改成W=W+S答案跑出來的結果卻不一致呢?
(是不能為3個變數嗎?可是我一開始有DIM宣告X,W,S為整數阿)
不好意思,為初學者,所以問題較多!
G. T. Wang
我想您的問題是屬於數學邏輯上的問題,並不是程式語法問題。簡單來說就是您還沒完全想懂這個程式是怎麼跑的,仔細多想幾遍應該就會想通了。
liu
請問迭代變數可以是sheet裡面的 N2 到 N31 嗎 ?
已經把”單一個欄位”(即 N2)的 判別 及 後續動作 都寫好,
但學得不多,
還沒弄懂如何用LOOP去處理在不同欄位下,同樣的 判別 及 後續動作,謝謝
G. T. Wang
可用 For Loop 配合 Cells,我已將範例加入文章內,請參考文章內容。
liu
T_T … 我成功了~非常感謝,
念書時期沒想很多,沒考慮過職場中excel的影響力及親切度,
所以當時用fortran程式,現在整個卡卡,還好有您的教學文,
太棒了~
YAN
若我想將第一欄中所有值是”ABC”與空值得欄位刪除,以下這樣寫有什麼錯誤嗎?
執行完的結果有點詭異,比如說(7,1)和(8,1)都是空值,執行一次後會刪掉一個空值,再執行一次才會兩個空值都刪掉。麻煩您幫忙看一下,感謝。
Dim i As Integer
For i = 1 To 874
If Cells(i, 1).Value = “ABC” Then
Cells(i, 1).Delete
ElseIf Cells(i, 1).Value = “” Then
Cells(i, 1).Delete
End If
Next i
YAN
喔…我想到了,我再刪除了一個欄位後,下方的空值欄位會像上補,所以就刪不到了..顆顆
感謝你寫的教學。
OWEN
請問如果B1:B26 中如果有空值就跳出迴圈
然後匯出TXT 我要怎麼加入判斷
Dim Rng As Object
Dim strData
For Each Rng In Range(“B1:B26”)
If Rng.Column = 1 Then
strData = strData & Rng & vbTab
ElseIf Rng.Column = 2 Then
strData = strData & Rng & vbCr
End If
Next
Debug.Print strData
Dim fsT As Object
Set fsT = CreateObject(“ADODB.Stream”)
fsT.Type = 2
fsT.Charset = “UTF-8”
fsT.Open
fsT.WriteText strData
fsT.SaveToFile “D:\ID.txt”, 2
End Sub
LEE
請問一下我有類似寫了迴圈的蛋為啥他還是會讀到重複的題目呢?
Attribute VB_Name = “Module1”
Dim data(2000, 9), test(100, 9)
Dim rno, tno
Sub new_test()
tno = InputBox(“請輸入考題數:”, , 80)
Call clean_data
Call read_data
Call choice
Call write_data
End Sub
Sub clean_data()
Worksheets(“W2”).Select
For i = 2 To 101
For j = 1 To 9
Cells(i, j) = “”
Next
Cells(i, 9).Interior.Color = xlNone
Next
End Sub
Sub read_data()
Worksheets(“W1”).Select
i = 1
Do While Cells(i, 1) “”
For j = 1 To 9
data(i, j) = Cells(i + 1, j)
Next
i = i + 1
Loop
rno = i – 2
End Sub
Sub choice()
Randomize
For i = 1 To tno
no = Int(Rnd * rno) + 1
For k = 1 To tno
If no = Val(test(i, 2)) Then Exit For
Next
If k < tno + 1 Then
i = i – 1
Else
For j = 1 To 9
test(i, j) = data(no, j)
Next
End If
Next
End Sub
Sub write_data()
Worksheets("W2").Select
For i = 1 To tno
Cells(i + 1, 1) = test(i, 2)
Cells(i + 1, 2) = test(i, 3)
Cells(i + 1, 3) = i
Cells(i + 1, 4) = test(i, 4)
Cells(i + 1, 5) = test(i, 5)
Cells(i + 1, 6) = test(i, 6)
Cells(i + 1, 7) = test(i, 7)
Cells(i + 1, 8) = test(i, 8)
Cells(i + 1, 9) = test(i, 9)
Next
End Sub
LEE
大大你好 我有寫類似迴圈的 可是我的總會獨到重複的?
大大請問有解嗎?
Attribute VB_Name = “Module1”
Dim data(2000, 9), test(100, 9)
Dim rno, tno
Sub new_test()
tno = InputBox(“請輸入考題數:”, , 80)
Call clean_data
Call read_data
Call choice
Call write_data
End Sub
Sub clean_data()
Worksheets(“W2”).Select
For i = 2 To 101
For j = 1 To 9
Cells(i, j) = “”
Next
Cells(i, 9).Interior.Color = xlNone
Next
End Sub
Sub read_data()
Worksheets(“W1”).Select
i = 1
Do While Cells(i, 1) “”
For j = 1 To 9
data(i, j) = Cells(i + 1, j)
Next
i = i + 1
Loop
rno = i – 2
End Sub
Sub choice()
Randomize
For i = 1 To tno
no = Int(Rnd * rno) + 1
For k = 1 To tno
If no = Val(test(i, 2)) Then Exit For
Next
If k < tno + 1 Then
i = i – 1
Else
For j = 1 To 9
test(i, j) = data(no, j)
Next
End If
Next
End Sub
Sub write_data()
Worksheets("W2").Select
For i = 1 To tno
Cells(i + 1, 1) = test(i, 2)
Cells(i + 1, 2) = test(i, 3)
Cells(i + 1, 3) = i
Cells(i + 1, 4) = test(i, 4)
Cells(i + 1, 5) = test(i, 5)
Cells(i + 1, 6) = test(i, 6)
Cells(i + 1, 7) = test(i, 7)
Cells(i + 1, 8) = test(i, 8)
Cells(i + 1, 9) = test(i, 9)
Next
End Sub
Ben
以變數作為巢狀迴圈層數,如何更有效率編碼,而非預設好一層包一層,因層數未能預知
Alice
請問dim設定變數後,需要釋放變數(set x = nothing)嗎?我這樣做都會跳出錯誤訊息。
還是只有用set設定變數,才需要釋放變數? 謝謝!