人人做人人澡人人爽欧美,国产主播一区二区,久久久精品五月天,羞羞视频在线观看免费

當(dāng)前位置:蘿卜系統(tǒng)下載站 > 辦公軟件教程 > 詳細(xì)頁(yè)面

Excel VBA 程序之出錯(cuò)處理 基礎(chǔ)圖文教程

Excel VBA 程序之出錯(cuò)處理 基礎(chǔ)圖文教程

更新時(shí)間:2024-01-23 文章作者:未知 信息來(lái)源:網(wǎng)絡(luò) 閱讀次數(shù):

Microsoft Excel是Microsoft為使用Windows和Apple Macintosh操作系統(tǒng)的電腦編寫的一款電子表格軟件。直觀的界面、出色的計(jì)算功能和圖表工具,再加上成功的市場(chǎng)營(yíng)銷,使Excel成為最流行的個(gè)人計(jì)算機(jī)數(shù)據(jù)處理軟件。

關(guān)于程序錯(cuò)誤處理,是一個(gè)常見而又非常被容易忽視的問題。錯(cuò)誤處理,顧名思義就是程序在發(fā)生錯(cuò)誤時(shí)的處理過程。為什么要有錯(cuò)誤處理?如果沒有錯(cuò)誤處理又會(huì)怎么樣呢?

Excel VBA 程序之錯(cuò)誤處理 基礎(chǔ)教程

我們首先來(lái)簡(jiǎn)單的說(shuō)說(shuō)上面兩個(gè)問題。

一、為什么要有錯(cuò)誤處理呢?這是因?yàn)槿魏我粋(gè)程序都不可能說(shuō)是不會(huì)發(fā)生任何錯(cuò)誤的(注意:我們這里說(shuō)的錯(cuò)誤只是指的狹義的邏輯錯(cuò),并不包括語(yǔ)法錯(cuò))。

二、如果沒有錯(cuò)誤處理會(huì)發(fā)生什么呢?我們先來(lái)看一段簡(jiǎn)單的代碼:

SubTest()

DimMAsLong

DimNAsLong

M=Val(InputBox("請(qǐng)輸入一個(gè)整數(shù)","M*N"))

N=Val(InputBox("請(qǐng)輸入一個(gè)整數(shù)","M*N"))

MsgBoxCStr(M)&"×"&CStr(N)&"="&CStr(M*N)

EndSub

這是一個(gè)輸入兩個(gè)整數(shù)然后輸出這個(gè)兩數(shù)乘積的過程,這段程序有沒有錯(cuò)誤呢?——沒有。輸入一個(gè)"3",再輸入一個(gè)"2",程序立即輸出了"3×2=6"。那這段程序能永遠(yuǎn)不出錯(cuò)嗎?答案也是否定的,兩次輸入時(shí)任意一次輸入"A"程序就會(huì)報(bào)錯(cuò)了,那么是否只要保證兩次輸入都是整數(shù)程序就不會(huì)出錯(cuò)了呢,答案還是否定的,只要輸出的兩個(gè)數(shù)乘積大于2147483647,程序還是會(huì)出錯(cuò)。這正驗(yàn)證了一句話:永遠(yuǎn)都不要相信用戶的輸入。

既然程序這么容易出錯(cuò),那么錯(cuò)誤處理就是一個(gè)程序必不可少的部分,任何一個(gè)好的程序員都不能忽視這一環(huán)節(jié),誰(shuí)也不會(huì)想讓自己的程序隨時(shí)都可能彈個(gè)錯(cuò)誤對(duì)話框后程序就被非法關(guān)閉了。

那么,現(xiàn)在我們就面對(duì)了一個(gè)新的問題:如何處理錯(cuò)誤?

