有没有办法在这种情况下避免使用GoTo?

时间:2015-02-18 09:59:34

标签: vba ms-access goto

所以我有一个sub(由一个命令按钮触发),它运行一个看似非常耗时的过程(5到20秒之间,取决于机器以及我们的网络感觉如何合作) 。为了向用户说明发生了什么事情,他们无法看到我将鼠标指针更改为沙漏,然后在子退出时将其更改回来,无论退出的原因如何。

考虑到这一点,我的代码看起来像这样(说明性示例,而不是实际代码):

Private Sub cmdDoTheThing_Click()
On Error GoTo Err_cmdDoTheThing

    Screen.MousePointer = 11 'Hourglass/Equivalent

    'Check all data is available to Do The Thing
    If Not MyModule.ThingIsDoable(Me.PrimaryKey) Then
        MsgBox "Cannot Do The Thing, more preliminary things must be done first."
        GoTo Exit_cmdDoTheThing
    End If

    'Try to Do The Thing (function returns false on failure)
    If Not MyModule.DoTheThing(Me.PrimaryKey) Then
        MsgBox "Processing of The Thing failed."
        GoTo Exit_cmdDoTheThing
    End If

    '...
    'Stuff here I don't want to do if either of the above failed
    '...

Exit_cmdDoTheThing:
    Screen.MousePointer = 0 'Default mouse pointer
    Exit Sub

Err_cmdDoTheThing:
    MsgBox "Error " & Err.Number & ": " & Err.Description
    Resume Exit_DoTheThing
End Sub

我不想在每个可能的出口点重复Screen.MousePointer = 0所以我认为GoTo可以作为一个不错的捷径,因为无论如何都需要Exit_cmdDoTheThing标签进行错误处理。

这是GoTo语句的有效用例吗?如果不是,还有其他方法可以实现相同的结果吗?毕竟,我不想突然raptor attack

2 个答案:

答案 0 :(得分:3)

可以使用do-while块(具有错误条件并仅运行一次)并使用“Exit Do”替换GoTo,而无需在任何地方跳过其余代码。

所以你的代码现在看起来像:

Private Sub cmdDoTheThing_Click()
On Error GoTo Err_cmdDoTheThing

    Do
        Screen.MousePointer = 11 'Hourglass/Equivalent

        'Check all data is available to Do The Thing
        If Not MyModule.ThingIsDoable(Me.PrimaryKey) Then
            MsgBox "Cannot Do The Thing, more preliminary things must be done first."
            Exit Do
        End If

        'Try to Do The Thing (function returns false on failure)
        If Not MyModule.DoTheThing(Me.PrimaryKey) Then
            MsgBox "Processing of The Thing failed."
            Exit Do
        End If

        '...
        'Stuff here I don't want to do if either of the above failed
        '...
    Loop While FALSE

Exit_cmdDoTheThing:
    Screen.MousePointer = 0 'Default mouse pointer
    Exit Sub

Err_cmdDoTheThing:
    MsgBox "Error " & Err.Number & ": " & Err.Description
    Resume Exit_DoTheThing
End Sub

必须谨慎使用GoTo,因为在代码中进行一些迭代后,代码可能会使代码变得非常复杂。 GoTo还允许你做一些非常奇怪/丑陋的事情,例如跳出范围而不会超出范围。通过这种方式,您可以确保代码的流动,同时保持代码的完整性和可读性。

答案 1 :(得分:1)

引发自定义错误可以避免将GoTo用于具有此错误处理结构的子例程。这样做的另一个好处是,任何阅读代码的人都可以清楚地知道,在这种情况下,某些功能的失败被认为是错误,即使它们在失败时不会引发错误。

Public Const cCustomErrNum = 9114

Private Sub cmdDoTheThing_Click()
On Error GoTo Err_cmdDoTheThing

    Screen.MousePointer = 11 'Hourglass/Equivalent

    'Check all data is available to Do The Thing
    If Not MyModule.ThingIsDoable(Me.PrimaryKey) Then
        Err.Raise cCustomErrNum,"cmd_DoTheThing_Click()", _
            "Cannot Do The Thing, more preliminary things must be done first."
    End If

    'Try to Do The Thing (function returns false on failure)
    If Not MyModule.DoTheThing(Me.PrimaryKey) Then
        Err.Raise cCustomErrNum,"cmd_DoTheThing_Click()", _
            "Processing of The Thing failed."
    End If

    '...
    'Stuff here I don't want to do if either of the above failed
    '...

Exit_cmdDoTheThing:
    Screen.MousePointer = 0 'Default mouse pointer
    Exit Sub

Err_cmdDoTheThing:
    MsgBox "Error " & Err.Number & ": " & Err.Description
    Resume Exit_DoTheThing
End Sub