2014-10-29 31 views
1

我发现自己在过程结束和错误处理程序中都写了一些命令。在这一切之上,我发现自己在我所有的功能写这几行:在程序结束和错误处理程序中编写关闭语句的最佳做法是什么?

Application.Cursor = xlDefault 
    Application.ScreenUpdating = True 

ErrHandler: 
    MsgBox ("An unforseen problem has occured. Please contact support.") 
    Application.Cursor = xlDefault 
    Application.ScreenUpdating = True 
End Sub 

我感觉像我重复自己比我要多。在程序结束和错误处理程序中写入这些“标准”行有没有更好的做法?

+0

可能出现的[VBA错误处理良好模式]的副本(http://stackoverflow.com/questions/1038006/good-patterns-for-vba-error-handling) – RubberDuck 2014-10-29 13:29:24

+0

可能出现[Error Handler - Exit Sub vs 。End Sub](http://stackoverflow.com/questions/1377152/error-handler-exit-sub-vs-end-sub) – 2015-04-08 07:44:28

回答

1

简化这种方法的一种方法是使用RAII模式:即编写一个在其Class_Terminate事件过程中进行清理的类。例如,您可以创建类模块“CursorSaver”包含:

Private m_SavedCursor As XlMousePointer 
Private m_SavedScreenUpdating As Boolean 

Private Sub Class_Initialize() 
    m_SavedCursor = Application.Cursor 
    m_SavedScreenUpdating = Application.ScreenUpdating 
End Sub 

Private Sub Class_Terminate() 
    Application.Cursor = m_SavedCursor 
    Application.ScreenUpdating = m_SavedScreenUpdating 
End Sub 

然后你可以在你的潜艇和功能开始创建这个类的一个实例,当函数退出,类的实例会出的范围和终止代码将被自动调用,并恢复到初始状态:

Public Sub MySub 
    Dim saver As New CursorSaver 
    ... 
    Exit Sub 
End Sub ' Cursor and ScreenUpdating are automatically restored when the Sub exits 

This answer to another question包含一个类似的例子。

+0

这很好,如果你有一个专门的'ErrorHandler'类或者什么的,但是我会很不高兴地发现一些类正在“悄然地”改变应用程序状态。如果由于某种原因,我会在子退出之前设置保护程序= Nothing? – RubberDuck 2014-10-29 13:31:14

+0

@RubberDuck - 不知道我理解你的顾虑。这种模式应该是一个明确设计用于在状态超出范围时保存/恢复状态的类:所以它不是“无声的”。如果您“设置保存=无”,您将在子退出之前明确恢复保存的状态。 – Joe 2014-10-29 20:59:39

+0

这正是我关心的问题。只要清楚地表明这不是一种编码模式,而是一个专门的类来处理它,这很好。事实上,我不觉得你的答案会说出来。 – RubberDuck 2014-10-29 21:01:37

4

您可以简单地在代码“清理”节也执行有错误处理程序的简历时,没有出现错误:

Clean_up: 
     Application.Cursor = xlDefault 
     Application.ScreenUpdating = True 
     Exit Sub 
    ErrHandler: 
     MsgBox "An unforeseen problem has occurred. Please contact support." 
     Resume Clean_up 
    End Sub 

如果你总是在你的程序代码,你可以将它到您从Clean_up部分调用的单独例程。

+0

+ 1我也喜欢这个比接受的答案中提到的'Class'因为如果代码打破了'Resume Clean_up'可以做相关的清理。使用“Application.EnableEvents”等事件时非常有效! – 2014-10-29 14:19:45

0

我也发现自己反复向我的程序中添加类似的错误处理代码,至少可以说有点乏味。有一个名为MZTools的VBIDE插件,可以添加代码片段,您可以轻松地将代码片段嵌入代码中,包括错误处理程序。片段允许包含占位符,例如过程名称,因此它可以适应目标过程。之前的版本是免费的,但v8确实需要花费,我认为它有点贵,但它有很多其他功能,它是您的选择。

这是一个典型的错误处理,你可以看到占位符是如何工作的

Dim mpSettings As ApplicationSettings 
Dim mpTopLevel As Boolean 

    Const mpProcedure As String = "{PROCEDURE_NAME}" 

    On Error GoTo {PROCEDURE_NAME}_Error 
    'can be a top-level call or initiated by another 
    mpTopLevel = IIf(IsArrayAllocated(mgVecProcStack), False, True) 
    PushProcedureStack mpProcedure, mpTopLevel 

    {PROCEDURE_NAME}= True 

    Call AppSettings(State:="Set", _ 
        AppType:=mpSettings, _ 
        AppEvents:=True, _ 
        AppScreen:=True, _ 
        AppAlerts:=False, _ 
        AppCalc:=appNotEnabled) 

    {PROCEDURE_BODY} 

{PROCEDURE_NAME}_Tidy: 
    PopProcedureStack  

{PROCEDURE_NAME}_Tear_Down:    

{PROCEDURE_NAME}_Exit: 
    Call AppSettings(State:="Reset", _ 
        AppType:=mpSettings, _ 
        AppEvents:=True, _ 
        AppScreen:=True, _ 
        AppAlerts:=False, _ 
        AppCalc:=appNotEnabled) 
    Exit Function 

{PROCEDURE_NAME}_Error: 
    If Err.Number = mgBypassErrorNum Then Resume {PROCEDURE_NAME}_Tear_Down 
    {PROCEDURE_NAME} = False 
    If AppErrorHandler(mmModule, mpProcedure, mpTopLevel) Then 
     Stop 
     Resume 
    Else 
     Resume {PROCEDURE_NAME}_Exit 
    End If 

我有MZTools或作者没有关系,它只是一个工具,我使用并从获得的价值。

相关问题