循環結構
循環結構允許重復執行一行或數行代碼。VisualBasic支持的循環結構有:
1.Do...Loop
2.For...Next
3.ForEach...Next
Do...Loop
用Do循環重復執行一語句塊,且重復次數不定。Do...Loop語句有幾種演變形式,但每種都計算數值條件以決定是否繼續執行。如同If...Thencondition必須是一個數值或者值為True(非零)或False(零)的表達式。在下面的Do...Loop循環中,只要condition為True就執行statements。
DoWhilecondition
statements
Loop
當VisualBasic執行這個Do循環時會首先測試condition。如果condition為False(零),則跳過所有語句。如果condition為True(非零),則VisualBasic執行語句,然後退回到DoWhile語句再測試條件。
因此,只要condition為True或非零,循環可以隨意執行多少次。如果condition一開始便為False,則不會執行語句。例如,以下過程將計算某一目標字符串在另一字符串中出現的次數,只要發現目標串就執行循環:
FunctionCountStrings(longstring,target)
Dimposition,count
position=1
DoWhileInStr(position,longstring,target)
position=InStr(position,longstring,target)_
1
count=count 1
Loop
CountStrings=count
EndFunction
如果目標字符串未出現在另一個字符串中,則InStr返回0,而且不再執行循環。
Do...Loop語句的另一種演變形式是先執行語句,然後在每次執行後測試condition。這種形式保證statements至少執行一次:
Do
statements
LoopWhilecondition
其它兩種演變形式類似於前兩個,所不同的是,只要condition為False而不是True,它們就執行循環。
For...Next000
在不知道循環內需要執行多少次語句時,宜用Do循環。但是,在知道要執行多少次時,則最好使用For...Next循環。與Do循環不同,For循環使用一個叫做計數器的變量,每重復一次循環之後,計數器變量的值就會增加或者減少。For循環的語法如下:
Forcounter=startToend[Stepincrement]
statements
Next[counter]
參數Counter、Start、end和increment都是數值型的。
注意increment參數可正可負。如果increment為正,則Start必須小於等於end,否則不能執行循環內的語句。如果increment為負,則Start必須大於等於end,這樣才能執行循環體。如果沒有設置Step,則increment缺省值為1。
在執行For循環時,VisualBasic
1.設置counter等於start。
2.測試counter是否大於end。若是的話,則VisualBasic退出循環。(若increment為負,則VisualBasic測試counter是否小於end。)
3.執行語句。
4.counter增加一,或者增加increment(如果已指定的話)。
5.重復步驟2到步驟4。
以下代碼打印出所有有效的屏幕字體名:
PrivateSubForm_Click()
DimIAsInteger
Fori=0ToScreen.FontCount
PrintScreen.Fonts(i)
Next
EndSub
在VCR示例應用程序中,HighlightButton過程使用For...Next循環,一步步經過VCR窗體的控件集合,並顯示適當的Shape控件:
SubHighlightButton(MyControlAsVariant)
DimiAsInteger
Fori=0TofrmVCR.Controls.Count-1
IfTypeOffrmVCR.Controls(i)IsShapeThen
IffrmVCR.Controls(i).Name=MyControlThen
frmVCR.Controls(i).Visible=True
Else
frmVCR.Controls(i).Visible=False
EndIf
EndIf
Next
EndSub
ForEach...Next
ForEach...Next循環與For...Next循環類似,但它對數組或對象集合中的每一個元素重復一組語句,而不是重復語句一定的次數。如果不知道一個集合有多少元素,ForEach...Next循環非常有用。
ForEach...Next循環的語法如下:
ForEachelementIngroup
statements
Nextelementt
例如,下面的子過程打開Biblio.mdb,把每一個表的名字加到列表框中。
SubListTableDefs()
DimobjDbAsDatabase
DimMyTableDefasTableDef
SetobjDb=OpenDatabase("c:vbiblio.mdb",_
True,False)
ForEachMyTableDefInobjDb.TableDefs()
List1.AddItemMyTableDef.Name
NextMyTableDef
EndSub
請記住使用ForEach...Next時的幾點限制:
1.對集合,element只能是Variant變量,或一般的Object變量,或“對象浏覽器”中列出的對象。
2.對數組,element只能是Variant變量。
3.ForEach...Next不能與用戶自定義類型的數組一起使用,因為Variant不可能包含用戶自定義類型。
使用控制結構
嵌套控制結構可以把控制結構放入另一個控制結構之內(例如在For...Next循環中的If...Then塊)。一個控制結構內部包含另一個控制結構叫做nest(嵌套)。在VisualBasic中,控制結構的嵌套層數沒有限制。按一般習慣,為了使判定結構和循環結構更具可讀性,總是用縮排方式書寫判定結構或循環的正文部分。
例如,下面的過程要把打印機和屏幕共有的字體名全部打印出來:
PrivateSubForm_Click()
DimSFont,PFont
ForEachSFontInScreen.Fonts()
ForEachPFontInPrinter.Fonts()
IfSFont=PFontThen
PrintSFont
EndIf
NextPFont
NextSFont
EndSub
注意,第一個Next關閉了內層的For循環,而最後一個For關閉了外層的For循環。同樣,在嵌套的If語句中,EndIf語句自動與最靠近的前一個If語句配對。嵌套的Do...Loop結構的工作方式也是一樣的,最內圈的Loop語句與最內圈的Do語句匹配。
退出控制結構
用Exit語句可以直接退出For循環、Do循環、子過程或函數過程。Exit語句的語法很簡單:ExitFor在For循環中出現的次數沒有限制,ExitDo在Do循環中出現的次數也沒有限制。
Forcounter=startToend
[Stepincrement]
[statementblock]
[ExitFor]
[statementblock]
Next[counter[,counter][,...]]
Do[{While|Until}condition]
[statementblock]
[ExitDo]
[statementblock]
Loop
ExitDo語句可以在Do循環語法的所有版本中使用。
ExitFor和ExitDo非常有用,因為它有時適於立即退出循環,而且不再執行循環中的任何進一步迭代或者語句。例如,在前面的打印屏幕和打印機共有字體的例子中,程序不斷將打印機字體和給定的屏幕字體作比較,甚至在已經找到了一個相符的打字機字體後還在繼續尋找。對這個函數有一個效率更高的改進版,在此,只要找到相匹配的字體後就立即退出循環:
PrivateSubForm_Click()
DimSFont,PFont
ForEachSFontInScreen.Fonts()
ForEachPFontInPrinter.Fonts()
IfSFont=PFontThen
PrintSfont
ExitFor '退出內圈循環。
EndIf
NextPFont
NextSFont
EndSub
正如此例所表明的,Exit語句幾乎總是出現在If語句或SelectCase語句內部,而If語句或SelectCase語句在循環內嵌套。
用Exit語句中斷循環時,計數器變量的值會因退出循環的方式而不同:
1.在完成循環時,計數器的值等於上限值加上步進值。
2.在提前退出循環時,計數器變量保持其值,並遵從有關取值范圍的一般規則。
3.在集合之外疊代時,如果計數器變量為Object類型,則其值為Nothing;如果計數器變量為Variant類型,則其值為Empty。
退出子過程或函數過程
也可從控制結構內部退出過程。ExitSub和ExitFunction的語法,和上一節“退出控制結構”中的ExitFor和ExitDo相似。ExitSub可以出現在子過程主體內的任何地方,出現的次數隨需要而定。
當過程已完成每個任務並可直接返回時,ExitSub和ExitFunction是非常有用的。例如,如果想改動前面的例子,使得對查找到的打印機和屏幕的共有字體,只打印其中的第一個,則可用ExitSub:
PrivateSubForm_Click()
DimSFont,PFont
ForEachSFontInScreen.Fonts()
ForEachPFontInPrinter.Fonts()
IfSFont=PFontThen
PrintSfont
ExitSub '退出過程。
EndIf
NextPFont
NextSFont
EndSub