【问题标题】:VBA error handler doesn't detect error within error handlerVBA 错误处理程序未在错误处理程序中检测到错误
【发布时间】:2019-02-26 09:27:54
【问题描述】:

我使用这个超级有用的论坛已经有一段时间了,总能找到我问题的答案。你是最棒的!

但这一次我似乎无法找到一个简单案例的解决方案。尝试了几个建议,但似乎不起作用...

所以,我想使用 GUI 从另一个软件下载两个报告。但有时,Report1 或/和 Report2 不存在。

Sub Report_download()
    On Error Goto RP1_err
        'GUI codes to download Report(1)

    On Error Goto RP2_err
        'GUI codes to download Report(2)

    MsgBox "Both Reports downloaded."

    Exit Sub

RP1_err:
        If MsgBox("Report(1) not found. Proceed to Report(2) download?", 
vbYesNo) = vbNo Then Exit Sub
        On Error Resume Next
            'GUI codes to download Report(2)
        If Err.Number > 0 Then
        MsgBox "Neither Report(1) nor Report(2) Found"
        End If
    Exit Sub


RP2_err:
    MsgBox "Report(1) downloaded, Report(2) not found. Review manually."

    Exit Sub

End Sub

当我在报告 (1) 和报告 (2) 都不存在的情况下运行此程序时,RP1_err 错误处理程序中的“用于下载报告 (2) 的 GUI 代码”中发生错误(应该如此),在我之后按“是”。但是,接下来会出现一个调试对话框,而不是显示消息“既未找到报告(1)也未找到报告(2)”。我做错了什么?

感谢您的帮助!

【问题讨论】:

  • 您需要使用Resume 语句清除活动异常(错误状态)(On Error Resume Next 不算在内)。 (从技术上讲,您可以使用On Error Goto -1 来清除它,但根据我的经验,这通常是糟糕设计的标志。
  • 这是应该避免“此类”错误处理的情况之一。使用布尔变量。更容易处理
  • 如果您分享GUI codes to download Report(1)GUI codes to download Report(2) 的确切代码,那么也许我可以演示布尔变量的使用
  • 最好的办法是重新组织您的代码并使用两个函数(由一个主函数调用)来下载每个报告。他们可以专注于处理一种错误并在下载成功时返回错误代码或布尔值,而 main 函数可以评估要回答用户的内容。
  • @SiddharthRout 有太多行要检查以审查数据,所以我不能但还是谢谢你!

标签: excel vba error-handling


【解决方案1】:

我会像这样重构你的代码:

Option Explicit

Sub Report_download()
    Dim blnSuccess1 As Boolean: blnSuccess1 = DownloadReport1
    Dim blnSuccess2 As Boolean: blnSuccess2 = DownloadReport2

    If blnSuccess1 = False And blnSuccess2 = False Then
        Debug.Print "Both reports failed to download"
    ElseIf blnSuccess1 = False And blnSuccess2 = True Then
        Debug.Print "Report 1 failed to download"
    ElseIf blnSuccess1 = True And blnSuccess2 = False Then
        Debug.Print "Report 2 failed to download"
    Else
        Debug.Print "Both reports successfully downloaded"
        ' Process the results
    End If
End Sub

Function DownloadReport1() As Boolean
    On Error GoTo ErrorHandler
    ' Your code to do the actual download 1, which may cause error
    On Error GoTo 0
    DownloadReport1 = True
    Exit Function
ErrorHandler:
    DownloadReport1 = False
End Function

Function DownloadReport2() As Boolean
    On Error GoTo ErrorHandler
    ' Your code to do the actual download 2, which may cause error
    On Error GoTo 0
    DownloadReport2 = True
    Exit Function
ErrorHandler:
    DownloadReport2 = False
End Function

这样,更容易理解错误处理,因为您只需关注每个函数中的一个问题。

此外,调试更容易,因为您可以跳过 DownloadReport1 或 DownloadReport2。

此外,它更灵活:您可以删除报告 1 和 2,或者更轻松地添加报告 3。

以后,您可能有报告 1、2 和 3 的功能。sub 用于下载报告 1 和 2,另一个用于下载 1 和 3。在这种情况下,您可以避免冗余(编码两次以下载报告 1) .

【讨论】:

  • 谢谢!我没有尝试过这种方法,但它让我探索了错误处理的可伸缩性! :)
【解决方案2】:

感谢所有cmets!根据您的建议,我想出了一个使用

的快速修复方法
on Error goto -1

这对我的情况很好。然后我去研究布尔是如何工作的,并想出了一个解决方案。 (虽然,我认为我的代码相当恶心......)

快速修复:

Sub Report_download()
    On Error Goto RP1_err
        'GUI codes to download Report(1)

    On Error Goto RP2_err
        'GUI codes to download Report(2)

        MsgBox "FVD reports downloaded."

        Exit Sub

RP1_err:
    AppActivate Application.Caption
    DoEvents
    If MsgBox("RP1 not found. Proceed to RP2?", vbYesNo) = vbNo Then Exit Sub
        On Error GoTo -1
        On Error GoTo VDC_err
        'GUI codes to download Report(2)

    Exit Sub

Both_err:
    AppActivate Application.Caption
    DoEvents
    MsgBox "No VDC report saved."

    Exit Sub

RP2_err:
    AppActivate Application.Caption
    DoEvents
    MsgBox "RP1 saved. RP2 not saved."

    Exit Sub

End Sub

布尔值

Sub Test_RP_DL_Boolean()
Dim RP1_state As Boolean, RP2_state As Boolean

On Error Resume Next
       'codes to download Report(1)
        If Err.Number > 0 Then
        RP1_state = False
        Else
        RP1_state = True
        End If
        On Error GoTo 0

On Error Resume Next
        'codes to download Report(2)
        If Err.Number > 0 Then
        RP2_state = False
        Else
        RP2_state = True
        End If
        On Error GoTo 0

If ((RP1_state = True) And (RP2_state = False)) Then
MsgBox "RP1 saved. RP2 not saved"
End If

If ((RP1_state = False) And (RP2_state = True)) Then
MsgBox "RP1 not saved. RP2 saved."
End If

If ((RP1_state = False) And (RP2_state = False)) Then
MsgBox "No report found"
End If

If ((RP1_state = True) And (RP2_state = True)) Then
MsgBox "RP1 and RP2 saved."
End If


End Sub

不确定这是否是您所说的“使用布尔值”,无论如何,这是一次学习经历。谢谢!

另外,我无法分享我的 GUI 确切代码,因为它们很长并且包含一些敏感数据,我需要检查每一行以将它们删掉。抱歉!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-08-18
    • 1970-01-01
    • 1970-01-01
    • 2015-03-29
    • 2015-03-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多