相信多數(shù)人立即想到了OnErrorGotoXXXX(XXXX表示一個(gè)標(biāo)簽或是一個(gè)行號(hào))和OnErrorResumeNext。是的,這是兩種最常見的錯(cuò)誤處理方式。但是,有多少人真正了解這兩條語(yǔ)句呢。我知道很多人天天都在用這兩條語(yǔ)句,對(duì)它們的作用隨口都能說(shuō)出來(lái)。今天我們暫時(shí)就先不說(shuō)明這兩條語(yǔ)句的作用和意義了。我們先還是把它們拆開來(lái)看。OnErrorGotoXXXX和OnErrorResumeNext我們就先把它們拆成OnError、Goto、ResumeNext。我們先來(lái)看看OnError的幫助。

OnError語(yǔ)句

啟動(dòng)一個(gè)錯(cuò)誤處理程序并指定該子程序在一個(gè)過程中的位置;也可用來(lái)禁止一個(gè)錯(cuò)誤處理程序。

語(yǔ)法

OnErrorGoToline

OnErrorResumeNext

OnErrorGoTo0

OnError語(yǔ)句的語(yǔ)法可以具有以下任何一種形式:

語(yǔ)句描述

OnErrorGoToline啟動(dòng)錯(cuò)誤處理程序,且該例程從必要的line參數(shù)中指定的line開始。line參數(shù)可以是任何行標(biāo)簽或行號(hào)。如果發(fā)生一個(gè)運(yùn)行時(shí)錯(cuò)誤,則控件會(huì)跳到line,激活錯(cuò)誤處理程序。指定的line必須在一個(gè)過程中,這個(gè)過程與OnError語(yǔ)句相同;否則會(huì)發(fā)生編譯時(shí)間錯(cuò)誤。

OnErrorResumeNext說(shuō)明當(dāng)一個(gè)運(yùn)行時(shí)錯(cuò)誤發(fā)生時(shí),控件轉(zhuǎn)到緊接著發(fā)生錯(cuò)誤的語(yǔ)句之后的語(yǔ)句,并在此繼續(xù)運(yùn)行。訪問對(duì)象時(shí)要使用這種形式而不使用OnErrorGoTo。

OnErrorGoTo0禁止當(dāng)前過程中任何已啟動(dòng)的錯(cuò)誤處理程序。

說(shuō)明:如果不使用OnError語(yǔ)句,則任何運(yùn)行時(shí)錯(cuò)誤都是致命的;也就是說(shuō),結(jié)果會(huì)導(dǎo)致顯示錯(cuò)誤信息并中止運(yùn)行。

一個(gè)“允許的”錯(cuò)誤處理程序是由OnError語(yǔ)句打開的一個(gè)處理程序;一個(gè)“活動(dòng)的”錯(cuò)誤處理程序是處理錯(cuò)誤的過程中允許的錯(cuò)誤處理程序。如果在錯(cuò)誤處理程序處于活動(dòng)狀態(tài)時(shí)(在發(fā)生錯(cuò)誤和執(zhí)行Resume、ExitSub、ExitFunction或ExitProperty語(yǔ)句之間這段時(shí)間)又發(fā)生錯(cuò)誤,則當(dāng)前過程的錯(cuò)誤處理程序?qū)o(wú)法處理這個(gè)錯(cuò)誤。控件返回調(diào)用的過程。如果調(diào)用過程有一個(gè)已啟動(dòng)的錯(cuò)誤處理程序,則激活錯(cuò)誤處理程序來(lái)處理該錯(cuò)誤。如果調(diào)用過程的錯(cuò)誤處理程序也是活動(dòng)的,則控件將再往回傳到前面的調(diào)用過程,這樣一直進(jìn)行下去,直到找到一個(gè)被允許的但不是活動(dòng)的錯(cuò)誤處理程序?yàn)橹埂H绻麤]有找到被允許而且不活動(dòng)的錯(cuò)誤處理程序,那么在錯(cuò)誤實(shí)際發(fā)生的地方,錯(cuò)誤本身是嚴(yán)重的。錯(cuò)誤處理程序每次將控件返回調(diào)用過程時(shí),該過程就成為當(dāng)前過程。在任何過程中,一旦錯(cuò)誤處理程序處理了錯(cuò)誤,在當(dāng)前過程中就會(huì)從Resume語(yǔ)句指定的位置恢復(fù)運(yùn)行。

