程序執(zhí)行就是指令執(zhí)行的循環(huán)過(guò)程
第9章 VBA與模塊
9.1 VBA基礎(chǔ)
宏的功能很強(qiáng)大而且易于掌握,如果要對(duì)數(shù)據(jù)庫(kù)對(duì)象進(jìn)行更復(fù)雜、更靈活的控制,就需要編程來(lái)實(shí)現(xiàn)。模塊對(duì)象可以解決此類問(wèn)題,它是一種重要的Access數(shù)據(jù)庫(kù)對(duì)象,以VBA(Visual Basic for Application)語(yǔ)言為基礎(chǔ)編寫的,是功能更強(qiáng)大的程序代碼集合。利用模塊可以將數(shù)據(jù)庫(kù)中的各種對(duì)象聯(lián)結(jié)起來(lái),從而使其構(gòu)成一個(gè)完整的系統(tǒng)。
VBA是一種應(yīng)用程序開(kāi)發(fā)工具,是基于VB(Visual Basic)發(fā)展而來(lái)的。微軟將VB引入Office軟件中用于開(kāi)發(fā)應(yīng)用程序,這種集成在Office中的VB被稱為VBA(Visual Basic for Application)。
使用VBA編寫的程序保存在Access數(shù)據(jù)庫(kù)文件中,無(wú)法脫離Access應(yīng)用程序環(huán)境而獨(dú)立運(yùn)行。
9.1.1 VBA的編程環(huán)境
VBA開(kāi)發(fā)環(huán)境又稱為VBE(Visual Basic Editor),在VBE中可以編寫VBA函數(shù)、過(guò)程和VBA模塊。VBE的打開(kāi)方法同標(biāo)準(zhǔn)模塊的創(chuàng)建方法,也可以使用Alt+F11快捷方式打開(kāi)編輯環(huán)境。
VBE窗口通常由一些常用工具和多個(gè)窗口組成,如圖9-1所示。
圖9-1 VBE窗口
VBE編輯器主要由代碼窗口、立即窗口、監(jiān)視窗口、本地窗口、屬性窗口、對(duì)象瀏覽器以及工程資源管理器等組成。
1.代碼窗口
用來(lái)編寫、顯示和修改VBA代碼。
2.工程資源管理器窗口
列出了所有的模塊以及類對(duì)象。
3.屬性窗口
屬性窗口列出了所選對(duì)象的各個(gè)屬性。
4.立即窗口
當(dāng)單步執(zhí)行程序時(shí),使用該窗口可以直接輸入語(yǔ)句或命令并查看執(zhí)行結(jié)果。
5.監(jiān)視窗口
用于顯示當(dāng)前工程中定義的監(jiān)視表達(dá)式的值。
6.本地窗口
用于顯示所有在當(dāng)前過(guò)程在執(zhí)行過(guò)程中的變量聲明和變量值。
7.對(duì)象瀏覽器
用于顯示對(duì)象模型中以及工程過(guò)程中的可用類、屬性、方法、事件及常數(shù)變量。
9.1.2 VBA的語(yǔ)法
任何程序語(yǔ)言編寫的代碼都是由語(yǔ)句組成的,而語(yǔ)句又是由數(shù)據(jù)、表達(dá)式、函數(shù)等基本語(yǔ)法單位構(gòu)成的。下面我們來(lái)介紹一下VBA的標(biāo)準(zhǔn)數(shù)據(jù)類型、常量、變量、運(yùn)算符、表達(dá)式等內(nèi)容。
VBA語(yǔ)句由保留字及語(yǔ)句體組成,而語(yǔ)句體由命令短語(yǔ)和表達(dá)式組成。
保留字和命令短語(yǔ)中的關(guān)鍵字是系統(tǒng)規(guī)定的專用符號(hào),通常由英文單詞或其縮寫表示,必須嚴(yán)格按照系統(tǒng)要求來(lái)寫。
通常每條語(yǔ)句占一行,一行最多允許有255個(gè)字符;如果一行書寫多個(gè)語(yǔ)句,語(yǔ)句之間用冒號(hào)“:”隔開(kāi);如果某個(gè)語(yǔ)句在一行內(nèi)沒(méi)有寫完,可用下劃線“_”作為連接符。
1.?dāng)?shù)據(jù)類型
與其他的編程語(yǔ)言一樣,VBA為數(shù)據(jù)操作提供了數(shù)據(jù)類型,稱為基本數(shù)據(jù)類型。表9-1列出了VBA程序中的基本數(shù)據(jù)類型,以及它們所占用的存儲(chǔ)空間、取值范圍等。
表9-1 VBA的基本數(shù)據(jù)類型
2.常量
常量是指在程序可以直接引用的量,其值在程序運(yùn)行期間保持不變。常量有文字常量、符號(hào)常量和系統(tǒng)常量3種表示形式。
文字常量也稱直接常量,實(shí)際就是常數(shù),直接出現(xiàn)在代碼中。例如#2014-5-1#是日期型常量,5000是數(shù)值型常量,如此等等。
符號(hào)常量是用標(biāo)識(shí)符來(lái)表示常量的名稱,使用關(guān)鍵字Const來(lái)聲明。例如,ConstPI= 3.14159。符號(hào)常量一般要求大寫,以便與變量區(qū)分。
系統(tǒng)常量是Visual Basic系統(tǒng)預(yù)先定義的常量,用戶可以直接引用。例如,vbBlack是color常數(shù),表示黑色;True是邏輯型常量,表示真;vbOKOnly是MsgBox常數(shù),如此等等。
3.變量
變量是在程序運(yùn)行期間其值可以改變的量,是內(nèi)存單元中用于存儲(chǔ)數(shù)值的臨時(shí)存儲(chǔ)單元,可以存放各種類型的數(shù)據(jù)。
每個(gè)變量都有一個(gè)名字,需要通過(guò)變量名來(lái)引用變量。一般來(lái)說(shuō),變量的命名要有一定的意義,必須以字母開(kāi)頭,不能含有空格、運(yùn)算符以及@、$等特殊字符,也不能使用系統(tǒng)保留字作為變量名。
一般來(lái)說(shuō),在程序中使用變量時(shí)需要先聲明,聲明變量可以起到兩個(gè)作用:一是指定變量的名稱和數(shù)據(jù)類型;二是指定變量的取值范圍。
在變量使用之前進(jìn)行聲明,稱為顯式聲明。也可以不聲明直接使用變量,系統(tǒng)將默認(rèn)該變量是變體數(shù)據(jù)類型,這種聲明方式稱為隱式聲明。
也可以在程序開(kāi)始處直接輸入語(yǔ)句“Option Explicit”進(jìn)行強(qiáng)制聲明。變量聲明語(yǔ)句的語(yǔ)法格式為:
Dim 變量名 [As 類型名|類型符] [,變量名[As 類型名|類型符]]
該語(yǔ)句的功能是,定義指定的變量并為其分配內(nèi)存空間?!癆s 類型名”用于指定變量的類型。如省略,則默認(rèn)變量為Variant類型。
例如,
Dim x As Single '聲明了一個(gè)單精度型變量x。
Dim name $, address $ '聲明了兩個(gè)字符串變量name,address,$是字符型數(shù)據(jù)的類型符。Dim m As Currency '聲明了一個(gè)貨幣型變量m。
變量都有一定的作用范圍,即作用域。按照變量的作用域可以將變量分為局部變量、模塊級(jí)變量、全局變量。
在過(guò)程內(nèi)部聲明的變量稱為局部變量,僅僅在過(guò)程范圍內(nèi)有效。
在模塊的起始位置、所有過(guò)程之外聲明的變量,稱為模塊級(jí)變量,在該模塊中有效。
在標(biāo)準(zhǔn)模塊起始位置、所有過(guò)程之外,用Public關(guān)鍵字聲明的變量稱為全局變量,在所有類模塊和標(biāo)準(zhǔn)模塊的所有過(guò)程中都是可見(jiàn)的。
4.表達(dá)式
表達(dá)式是指用運(yùn)算符將常量、變量和函數(shù)連接起來(lái)的式子。表達(dá)式的構(gòu)成必須符合VBA的語(yǔ)法規(guī)則。
5.運(yùn)算符
VBA提供許多運(yùn)算符來(lái)完成各種計(jì)算和處理。根據(jù)運(yùn)算的不同,可以分為算術(shù)運(yùn)算符、連接運(yùn)算符、關(guān)系運(yùn)算符和邏輯運(yùn)算符。
算術(shù)運(yùn)算符用于數(shù)值的算術(shù)運(yùn)算,共有7個(gè),如表9-2所示。
表9-2 算術(shù)運(yùn)算符
連接運(yùn)算符用于連接兩個(gè)字符串,有&和+這兩種運(yùn)算符。使用&運(yùn)算符,會(huì)將數(shù)值型數(shù)據(jù)先轉(zhuǎn)換成字符串類型后再進(jìn)行連接。使用+,當(dāng)字符串類型數(shù)據(jù)是數(shù)字字符串時(shí),則直接進(jìn)行加法運(yùn)算。
關(guān)系運(yùn)算符也稱為比較運(yùn)算符,其結(jié)果為布爾型數(shù)據(jù)True或者False。關(guān)系運(yùn)算符有6個(gè),分別是<,<=,>,>=,<>,=。
邏輯運(yùn)算符也稱為布爾運(yùn)算符,運(yùn)行結(jié)果為布爾型數(shù)據(jù)True或者False。按照優(yōu)先級(jí),邏輯運(yùn)算符依次為Not,And,Or。
6.內(nèi)部函數(shù)
內(nèi)部函數(shù)也稱標(biāo)準(zhǔn)函數(shù),是VBA為用戶提供的標(biāo)準(zhǔn)過(guò)程。使用這些函數(shù),可以使某些特定的操作更加簡(jiǎn)便。
根據(jù)標(biāo)準(zhǔn)函數(shù)的功能,可以將標(biāo)準(zhǔn)函數(shù)分為數(shù)學(xué)函數(shù)、字符串函數(shù)、轉(zhuǎn)換函數(shù)、日期函數(shù)、測(cè)值函數(shù)、顏色函數(shù)等。
數(shù)學(xué)函數(shù)用于數(shù)學(xué)計(jì)算,表9-3列出了常用的數(shù)學(xué)函數(shù)。
表9-3 數(shù)學(xué)函數(shù)
說(shuō)明:表中的自變量x可以為常量、變量和數(shù)值表達(dá)式,但必須寫在圓括號(hào)中。
字符串函數(shù)是指自變量或函數(shù)值為字符串的函數(shù)。表9-4列出了常用的字符串函數(shù)。
表9-4 字符串函數(shù)
說(shuō)明:表中的n和s分別表示數(shù)值表達(dá)式和字符表達(dá)式,函數(shù)名和參數(shù)后可帶后綴“$”,表明函數(shù)值為字符串。
日期函數(shù)對(duì)日期型數(shù)據(jù)進(jìn)行運(yùn)算,表9-5列出了常用的日期函數(shù)。
表9-5 日期函數(shù)
9.2 VBA的程序控制
VBA與其他程序設(shè)計(jì)語(yǔ)言一樣,也具有結(jié)構(gòu)化程序設(shè)計(jì)的3種結(jié)構(gòu):順序結(jié)構(gòu)、選擇結(jié)構(gòu)和循環(huán)結(jié)構(gòu)。
9.2.1 順序結(jié)構(gòu)
在順序結(jié)構(gòu)中,通常使用賦值語(yǔ)句、輸入語(yǔ)句、輸出語(yǔ)句、注釋語(yǔ)句等。
1.賦值語(yǔ)句
變量聲明以后,需要為變量賦值,為變量賦值應(yīng)使用賦值語(yǔ)句。
賦值語(yǔ)句的語(yǔ)法格式為:
變量名=表達(dá)式
該語(yǔ)句的功能是,首先計(jì)算表達(dá)式的值,然后將該值賦給賦值號(hào)“=”左邊的變量。
已經(jīng)賦值的變量可以在程序中使用,還可以改變變量的值。
2.輸入語(yǔ)句
可以利用InputBox函數(shù)進(jìn)行數(shù)據(jù)的輸入。
3.輸出語(yǔ)句
可以利用MsgBox語(yǔ)句進(jìn)行信息輸出,它沒(méi)有返回值,通常使用該語(yǔ)句顯示一條提示信息。
4.注釋語(yǔ)句
注釋語(yǔ)句用于對(duì)程序或語(yǔ)句的功能給出解釋和說(shuō)明。
注釋語(yǔ)句的語(yǔ)法格式為:
格式1:
Rem 注釋內(nèi)容
格式2
'注釋內(nèi)容
【例9-1】在“教學(xué)管理”數(shù)據(jù)庫(kù)中,創(chuàng)建一個(gè)模塊,在其中創(chuàng)建一個(gè)welcome過(guò)程,可以根據(jù)輸入的人名,彈出消息框表示歡迎。
操作步驟如下:
(1)打開(kāi)“教學(xué)管理”數(shù)據(jù)庫(kù),選擇“創(chuàng)建”選項(xiàng)卡中的“宏與代碼”組,單擊“模塊”按鈕,打開(kāi)VBE窗口。
(2)在模塊1的代碼窗口(見(jiàn)圖9-2)中,輸入如表9-5所示的代碼。
圖9-2 welcome過(guò)程
(3)單擊運(yùn)行按鈕,或者按F5功能鍵,查看運(yùn)行效果。
9.2.2 選擇結(jié)構(gòu)
選擇結(jié)構(gòu)也稱為分支結(jié)構(gòu),對(duì)給定的條件進(jìn)行分析、比較和判斷,并根據(jù)判斷結(jié)果決定程序的走向。選擇結(jié)構(gòu)語(yǔ)句有If條件語(yǔ)句和Select Case語(yǔ)句兩種。
1.If語(yǔ)句
1)單分支If語(yǔ)句
單分支If語(yǔ)句的語(yǔ)句格式如下:
格式1:
If <表達(dá)式> Then <語(yǔ)句>
格式2:
If <表達(dá)式> Then
<語(yǔ)句序列>
End If
功能:先計(jì)算表達(dá)式的值,當(dāng)表達(dá)式的值為真(True)時(shí),執(zhí)行<語(yǔ)句序列>中的語(yǔ)句,然后執(zhí)行if語(yǔ)句的下一條語(yǔ)句,如果表達(dá)式的值為假(False),直接執(zhí)行if語(yǔ)句的下一條語(yǔ)句。
【例9-2】北京市內(nèi)快遞的收費(fèi)標(biāo)準(zhǔn)是3公斤內(nèi)收費(fèi)10元,超出部分5元/公斤。編寫程序根據(jù)貨物的重量計(jì)算快遞費(fèi)用。
分析:根據(jù)題意,計(jì)算規(guī)則為:如果重量不大于3公斤,費(fèi)用為10元;如果重量大于3公斤,費(fèi)用為10+(重量-3)*5元。
操作步驟如下:
(1)打開(kāi)“教學(xué)管理”數(shù)據(jù)庫(kù),打開(kāi)VBE窗口。
(2)在模塊1的代碼窗口中,輸入下面的代碼。
Sub mailfee( )
Dim w, fee As Single
w=InputBox("請(qǐng)輸入貨物重量(公斤)","輸入重量")
If w<=3 Then fee=10
If w>3 Then fee=10+(w-3)*5
MsgBox "需要支付的郵費(fèi)是:"&fee&"元",vbOKOnly,"計(jì)算結(jié)果"
End Sub
(3)單擊“運(yùn)行”按鈕,或者按F5功能鍵,查看運(yùn)行效果。
2)雙分支If語(yǔ)句
雙分支If語(yǔ)句的語(yǔ)句格式如下:
格式1:
If <表達(dá)式> Then <語(yǔ)句1> Else <語(yǔ)句2>
格式2:
If <表達(dá)式> Then
<語(yǔ)句序列1>
Else
<語(yǔ)句序列2>
End If
功能:先計(jì)算<表達(dá)式>中表達(dá)式的值,當(dāng)表達(dá)式的值為真(True)時(shí),執(zhí)行<語(yǔ)句序列1>中的語(yǔ)句,然后執(zhí)行If語(yǔ)句的下一條語(yǔ)句;當(dāng)表達(dá)式的值為真(False)時(shí),執(zhí)行<語(yǔ)句序列2>中的語(yǔ)句,然后執(zhí)行If語(yǔ)句的下一條語(yǔ)句。
【例9-3】使用雙分支語(yǔ)句重新計(jì)算例9-2中的郵費(fèi)。
將代碼修改如下:
Sub mailfee2( )
Dim w, fee As Single
w=InputBox("請(qǐng)輸入貨物重量(公斤)","輸入重量")
If w<=3 Then
fee=10
Else
fee=10+(w-3)*5
End If
MsgBox "需要支付的郵費(fèi)是:"&fee&"元",vbOKOnly,"計(jì)算結(jié)果"
End Sub
3)If嵌套條件語(yǔ)句
格式:
If <表達(dá)式1> Then
<語(yǔ)句序列1>
ElseIf <表達(dá)式2> Then
<語(yǔ)句序列2>
……
ElseIf <表達(dá)式n> Then
<語(yǔ)句序列n>
Else
<語(yǔ)句序列n十1>
End If
功能:判斷條件,執(zhí)行第一個(gè)滿足條件的語(yǔ)句序列。當(dāng)多個(gè)條件為True時(shí),只能執(zhí)行第一個(gè)條件為True的語(yǔ)句塊。
【例9-4】輸入一個(gè)學(xué)生的成績(jī)score(百分制),當(dāng)score=100時(shí),輸出“滿分”;當(dāng)90<=score<100時(shí),輸出“優(yōu)秀”;當(dāng)80<=score<90時(shí),輸出“良好”;當(dāng)70<=score<80時(shí),輸出“一般”;當(dāng)60<=score<70時(shí),輸出“及格”;當(dāng)score<60時(shí),輸出“不及格”。
操作步驟如下:
(1)打開(kāi)“教學(xué)管理”數(shù)據(jù)庫(kù),打開(kāi)VBE窗口。
(2)在模塊1的代碼窗口中,輸入下面的代碼:
Sub grade( )
Dim score As Integer
score=InputBox("請(qǐng)輸入成績(jī)(0至100分)","輸入成績(jī)")
If score=100 Then
MsgBox "滿分"
ElseIf score>=90 Then
MsgBox "優(yōu)秀"
ElseIf score>=80 Then
MsgBox "良好"
ElseIf score>=70 Then
MsgBox "一般"
ElseIf score>=60 Then
MsgBox "及格"
Else
MsgBox "不及格"
End If
End Sub
(3)單擊“運(yùn)行”按鈕,或者按F5功能鍵,查看運(yùn)行效果。
2.Select Case語(yǔ)句
對(duì)于多種選擇來(lái)說(shuō),可以通過(guò)If語(yǔ)句嵌套實(shí)現(xiàn),但如果嵌套的層次多了,則容易引起混亂,因此,使用多分支控制結(jié)構(gòu)將會(huì)更清晰、有效地解決此類問(wèn)題。多分支控制結(jié)構(gòu)語(yǔ)句又稱情況語(yǔ)句。
Select Case <表達(dá)式>
Case <表達(dá)式值列表1>
<語(yǔ)句序列1>
Case <表達(dá)式值列表2>
<語(yǔ)句序列2>
……
Case <表達(dá)式值列表n>
<語(yǔ)句序列n>
Case Else
<語(yǔ)句序列n+1>
End Select
功能:執(zhí)行該語(yǔ)句時(shí),計(jì)算<表達(dá)式>的值,然后進(jìn)行判斷,如果表達(dá)式的值與第i(i=1,2,…,n)個(gè)表達(dá)式值列表的值相匹配,則執(zhí)行語(yǔ)句序列i中的語(yǔ)句,如果<表達(dá)式>的值與所有的<表達(dá)式列表>中的值都不匹配時(shí),則執(zhí)行語(yǔ)句序列n+1。
【例9-5】使用Select Case重新編程實(shí)現(xiàn)例9-4的功能。
將代碼修改如下:
Sub grade2( )
Dim score As Integer
Dim s As Integer
score=InputBox("請(qǐng)輸入成績(jī)(0至100分)","輸入成績(jī)")
s=Int(score/10)
Select Case s
Case10
MsgBox"滿分"
Case9
MsgBox"優(yōu)秀"
Case8
MsgBox"良好"
Case7
MsgBox"一般"
Case6
MsgBox"及格"
Case Else
MsgBox"不及格"
End Select
End Sub
9.2.3 循環(huán)結(jié)構(gòu)
循環(huán)結(jié)構(gòu)能夠使某些語(yǔ)句或程序段重復(fù)執(zhí)行若干次。每一個(gè)循環(huán)都由循環(huán)的初始狀態(tài)、循環(huán)體、循環(huán)計(jì)數(shù)器和條件表達(dá)式等4個(gè)部分組成。實(shí)現(xiàn)循環(huán)結(jié)構(gòu)的語(yǔ)句有3種:For…Next語(yǔ)句、While…Wend語(yǔ)句和Do…Loop語(yǔ)句。
1.For…Next語(yǔ)句
如果能夠確定循環(huán)執(zhí)行的次數(shù),可以使用For…Next語(yǔ)句。For…Next語(yǔ)句通過(guò)循環(huán)變量來(lái)控制循環(huán)的執(zhí)行,每執(zhí)行一次,循環(huán)變量會(huì)自動(dòng)增加(減少)。
For…Next語(yǔ)句的語(yǔ)句格式為:
For <循環(huán)變量>=<初值> to <終值> [Step<步長(zhǎng)>]
<循環(huán)體>
[ExitFor]
Next <循環(huán)變量>
功能:用循環(huán)計(jì)數(shù)器<循環(huán)變量>來(lái)控制<循環(huán)體>內(nèi)的語(yǔ)句的執(zhí)行次數(shù)。先將<初值>賦給<循環(huán)變量>,然后判斷<循環(huán)變量>是否超過(guò)<終值>,若超過(guò)則結(jié)束循環(huán),執(zhí)行Next后面的語(yǔ)句;否則執(zhí)行<循環(huán)體>內(nèi)的語(yǔ)句,再將<循環(huán)變量>自動(dòng)增加一個(gè)<步長(zhǎng)>,再重新判斷<循環(huán)變量>的值是否超過(guò)<終值>,若結(jié)果為真,則結(jié)束循環(huán),重復(fù)上述過(guò)程。
說(shuō)明:
(1)<循環(huán)變量>是數(shù)值型的變量,通常為整型變量。
(2)<步長(zhǎng)>是<循環(huán)變量>的增量,通常取大于0或小于0的數(shù)。
(3)<循環(huán)體>是在For語(yǔ)句和Next語(yǔ)句之間的語(yǔ)句序列,可以是一條或多條語(yǔ)句。
(4)Next后面的循環(huán)變量與For語(yǔ)句中的循環(huán)變量必須相同,F(xiàn)or語(yǔ)句和Next語(yǔ)句必須成對(duì)出現(xiàn)。
(5)Exit For:當(dāng)執(zhí)行到該語(yǔ)句時(shí),退出循環(huán),執(zhí)行Next下面的語(yǔ)句。
語(yǔ)句執(zhí)行過(guò)程:
(1)將初值賦給循環(huán)變量,并自動(dòng)記下終值和步長(zhǎng)。
(2)判斷循環(huán)變量的值是否超過(guò)終值。如果沒(méi)有超過(guò),執(zhí)行一次循環(huán)體;如果超過(guò)就結(jié)束循環(huán),執(zhí)行Next后面的語(yǔ)句。這里所說(shuō)的“超過(guò)”有兩種含義,即大于或小于。當(dāng)步長(zhǎng)為正值時(shí),循環(huán)變量大于終值為“超過(guò)”;當(dāng)步長(zhǎng)為負(fù)值時(shí),循環(huán)變量小于終值為“超過(guò)”。
(3)執(zhí)行Next語(yǔ)句,將循環(huán)變量增加一個(gè)步長(zhǎng)值,轉(zhuǎn)到(2)繼續(xù)循環(huán)。
【例9-6】編寫程序求1+3+5+…+99的值。
操作步驟如下:
(1)打開(kāi)“教學(xué)管理”數(shù)據(jù)庫(kù),打開(kāi)VBE窗口。
(2)在模塊1的代碼窗口中,輸入下面的代碼:
Sub Sum( )
Dim Sum As Integer, i As Integer
Sum=0 '保存累加和,先清零
For i=1 To 99 Step2
Sum=Sum+i
Next i
MsgBox "1+3+5+…+99=" & Sum
End Sub
(3)單擊“運(yùn)行”按鈕,或者按F5功能鍵,查看運(yùn)行效果。
2.While…Wend語(yǔ)句
While…Wend語(yǔ)句的格式如下:
While<條件表達(dá)式>
<循環(huán)體>
Wend
功能:計(jì)算<條件表達(dá)式>的值并進(jìn)行判斷,如果為假,則退出循環(huán),執(zhí)行Wend下面的語(yǔ)句;如果為真,則執(zhí)行<循環(huán)體>的語(yǔ)句,然后再判斷條件表達(dá)式的值,重復(fù)該過(guò)程。
說(shuō)明:
(1)While循環(huán)語(yǔ)句本身不能修改循環(huán)條件,所以必須在While…Wend語(yǔ)句的循環(huán)體內(nèi)設(shè)置相應(yīng)語(yǔ)句,使得整個(gè)循環(huán)趨于結(jié)束,以避免死循環(huán)。
(2)While循環(huán)語(yǔ)句先對(duì)條件進(jìn)行判斷,然后才決定是否執(zhí)行循環(huán)體。如果開(kāi)始條件就不成立,則循環(huán)體一次也不執(zhí)行。
語(yǔ)句執(zhí)行過(guò)程:
(1)判斷條件是否成立,如果條件成立,就執(zhí)行循環(huán)體;否則轉(zhuǎn)到(3)執(zhí)行。
(2)執(zhí)行Wend語(yǔ)句,轉(zhuǎn)到(1)執(zhí)行。
(3)執(zhí)行Wend語(yǔ)句下面的語(yǔ)句。
【例9-7】編寫程序求1+2+3+…+100的值。
操作步驟如下:
(1)打開(kāi)“教學(xué)管理”數(shù)據(jù)庫(kù),打開(kāi)VBE窗口。
(2)在模塊1的代碼窗口中,輸入下面的代碼:
Sub Sum2( )
Dim Sum As Integer, i As Integer
Sum=0 '保存累加和,先清零
i=1
While i<=100
Sum=Sum+i
i=i+1
Wend
MsgBox "1+2+3+…+100=" & Sum
End Sub
(3)單擊“運(yùn)行”按鈕,或者按F5功能鍵,查看運(yùn)行效果。
3.Do…Loop語(yǔ)句
Do…Loop也是實(shí)現(xiàn)循環(huán)結(jié)構(gòu)的語(yǔ)句,它有Do While…Loop和Do…Loop While 2種形式。
Do While…Loop的語(yǔ)句格式:
Do While<條件表達(dá)式>
<循環(huán)體>
Loop
功能:計(jì)算<條件表達(dá)式>的值并進(jìn)行判斷,如果為假,則退出循環(huán),執(zhí)行Loop下面的語(yǔ)句;如果為真,則執(zhí)行<循環(huán)體>的語(yǔ)句,然后再判斷條件表達(dá)式的值,重復(fù)該過(guò)程。
Do…Loop While的語(yǔ)句格式:
Do
<循環(huán)體>
Loop While<條件表達(dá)式>
功能:首先執(zhí)行<語(yǔ)句序列>的語(yǔ)句,然后計(jì)算<條件表達(dá)式>的值并進(jìn)行判斷,如果<條件表達(dá)式>為假,則退出循環(huán),執(zhí)行Loop下面的語(yǔ)句;如果為真,則執(zhí)行<循環(huán)體>的語(yǔ)句,重復(fù)該過(guò)程。
【例9-8】編寫一個(gè)程序,使用兩種Do…Loop形式計(jì)算由鍵盤輸入的任意個(gè)學(xué)生成績(jī)的平均值。
操作步驟如下:
(1)打開(kāi)數(shù)“教學(xué)管理”據(jù)庫(kù),打開(kāi)VBE窗口。
(2)在模塊1的代碼窗口中,輸入下面的代碼:
Sub avg1( )
Dim Data As Integer,Sum As Integer,n As Integer
Dim Average As Single
Sum=0
n=0
Data=InputBox("輸入第"& n+1 &"個(gè)同學(xué)的成績(jī)","求平均分")
Do While Data < >-1 '-1表示結(jié)束輸入
Sum=Sum+Data
n=n+1
Data=InputBox("輸入第"& n+1 &"個(gè)同學(xué)的成績(jī)","求平均分")
Loop
Average=Sum/n
MsgBox n & "位同學(xué)的平均分為"& Average,vbOKOnly,"求平均分"
End Sub
(3)在模塊1的代碼窗口中,輸入下面的代碼:
Sub avg2( )
Dim Data As Integer,Sum As Integer,n As Integer
Dim Average As Single
Sum=0
n=0
Data=InputBox("輸入第"&n+1&"個(gè)同學(xué)的成績(jī)","求平均分")
Do Until Data=-1 '-1表示結(jié)束輸入
Sum=Sum+Data
n=n+1
Data=InputBox("輸入第"&n+1&"個(gè)同學(xué)的成績(jī)","求平均分")
Loop
Average=Sum/n
MsgBox n &"位同學(xué)的平均分為"& Average,vbOKOnly,"求平均分"
End Sub
請(qǐng)讀者比較兩種代碼的不同。
9.3 模塊
9.3.1 模塊的概念
模塊是VBA代碼的容器,使用模塊可以建立自定義函數(shù)或者過(guò)程,引用數(shù)據(jù)庫(kù)中的對(duì)象。模塊主要由VBA聲明語(yǔ)句和一個(gè)或者多個(gè)過(guò)程組成。
聲明部分主要包括Option聲明,變量、常量或者自定義數(shù)據(jù)類型的聲明。
1.Option Explicit語(yǔ)句
強(qiáng)制顯式聲明模塊中的所有變量,即要求變量在使用之前必須先進(jìn)行聲明。如果沒(méi)有使用Option Explicit語(yǔ)句,變量未經(jīng)定義就可以使用。
2.Option Base 1語(yǔ)句
聲明模塊中數(shù)組下標(biāo)的默認(rèn)下界為1,不聲明則為0。
3.Option Compare Database語(yǔ)句
聲明模塊中需要字符串比較時(shí),將根據(jù)數(shù)據(jù)庫(kù)的區(qū)域ID確定的排序級(jí)別進(jìn)行比較;不聲明則按字符ASCⅡ碼進(jìn)行比較。
9.3.2 模塊的分類
在Access中,模塊分為兩種類型:類模塊和標(biāo)準(zhǔn)模塊(簡(jiǎn)稱模塊)。
類模塊是與類對(duì)象相關(guān)聯(lián)的模塊,當(dāng)為窗體等類對(duì)象或者控件創(chuàng)建第一個(gè)事件過(guò)程的時(shí)候,Access將自動(dòng)創(chuàng)建與之關(guān)聯(lián)的類模塊。同嵌入宏一樣,類模塊不會(huì)出現(xiàn)在導(dǎo)航窗格的模塊對(duì)象中。
用戶也可以自己定義一個(gè)獨(dú)立的類模塊,包括成員變量和方法的定義,然后在過(guò)程中通過(guò)定義的類來(lái)創(chuàng)建對(duì)象。獨(dú)立的類模塊是可以在導(dǎo)航窗格中看到的,這涉及面向?qū)ο缶幊趟枷耄诖瞬蛔鲞^(guò)多闡述。
標(biāo)準(zhǔn)模塊是存放通用過(guò)程的模塊,主要包含公用函數(shù)過(guò)程和子過(guò)程,這些公用過(guò)程不與任何對(duì)象關(guān)聯(lián),可以被任何數(shù)據(jù)庫(kù)對(duì)象使用。標(biāo)準(zhǔn)模塊中的公共變量或公共過(guò)程具有全局性,其作用范圍在整個(gè)應(yīng)用程序的生命周期內(nèi)。
9.3.3 模塊的創(chuàng)建
1.窗體模塊和報(bào)表模塊的創(chuàng)建
只要為窗體或者報(bào)表創(chuàng)建了第一個(gè)事件過(guò)程,就創(chuàng)建了對(duì)應(yīng)的代碼模塊。在窗體或者控件的屬性表中,單擊事件選項(xiàng)卡中某個(gè)事件后面的生成器按鈕,選擇“代碼生成器”,即可打開(kāi)VBA編輯器,此時(shí)系統(tǒng)自動(dòng)創(chuàng)建一個(gè)類模塊。
2.標(biāo)準(zhǔn)模塊的創(chuàng)建
標(biāo)準(zhǔn)模塊的創(chuàng)建有3種方法:
(1)在數(shù)據(jù)庫(kù)窗口“創(chuàng)建”選項(xiàng)卡上的“宏與代碼”組中單擊“模塊”按鈕。
(2)在數(shù)據(jù)庫(kù)窗口“創(chuàng)建”選項(xiàng)卡上的“宏與代碼”組中單擊“Visual Basic”按鈕,打開(kāi)VBA編輯器。在“插入”菜單中選擇“模塊”。
(3)在VBA編輯器中的“工程管理器”任意區(qū)域,從右鍵快捷菜單中插入模塊。
9.3.4 過(guò)程
過(guò)程是模塊的主要組成部分,也是VBA編寫程序的最小單元,用于完成一個(gè)相對(duì)獨(dú)立的操作。過(guò)程可以分為事件過(guò)程和通用過(guò)程。
事件過(guò)程就是事件的處理程序,用于完成窗體等對(duì)象事件的任務(wù),如按鈕的單擊事件等,它是為了響應(yīng)用戶或系統(tǒng)引發(fā)的事件而運(yùn)行的過(guò)程。
通用過(guò)程是用戶自行編寫的程序代碼,可以獨(dú)立運(yùn)行或者由別的過(guò)程調(diào)用。
事件過(guò)程與通用過(guò)程的區(qū)別是前者的名字是由系統(tǒng)自動(dòng)生成,并且依附于窗體等對(duì)象而存在,而后者是由用戶自己按照習(xí)慣命名并且是獨(dú)立存在的。
過(guò)程是由VBA代碼組成的單元。它包含一系列執(zhí)行操作或計(jì)算值的語(yǔ)句和方法。過(guò)程分兩種類型:Sub子過(guò)程和Function函數(shù)過(guò)程。
1.Sub過(guò)程
Sub子過(guò)程執(zhí)行一項(xiàng)操作或一系列操作,是執(zhí)行特定功能的語(yǔ)句塊。Sub子過(guò)程可以被置于標(biāo)準(zhǔn)模塊或類模塊中。所有的Sub過(guò)程都要事先定義,然后被其他的模塊調(diào)用。Sub過(guò)程定義的格式如下:
[Public|Private] [Static] Sub 子過(guò)程名(<形參表>)
[子過(guò)程語(yǔ)句]
[ExitSub]
[子過(guò)程語(yǔ)句]
End Sub
Sub過(guò)程由Sub語(yǔ)句開(kāi)頭,以End Sub結(jié)束。Public和Private關(guān)鍵字用于說(shuō)明子過(guò)程的訪問(wèn)屬性。Static表示子過(guò)程為靜態(tài)子過(guò)程。Sub子過(guò)程不需要返回值。
調(diào)用子過(guò)程的語(yǔ)句格式如下:
Call子過(guò)程(實(shí)參表)
或
子過(guò)程(實(shí)參表)【例9-9】編寫一個(gè)程序,計(jì)算斐波那契數(shù)列的第10項(xiàng)。分析:斐波那契級(jí)數(shù)是這樣定義的:第一、二項(xiàng)為1,第三項(xiàng)開(kāi)始,每一項(xiàng)的值是前兩項(xiàng)值之和。
操作步驟如下:
(1)打開(kāi)“教學(xué)管理”數(shù)據(jù)庫(kù),打開(kāi)VBE窗口。
(2)在模塊1的代碼窗口中執(zhí)行“插入”菜單的“過(guò)程”命令,彈出“添加過(guò)程”對(duì)話框,如圖9-3所示。
圖9-3 “添加過(guò)程”對(duì)話框
(3)創(chuàng)建一個(gè)名稱為fab的過(guò)程,系統(tǒng)會(huì)自動(dòng)生成如下代碼:
Public Sub fab( )
End Sub
這就是使用菜單添加過(guò)程的方法,與手工輸入代碼的效果是一樣的。
在該過(guò)程內(nèi)輸入:
Dim A,B,i,T As Integer
A=1
B=1 '生成級(jí)數(shù)第一、二項(xiàng)
For i=3 To 10
T=A+B '產(chǎn)生級(jí)數(shù)新的一項(xiàng)
A=B '讓B成為下一組的A
B=T '原來(lái)A+B的值成為下一組的B
Next i
MsgBox "斐波那契數(shù)列的第10項(xiàng)是:"&B
運(yùn)行該過(guò)程,查看運(yùn)行結(jié)果。
2.Function函數(shù)過(guò)程
函數(shù)定義的格式如下:
[Public|Private] [Static] Function 函數(shù)過(guò)程名(<形參表>)[As 數(shù)據(jù)類型]
[函數(shù)過(guò)程語(yǔ)句]
[ExitFunction]
[函數(shù)過(guò)程語(yǔ)句]
函數(shù)名=表達(dá)式
End Function
Function函數(shù)過(guò)程與Sub過(guò)程的區(qū)別是它可以有返回值。
【例9-10】編寫一個(gè)程序,計(jì)算斐波那契數(shù)列的任意項(xiàng)。
分析:可以先寫一個(gè)Function函數(shù)過(guò)程,參數(shù)為n,用以計(jì)算斐波那契數(shù)列的第n項(xiàng),然后在另外一個(gè)過(guò)程中調(diào)用這個(gè)函數(shù)。
操作步驟如下:
(1)打開(kāi)“教學(xué)管理”數(shù)據(jù)庫(kù),打開(kāi)VBE窗口。
(2)在模塊1的代碼窗口中執(zhí)行“插入”菜單的“過(guò)程”命令,彈出“添加過(guò)程”對(duì)話框,如圖9-4所示。
圖9-4 “添加過(guò)程”對(duì)話框
(3)創(chuàng)建一個(gè)名稱為f的函數(shù),系統(tǒng)會(huì)自動(dòng)生成Function函數(shù)過(guò)程的框架,增加參數(shù)和代碼如下:
Public Function f (n As Integer)
Dim A,B,i,T As Integer
A=1
B=1 '生成級(jí)數(shù)第一、二項(xiàng)
For i=3 To n
T=A+B '產(chǎn)生級(jí)數(shù)新的一項(xiàng)
A=B '讓B成為下一組的A
B=T '原來(lái)A+B的值成為下一組的B
Next i
f=B
End Function
注意:這個(gè)函數(shù)是不能直接執(zhí)行的,必須新建一個(gè)過(guò)程fab1( )來(lái)調(diào)用它,代碼如下:
Public Sub fab1( )
Dim m As Integer
m=InputBox("計(jì)算第幾項(xiàng)斐波那契數(shù)列?")
MsgBox "第" & m & "項(xiàng)斐波那契數(shù)列是:"& f(m)
End Sub
在過(guò)程fab1( )中調(diào)用了f函數(shù),而m是從鍵盤得到的項(xiàng)數(shù),用作f函數(shù)的參數(shù)。
9.4 VBA程序的調(diào)試
VBA代碼輸入后,在運(yùn)行過(guò)程中,不可避免地會(huì)出現(xiàn)各種錯(cuò)誤。這時(shí),就需要借助調(diào)試工具,快速定位錯(cuò)誤。VBE環(huán)境提供了一整套完整的調(diào)試工具和方法。
VBA代碼運(yùn)行時(shí),可能會(huì)產(chǎn)生3種類型的錯(cuò)誤:編譯時(shí)錯(cuò)誤、運(yùn)行時(shí)錯(cuò)誤和邏輯錯(cuò)誤。
編譯時(shí)錯(cuò)誤是在程序編譯時(shí),由于變量未定義、忘了語(yǔ)句配對(duì)(如If和End If或者For和Next)或拼寫錯(cuò)誤等原因產(chǎn)生的不正確代碼而引起的錯(cuò)誤。
運(yùn)行時(shí)錯(cuò)誤發(fā)生在應(yīng)用程序開(kāi)始運(yùn)行之后的錯(cuò)誤。運(yùn)行時(shí)錯(cuò)誤包括企圖執(zhí)行非法運(yùn)算,例如被零除或向不存在的文件中寫入數(shù)據(jù)。
邏輯錯(cuò)誤是編程人員在程序設(shè)計(jì)或者編寫的時(shí)候犯下的錯(cuò)誤,無(wú)法得到預(yù)期的運(yùn)行結(jié)果。例如,循環(huán)變量的初值和終值設(shè)置錯(cuò)誤、變量類型不正確、語(yǔ)句代碼順序不正確等。
9.4.1 錯(cuò)誤調(diào)試
1.設(shè)置斷點(diǎn)
通過(guò)設(shè)置斷點(diǎn),可以掛起代碼。掛起的代碼仍在運(yùn)行當(dāng)中,只是在某個(gè)語(yǔ)句位置暫停下來(lái)。
將光標(biāo)定位到準(zhǔn)備設(shè)置斷點(diǎn)的代碼行,單擊“調(diào)試菜單中的切換斷點(diǎn)”按鈕,或者按F9功能鍵,可以設(shè)置或者取消斷點(diǎn)。
下面以計(jì)算1+3+5+…+99的sum過(guò)程為例,來(lái)設(shè)置斷點(diǎn)調(diào)試程序。
在Sum=Sum+i所在的代碼行設(shè)置一個(gè)斷點(diǎn),如圖9-5所示。
圖9-5 設(shè)置斷點(diǎn)
設(shè)置好斷點(diǎn)后,按運(yùn)行按鈕或者F5功能鍵,則運(yùn)行到該過(guò)程的斷點(diǎn)行時(shí)程序會(huì)停下來(lái),該代碼行以黃色顯示。
此時(shí)查看本地窗口,可以觀察到當(dāng)前過(guò)程中的所有變量和其當(dāng)前值,如圖9-6所示。
圖9-6 本地窗口
2.單步執(zhí)行
單步執(zhí)行用于檢查程序每一條語(yǔ)句的執(zhí)行結(jié)果,可以與本地窗口配合,觀察每個(gè)變量的變化情況。
在程序運(yùn)行到斷點(diǎn)所在的代碼行時(shí),執(zhí)行“調(diào)試”菜單中的“逐語(yǔ)句”命令或者按下F8功能鍵,則當(dāng)前代碼被執(zhí)行(下一條待執(zhí)行的代碼會(huì)黃色顯示)。此時(shí)觀察本地窗口,可以看到Sum值發(fā)生了變化。反復(fù)單步執(zhí)行,能夠在本地窗口中觀察到Sum變量累加的過(guò)程。
當(dāng)代碼出現(xiàn)錯(cuò)誤時(shí),可以在代碼中的適當(dāng)位置添加MsgBox語(yǔ)句,或者使用debug.print語(yǔ)句(結(jié)果顯示在立即窗口中,也可以在立即窗口中輸入“debug.print變量名”來(lái)查看變量值),顯示代碼中變量的值,從而推斷錯(cuò)誤出處。
9.4.2 錯(cuò)誤處理
錯(cuò)誤處理,就是當(dāng)代碼運(yùn)行時(shí),如果發(fā)生錯(cuò)誤,可以捕獲錯(cuò)誤,并按照程序設(shè)計(jì)者事先設(shè)計(jì)的方法來(lái)處理。使用錯(cuò)誤處理的好處是:代碼的執(zhí)行不會(huì)中斷,甚至可以讓用戶感覺(jué)不到錯(cuò)誤的存在。
在代碼中使用On Error語(yǔ)句,當(dāng)運(yùn)行錯(cuò)誤發(fā)生時(shí),將錯(cuò)誤攔截下來(lái)。
On Error語(yǔ)句的形式有3種:
1.On Error Resume Next
當(dāng)錯(cuò)誤發(fā)生時(shí),忽略錯(cuò)誤行,繼續(xù)執(zhí)行下面的語(yǔ)句,不停止代碼的執(zhí)行。
2.On Error GoTo語(yǔ)句標(biāo)號(hào)
當(dāng)錯(cuò)誤發(fā)生時(shí),直接跳轉(zhuǎn)到語(yǔ)句標(biāo)號(hào)位置所示的錯(cuò)誤處理代碼,錯(cuò)誤處理代碼需要實(shí)現(xiàn)寫好。
3.On Error GoTo 0
禁止當(dāng)前過(guò)程中任何已啟動(dòng)的錯(cuò)誤處理程序。
思考題
(1)什么VBA?
(2)VBA有哪幾種程序控制結(jié)構(gòu)?
(3)什么是模塊,簡(jiǎn)述類模塊和標(biāo)準(zhǔn)模塊的區(qū)別?
(4)什么是事件過(guò)程?什么是通用過(guò)程?
(5)事件過(guò)程和通用過(guò)程有什么區(qū)別?
(6)過(guò)程與函數(shù)有什么區(qū)別?
上機(jī)題
(1)出租車的計(jì)價(jià)方式為:起步3公里13元,每超出1公里加收2元。編寫一個(gè)taxi( )過(guò)程,根據(jù)用戶輸入的里程(單位:公里)計(jì)算應(yīng)支付金額。
(2)編寫一個(gè)mysum過(guò)程,分別為For…Next語(yǔ)句、While…Wend語(yǔ)句和Do…Loop語(yǔ)句,計(jì)算1+2+…+100。(3)編寫一個(gè)add過(guò)程,用來(lái)計(jì)算1+2+…+n,n是大于1的整數(shù),由用戶從鍵盤輸入。(4)編寫一個(gè)函數(shù)add(n),用來(lái)計(jì)算1+2+…+n,n是大于1的整數(shù),從另外一個(gè)過(guò)程mainadd( )調(diào)用這個(gè)函數(shù)得到計(jì)算結(jié)果。
(5)創(chuàng)建一個(gè)窗體“查看日期”,新建一個(gè)命令按鈕,單擊該按鈕時(shí)會(huì)彈出一個(gè)消息框,提示當(dāng)前日期。
免責(zé)聲明:以上內(nèi)容源自網(wǎng)絡(luò),版權(quán)歸原作者所有,如有侵犯您的原創(chuàng)版權(quán)請(qǐng)告知,我們將盡快刪除相關(guān)內(nèi)容。