【问题标题】:Do While loop is not exiting its x<y loop despite x>yDo While 循环没有退出它的 x<y 循环,尽管 x>y
【发布时间】:2018-01-09 16:48:40
【问题描述】:

抱歉标题冗长...

我在一长串 VBA 代码中有一个(第二个)循环。循环是这样的:

Do While counterB < 40000
    On Error Resume Next
    AppActivate "Oracle Fusion Middleware Forms Services"
    If Err.Number <> 0 Then
        counterB = counterB + 100
        Sleep 100
    Else
        counterB = counterB + 40001
    End If
Loop

现在,有一个类似的循环在这个循环之前检查一个不同的程序,它工作得很好。检查程序是否打开,增加它的计数器(两个循环的计数器有不同的名称),再次检查,增加,冲洗和重复,最终找到它的程序,踢出它的循环,VBA 代码继续。

但是这第二个循环......它只是循环。一遍又一遍......它进入If/Else 就好了(所以,它看到或没有看到AppActivate 中调用的程序),但While 语句没有确认 counterB 大于 40,000。

有没有人看到我做错了什么...? 提前致谢。

【问题讨论】:

  • dim counterB as integer并使用on error resume next吗?
  • 我不完全确定你在这里做什么,但我可以看到你在发现错误后并没有清除它 - 所以一旦 Err.Number 有一个值,它就永远不会没有.也许在AppActivate 之前使用Err.Clear
  • 就循环而言,您的代码没有问题;即使 Err.Number 总是 0 它最终也应该结束。尝试调试,逐步执行,在 counterB 上使用“watch”。
  • 但其他的都是对的:如果你将 counterB 定义为一个整数,它就会出错。可能 counterB = counterB + 40001 什么都不做,让 counterB 保持原样。
  • 这就是为什么On Error Resume Next 是毒药。避免可避免的错误,处理其他错误。不要只是把它们推到众所周知的地毯下。

标签: vba excel loops


【解决方案1】:

只是为了解释integer 的东西 CLRJeeped 正在谈论:

VBA 中的整数是 2 个字节且有符号(可以有负值),因此最大值为 32767。如果您尝试向其中写入更大的值,则会收到运行时错误 6(溢出)并且该值保持不变不变。由于存在on error resume next,因此未显示错误,该值保持在最大值 32767 并且永远不会达到值 40000 - 您陷入了无限循环。

如果您的代码中确实需要 on error resume next,您应该检查 Err.Number 以获得您期望的特定值(并重新引发错误或显示 MsgBox 或类似的东西)。

您的代码可能如下所示:

Do While counterB < 40000
    Dim saveError As Long
    On Error Resume Next
    AppActivate "Oracle Fusion Middleware Forms Services"
    saveError = Err.Number
    On Error GoTo 0

    If saveError <> 0 Then
        If Err.Number = <ENTER YOUR SPECIFIC ERROR CODE> Then
            counterB = counterB + 100
            Sleep 100
        Else
            Err.Raise saveError
        End If
    Else
        counterB = counterB + 40001
    End If
Loop

【讨论】:

  • 太棒了!!我刚刚将计数器金额更改为 32,000 而不是 40,000,并且成功了!谢谢!我将 counterB 更改为 Sleep 数量设置为 1000,这样我将获得相同的等待时间。感谢您提供有关 Err.Number 如何工作的信息,我需要了解更多有关它的信息及其具体值。
  • @rdplanglois:很高兴你能修复它。一般建议:始终使用 long 而不是 integer 数据类型。几乎没有情况需要integer 或使用它有优势。使用long,您可以避免这些溢出问题。
  • @FunThomas:谢谢,这是非常有用的建议!
【解决方案2】:

虽然讨论和接受的答案解释了 OP 代码失败的原因,但 OP 采用的整个方法并不理想。

我会这样做

Sub Demo()
    Dim saveError As Long
    Dim counterB As Long
    Dim AppActivated  As Boolean

    For counterB = 1 To 400
        On Error Resume Next
            AppActivate "Oracle Fusion Middleware Forms Services"
            saveError = Err.Number
        On Error GoTo 0

        If saveError = 0 Then
            AppActivated = True
            Exit For
        Else
            Select Case saveError
                '<ENTER YOUR SPECIFIC ERROR CODES HERE>
                Case 5, 6, 7 ' for example
                    Sleep 100
                Case Else
                    Err.Raise saveError
            End Select
        End If
    Next

    If Not AppActivated Then
        ' Loop timed out.  What Now?
    Else
        ' App is activated
        '  More code...
    End If
End Sub

【讨论】:

  • 谢谢你,克里斯。您的代码更加优雅。我仍在学习如何编写一般代码,所以,“将一些东西拼凑在一起,一瘸一拐”是我目前的一般技能水平。但是,当我最终进入功能状态时,我会保存您的代码以备将来使用...
【解决方案3】:

假设@Jeeped 提到,counterB 不是整数.. 请尝试以下操作:

Do While counterB < 40000
    On Error Resume Next
    AppActivate "Oracle Fusion Middleware Forms Services"
    If Err.Number <> 0 Then
        counterB = counterB + 100
        Sleep 100
        Err.Clear
    Else
        counterB = counterB + 40001
    End If
Loop

【讨论】:

    猜你喜欢
    • 2013-03-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-04-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-11-20
    相关资源
    最近更新 更多