注意一個(gè)錯(cuò)誤處理程序不是Sub過程或Function過程。它是一段用行標(biāo)簽或行號(hào)標(biāo)記的代碼。

大家看到這里是不是對(duì)OnError已經(jīng)有了一個(gè)比較清晰的了解了吧。如果還不是很清楚的話可以再看看下面的過程,它演示了OnErrorGotoXXXX和OnErrorResumeNext,相信大家看完后就能立即明白這兩條語(yǔ)句了。

SubTestError1()

DimIAsLong

OnErrorResumeNext'指定發(fā)生錯(cuò)誤時(shí)不處理,直接運(yùn)行下一條語(yǔ)句

I="A1"'發(fā)生錯(cuò)誤,由于已經(jīng)指定了發(fā)生錯(cuò)誤時(shí)不處理,故Err對(duì)象立即返回直接運(yùn)行下一條語(yǔ)句。

Debug。Print"被忽略的錯(cuò)誤,錯(cuò)誤代碼:"&Err。Number&"錯(cuò)誤信息"&Err。Description&"錯(cuò)誤源:"&Err。Source&"當(dāng)前I的值="&I

Err。Clear'清空所有錯(cuò)誤記錄

OnErrorGoToERROR1'指定下面的錯(cuò)誤發(fā)生時(shí)直接跳轉(zhuǎn)至Error1標(biāo)號(hào)處

I=2147483648#'發(fā)生錯(cuò)誤,由于指定了跳轉(zhuǎn),故直接轉(zhuǎn)至Error1,而不會(huì)再執(zhí)行下面的語(yǔ)句

I=100

Debug。Print"程序正常返回,當(dāng)前I的值="&I

ExitSub

ERROR1:

Debug。Print"發(fā)生錯(cuò)誤,錯(cuò)誤代碼:"&Err。Number&"錯(cuò)誤信息"&Err。Description&"錯(cuò)誤源:"&Err。Source&"當(dāng)前I的值="&I

EndSub

相信現(xiàn)在大家已經(jīng)完全明白了這兩條語(yǔ)句的用法了。但是,大家也看到了,第二條語(yǔ)句出錯(cuò)時(shí),輸出錯(cuò)誤代碼后程序直接退出了,或許有人又會(huì)想,如果當(dāng)?shù)诙五e(cuò)誤發(fā)生時(shí)能不能輸出錯(cuò)誤代碼后再返回到出錯(cuò)的下一條語(yǔ)句再斷續(xù)執(zhí)行程序呢?這時(shí)我們就要使用到ResumeNext了。還是老規(guī)矩,把它拆成Resume、Next來(lái)看,我們看看Resume的幫助。

Resume語(yǔ)句

在錯(cuò)誤處理程序結(jié)束后,恢復(fù)原有的運(yùn)行。

語(yǔ)法

Resume[0]

ResumeNext

Resumeline

Resume語(yǔ)句的語(yǔ)法可以具有以下任何一種形式:

語(yǔ)句描述

Resume如果錯(cuò)誤和錯(cuò)誤處理程序出現(xiàn)在同一個(gè)過程中,則從產(chǎn)生錯(cuò)誤的語(yǔ)句恢復(fù)運(yùn)行。如果錯(cuò)誤出現(xiàn)在被調(diào)用的過程中,則從最近一次調(diào)用包含錯(cuò)誤處理程序的過程的語(yǔ)句處恢復(fù)運(yùn)行。

ResumeNext如果錯(cuò)誤和錯(cuò)誤處理程序出現(xiàn)在同一個(gè)程序中,則從緊隨產(chǎn)生錯(cuò)誤的語(yǔ)句的下個(gè)語(yǔ)句恢復(fù)運(yùn)行。如果錯(cuò)誤發(fā)生在被調(diào)用的過程中,則對(duì)最后一次調(diào)用包含錯(cuò)誤處理程序的過程的語(yǔ)句(或OnErrorResumeNext語(yǔ)句),從緊隨該語(yǔ)句之后的語(yǔ)句處恢復(fù)運(yùn)行。

