VBA基础
Access中如何灵活运用错误处理
2017-01-22 23:12:05

作者:阿罗-Office中国版主

今天在论坛看见有讨论如何处理错误的,很有代表性,看来有一些初学者对错误处理不是很清楚。而在两个论坛上,有关错误处理的讨论也不是很多。所以,我就借此机会,说说自己的一些体会,希望能够起到抛砖引玉之效。在论坛,有提问说,1楼:setwarning 语句不能屏蔽error,有别的办法吗?2楼回复说例子 Private Sub 命令6_Click() On Error GoTo Err_命令6_Click '////////////////////////////////Exit_命令6_Click:   Exit Sub Err_命令6_Click:   MsgBox Err.Description   Resume Exit_命令6_Click    End Sub 3楼回复说:我觉得屏蔽error不是一个好注意! 屏蔽错误这个问题,要辩证地看。虽然“错误”这个词看上去蛮可怕的,但这只是人的感觉。有时候只是提醒,甚至是access本身设计不良。 1楼的同学想用setwarning来处理错误,这就对不上号了。setwarning是处理系统信息,不是错误。不要把两个不同的概念弄混了。 2楼的同学摘录了一段代码,如果他把倒数第3条语句MsgBox Err.Description注释掉,就回答了1楼的问题。当然,这样的话,如果错误导致某个纪录不能被修改,用户是不知道的了。显然,这样的屏蔽错误方法不好。所以,重要的是需要知道什么样的错误发生,然后针对某种错误,要做什么。 可以仔细研究一下access的err对象,非常有意思。err.Description是返回错误的内容,而err.number则返回错误的号码。这对编程非常有用。结合err的其他属性,大多数情况下可以知道发生了什么类型的错误,原因在那里,有什么影响。这样,在on error语句捕捉到错误以后,你就可以将err.number等输出,分析不同错误的种类,然后进行处理。 为了更好的说明我的观点,下面我举个例子: 我有一个绑定纪录的窗体,用FORM_beforeUpdate事件来提醒是否修改或者回滚用户(Cancel=true, me.undo)的修改。但是,有一个问题,当用户修改了纪录,没有保存或取消,而是直接点窗体右上角的X来关闭窗体,这时候,FORM_beforeUpdate事件先触发,弹出提醒,如果用户选择不保存记录,系统会产生一个错误,客户被告知更改数据库时出现了一个错误,如果关闭窗体,记录将不会被保存。由于用户确实是选择取消修改的,所以系统的这个错误信息是废话,要屏蔽。在窗体FORM_error事件中,输出错误号,是2169。所以,我就这样改写FORM_error事件: Private Sub FORM_Error(DataErr As Integer, response As Integer) Select Case DataErr   Case 2169     response = acDataErrContinue   Case Else     response = acDataErrDisplay End Select End Sub 如果错误号是2169,那么就让代码继续执行,否则(就是其他我们目前还没碰到的错误),就显示错误信息。 这个处理方法,干脆利落,比增加一个关闭按钮外加一大堆判断逻辑要好得多。那么,大家常碰到的按钮单击事件,如何改写错误代码呢? 首先,还是按照标准的错误处理过程,捕捉任何错误,然后将错误号和描述输出: Private Sub button1_Click() On Error GoTo catch   '这里是按钮处理程序主体 finally:   '一些清除工作,例如set myRecordSet = Nothing等   Exit Sub catch:   MsgBox Err.Number & "/" & Err.Description   Resume finally    End Sub 如果产生了错误,你也就知道了错误号和描述,假定错误号是513,然后你找一找原因。分析完毕后,知道了原因和如何处理之后,改写代码如下: Private Sub button1_Click() On Error GoTo catch   '这里是按钮处理程序主体 finally:   '一些清除工作,例如set myRecordSet = Nothing等   Exit Sub catch:   if Err.Number = 513 then      '针对已知错误的处理   else              '显示未知错误    MsgBox Err.Number & "/" & Err.Description   end if   Resume finally    End Sub如果要处理数个错误,当然用select case...语句,注意要把最常发生的错误放在前面,这样可以提高程序的运行效率。更进一步,可以创造错误,让其他程序去处理。例如,你有一个模块,是处理用户登陆的,这个模块被数个其它窗体调用。如果用户登陆过程当中有什么不对,那么最好的办法就是让这个模块产生错误,然后让调用它的程序根据这个错误决定采取什么样的对策。模块程序Public sub login(byVal userName As String, byVal pwd As String)   '处理用户登陆,例如核对用户名、密码、取得权限等   If '用户名不存在 then Err.Raise 513, "userLogin", "用户不存在"   If '密码不对 then Err.Raise 514, "userLogin", "错误的密码"   If '没能获取权限 then Err.Raise 515, "userLogin", "没有使用权限"end sub某个窗体调用时,代码看起来是这样的Private sub btnOk_click()On Error Goto catch    Call login(txtName, txtPwd)    '进入应用程序,关闭本窗体finally:    exit subcatch:    MsgBox Err.Description