Application.Wait 破坏了我的代码

Application.Wait Breaks my Code

Original

我有以下代码为单元格着色以演示毫秒等待时间的使用。但是,当 i = 500 代码中断时。我得到的错误是 Code Execution has been Interrupted 并且从 500 到 1000 我必须继续点击继续。我试图将我的代码包装在 Application.DisplayAlerts = FalseTrue 中,但它仍然被中断并且无法完成。我估计随着 i 接近 1000,此代码大约需要 6 分钟。我不知道是什么原因造成的。我已经完成了我能想到的所有设置,并且它不会在不中断的情况下继续超过 500。毫秒是根据 1/(1000*24*60*60).

计算得出的

Excel 2007

Sub Kaleidoscope()
Dim r, g, b, i As Integer, ms As Double

ms = 0.0000000115741
For i = 1 To 1000
    r = WorksheetFunction.RandBetween(1, 255)
    g = WorksheetFunction.RandBetween(1, 255)
    b = WorksheetFunction.RandBetween(1, 255)
    Range("A1").Interior.Color = RGB(r, g, b)
    Application.Wait (Now + (ms * i))
Next i

End Sub

提前致谢!

Update

@MarcoMarc (whosebug.com/a/5823507/5175942) 提供的 link 解决了我问题的初始中断问题。但是,它似乎仍然没有正确递增。就好像它没有等到 i = 500 然后似乎每次都停滞了 1 秒。这是您所说的限制,最终不可能等待 1 毫秒吗?无需更改原始代码即可防止中断。

Final Thoughts

@JohnMuggins 对我的原始代码进行了很大的调整,并提供了额外的工具来查看幕后的计算。不过,最终,他还必须像@MacroMarc 一样调用 winAPI 才能将代码暂停不到 1 秒。通过对其他网站和 Stack Overflow 的研究,似乎无法单独使用 VBA 将程序暂停少于 1 秒。它要么以正常速度运行,要么在达到 500 毫秒时四舍五入为 1 秒,并将代码延迟 1 秒而不是 500 毫秒。我的最终演示代码在下面带有@JohnMuggins 调整。

Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)

Sub Kaleidascope()
Dim StartTime As Double
Dim EndTime As Double
Dim ms As Double
Dim i, r, g, b As Integer
Dim count As Long

StartTime = Timer

For i = 1 To 500
    ms = i
    r = WorksheetFunction.RandBetween(1, 255)
    g = WorksheetFunction.RandBetween(1, 255)
    b = WorksheetFunction.RandBetween(1, 255)
    Range("A1").Interior.Color = RGB(r, g, b)
    Sleep ms
    Range("B1").Value = "Time: " & Format(Timer - StartTime, "####.###")
    Range("C1").Value = "ms =  " & Format(ms, "####.####")
    Range("D1").Value = i & " of 500"
Next i

EndTime = Timer - StartTime
Debug.Print Format(EndTime, "####.##")
End Sub

0m3r 是正确的。问题出在 application.wait 函数上。请尝试以下执行事件例程。

Sub Kaleidoscope()
Dim r, g, b, i As Integer, ms As Double

ms = 0.0000000115741
For i = 1 To 1000
    r = WorksheetFunction.RandBetween(1, 255)
    g = WorksheetFunction.RandBetween(1, 255)
    b = WorksheetFunction.RandBetween(1, 255)
    Range("A1").Interior.Color = RGB(r, g, b)
    Range("A1").Value = i
    For j = Now To (Now + (ms * i))
        DoEvents
    Next j
    
Next i

End Sub

这是我达到你的 objective 的唯一方法 运行 - 时间为 2 分 9 秒。

Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)

'   run time on my computer 2:09:07
'   runs from 6 ms to 751.5 ms
Sub ewhgfsd()
Dim StartTime As Double
Dim EndTime As Double

StartTime = Timer

For i = 1 To 500
    ms = ms + (i * 0.006)
    r = WorksheetFunction.RandBetween(1, 255)
    g = WorksheetFunction.RandBetween(1, 255)
    b = WorksheetFunction.RandBetween(1, 255)
    Range("A1").Interior.Color = RGB(r, g, b)
    Sleep ms
    Range("B1").Value = "Time: " & Format(Timer - StartTime, "####.##")
    Range("C1").Value = "ms =  " & Format(ms, "####.#####")
    Range("D1").Value = i & " of 500"
Next i

EndTime = Timer - StartTime
Debug.Print Format(EndTime, "####.##")
End Sub

您可以使用 winAPI 的睡眠功能。

模块顶部:

Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)

然后在你的代码中:

Sleep i ' where i is now in milliseconds

请注意,睡眠会延迟所有 VBA 代码。