Resumeline在必要的line參數(shù)指定的line處恢復(fù)運(yùn)行。line參數(shù)是行標(biāo)簽或行號(hào),必須和錯(cuò)誤處理程序在同一個(gè)過程中。

說(shuō)明:在錯(cuò)誤處理程序之外的任何地方使用Resume語(yǔ)句都會(huì)導(dǎo)致錯(cuò)誤發(fā)生。

我們看到了ResumeNext,但是很明顯,它只是Resume三種調(diào)用方式中最常見的一種,不過上面的信息已經(jīng)足夠了,我們使用ResumeNext就可以達(dá)到上面的要求了。

SubTestError2()

DimIAsLong

OnErrorResumeNext'指定發(fā)生錯(cuò)誤時(shí)不處理,直接運(yùn)行下一條語(yǔ)句

I="A1"'發(fā)生錯(cuò)誤,由于已經(jīng)指定了發(fā)生錯(cuò)誤時(shí)不處理,故Err對(duì)象立即返回。

Debug。Print"被忽略的錯(cuò)誤,錯(cuò)誤代碼:"&Err。Number&"錯(cuò)誤信息"&Err。Description&"錯(cuò)誤源:"&Err。Source&"當(dāng)前I的值="&I

Err。Clear'清空所有錯(cuò)誤記錄

OnErrorGoToERROR2'指定下面的錯(cuò)誤發(fā)生時(shí)直接跳轉(zhuǎn)至Error2標(biāo)號(hào)處

I=2147483648#'發(fā)生錯(cuò)誤,由于指定了跳轉(zhuǎn),故直接轉(zhuǎn)至Error1,而不會(huì)再執(zhí)行下面的語(yǔ)句

I=100'由于在Error2后面指定了ResumeNext,所以程序還會(huì)再次返回到這里開始執(zhí)行,這就是和過程TestError1不同之處

Debug。Print"程序正常返回,當(dāng)前I的值="&I

ExitSub

ERROR2:

Debug。Print"發(fā)生錯(cuò)誤,錯(cuò)誤代碼:"&Err。Number&"錯(cuò)誤信息"&Err。Description&"錯(cuò)誤源:"&Err。Source&"當(dāng)前I的值="&I

ResumeNext'返回發(fā)生錯(cuò)誤處的下一條語(yǔ)句,繼續(xù)執(zhí)行

EndSub

如果是在錯(cuò)誤處理過程中再發(fā)生錯(cuò)誤怎么辦?或許你想到了用OnErrorResumeNext,于是我們就有了這樣一段程序

SubTestError3()

DimIAsLong

OnErrorGoToERROR3'指定發(fā)生錯(cuò)誤時(shí)不處理,直接運(yùn)行下一條語(yǔ)句

I="A1"'發(fā)生錯(cuò)誤,由于指定了跳轉(zhuǎn),故直接轉(zhuǎn)至Error3,而不會(huì)再執(zhí)行下面的語(yǔ)句

Debug。Print"發(fā)生錯(cuò)誤,錯(cuò)誤代碼:"&Err。Number&"錯(cuò)誤信息"&Err。Description&"錯(cuò)誤源:"&Err。Source&"當(dāng)前I的值="&I

ERROR3:

Err。Clear'清空所有錯(cuò)誤記錄

OnErrorResumeNext'指定下面的錯(cuò)誤發(fā)生時(shí)忽略錯(cuò)誤,直接跳轉(zhuǎn)至下一條語(yǔ)句繼續(xù)執(zhí)行

I=2147483648#'發(fā)生錯(cuò)誤,由于已經(jīng)指定了發(fā)生錯(cuò)誤時(shí)不處理,故Err對(duì)象應(yīng)立即返回,

'但是由于Err對(duì)象本身因上一條I="A1"錯(cuò)誤而處于激活狀態(tài),這條錯(cuò)誤并不能像我們所預(yù)期的

