如何在不破坏对象的情况下停止VBAmacros

我写了一个VBA程序,它在Workbook_Open上创build一个将错误写入错误日志的文件stream。 如果我遇到一个致命的错误(因此需要暂停执行macros),程序将执行一个End语句,突然停止macros。 我知道这个解决scheme并不是一个理想的解决scheme,但是如果我深入了几个函数,我不能看到更好的方法来快速结束问题(也就是说,一个函数调用另一个函数调用另一个函数,第三个函数产生错误)。 退出发生错误的function只会影响该特定function,导致无效数据,意外单元值等的可能性。

但是这种方法会导致我另一个问题 – 当End执行时会销毁所有的对象,包括错误stream。 因此,当用户做了一些新的事情并且运行一个致命的错误时,他们得到了一个VBA运行时错误(91:Object …没有设置),因为代码写入了现在设置为Nothing.的文件streamNothing.

有没有更好的方法来结束macros(并因此避免错误后的意外行为),而不会丢失我的所有对象? 官方的VBA文档没有任何帮助。 提前致谢。

结束:

立即终止执行。 从不需要它自己,但可以放置在过程中的任何地方以结束代码执行,closures使用Open语句打开的文件并清除variables。 执行时,End语句将重置所有模块级别的variables和所有模块中的所有静态局部variables。

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”,则variables不会被重置。

或者你可以在Thisworkbook类模块中使error-streamvariablesprivate,并添加属性,如果variables为Nothing,将会创buildstream。 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 

在模块级声明你的variables,而不是在函数中。 在VBA中,默认情况下可以在左侧的“项目”导航中看到各种图纸。 在表单下方有一个名为“Modules”的文件夹:如果您没有看到“Module1”或变体作为此文件夹的子项,请右键单击该文件夹并select“Insert \ Module”。
这些应该对你持久。

也许尝试Exit而不是End

如果你正试图退出一个function

 Function a() If blahblah.. Then Exit Function End If End Function 

我不确定你的对象是如何声明和处理什么模块,所以…如果你可以发布代码,这可能会有很大的帮助。

使用顶级error handling程序,并且只在您要处理的例程中捕获错误而不会完全中止

演示:

 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的error handling会覆盖主程序中的处理,所以不会引发错误。 在第二个test2 ,没有error handling,所以信息被传递到前一个程序来处理(如果该程序被别的东西调用,它会把它传递给链),错误可以是干净地处理你的主要程序,把所有的东西都整理一下。