【问题标题】:Error (Run-time error 5) will not raise when "On error resume next" is active当“On error resume next”处于活动状态时,不会引发错误(运行时错误 5)
【发布时间】:2015-07-18 06:42:24
【问题描述】:

我在下面提供了我正在使用的实际代码。 我要处理的确切条件是将 strCurrentRev 参数作为零长度字符串。 (例如strCurrentRev=""

如果我注释掉错误处理语句,尝试对长度为零的字符串执行 ASC 方法会抛出 Run-Time Error 5 用于“无效的过程调用或参数”。
如果我然后检查 err.Number 它是 = 5。

如果我尝试在 on error resume next 处于活动状态的情况下运行完全相同的语句,它不会引发任何错误,例如执行后err.number 总是 = 0。

如果 on error resume next 处于活动状态,并且您尝试从即时窗口执行 ASC 方法(例如,键入 asc(strcurrentrev) 并点击 Enter),它将引发运行时错误并将 err.number 属性设置为5.

我以前从未经历过这种情况。为什么让on error resume next 处于活动状态会导致错误在正常执行中不出现???

Function NextRevLetter(strCurrentRev As String) As String
'This function returns the next revision letter given an existing revision letter.

'Declare variables
    Dim lngX As Long
    Dim strX As String
    Dim strY As String

'First, check if we are dealing with rev A-Z or AA-ZZ
        If Len(strCurrentRev) <= 1 Then
        'Check that we can work with revision letter ***THIS IS WHERE I AM HAVING A PROBLEM!***
            On Error Resume Next
            Err.Clear
            'Procedure call to flag errors with ASC method without changing any values
                lngX=Asc(strCurrentRev) 
                lngX=0
            On Error GoTo 0
                If Err.Number > 0 Then
                    Err.Clear
                        If Len(strCurrentRev) < 1 Then
                        'No revision specified, assign first revision"
                            strCurrentRev = "-"
                        Else
                            MsgBox "The revision letter specified is not compliant.  The next revision letter cannot be determined.", vbOKOnly, "Error: Revision does not follow rules"
                        'Return the existing revision (no change) and exit function
                            NextRevLetter = strCurrentRev
                            Exit Function
                        End If
                End If

            'Code continues - not important for this question...
Exit Function

【问题讨论】:

  • 提示:当On Error Resume Next 处于活动状态时,将永远引发no error。这是指令的目的!避免它,除非你知道你在做什么;-)
  • @Mat's Mug,您的评论不正确。在On Error Resume Next 处于活动状态时仍然会引发错误ARE,但是该语句告诉运行时环境忽略错误并继续执行。
  • 当然是提出来的,你可以查看Err.Number。但对于普通人来说,可能更容易理解On Error Resume Next 将运行时错误隐藏在地毯下——这绝不是一个错误的说法。
  • 嗯。不,不,这不是以不同方式捕获和处理特定错误的最佳方法。一点也不。不不不不。
  • @CBRF23 我同意这是一个“强大的工具” - 权力越大,责任越大。首先要做的是首先avoid executing code that can fail in known ways

标签: vba error-handling runtime runtime-error


【解决方案1】:

我刚刚想通了。 On Error GoTo 0 语句将 Err.Number 属性重置为 0。

抱歉浪费了大家的时间!!!!

【讨论】:

  • 您应该知道 any On Error 语句将 Clear 全局 Err 对象。
  • @RubberDuck,我不是每天都在编程,所以有时我会忘记这些基本的东西。我会删除这个问题,但认为它可能会帮助其他偶然发现它的人,因为我只是在我找不到问题搜索的答案时才问它。也许我在搜索错误的术语,但我只是认为它可以帮助某人。
  • 其实不是很基础的东西。今天早上,我对自己代码中的相同问题感到困惑。我相信这个问题会帮助一些人。
【解决方案2】:

您没有使用正确的工具来完成这项工作。运行时错误应该处理,而不是隐藏在地毯下(因为这就是On Error Resume Next 所做的 - 执行愉快地继续,好像什么都没发生一样)。

您首先需要尝试避免引发该错误。是什么原因造成的?

lngX=Asc(strCurrentRev) 

你已经知道发生了什么:

我要处理的确切条件是将 strCurrentRev 参数作为零长度字符串。

那么,处理这个问题的正确方法是验证strCurrentRev 的长度你将它传递给Asc 函数之前,你知道会如果给它一个空字符串,则会引发运行时错误 #5!

If strCurrentRev <> vbNullString Then
    'calling Asc(strCurrentRev) here will not fail!
End If

【讨论】:

  • 我不同意这是“错误的工作工具”。这个函数是从无数(至少比我现在想猜测的)项目中访问的,所以必须在调用过程中整理和添加额外的代码是浪费时间,我们都知道冗余代码是一个维护问题.我正在处理错误,而不是将其推到地毯下 - 检查错误号,做一些事情来处理它。这已被 .NET 中的 Try/Catch 淘汰,但在 VBA 中,如果您想在根级过程中处理特定错误,这是最好的方法。
  • 另外,如果您完全使用 VBA for Solidworks(也许您不使用),许多互操作对象无法检查过程调用的返回,因此您无法检查之前的值试图访问该对象。这需要使用我喜欢称之为“ghetto try/catch”的循环,如上所示。并不是说这适用于所有情况,但我认为在没有任何项目细节的情况下假设什么是或不是工作的正确选择有点冒昧。
  • 另外,不要继续这个讨论 - 但当我专门尝试处理零长度字符串时,错误是由可能从数据库中提取的其他非 ASC 字符引发的,通过论据。抱歉,最初的问题并不清楚,但这是我不想只检查长度的原因。您的解决方案适用于我的问题措辞方式!
  • @CBRF23 不要误会我的意思——我几乎从不使用GoTo 声明。我诚挚地邀请您将一些工作代码带到Code Review(当然包括更多的上下文代码),我敢肯定,这是一个完整的代码审查问答程序(或整个模块)甚至!)会比这个小小的评论讨论有用得多。
  • @Mat'sMug 我以前从未见过代码审查。很酷。当我靠近它们时,我会在那里发布一些项目。这个项目仍处于粗略的开发阶段,我现在没有足够的时间来清理它。我有几个模块,我知道可能会更好,希望能提供一些意见!
【解决方案3】:

我被要求详细说明处理错误的更好方法,这是最简单的方法。我认为没关系,因为在某种程度上它也回答了最初的问题。但是,我首先要说的是,这里正确的做法是完全避免错误,但为了完整起见,有一种方法可以干净地使用错误处理程序。

想法是检查错误号,通过修复值来处理它,然后然后恢复下一行代码。

Function NextRevLetter(strCurrentRev As String) As String
'This function returns the next revision letter given an existing revision letter.

On Error GoTo ErrHandler

'Declare variables
    Dim lngX As Long
    Dim strX As String
    Dim strY As String

'First, check if we are dealing with rev A-Z or AA-ZZ
    If Len(strCurrentRev) <= 1 Then

        'Procedure call to flag errors with ASC method without changing any values
        lngX = Asc(strCurrentRev)
        lngX = 0

        'Code continues - not important for this question...

    End If

Exit Function

ErrHandler:
    If Err.Number = 5 Then
        lngX = 0
        If Len(strCurrentRev) < 1 Then
        'No revision specified, assign first revision"
            strCurrentRev = "-"
            Resume Next
        Else
            MsgBox "The revision letter specified is not compliant.  The next revision letter cannot be determined.", vbOKOnly, "Error: Revision does not follow rules"
            'Return the existing revision (no change) and exit function
            NextRevLetter = strCurrentRev
            Exit Function
        End If

    Else If Err.Number = someOtherExpectedError        
        'handle it appropriately

    Else
        ' !!! This is important.
        ' If we come across an error we don't know how to handle, we re-raise it.
        Err.Raise Err.Number, Err.Source, Err.Description
    End If

End Function

请注意,您的程序流程不会被所有这些错误处理中断,我们只处理我们预期的错误。因此,如果出现错误,我们只有在我们知道如何恢复的情况下才能恢复。否则,停止执行。

不过,我仍然更愿意检查该值是否为 = vbNullString

【讨论】:

    猜你喜欢
    • 2017-10-01
    • 2019-09-08
    • 1970-01-01
    • 1970-01-01
    • 2017-03-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多