第7章 程序控制結(jié)構(gòu)
程序代碼需要按一定的順序執(zhí)行,,有時需要選擇某一部分代碼執(zhí)行;有時需要反復(fù)執(zhí)行某一段代碼,。通過程序結(jié)構(gòu)控制代碼可以完成這些功能,。
7.1 算法的概念及表示
對于稍微復(fù)雜一點的應(yīng)用程序,在開始編寫代碼之前,,應(yīng)該先設(shè)計其算法,。本節(jié)首先簡單地介紹一下算法和流程圖方面的知識。
7.1.1 算法簡介
使用計算機處理各種不同的問題時,,必須事先對各類問題進(jìn)行分析,,確定解決問題的具體方法和步驟,再編寫好一組讓計算機執(zhí)行的代碼,,交給計算機,,讓計算機按設(shè)計好的步驟進(jìn)行工作。這些具體的方法和步驟其實就是解決一個問題的算法,。根據(jù)算法,,選擇一種程序設(shè)計語言編寫完成任務(wù)的代碼,也就是編制程序,。一個算法應(yīng)該具有以下5個重要的特征,。
a,、有窮性,,一個算法必須保證執(zhí)行有限步之后結(jié)束。
?。?、確切性,算法的每一步驟必須有確切的定義,。
?。恪⑤斎?,一個算法有一個或多個輸出,,以反映對輸入數(shù)據(jù)加工后的結(jié)果。算法是毫無意義的,。
d,、可行性,算法原則上能夠精確地運行,,而且人們用筆和紙做有限次運算后也可完成,。
例如下面設(shè)計求三個數(shù)中最大數(shù)的算法。
首先,,定義三個A,,B,C用來保存三個數(shù),,再定義一個變量MAX用來保存最大數(shù),。其算法如下:
1)輸入三個數(shù)分別保存到A,,B,,C中。
?。玻⒆兞浚僚cB進(jìn)行比較,,如果A大于B,則將A的值存入變量MAX中,;否則將變量B的值存入變量MAX中,。
3)將變量C與MAX進(jìn)行比較,,如果C大于MAX,,則將C的值存入變量MAX中。
?。矗┹敵鲎畲髷?shù)MAX的值,。
使用相應(yīng)的程序設(shè)計語言將以上步驟進(jìn)行編碼后,即可交給計算機進(jìn)行運算處理了,。
7.1.2 流程圖
一般情況下,,使用應(yīng)用程序解決的問題都比較復(fù)雜,,故大家喜歡用一種框圖來描述算法,這樣就可以把解決問題的思路更加清晰,、形象,、直觀地表現(xiàn)出來,為下一步的程序編制打下基礎(chǔ),。使用圖形表示算法的思路是一種極好的方法,,因為千言萬語不如一張圖。常用的流程圖符號如圖7-1所示,。
使用流程圖描述上例的算法如圖7-2所示,。
由圖7-2可以看出,使用流程圖比用文字描述算法更清晰明了,。
7.2 程序結(jié)構(gòu)概述
結(jié)構(gòu)化程序設(shè)計的基本控制結(jié)構(gòu)有三種:順序結(jié)構(gòu),、選擇結(jié)構(gòu)和循環(huán)結(jié)構(gòu)。
?。?、順序結(jié)構(gòu):就是按照語句的書寫順序從上到下、逐條語句地執(zhí)行,。執(zhí)行時,,排在前面的代碼先執(zhí)行,排在后面的代碼后執(zhí)行,,執(zhí)行過程中沒有任何分支,。順序結(jié)構(gòu)是最普遍的結(jié)構(gòu)形式,也是后面兩種結(jié)構(gòu)的基礎(chǔ),。
?。狻⑦x擇結(jié)構(gòu):又叫分支結(jié)構(gòu),。是根據(jù)“條件”來選擇執(zhí)行哪一分支中的語句,。包括二分支和多分支,以及分支的嵌套,。
?。恪⒀h(huán)結(jié)構(gòu):循環(huán)結(jié)構(gòu)的程序設(shè)計比分支結(jié)構(gòu)復(fù)雜,。循環(huán)結(jié)構(gòu)的思想是利用計算機高速處理運算的特性,,重復(fù)執(zhí)行某一部分代碼,以完成大量有規(guī)則的重復(fù)運算,。
7.3 分支程序結(jié)構(gòu)
在日常生活中,,常常需要對給定的條件進(jìn)行分析、比較和判斷,并根據(jù)判斷結(jié)果采取不同的操作,。在VBA的程序中對這種情況可通過分支結(jié)構(gòu)程序來解決,。利用分支結(jié)構(gòu)使VBA能對數(shù)據(jù)進(jìn)行判斷,然后選擇需要的分支進(jìn)行處理,,從而使系統(tǒng)具有了智能功能,。
7.3.1 If……Then語句
要在VBA中做出判斷,最簡單的方法是使用“If……Then”語句,。用“If……Then”結(jié)構(gòu)有條件地執(zhí)行一個或多個語句有兩種語法形式。
1.單行結(jié)構(gòu)條件語句
單行結(jié)構(gòu)條件語句是最基本的條件語句,,其語法為:
If 邏輯表達(dá)式 Then 語句
邏輯表達(dá)式也可以是任何計算數(shù)值的表達(dá)式,VBA將這個值解釋為True或False: 為零的數(shù)值為False,而任何非零數(shù)值都被看作True,?! ?/div>
該語句的功能為:若邏輯表達(dá)式的值是Ture,則執(zhí)行Then后的語句,;若邏輯表達(dá)式的值是False,,則不執(zhí)行Then后的語句,而執(zhí)行下一條語句,。其流程圖如圖7-3所示,。
例如,要刪除工作表中的空行,,首先檢查當(dāng)前單元格是否為空,,如果為空,則刪除當(dāng)前單元格所在的行,。
If ActiveCell = "" Then Selection.EntireRow.Delete
執(zhí)行以上語句分兩種情況:第一種情況是活動單元格為空,,則執(zhí)行Then后面的語句并刪除當(dāng)前行,然后執(zhí)行If語句后面的語句,;第二種情況是活動單元格不為空,,則不執(zhí)行Then后面的語句,而直接執(zhí)行If語句后面的語句,。
2.塊結(jié)構(gòu)條件語句
在“If……Then”語句中,,如果條件成立時需要執(zhí)行多個操作,可將多個語句寫在Then后面,,并用冒號(:)分隔,。“If……Then”語句還提供另外一種塊結(jié)構(gòu)的方法,可使執(zhí)行多行代碼的過程更清晰,,其語法如下:
If 邏輯表達(dá)式 Then
語句1
語句2
……
End If
塊結(jié)構(gòu)條件語句的作用與單行結(jié)構(gòu)條件語句的功能相同,。要注意的是“If……Then”的單行格式不用“End If”語句,而塊語句則必須在條件語句的結(jié)束處有“End If”。例如,,如果當(dāng)前工作表名稱為“基礎(chǔ)資料”,,則向其中添加表頭數(shù)據(jù):
If ActiveSheet.Name = "基礎(chǔ)資料" Then
Range("A1") = "姓名"
Range("B1") = "性別"
Range("C1") = "住址"
End If
7.3.2 If……Then……Else語句
在“If……Then”語句中,當(dāng)條件為False時,,不執(zhí)行任何語句,。若要求在條件為False時執(zhí)行另一段代碼,可用“If……Then……Else”語句完成,。“If……Then……Else”語句也有兩種格式:單行和多行,。單行的格式為:
If 邏輯表達(dá)式 Then 語句1 Else 語句2
當(dāng)“邏輯表達(dá)式”的值為True時,執(zhí)行關(guān)鍵字Then后面的“語句1”,;當(dāng)“邏輯表達(dá)式”的值為False時,,執(zhí)行關(guān)鍵字Else后面的“語句2”。
多行條件語句將根據(jù)條件表達(dá)式的值來判斷并執(zhí)行其中一個語句塊,。語法格式如下:
If 邏輯表達(dá)式 Then
語句序列1
Else
語句序列2
End If
?。郑拢僚袛?#8220;邏輯表達(dá)式”的值如果為True,執(zhí)行“語句序列1”中的各條語句,;如果“邏輯表達(dá)式”的值為False時,,就執(zhí)行“語句序列2”中的各條語句。其流程圖如圖7-4所示,。
例如,,下面的程序用于判斷單元格“A1”的值:如果為空,則在該單元格中寫入數(shù)據(jù)“10”,,否則將單元格中的值增加10,。
If IsEmpty(Range("A1")) Then
Range("A1") = 10
Else
Range("A1") = Range("A1") + 10
End If
7.3.3 IIf函數(shù)
IIf函數(shù)可用來執(zhí)行簡單的條件判斷操作,它是“If……Then……Else”結(jié)構(gòu)的簡寫版本,,其語法格式如下:
.result=IIf(邏輯條件表達(dá)式,,true部分,false部分)
變量result保存函數(shù)的返回值,。“邏輯條件表達(dá)式”為判斷的條件,,當(dāng)條件為True時,IIf函數(shù)返回“true部分”,;當(dāng)條件為False時,,IIf函數(shù)返回“false部分”。
例如,,有以下的If……Then……Else語句:
If?。幔?0 Then
b = 1
Else
b = 2
End If
可改寫為IIF函數(shù)樣式:
b = IIf(a > 10, 1, 2)
技巧:“true部分”和“false部分”可以是表達(dá)式、變量或其他IIf函數(shù),。
7.3.4 If……Then……ElseIf語句
在很多情況下,,可能需要判斷幾個不同的條件,,并根據(jù)不同條件執(zhí)行不同的語句。這時可使用“If……Then……ElseIf”語句來對多個不同條件進(jìn)行判斷,,并在多個語句塊中選擇執(zhí)行其中的一個,,其語法格式如下:
If 邏輯表達(dá)式1 Then
語句序列1
ElseIf 邏輯表達(dá)式2 Then
語句序列2
ElseIf 邏輯表達(dá)式3 Then
語句序列3
……
Else
語句序列n
End If
在以上結(jié)構(gòu)中,可以包括任意數(shù)量的ElseIf子句和條件,,ElseIf子句總是出現(xiàn)在Else子句之前,。
VBA首先判斷“邏輯表達(dá)式1”的值,。如果它為False,,再判斷“邏輯表達(dá)式2”的值,以此類推,,當(dāng)找到一個為True的條件,,就會執(zhí)行相應(yīng)的語句塊,然后執(zhí)行End If后面的代碼,。如果所有“邏輯表達(dá)式”都為False,且包含Else語句塊,則執(zhí)行Else語句塊,。其流程圖如圖7-5所示,。
例如,用以下代碼對企業(yè)員工職務(wù)進(jìn)行判斷,,根據(jù)不同的職務(wù)返回不同的職務(wù)工資標(biāo)準(zhǔn):
If Range("職務(wù)")="總經(jīng)理" Then
curPay = 1000
ElseIf Range("職務(wù)") = "副總經(jīng)理" Then
curPay = 900
ElseIf Range("職務(wù)") = "廠長" Then
curPay = 800
ElseIf Range("職務(wù)") = "副廠長" Then
curPay = 700
ElseIf Range("職務(wù)") = "部門主任" Then
curPay = 500
Else
curPay = 0
End If
7.3.5 Select Case語句
在“If……Then”分支語句中,,問題可以添加更多的ElseIf塊,但是,,當(dāng)每個ElseIf塊都將相同的表達(dá)式與不同的數(shù)值比較時,,這個結(jié)構(gòu)編寫起來很乏味,也不易閱讀,。在這種情況下可以用多分支選擇結(jié)構(gòu)“Select Case”語句,。
“Select Case”語句的功能與“If……Then……Else”語句類似,但對多重選擇的情況,,“Select Case”語句可使代碼更加易讀,。
“Select Case”在結(jié)構(gòu)的開始處理一個測試表達(dá)式并只計算一次,然后,,VBA將表達(dá)式的值與結(jié)構(gòu)中的每個Case的值進(jìn)行比較,,如果相等,就執(zhí)行與該Case相關(guān)聯(lián)的語句塊,,執(zhí)行完畢再跳轉(zhuǎn)到End Select語句后執(zhí)行,。其語法格式如下:
Select Case 測試表達(dá)式
Case 表達(dá)式列表1
語句序列1
Case 表達(dá)式列表2
語句序列2
……
Case Else
語句序列n
End Select
其中“測試表達(dá)式”可以是數(shù)值型或字符型的表達(dá)式,通常是一個數(shù)值型或字符型的變量,。表達(dá)式列表可以是一個或幾個值的列表,。如果在一個列表中有多個值,就用逗號將各個值分隔開。每一個語句序列中含零個或多個語句,。如果不止一個Case與測試表達(dá)式相匹配,,則只對第一個匹配的Case執(zhí)行與之相關(guān)聯(lián)的語句塊vkjs如果表達(dá)式列表中沒有一個值與測試表達(dá)式相匹配,則VBA執(zhí)行Case Else子句(此項可選)中的語句,。其流程圖如圖7-6所示,。表達(dá)式列表可以按以下幾種情況進(jìn)行書寫。
表達(dá)式:這種方式用來表達(dá)一些具體的取值,。例如,,Case1,3,,5,。
表達(dá)式 A To表達(dá)式B:這種方式用來表示一個數(shù)據(jù)范圍。例如,,Case 1 To 10,。
Is比較運算符表達(dá)式。例如,,Case Is<60表示所有小于60的值,。
以上三種情況的混合。例如,,Case 0 To 60,,80,Is>90
注意:Select Case結(jié)構(gòu)每次都要在開始處計算表達(dá)式的值,;If……Then……Else結(jié)構(gòu)為每個ElseIf語句計算不同的表達(dá)式,。只有當(dāng)If語句和每一個ElseIf語句計算的表達(dá)式相同時,才能用Select Case結(jié)構(gòu)替換If……Then……Else結(jié)構(gòu),。
例如,,將上例中使用“If……Then……ElseIf”語句編寫的程序改寫為以下形式:
Select Case Range("職務(wù)")
Case "總經(jīng)理"
curPay = 1000
Case?。⒏笨偨?jīng)理"
curPay = 900
Case?。S長"
curPay = 800
Case "副廠長"
curPay = 700
Case?。⒉块T主任"
curPay = 500
Case Else
curPay = 0
End Select
在Select Case語句中,,可以使用Is關(guān)鍵字后面加上比較運算符來對某一個區(qū)間進(jìn)行判斷。例如用以下代碼計算個人所得稅,,其中個人所得稅的稅率如圖7-7所示,。
Function 計算個人所得稅(curPay As Currency)
Dim curTemp As Currency
Dim CurPay1 As Currency
curPay1 = curPay - 1600
Select Case curPay
Case Is <= 500
curTemp = curPay1*0.05
Case Is <= 2000
curTemp = (curPay1-500)*0.1+25
Case Is <= 5000
curTemp = (curPay1-2000)*0.15+125
Case Is <= 20000
curTemp = (curPay1-5000)*0.2+375
Case Is <= 40000
curTemp = (curPay1-20000)*0.25+1375
Case Is <60000
curTemp = (curPay1-40000)*0.3+3375
Case Is <80000
curTemp = (curPay1-60000)*0.35+6375
Case Is <100000
curTemp = (curPay1-60000)*0.4+10375
Case Else
curTemp = (curPay1-100000)*0.45+15375
End Select
計算個人所得稅 = curTemp
End Function
在使用Is關(guān)鍵字進(jìn)行條件判斷時,條件的先后順序很重要,。如本例中,,若將Is<100000寫在第一個條件位置,,程序運行將得不到正確的結(jié)果。
7.3.6 分支結(jié)構(gòu)的嵌套
在一個分支結(jié)構(gòu)語句中還可以包含另一個分支結(jié)構(gòu)語句,,這稱為嵌套,。例如,以下程序用于判斷當(dāng)前單元格中保存值的類型:
Sub 判斷當(dāng)前單元格數(shù)據(jù)類型()
If IsEmpty(ActiveCell) Then '單元格為空
MsgBox?。?dāng)前單元格為空,,請輸入數(shù)據(jù)后再執(zhí)行本程序!"
Else '單元格不為空
If IsNumeric(ActiveCell.Value) Then '單元格為數(shù)值
If ActiveCell.Value?。健? Then '數(shù)據(jù)為零
ActiveCell.offset(0,1).Value = "零"
ElseIf ActiveCell.Value?。尽? Then '數(shù)據(jù)為正數(shù)
ActiveCell.offset(0,1).Value = "正數(shù)"
Else '數(shù)據(jù)為負(fù)數(shù)
ActiveCell.offset(0,1).Value = "負(fù)數(shù)"
End If
Else '數(shù)據(jù)不為數(shù)值,則為文本
ActiveCell.offset(0,1).Validation = "文本"
End If
End If
End Sub
這段代碼使用了If語句的嵌套結(jié)構(gòu),,嵌套的層次最多為三層,。程序代碼的功能在代碼后面的注釋中都進(jìn)行了說明,其流程圖如圖7-8所示,。
注意:在塊If語句的嵌套中,,每一個If語句都需要一個End If語句與之對應(yīng),在輸入代碼時最好采用縮進(jìn)結(jié)構(gòu),,以便于看清楚嵌套的層次,,防止少寫End If語句。
7.4 循環(huán)程序結(jié)構(gòu)
前面介紹了使用分支結(jié)構(gòu)讓VBA程序具有判斷能力,,從而使程序?qū)崿F(xiàn)一定的智能化,。但是這種分支結(jié)構(gòu)的程序都是從代碼的開始處按順序執(zhí)行,,只是路途跳過一些語句不執(zhí)行,。
在實際需要中,有時還需要反復(fù)操作某一個或幾個動作,。如果將這種操作編寫成VBA代碼來完成,,則表示程序運行到一個位置后,又返回前面的代碼來進(jìn)行操作,,這種結(jié)構(gòu)稱為循環(huán)結(jié)構(gòu),。VBA中提供了多種循環(huán)結(jié)構(gòu)控制語句。
7.4.1 Do……Loop循環(huán)
用Do循環(huán)重復(fù)執(zhí)行一語句塊,,且重復(fù)次數(shù)不定,。“Do……Loop”語句有4種演變形式,但每種都需要計算條件表達(dá)式的值,,以決定是否繼續(xù)執(zhí)行,。在Do循環(huán)中可以使用“Exit Do”語句中途退出該循環(huán)。
1. Do While……Loop循環(huán)
“Do While”語句屬于先測試循環(huán)條件的“Do……Loop”語句,,其語法格式如下:
Do While 邏輯表達(dá)式
語句序列1
?。跡xit Do]
?。壅Z句序列2]
Loop
其中Do While和Loop都是關(guān)鍵字,在Do While和Loop之間的語句稱為循環(huán)體,。
當(dāng)VBA執(zhí)行這個Do循環(huán)時,,首先判斷邏輯表達(dá)式:如果為False(或零),則跳過所有語句,,執(zhí)行Loop的下一條語句:如果為True(或非零),,則執(zhí)行循環(huán)體,當(dāng)執(zhí)行到Loop語句后,,又跳回到Do While語句再次判斷條件,。在循環(huán)體中如果包含有Exit Do語句,當(dāng)執(zhí)行到Exit Do語句,,馬上跳出循環(huán),,執(zhí)行Loop的下一條語句。其流程圖如圖7-9所示,。
這種形式的循環(huán)體可能執(zhí)行零次或多次,。只要條件表達(dá)式為True或非零,循環(huán)就會重復(fù)執(zhí)行,。如果邏輯表達(dá)式最初就為False,則不會執(zhí)行循環(huán)語句,。
2. Do……Loop While循環(huán)
“Do……Loop While”語句屬于后測試循環(huán)條件的“Do……Loop”語句,該結(jié)構(gòu)先執(zhí)行循環(huán)體中的語句,,然后再進(jìn)行條件判斷,。這種形式的循環(huán)體至少執(zhí)行一次,其語法格式如下:
Do
語句序列1
?。跡xit Do]
?。壅Z句序列2]
Loop While 邏輯表達(dá)式
其流程圖7-10所示。
3. Do Until……Loop循環(huán)
該語句為先測試結(jié)束條件的“Do……Loop”語句,,其語法形式如下:
Do Until 邏輯表達(dá)式
語句序列1
?。跡xit Do]
[語句序列2]
Loop
這種形式與“Do While……Loop”類似,,不同的是當(dāng)邏輯表達(dá)式的值為False時才執(zhí)行循環(huán)體,,否則退出循環(huán)。這種形式的循環(huán)體可能執(zhí)行零次或多次,。
4.Do……Loop Until循環(huán)
這是后測試結(jié)束條件的“Do……Loop”語句,,其語法形式如下:
Do
語句序列1
[Exit Do]
?。壅Z句序列2]
Loop Until 邏輯表達(dá)式
這種形式與“Do……Loop While”類似,,不同的是當(dāng)邏輯表達(dá)式的值為False時才執(zhí)行循環(huán)體,否則退出循環(huán),。這種形式的循環(huán)體至少能被執(zhí)行一次,。
例如,,在要求用戶輸入密碼時,一般都要給用戶三次機會,,每次的輸入過程和判斷過程都相同,,這時就可以使用循環(huán)語句。
Sub 輸入密碼()
Dim strPassword As String '保存密碼
Dim i As Integer '輸入密碼的次數(shù)
Do
strPasswor = InputBox("請輸入密碼") '輸入密碼
If strPassword = "wyh" Then '判斷密碼是否正確
Exit Do '退出循環(huán)
Else
MsgBox("請輸入正確的密碼,!")
End If
i = i + 1
Loop While i < 3
If i >= 3 Then '超過正常輸入密碼次數(shù)
MsgBox "未登錄用戶"
End
Else
MsgBox "歡迎你使用本系統(tǒng),!"
End If
End Sub
程序中使用“Do……Loop While”循環(huán)讓循環(huán)體至少執(zhí)行一次。程序的流程圖如圖7-11所示,。
在循環(huán)體中,,首先是顯示一個輸入框讓用戶輸入密碼;接著對用戶輸入的密碼進(jìn)行判斷,,如果密碼正確,,則執(zhí)行Exit Do語句退出循環(huán),執(zhí)行Loop While下面的語句,,如果密碼錯誤,,將顯示一個提示信息,并累計錯誤次數(shù),;最后判斷是否繼續(xù)循環(huán),。
7.4.2 While……Wend循環(huán)
“While……Wend”循環(huán)語句的功能與“Do……While”循環(huán)相同,是從Basic的早期版本中保留下來的語句,,VBA保留它是為了向后兼容,,其語法格式如下:
While 邏輯表達(dá)式
循環(huán)體
……
Wend
如果“邏輯表達(dá)式”為True,則所有的“循環(huán)體”語句都會執(zhí)行,,一直執(zhí)行到Wend語句,,然后再回到While語句,并再一次檢查“邏輯表達(dá)式”的值,,如果還是為True,,則重復(fù)執(zhí)行,;如果不為True,,則程序會從Wend語句之后的語句繼續(xù)執(zhí)行。
7.4.3 For……Next循環(huán)
“For……Next”語句以指定次數(shù)來重復(fù)執(zhí)行循環(huán)體,。與Do循環(huán)不同,,F(xiàn)or循環(huán)使用一個叫做計數(shù)器的變量,每重復(fù)一次循環(huán)之后,,計數(shù)器變量的值就會增加或減少,。在For循環(huán)中可以使用Exit For語句隨時退出該循環(huán)。For循環(huán)的語法格式如下:
For 循環(huán)變量=初始值 To 終值 [Step 步長值]
語句序列1
?。跡xit For]
語句序列2
Next?。垩h(huán)變量]
其中:步長值可正可負(fù),。如果步長值為正,則初始值必須小于或等于終值才能執(zhí)行循環(huán)體,,否則退出循環(huán),;如果步長值為負(fù),則初始值必須大于或等于終值,,這樣才能執(zhí)行循環(huán)體,。如果沒能設(shè)置Step,則步長值默認(rèn)為1,。“For……Next”循環(huán)結(jié)構(gòu)的流程圖如圖7-12所示,。
VBA執(zhí)行For循環(huán)時的過程如下:
步驟1 將初始值賦值給循環(huán)變量,。
步驟2 判斷循環(huán)變量是否超過終值,,若為真(True),退出循環(huán),,執(zhí)行Next的下一語句,。這里的“超過終值”有兩種意思:若步長值為負(fù)數(shù)時,超過就是循環(huán)變量的值小于終值,;而當(dāng)步長值為正數(shù)時,,超過就是循環(huán)變量的值大于終值。
步驟3 執(zhí)行循環(huán)體,。
步驟4 循環(huán)體執(zhí)行完后到達(dá)Next語句時,,循環(huán)變量累加上步長值。
步驟5 重復(fù)步驟2到步驟4,。
For循環(huán)一般都可計算出循環(huán)體的執(zhí)行次數(shù),,計算公式如下:
循環(huán)次數(shù)=【(終值-初值)/步長值】+1
這里用中括號表示取整。
在事先不知道循環(huán)體需要執(zhí)行多少次時,,應(yīng)該用Do循環(huán),;而在知道循環(huán)體要執(zhí)行的次數(shù)時,最好使用“For……Next”循環(huán),。
例如,,要編寫代碼完成以下工作:在工作表“Sheet2”的前100行中,如果第2列單元格的值為0,,則刪除所在行,。可使用“For……Next”循環(huán)語句編寫如下代碼:
Sub 使用 For 循環(huán)刪除為0的行()
Dim?。椤s Integer
With Sheets("sheet2")
For i = 1 To 100
If .Cells(i,2).EntireRow.Delete
End If
Next
End With
End Sub
比較兩個過程可以看出,,使用“For……Next”循環(huán)時,不需要開發(fā)人員手工編寫代碼更新循環(huán)變量,,而使用“Do While……Loop”循環(huán)時,,必須在循環(huán)體中包含更改循環(huán)條件的語句,,否則循環(huán)將一直執(zhí)行下去,永遠(yuǎn)退不出來,,形成死循環(huán),。
7.4.4 循環(huán)的嵌套
與分支結(jié)構(gòu)類似,循環(huán)結(jié)構(gòu)也可進(jìn)行嵌套,,即將一個循環(huán)放置在另一個循環(huán)中,。VBA允許在同一過程里嵌套多種類型的循環(huán)。
在編寫嵌套循環(huán)程序的代碼時一定要注意每個循環(huán)語句的配對情況,。如圖7-13所示,,其中(a)是正確的嵌套關(guān)系,第一個Next關(guān)閉了內(nèi)層的For循環(huán),,而最后一個Loop關(guān)閉了外層的Do循環(huán),。同樣,在嵌套的If語句中,,End If語句自動與最靠近的前一個If語句配對。嵌套的Do……Loop結(jié)構(gòu)的工作方式也是一樣的,,最內(nèi)圈的Loop語句與最內(nèi)圈的Do語句匹配,。圖7-13(b)則是錯誤的嵌套關(guān)系,。
第4章中編寫的九九乘法表就使用了兩個For循環(huán)進(jìn)行嵌套,,其代碼如下:
Private Sub cmd99_Click()
Dim i As Integer
Dim j As Integer
Dim StrMsg As String
For i = 1 To 9
For j = 1 To 9
strMsg = strMsg & "*" & j & "=" & i * j & ""
Next j
strMsg = strMsg & vbCrLf
Next i
MsgBox strMsg , , "九九乘法表"
End Sub
分析嵌套循環(huán)時,可從最內(nèi)層的循環(huán)開始,。以上代碼最內(nèi)層循環(huán)的語句為:
For?。辏健? To 9
strMsg = strMsg & i & "*" & j & "=" & i * j & " "
Next j
這部分代碼用來生成一行數(shù)據(jù),,假設(shè)i為1,,執(zhí)行完以上代碼后,變量strMsg保存的內(nèi)容如下:
1*1=1 1*2=2 1*3=3 1*4=4 1*5=5 1*6=6 1*7=7 1*8=8 1*9=9
將內(nèi)循環(huán)精簡為一個命令(如本例中的“輸出一行數(shù)據(jù)”),,則九九乘法表的程序變?yōu)橐韵滦问剑?/div>
Private Sub cmd99_Click()
Dim i As Integer
Dim j As Integer
Dim strMsg As String
For i = 1 To 9
輸出一行數(shù)據(jù)
strMsg = strMsg & vbCrLf
Next i
MsgBox strMsg, , "九九乘法表"
End Sub
即可得到一個單循環(huán),。該單循環(huán)執(zhí)行9次即可得到9行數(shù)據(jù),也就得到了需要的乘法表,。
注意:在嵌套結(jié)構(gòu)里的循環(huán)結(jié)構(gòu)中使用Exit語句時,,退出的只是包含該語句的當(dāng)前循環(huán)結(jié)構(gòu),,而不是整個黃磊結(jié)構(gòu),。
7.4.5 Goto語句
使用Goto語句,可無條件地將程序代碼跳轉(zhuǎn)到指定的行去執(zhí)行,。VBA中保留Goto語句是為了保持與早期的Basic版本兼容,。Goto語句的語法格式如下:
Goto 行號/標(biāo)號
注意:Goto只能跑到它所在過程中的行,。
要使用Goto語句,首先需用了解VBA中語句的行號和標(biāo)號,。在早期的Basic語言中,,每一行程序都有一個行號,行號按從小到大的順序排列,,例如:
Sub 使用Do循環(huán)刪除為0的行()
10 Dim i As Integer
20 i = 1
30 With Sheets("sheet2")
40 Do While i <= 100
50 If .Cells(i,2) = 0 Then
60 .Cells(i,2).EntireRow.Delete
70 End If
80 i = i + 1
90 Loop
100 End With
End Sub
在VBA中,,執(zhí)行這樣的代碼也不會出錯。為程序添加行號的目的就是方便使用Goto語句跳轉(zhuǎn)到相應(yīng)的語句去執(zhí)行,。
隨著結(jié)構(gòu)化程序設(shè)計方法的使用,,使用Goto語句跳轉(zhuǎn)的方式已經(jīng)不常用了,也就不再需要為每行代碼添加行號了,。
為了使Goto跳轉(zhuǎn)到需要的地方,,可在程序中添加標(biāo)號。標(biāo)號是以英文字母開頭的一個標(biāo)識符后加上一個冒號構(gòu)成的,。在程序代碼中輸入的標(biāo)號始終是靠左對齊的,。
例如,以下代碼使用Goto語句來進(jìn)行循環(huán)操作,,刪除單元格為0的行,。
Sub 使用Goto語句刪除為0的行()
Dim i As Integer
i = 1
linel:
With Sheets("sheet2")
If .Cells(i,2) = 0 Then
.Cells(i,2).EntireRow.Delete
End If
i = i + 1
If i <= 100 Then GoTo linel
End With
End Sub
注意:這里只是演示Goto語句的用法,不建議讀者在程序中使用太多的Goto語句,,因為使用Goto語句會使程序代碼不容易閱讀及調(diào)試,。應(yīng)盡可能使用結(jié)構(gòu)化控制語句(Do……Loop,F(xiàn)or……Next,,If……Then……Else和Select Case),。
|
|