我编写了一个VBA程序,它在Workbook_Open
上创建了一个将错误写入错误日志的文件流。如果我遇到致命错误(因此需要暂停宏的执行),程序将执行End
语句,突然停止宏。我知道这个解决方案不是一个理想的解决方案,但是如果我有几个函数深度(即,一个函数调用另一个调用另一个函数而另一个调用另一个函数,第三个函数生成),我看不到更好的方法来快速结束事物错误)。退出发生错误的功能只会影响该特定功能,从而可能导致数据无效,意外的单元格值等。
但是这种方法导致了另一个问题 - 当End
执行时它会破坏我的所有对象,包括错误流。因此,当用户执行新操作并遇到致命错误时,他们会收到VBA运行时错误(91:对象...未设置),因为代码会写入现在设置为Nothing.
的文件流
有没有更好的方法来结束宏(从而避免错误后的意外行为)而不会丢失所有对象?官方的VBA文档没有任何帮助。提前致谢。
答案 0 :(得分:3)
<强>结束:强>
立即终止执行。从来没有要求,但可能是 放置在程序中的任何位置以结束代码执行,关闭文件 用Open语句打开并清除变量。执行时 End语句重置所有模块级变量和所有静态 所有模块中的局部变量。
ThisWorkbook模块:
Public fileSystem As FileSystemObject
Public errorStream As TextStream
Private Sub Workbook_Open()
Set fileSystem = New FileSystemObject
Set errorStream = fileSystem.CreateTextFile("c:\temp\error.log", True)
End Sub
标准模块:
Public Sub First()
If (Not ThisWorkbook.errorStream Is Nothing) Then
Debug.Print VBA.TypeName(ThisWorkbook.errorStream)
End If
End
' Exit Sub
End Sub
Public Sub Second()
If (Not ThisWorkbook.errorStream Is Nothing) Then
Debug.Print VBA.TypeName(ThisWorkbook.errorStream)
End If
End Sub
当'First'方法先执行'End'然后执行'Second'方法时,errorStream将为Nothing。 'End'的Instaead使用'ExitSub',然后该变量将不会被重置。
或者您可以在Thisworkbook类模块中创建错误流变量private并添加属性,如果变量为Nothing,则会创建流。 HTH
ThisWorkbook模块:
Private m_errorStream As TextStream
Private Const FILE_PATH_NAME As String = "c:\temp\error.log"
Public Property Get ErrorStream() As TextStream
If (m_errorStream Is Nothing) Then
Dim fileSystem As FileSystemObject
Set fileSystem = New FileSystemObject
If (fileSystem.FileExists(FILE_PATH_NAME)) Then
Set m_errorStream = fileSystem.GetFile(FILE_PATH_NAME).OpenAsTextStream
Else
Set m_errorStream = fileSystem.CreateTextFile(FILE_PATH_NAME, False)
End If
End If
Set ErrorStream = m_errorStream
End Property
标准模块:
Public Sub First()
If (Not ThisWorkbook.ErrorStream Is Nothing) Then
Debug.Print VBA.TypeName(ThisWorkbook.ErrorStream)
End If
End
End Sub
Public Sub Second()
If (Not ThisWorkbook.ErrorStream Is Nothing) Then
Debug.Print VBA.TypeName(ThisWorkbook.ErrorStream)
End If
End Sub
答案 1 :(得分:0)
在模块级别而不是在函数中声明变量。在VBA中,默认情况下,您会在左侧的“项目”导航中看到各种工作表。工作表下方是一个名为“模块”的文件夹:如果您没有看到“Module1”或变体作为此文件夹的子项,请右键单击该文件夹并选择“插入\模块”。 这些应该是持久的。
答案 2 :(得分:0)
也许尝试Exit
代替End
?
如果您尝试退出功能
Function a()
If blahblah.. Then
Exit Function
End If
End Function
我不确定你的对象是如何在哪些模块上声明和处理的......所以如果你可以发布代码,它可能会有很大的帮助。
答案 3 :(得分:0)
使用顶级错误处理程序,并且只捕获要处理的例程中的错误而不会完全中止
演示:
Option Explicit
Sub test()
On Error GoTo Top_Error_Handler
Debug.Print "Error handled in sub routine: test1"
test1
Debug.Print "Error NOT handled in sub routine: test2"
test2
Exit Sub
Top_Error_Handler:
MsgBox "Top Level Error Handler: Error Number:" & Err.Number _
& ":" & Err.Description
End Sub
Sub test1()
On Error Resume Next
Debug.Print 1 / 0
End Sub
Sub test2()
Debug.Print 1 / 0
End Sub
如您所见,test1
中的错误处理会覆盖主程序中的处理,因此不会引发错误。在第二个Sub test2
中,没有错误处理,因此信息被传递到前一个程序来处理(如果该程序被其他东西调用,它将把它传递给链),并且您的主程序可以干净地处理错误,以便整齐地关闭所有内容。