'一樣直接忽略錯(cuò)誤跳到下一條,而是產(chǎn)生了一條嚴(yán)重錯(cuò)誤,將會(huì)彈出錯(cuò)誤提示對(duì)話框,程序掛起

Debug。Print"被忽略的錯(cuò)誤,錯(cuò)誤代碼:"&Err。Number&"錯(cuò)誤信息"&Err。Description&"錯(cuò)誤源:"&Err。Source&"當(dāng)前I的值="&I

I=100

Debug。Print"程序正常返回,當(dāng)前I的值="&I

EndSub

執(zhí)行它后,我們發(fā)現(xiàn)了一個(gè)嚴(yán)重問題,程序還是拋出了一個(gè)異常并被掛起。這是怎么回事?難到是ResumeNext不起作用了?帶著這個(gè)疑問我們?cè)俅畏祷氐絆nError的幫助,有這么一段話:

一個(gè)“活動(dòng)的”錯(cuò)誤處理程序是處理錯(cuò)誤的過程中允許的錯(cuò)誤處理程序。如果在錯(cuò)誤處理程序處于活動(dòng)狀態(tài)時(shí)(在發(fā)生錯(cuò)誤和執(zhí)行Resume、ExitSub、ExitFunction或ExitProperty語(yǔ)句之間這段時(shí)間)又發(fā)生錯(cuò)誤,則當(dāng)前過程的錯(cuò)誤處理程序?qū)o(wú)法處理這個(gè)錯(cuò)誤

原來(lái)如此,錯(cuò)誤處理過程只能是處理別人的錯(cuò)誤,一旦處理過程本身發(fā)生錯(cuò)誤,由于錯(cuò)誤處理過程已經(jīng)處于激活狀態(tài),就會(huì)導(dǎo)致無(wú)法再繼續(xù)處理錯(cuò)誤了。我們正是因?yàn)樵阱e(cuò)誤處理過程中又產(chǎn)生了錯(cuò)誤,所以程序還是被掛起了。那么,我們?cè)撛趺刺幚聿拍艿玫阶约合胍慕Y(jié)果呢?既然只是錯(cuò)誤處理過程在激活狀狀態(tài)下無(wú)法處理錯(cuò)誤,那么我們是不是只要讓錯(cuò)誤處理過程返回到非激活狀態(tài)下,就可以了呢?我們只好請(qǐng)出Resumeline上場(chǎng)。

SubTestError4()

DimIAsLong

OnErrorGoToERROR4'指定發(fā)生錯(cuò)誤時(shí)不處理,直接運(yùn)行下一條語(yǔ)句

I="A1"'發(fā)生錯(cuò)誤,由于指定了跳轉(zhuǎn),故直接轉(zhuǎn)至Error3,而不會(huì)再執(zhí)行下面的語(yǔ)句

Debug。Print"發(fā)生錯(cuò)誤,錯(cuò)誤代碼:"&Err。Number&"錯(cuò)誤信息"&Err。Description&"錯(cuò)誤源:"&Err。Source&"當(dāng)前I的值="&I

ERROR4:

Err。Clear'清空所有錯(cuò)誤記錄

ResumeERROR4_Next'指定錯(cuò)誤陷井處理完畢并返回ERROR4_Next,

'這樣就做的目的就是為了釋放Err對(duì)象錯(cuò)誤處理,使下面的OnErrorResumeNext生效

ERROR4_Next:

OnErrorResumeNext'指定下面的錯(cuò)誤發(fā)生時(shí)忽略錯(cuò)誤,直接跳轉(zhuǎn)至下一條語(yǔ)句繼續(xù)執(zhí)行

I=2147483648#'發(fā)生錯(cuò)誤,由于已經(jīng)指定了發(fā)生錯(cuò)誤時(shí)不處理,故Err對(duì)象立即返回

Debug。Print"被忽略的錯(cuò)誤,錯(cuò)誤代碼:"&Err。Number&"錯(cuò)誤信息"&Err。Description&"錯(cuò)誤源:"&Err。Source&"當(dāng)前I的值="&I

