Function VerifyFile() As String
Const mnErrBadFileName = 52, mnErrDriveDoorOpen = 71
Const mnErrDeviceUnavailable = 68, mnErrInvalidFileName = 64
Dim strPrompt As String, strMsg As String, strFileSpec As String
strPrompt = "Enter file specification to check:"
StartHere:
strFileSpec = "*.*" ' Start with a default specification.
strMsg = strMsg & vbCrLf & strPrompt
' Let the user modify the default.
strFileSpec = InputBox(strMsg, "File Search", strFileSpec, 100, 100)
' Exit if user deletes default.
If strFileSpec = "" Then Exit Function
On Error GoTo Handler
VerifyFile = Dir(strFileSpec)
Exit FunctionHandler:
Select Case Err.Number ' Analyze error code and load message.
Case ErrInvalidFileName, ErrBadFileName
strMsg = "Your file specification was "
strMsg = strMsg & "invalid; try another."
Case mnErrDriveDoorOpen
strMsg = "Close the disk drive door and "
strMsg = strMsg & "try again."
Case mnErrDeviceUnavailable
strMsg = "The drive you specified was not "
strMsg = strMsg & "found. Try again."
Case Else
Dim intErrNum As Integer
intErrNum = Err.Number
Err.Clear ' Clear the Err object.
Err.Raise Number:=intErrNum ' Regenerate the error.
End Select
Resume StartHere ' This jumps back to StartHere label so the user can try another file name.
End Function以上这段代码来自MSDN。Using Visual Basic\Programmer’s Guide\Part 2: What Can You Do With Visual Basic\Debugging Your Code and Handling Errors\这是一个用来示范错误处理的例子。我不明白最后一个case里的Err.Raise Number:=intErrNum语句的作用。在MSDN里有如下解释:In this case, intErrNum is a variable that contains the error number which triggered the error handler. When the code reaches a Resume statement, the Clear method of the Err object is invoked. It is necessary to regenerate the error in order to pass it back to the previous procedure on the call stack.可是的话,这个err.raise明明是在resume语句之前哪?这是不是MSDN的笔误,还是俺理解有误?请好心回答的朋友帮助剖析一下:这个err.raise如果没用错的话,这个调用堆栈是个什么情况?
Const mnErrBadFileName = 52, mnErrDriveDoorOpen = 71
Const mnErrDeviceUnavailable = 68, mnErrInvalidFileName = 64
Dim strPrompt As String, strMsg As String, strFileSpec As String
strPrompt = "Enter file specification to check:"
StartHere:
strFileSpec = "*.*" ' Start with a default specification.
strMsg = strMsg & vbCrLf & strPrompt
' Let the user modify the default.
strFileSpec = InputBox(strMsg, "File Search", strFileSpec, 100, 100)
' Exit if user deletes default.
If strFileSpec = "" Then Exit Function
On Error GoTo Handler
VerifyFile = Dir(strFileSpec)
Exit FunctionHandler:
Select Case Err.Number ' Analyze error code and load message.
Case ErrInvalidFileName, ErrBadFileName
strMsg = "Your file specification was "
strMsg = strMsg & "invalid; try another."
Case mnErrDriveDoorOpen
strMsg = "Close the disk drive door and "
strMsg = strMsg & "try again."
Case mnErrDeviceUnavailable
strMsg = "The drive you specified was not "
strMsg = strMsg & "found. Try again."
Case Else
Dim intErrNum As Integer
intErrNum = Err.Number
Err.Clear ' Clear the Err object.
Err.Raise Number:=intErrNum ' Regenerate the error.
End Select
Resume StartHere ' This jumps back to StartHere label so the user can try another file name.
End Function以上这段代码来自MSDN。Using Visual Basic\Programmer’s Guide\Part 2: What Can You Do With Visual Basic\Debugging Your Code and Handling Errors\这是一个用来示范错误处理的例子。我不明白最后一个case里的Err.Raise Number:=intErrNum语句的作用。在MSDN里有如下解释:In this case, intErrNum is a variable that contains the error number which triggered the error handler. When the code reaches a Resume statement, the Clear method of the Err object is invoked. It is necessary to regenerate the error in order to pass it back to the previous procedure on the call stack.可是的话,这个err.raise明明是在resume语句之前哪?这是不是MSDN的笔误,还是俺理解有误?请好心回答的朋友帮助剖析一下:这个err.raise如果没用错的话,这个调用堆栈是个什么情况?
揍当友情散分帖8
Err.Clear ' Clear the Err object.就看到你也发现了
那我就不客气了
前面的 Err.Clear 只是一个好的习惯,而不是必要条件。
还真是这样的:
Public Sub TestErr()
On Error GoTo ErrHandle
Dim i As Integer
i = 1 / 0
Exit Sub
ErrHandle:
Debug.Print Err.Description
Dim intErrNum As Integer
intErrNum = Err.Number
' Err.Clear ' Clear the Err object.
Err.Raise Number:=intErrNum ' Regenerate the error.
Resume NextEnd SubPublic Sub TestErrs()
On Error GoTo ErrHandle
Call TestErr
Debug.Print "next line after testerr"
Exit Sub
ErrHandle:
Debug.Print "error handle in outer procedure"
Resume Next
End Sub
On Error GoTo ErrHandle
Dim i As Integer
' i = 1 / 0
Err.Raise 11
Exit Sub
ErrHandle:
Debug.Print Err.Description
Dim intErrNum As Integer
intErrNum = Err.Number
Debug.Print Err.Number
' Err.Clear ' Clear the Err object.
Err.Raise Number:=intErrNum ' Regenerate the error.
Resume NextEnd SubPublic Sub TestErrs()
On Error GoTo ErrHandle
Call TestErr
Debug.Print "next line after testerr"
Exit Sub
ErrHandle:
Debug.Print "error handle in outer procedure"
Resume Next
End Sub
如果你自己设个断点,单步走一下,早就发现 Err.Raise 的作用了。
自己总结出来印象会更深刻。
这里还有一段话,也许能用来解释你描述的这个现象:Visual Basic calls the Clear method automatically whenever it executes any type of Resume statement, Exit Sub, Exit Function, Exit Property, or any On Error statement.
通常用在自定义错误...比如改下楼主的示例:Public Sub TestErr(i As Long, j As Long)
If j = 0 Then
Err.Raise 555, , "除数不能为0" '512以前是系统错误号
Exit Sub
End If
MsgBox i / j
End Sub
Private Sub Command1_Click()
On Error GoTo 100
TestErr 100, 0
Exit Sub
100:
Debug.Print Err.Number & " : " & Err.Description
End Sub
on error goto 100
If j = 0 Then
Err.Raise 555, , "除数不能为0" '512以前是系统错误号
End If
MsgBox i / j
exit sub
100:
msgbox err.number;Err.description
End Sub
恩,你说得很对。这个err.clear其实也有它的作用。比如像下面这段,有没有clear,效果是不一样的。Public Sub TestErr()
On Error GoTo ErrHandle Err.Raise 11 '除数为0
Exit SubErrHandle:
' Err.Clear
Err.Raise 57 'I/O设备错
Resume NextEnd Sub
On Error GoTo ErrHandle Err.Raise 11 '除数为0
Exit SubErrHandle:
' Err.Clear
Err.Raise 57 'I/O设备错
Resume Next
End SubSub DoTheTest()
On Error GoTo handle
TestErr
Exit Sub
handle:
MsgBox "Error # " & Err.Number & ", " & Err.Description & vbCrLf & "Source:" & Err.Source
End Sub如果没有clear,调用程序检测到的错误值是原始错误值,在这个用例中就是“除数为0”;如果先用clear将原来的错误清除掉,则应能将自定义错误返回调用者,这里就是“I/O设备错”。
Raise 方法产生运行时错误。语法object.Raise number, source, description, helpfile, helpcontext说明除了 number 之外,所有参数都是可选的。如果使用 Raise 而不指定一些参数,并且 Err 对象的属性设置含有未清除的值,则视这些值为错误的值。
这段中文翻译比较拗口,看原文是酱紫的:All of the arguments are optional except number. If you use Raise without specifying some arguments, and the property settings of the Err object contain values that have not been cleared, those values serve as the values for your error.
也就是说,之前没清掉的值,会用作新生成的error的属性值。原理么,我觉得就是我在18楼说的道理。
你看MSDN里“Error Handling with ActiveX Components”那一篇。它的例子是这样给的:MyServerHandler:
Select Case ErrNum
Case 7 ' Handle out-of-memory error.
.
.
.
Case 440 ' Handle external object error.
Err.Raise Number:=vbObjectError + 9999
' Error from another Visual Basic object.
Case Is > vbObjectError and Is < vbObjectError _
+ 65536
ObjectError = ErrNum
Select Case ObjectError
' This object handles the error, based on
' error code documentation for the object.
Case vbObjectError + 10
.
.
.
Case Else
' Remap error as generic object error and
' regenerate.
Err.Raise Number:=vbObjectError + 9999
End Select
Case Else
' Remap error as generic object error and
' regenerate.
Err.Raise Number:=vbObjectError + 9999
End Select
Err.Clear
Resume Next它的说明里提到:Any error not handled should be regenerated with a new number, as shown in the Case Else statement. 不过它的示例代码里并没有用clear方法。我理解它是用了新的错误号,其他全用老值。因为外部来的错误号有可能在VB里是无意义的。所以,似乎也许貌似永远都没有必要用clear方法。我是说在这种向上抛出异常的情况下?
Error (17) '也可以写 Error 17
我看楼主也‘中毒’了:
Public Sub TestErrs()
On Error GoTo ErrHandle
Call TestErr
Debug.Print "next line after testerr"
Exit Sub
ErrHandle:
Debug.Print "error handle in outer procedure"
Resume Next
End Sub已经到最后了,还 Resume Next 去 Exit Sub 。
绕那么远的圈子干吗
A)Err.Number 被替换方便程序进行归类处理,而保留 Err.Description 可以得到更详细的错误信息。
B)如果是多语言版的程序,通常是直接按照 Err.Number 显示对应语言的错误信息,Err.Description 就不需要用到了。还有要记住:所有的 On Error 语句都会清除错误的。
Sub Main()
On Error GoTo ErrHandler
TestErrExitEntry:
Exit Sub
ErrHandler:
Debug.Print Err.Number, Err.Description
Resume ExitEntry
End Sub
这句话我昨天在MSDN里也看到了,还摘了给你看。可是我却不大理解它。比如下面这段程序:Sub ErrDemoSub()
On Error GoTo SubHandler
Err.Raise 11
Err.Raise 57 Exit Sub
SubHandler:
Stop
End Sub在第一次stop之后,你设置下一条语句到Err.Raise 57,执行它之前,在立即窗口
?err.Description
得到的是11号错误,也就是它并没有被clear那么,“所有的 On Error 语句都会清除错误的。”这个“清除错误的”动作是发生在什么时刻?
On Error GoTo ErrHandle Err.Raise 11 '除数为0
Exit SubErrHandle:
' Err.Clear
Debug.Print "inner err handle: " & Err.Description
Err.Raise 57 'I/O设备错
Resume NextEnd SubPublic Sub TestErrs()
On Error GoTo ErrHandle
Call TestErr
Debug.Print "next line after testerr"
Exit Sub
ErrHandle:
Debug.Print "error handle in outer procedure: " & Err.Description
Resume Next
End Sub比如这个例子,在立即窗口TestErrs
可以看到,外层的on error语句被触发了,但是err.description并未被clear
Option ExplicitSub Main()
Dim hFile As Integer
On Error GoTo ErrHandler hFile = FreeFile()
Open "C:\temp\1.dat" For Binary Access Write As #hFile
Print #hFile, , CLng(1 / 0)
Close #hFile Exit Sub
ErrHandler:
On Error Resume Next
Close #hFile
MsgBox Err.Number & ":" & Err.Description
End Sub
特意查了哈MSDN,里面这么描述error语句:
The Error statement is supported for backward compatibility. In new code, especially when creating objects, use the Err object's Raise method to generate run-time errors.
我的感觉是:所有的resume语句会清除错误,但是on error语句不一定会清除错误。
Private Sub Form_Load()
On Error GoTo ToExit '打开错误陷阱
Debug.Print Err.Number, "--", 1
Err.Raise 11l: Debug.Print Err.Number, "--", 3 Exit Sub
'----------------
ToExit:
Debug.Print Err.Number, "--", 2
'GoTo l
Resume Next
End SubPrivate Sub Form_Load()
On Error GoTo ToExit '打开错误陷阱
Debug.Print Err.Number, "--", 1
Err.Raise 11l: Debug.Print Err.Number, "--", 3 Exit Sub
'----------------
ToExit:
Debug.Print Err.Number, "--", 2
GoTo l
End Sub
On Error GoTo ErrHandle
Debug.Print Err.Number, "--", 1
Err.Raise 11l:
Debug.Print Err.Number, "--", 3
Exit Sub
2:
Debug.Print "zhaotiger"
Exit Sub
ErrHandler:
Debug.Print Err.Number, "--", 2
On Error GoTo 2
Debug.Print Err.Number, "--", 3
GoTo lEnd Sub
(2)关于Err.Clear, 15楼和18楼和21楼
(3)关于错误捕获的层次,7楼和8楼
(4)关于错误上抛:22F, 29F汗,才发现居然没结帖。