gpt4 book ai didi

vba - 如何在 VBA 的子函数中从调用函数恢复错误处理?

转载 作者:行者123 更新时间:2023-12-03 07:43:14 25 4
gpt4 key购买 nike

当我为 Word 或 Excel 编写 VBA 时,我通常在我的主函数中有一个错误处理程序并从中调用几个子函数,并且大多数时候,我希望子函数的消息被捕获在主函数中。通常,这种策略一切都很好,它模仿了我在 C++ 中所习惯的。

但是,当我需要在一两个潜艇中进行不同类型的错误处理时,我会遇到麻烦。

比如当我需要开启Resume Next为了检查对象是否失败并设置为空。当我想打开错误处理时,我的 MainErrorHandler现在超出​​范围。

Sub Main()
On Error GoTo MainErrorHandler

Application.ScreenUpdating = False
Call OpenFile
Call SubWithOwnErrorHandling

'Do more stuff

GoTo CleanExit

MainErrorHandler:
MsgBox Err.Description

CleanExit:
Application.ScreenUpdating = True
End Sub

Sub OpenFile()

On Error Resume Next
Set objFile = objFSO.OpenTextFile(fileLocation & fileName, 1)
On Error GoTo ErrorHandler ' Label Not Defined!

If objFile Is Nothing Then
Call Err.Raise(2009, , "Out File doesn’t exist.")
End If
End Sub

同样,当我想在本地处理错误并偶尔提升错误时,我不确定该怎么做。
Sub SubWithOwnErrorHandling()
On Error GoTo SubErrorHandler

isReallyBad = True

If isReallyBad Then
Call Err.Raise(2020, , "Error that needs to cause application to exit!")
Else
Call Err.Raise(2001, , "Error that just needs the function to exit!")
End If

SubErrorHandler:
On Error GoTo MainErrorHandler ' Label Not Defined!

If Err.Number = 2020 Then
Call Err.Raise(2020, , Err.Description)
End If

End Sub

对于这两种情况,有什么方法可以做我想要完成的事情吗?

最佳答案

标签始终是本地的。
On Error也总是本地的 - 见鬼,它被弃用的祖先是 On Local Error !

所以你不能GoTo - 在程序范围之间跳转(感谢上帝!!)

这意味着在任何给定时间,运行时只能做两件事中的一件 On Error :

  • 跳转到本地错误处理程序
  • 炸掉当前栈帧,看看调用者是否处理它
  • [忽略错误,在蓝天和阳光下愉快地蒙着眼睛继续奔跑]

  • 第三点,你猜对了,就是 On Error Resume Next做。

    您犯的一个严重错误是指定 On Error错误处理子例程中的语句,并且无论您是否处于错误状态,错误处理子例程都会运行。即使该标签是合法的,这也会使后续执行变得非常困惑。 Exit SubExit Function (或者见鬼, Exit Property ,取决于你的范围)在处理程序之前,并确保错误处理代码只在错误状态下被命中。

    重置错误处理

    所以,你想做的一件事是重置错误处理 - 这里:
    On Error Resume Next
    Set objFile = objFSO.OpenTextFile(fileLocation & fileName, 1)
    On Error GoTo ErrorHandler ' Label Not Defined!

    你知道 objFSO.OpenTextFile可能会爆炸,您想自己处理,即处理 objFile Is Nothing手动的可能性。您绝对可以这样做,但是您需要的是:
    On Error Resume Next
    Set objFile = objFSO.OpenTextFile(fileLocation & fileName, 1)
    On Error GoTo 0
    On Error GoTo 0重置错误处理,即下一条抛出错误的指令将在调用堆栈中冒泡,直到一切都化为乌有。

    自定义错误

    您要做的下一件事是引发自定义错误。

    If isReallyBad Then
    Call Err.Raise(2020, , "Error that needs to cause application to exit!")
    Else
    Call Err.Raise(2001, , "Error that just needs the function to exit!")
    End If


    这实际上很容易 - 但使用 Enum 会更容易:
    Public Enum AppCustomError
    ERR_ReallyBad = vbObjectError + 42
    ERR_ReallyReallyBad
    ERR_VeryReallyTerriblyBad
    ERR_YouGetTheIdea
    End Enum
    vbObjectError常量确保您的自定义错误编号不会踩到脚趾;您的错误编号都是负数 - 并且带有 Enum对于你可以抛出的每个可能的错误,你不需要关心实际的错误号是多少,所以你让枚举成员机制做他们的事情(例如 ERR_ReallyReallyBad 将自动成为 ERR_ReallyBad + 1 )。

    然后你可以这样做(假设你在一个类模块中 - 否则将 TypeName(Me) 替换为一些字符串文字,或跳过它):
        On Error GoTo ErrHandler
    If isReallyBad Then
    Err.Raise ERR_VeryReallyTerriblyBad, TypeName(Me), "Blow up the app!"
    Else
    Err.Raise ERR_ReallyBad, TypeName(Me), "Blow up this function!"
    End If
    Exit Sub
    ErrHandler:
    With Err
    Select Case .Number
    Case ERR_VeryReallyTerriblyBad
    .Raise .Number 'rethrow
    Case ERR_ReallyBad
    'function blew up, we're done here.
    '...
    End Select
    End With

    然后调用代码,它有自己的错误处理子程序,可以决定它不能处理 ERR_VeryReallyTerriblyBad。 ,然后通过重新抛出来炸毁一切:
        Exit Sub
    MainErrorHandler:
    With Err
    Select Case .Number
    Case ERR_VeryReallyTerriblyBad
    .Raise .Number 'rethrow
    Case Else
    MsgBox .Description
    End Select
    End With

    关于vba - 如何在 VBA 的子函数中从调用函数恢复错误处理?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46082136/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com