I=100

Debug。Print"程序正常返回,當(dāng)前I的值="&I

EndSub

運(yùn)行后,我們終于看到了自己想要的結(jié)果。

有了上面的一系列實(shí)驗(yàn),我們?cè)倩仡^來(lái)看OnErrorGoto0和Resume0就非常容易理解了。我們還是再用兩段程序來(lái)實(shí)驗(yàn)一下吧:

SubTestError5()

DimIAsLong

OnErrorResumeNext

I=2147483648#'發(fā)生錯(cuò)誤,由于已經(jīng)指定了發(fā)生錯(cuò)誤時(shí)不處理,故Err對(duì)象立即返回

Debug。Print"被忽略的錯(cuò)誤,錯(cuò)誤代碼:"&Err。Number&"錯(cuò)誤信息"&Err。Description&"錯(cuò)誤源:"&Err。Source&"當(dāng)前I的值="&I

OnErrorGoTo0'停止在當(dāng)前過程中處理錯(cuò)誤。

I="A1"'由于錯(cuò)誤處理被停止,所以程序會(huì)在這里彈出錯(cuò)誤,并掛起。

Debug。Print"程序正常返回,當(dāng)前I的值="&I

EndSub

SubTestError6()

DimIAsLong

DimDAsDouble

OnErrorGoToERROR6'指定發(fā)生錯(cuò)誤時(shí)跳轉(zhuǎn)至標(biāo)號(hào)Error6處開始執(zhí)行

D=2147483650#

I=D'發(fā)生隱性錯(cuò)誤,D的值大于Long能表達(dá)的最大值2,147,483,647

Debug。Print"程序正常返回,當(dāng)前I的值="&I

ExitSub

ERROR6:

Debug。Print"發(fā)生錯(cuò)誤,錯(cuò)誤代碼:"&Err。Number&"錯(cuò)誤信息"&Err。Description&"錯(cuò)誤源:"&Err。Source&"當(dāng)前I的值="&I&"當(dāng)前D的值="&Format(D,"###,###")

D=D-1

Resume'Resume等價(jià)于Resume0,即返回上次出錯(cuò)的語(yǔ)句繼續(xù)執(zhí)行,注意區(qū)分它與ResumeNext的區(qū)別。

'由于前面的D=D-1使得發(fā)生一次錯(cuò)誤就讓D自減1,

'這樣就使得程序在D的等于2,147,483,647時(shí)正常返回退出,但要小心使用這種方式,

'因?yàn)槿绻鸇是小于Long能表達(dá)的最小負(fù)數(shù)-2,147,483,648時(shí)會(huì)使得程序不斷循環(huán)出錯(cuò),

'最終停止在D溢出錯(cuò)誤上,相信我,這一定會(huì)是個(gè)非常痛苦的等待^_^

EndSub

這兩段代碼非常的明了,只要運(yùn)行后就可以直白的看到結(jié)果了。

?


Excel整體界面趨于平面化,顯得清新簡(jiǎn)潔。流暢的動(dòng)畫和平滑的過渡,帶來(lái)不同以往的使用體驗(yàn)。

溫馨提示:喜歡本站的話,請(qǐng)收藏一下本站!

本類教程下載

系統(tǒng)下載排行

網(wǎng)站地圖xml | 網(wǎng)站地圖html
主站蜘蛛池模板: 离岛区| 明水县| 无棣县| 贡嘎县| 当雄县| 安多县| 东方市| 兰西县| 蓝田县| 怀远县| 遵化市| 邵东县| 方正县| 什邡市| 上虞市| 五指山市| 桐城市| 长葛市| 手游| 浑源县| 宜章县| 泸溪县| 邛崃市| 高雄县| 瓦房店市| 昌邑市| 揭东县| 兴业县| 嵊泗县| 巴彦县| 错那县| 张家界市| 合肥市| 玉龙| 丹凤县| 东山县| 龙里县| 嘉禾县| 时尚| 甘肃省| 黄浦区|