【问题标题】:milliseconds-timer returns Unexpected error 35010毫秒计时器返回意外错误 35010
【发布时间】:2020-09-20 11:47:43
【问题描述】:

我在 Excel VBA 中有代码,我喜欢每秒运行几次。

在我使用这种方法之前:

Application.On Time Now + Timevalue("00:00:01")

虽然这种方法只能处理秒数(并且不能处理毫秒数)。

出于这个原因,我用毫秒计时器替换了这个计时器(参见下面的代码)。 虽然由于我将毫秒计时器与我的其他 Excel VBA 代码集成,它有时会给出此错误:“意外错误 35010”。

这个错误有几个原因提到:

VBA compile Error: unexpected error 35010

我确实在两台计算机上测试了代码,并且在两台计算机上都返回了错误。 我还在 Excel Pro Plus 2019 和 Excel Pro Plus 2016 上进行了测试。都是 64 位版本。两者都返回错误。

由于我预计这是由于文件损坏,我确实制作了一个新工作簿并将所有 VBA 代码复制到此工作簿中。我从空工作表开始,将旧工作簿中的所有公式复制到新工作簿表中。尽管这些文件仍然返回错误,但我这样做了两次。

错误总是在我启动代码后直接发生。该错误不涉及特定的代码行(黄色)。

有时会发生错误,而完全相同的文件和内容不会发生错误。

这是计时器的代码:

Option Explicit

Private Declare PtrSafe Function SetTimer Lib "user32" _
(ByVal hWnd As LongPtr, _
ByVal nIDEvent As LongPtr, _
ByVal uElapse As Long, _
ByVal lpTimerFunc As LongPtr) As LongPtr

Private Declare PtrSafe Function KillTimer Lib "user32" _
(ByVal hWnd As LongPtr, _
ByVal nIDEvent As LongPtr) As Long

Private m_TimerID As LongPtr

'Note: The duration is measured in milliseconds.
' 1,000 milliseconds = 1 second
Public Sub StartTimer(ByVal Duration As Long)
    'If the timer isn't already running, start it.
    If m_TimerID = 0 Then
        If Duration > 0 Then
            m_TimerID = SetTimer(0, 0, Duration, AddressOf TimerEvent)
            If m_TimerID = 0 Then
                MsgBox "Timer initialization failed!"
            End If
        Else
            MsgBox "The duration must be greater than zero."
        End If
    Else
        MsgBox "Timer already started."
    End If
End Sub

Public Sub StopTimer()
    'If the timer is already running, shut it off.
    If m_TimerID <> 0 Then
        KillTimer 0, m_TimerID
        m_TimerID = 0
    Else
        MsgBox "Timer is not active."
    End If
End Sub

Public Property Get TimerIsActive() As Boolean
'A non-zero timer ID indicates that it's turned on.
    TimerIsActive = (m_TimerID <> 0)
End Property

这是我如何使用计时器的示例代码:

Public CountSomething As Variant
Private timerRunning As Boolean


Sub UPDATECLOCK()


''Application.Calculation = xlManual


If Not timerRunning Then
            CountSomething = 0
            r = 0
            StartTimer 100
            timerRunning = True
End If
 

End Sub

Sub STOPCLOCK()


            StopTimer
            timerRunning = False



End Sub

Sub TimerEvent()


On Error GoTo ErrHandler

    'force code to run on the main thread instead of Windows api thread:
    If timerRunning Then Application.OnTime Now, "updateWorksheet"
    Exit Sub

ErrHandler:
    Debug.Print Err.Number

End Sub

Sub updateWorksheet()
    
    'call code to process here
    'or this example code in this case:
    
    CountSomething = CountSomething + 1
    Worksheets("Sheet1").Cells(2, 9).Value = CountSomething
    
    'write 1 in cel A1 to stop code running:
    knop = ActiveSheet.Cells(1, 1)

    If knop = 1 And timerRunning Then
        StopTimer
        timerRunning = False
    End If
    
    
End Sub

有谁知道错误的原因是什么?

非常感谢!

【问题讨论】:

  • 如果您使用毫秒,则更容易执行(TimeValue("00:50:00") / 1000) 之类的操作。例如Application.Wait Now + (TimeValue("00:50:00") / 1000) 将暂停代码 3000 毫秒(3 秒)
  • @Foxfire And Burns And Burns 谢谢,虽然 Excel 应用程序在使用 Wait 时被冻结,这对我来说不可行。
  • 由于您的Timer 函数只有一秒的精度,您是在 Mac 上运行吗?
  • @Ron Rosenfeld 的确如此,这就是我尝试使用此 Windows API 解决方案的原因。我正在使用 Excel Pro Plus 64 位的 Windows 10 Pro 64 位运行。
  • 不知道您可以在 Mac 上使用 Windows API。我认为您可以使用evaluate("=now()") 来获得毫秒精度。在 Windows 上,我通常使用 hiRes 计时器,它使用滴答计数来获取时间间隔。互联网上的例子比比皆是。

标签: excel vba winapi timer milliseconds


【解决方案1】:

代码中存在一些概念性错误:使用 OnTime Now ... 相当于立即调用 updateWorksheet。 timerRunning 变量是多余的,可以使用 TimerIsActive 函数。 updateWorksheet 的代码可以(应该)插入到 TimerEvent 中,并且没有理由检查计时器是否处于活动状态;仅当计时器处于活动状态时才调用该例程。 这段代码是等价的

Sub UPDATECLOCK()

    If Not TimerIsActive Then
        CountSomething = 0
        r = 0
        StartTimer 100
    End If
 
End Sub

Sub STOPCLOCK()

    StopTimer

End Sub

Sub TimerEvent()

    CountSomething = CountSomething + 1
    Worksheets("Sheet1").Cells(2, 9).Value = CountSomething
    'write 1 in cel A1 to stop code running:
    If ActiveSheet.Cells(1, 1) = 1 Then 'why ActiveSheet?
        StopTimer
    End If
    
End Sub

【讨论】:

  • OnTime Now 强制代码在主线程而不是 Windows api 线程上运行。这是一个巨大的改进,因为我最初遇到了很多错误,因为 Excel 不喜欢由外部计时器计时。使用 OnTime Now,所有被调用的代码都在同一个线程上运行(由 Excel 本身启动)。我同意代码的组织方式可能会有所不同,尽管这不能解决意外错误 35010。
  • 我见过;但你不能忽略错误吗?它给你带来了什么问题?
  • 错误 1004 和 50290。我可以抑制错误,但我更愿意阻止它们。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-07-13
  • 2021-04-02
  • 2016-08-10
  • 2022-11-21
  • 1970-01-01
相关资源
最近更新 更多