简体   繁体   English

未执行Application.OnTime

[英]Application.OnTime not executed

I am trying to cancel a timer in the Workbook_Close routine in the ThisWorkbook module. 我正在尝试在ThisWorkbook模块的Workbook_Close例程中取消计时器。 Can anyone explain the following behaviour?: 谁能解释以下行为?:

Closing the workbook manually Application.OnTime functions as expected and cancels the timer. 手动关闭工作簿 Application.OnTime将按预期运行,并取消计时器。 If I try to kill the same timer more than once, or a non-existent timer, I get an error 如果我多次尝试杀死同一计时器或不存在的计时器,则会收到错误消息

ERROR: 1004: Method 'OnTime' of object '_Application' failed 错误:1004:对象“ _Application”的方法“ OnTime”失败

To me, this is supporting evidence that the function is working properly. 对我来说,这是功能正常运行的佐证。

Closing the Workbook using ThisWorkbook.Close The timer is not killed as evidenced by the facts that: 使用ThisWorkbook.Close关闭工作簿 。以下事实并未证明计时器被杀死:

  1. The workbook re-opens when the timer expires 计时器到期时,工作簿将重新打开
  2. VBA does not throw any error if the same timer is killed more than once 如果同一个计时器被杀死多次,则VBA不会引发任何错误
  3. VBA does not throw an error on attempting to kill a non-existent timer VBA在尝试终止不存在的计时器时不会引发错误

Further Context 进一步的背景

Application.Run fires as expected in both cases. 在两种情况下均按预期运行应用程序。 To me this indicates that the Application Object is still loaded and the VBA Runtime is still functioning properly. 对我来说,这表明该应用程序对象仍在加载,并且VBA运行时仍在正常运行。

Test Code 测试代码

In a standard Module called minUnit 在名为minUnit的标准模块中

Private Sub testCallBack(name As String, nextTime As String)
  MsgBox "callback " & name & " " & nextTime
End Sub

Public Function sProcedure(callBackProcedure As String, mName As String, nextTime As Date) As String
' Constructs a properly formatted string to feed to OnTime for a call back with two parameters
  sProcedure = "'" & callBackProcedure & " " & """" & mName & """," & """" & fmtTime(nextTime) & """'"
End Function

Private Sub testTimerSet()
  gnextTime = Now() + TimeSerial(1, 0, 0)
  Application.OnTime gnextTime, sProcedure("Globals.testCallBack", _
                                            "testTimer", gnextTime)
End Sub

Public Sub testTimerKill()
  On Error Resume Next
  Application.OnTime gnextTime, sProcedure("Globals.testCallBack", _
                                           "testTimer", gnextTime), _
                                          , False
End Sub

In ThisWorkbook 在本工作簿中

Private Sub Workbook_BeforeClose(Cancel As Boolean)

  Globals.testTimerKill
  Globals.testTimerKill
  Globals.testTimerKill

  On Error Resume Next

  Application.OnTime 0, "Nothing", , False

  Application.Run sProcedure("minUnit.testCallBack", "Application.Run", Now())

  Application.OnTime Now(), sProcedure("minUnit.testCallBack", "Application.OnTime Now()", Now()), , True

End Sub

Sub closeWorkbook()
    ThisWorkbook.Close
End Sub

Trace for manual closing (errors thrown as expected)... 跟踪手动关闭(按预期引发错误)...

 20:27:07:206 minUnit.testTimerSet: START 20:27:07:209 Application.OnTime 'minUnit.testCallBack "testTimer","21:27:07"' :0.003532 20:27:07:212 minUnit.testTimerSet: END :0.006447 20:27:13:618 minUnit.testTimerKill: START 20:27:13:621 minUnit.testTimerKill: END :0.003337 20:27:21:240 minUnit.testTimerSet: START 20:27:21:244 Application.OnTime 'minUnit.testCallBack "testTimer","21:27:21"' :0.004301 20:27:21:246 minUnit.testTimerSet: END :0.006274 20:27:33:946 ThisWorkbook.Workbook_BeforeClose: START 20:27:33:949 minUnit.testTimerKill: START 20:27:33:951 minUnit.testTimerKill: END :0.001921 20:27:33:953 minUnit.testTimerKill: START 20:27:33:957 minUnit.testTimerKill: END 20:27:33:957**ERROR: 1004: Method 'OnTime' of object '_Application' failed :0.002433 20:27:33:963 minUnit.testTimerKill: START 20:27:33:967 minUnit.testTimerKill: END 20:27:33:967**ERROR: 1004: Method 'OnTime' of object '_Application' failed :0.002230 20:27:33:972 Application.OnTime 0, "Nothing", , False 20:27:33:972**ERROR: 1004: Method 'OnTime' of object '_Application' failed :0.024134 20:27:33:977 Application.Run 'minUnit.testCallBack "Application.Run","20:27:33"' :0.031184 20:27:33:983 minUnit.testCallBack: START 20:27:35:995 minUnit.testCallBack: END :2.012402 20:27:35:997 Application.OnTime Now() 'minUnit.testCallBack "Application.OnTime Now()","20:27:35"':2.051651 20:27:35:999 ThisWorkbook.Workbook_BeforeClose: END :2.053604 

Trace for closing with .Close by running closeWorkbook (should have thrown the first error at 20:30:11:979)... 通过运行closeWorkbook关闭的跟踪。(应该在20:30:11:979引发第一个错误)...

 20:29:48:201 minUnit.testTimerSet: START 20:29:48:204 Application.OnTime 'minUnit.testCallBack "testTimer","21:29:48"' :0.003342 20:29:48:206 minUnit.testTimerSet: END :0.005207 20:29:51:942 minUnit.testTimerKill: START 20:29:51:945 minUnit.testTimerKill: END :0.002946 20:29:55:444 minUnit.testTimerSet: START 20:29:55:448 Application.OnTime 'minUnit.testCallBack "testTimer","21:29:55"' :0.003535 20:29:55:450 minUnit.testTimerSet: END :0.005446 20:30:11:966 ThisWorkbook.closeWorkbook: START 20:30:11:971 ThisWorkbook.Workbook_BeforeClose: START 20:30:11:973 minUnit.testTimerKill: START 20:30:11:975 minUnit.testTimerKill: END :0.001994 20:30:11:979 minUnit.testTimerKill: START 20:30:11:981 minUnit.testTimerKill: END :0.001847 20:30:11:983 minUnit.testTimerKill: START 20:30:11:986 minUnit.testTimerKill: END :0.002271 20:30:11:988 Application.OnTime 0, "Nothing", , False :0.016905 20:30:11:991 Application.Run 'minUnit.testCallBack "Application.Run","20:30:11"' :0.019140 20:30:11:996 minUnit.testCallBack: START 20:30:13:976 minUnit.testCallBack: END :1.979131 20:30:13:977 Application.OnTime Now() 'minUnit.testCallBack "Application.OnTime Now()","20:30:13"':2.005963 20:30:13:985 ThisWorkbook.Workbook_BeforeClose: END :2.013265 

I have made some modifications. 我做了一些修改。 For testing purposes we only need a msgbox to notice whether the routine has been run/stopped correctly. 出于测试目的,我们只需要一个msgbox来注意例程是否已正确运行/停止。

In standard module: 在标准模块中:

Option Explicit
Public dTime As Date ' Needs to be a public/global variable

Public Sub TimerStart()
    dTime = Now() + TimeSerial(0, 0, 5)
    Application.OnTime dTime, "TimerStart"

    MsgBox "Callback " & TimeValue(dTime)
End Sub

Public Sub TimerKill()
    On Error Resume Next
    Application.OnTime dTime, "TimerStart", , False
End Sub

Public Sub CloseWB()
    TimerKill
    ThisWorkbook.Close SaveChanges:=True
End Sub

In ThisWorkbook module: 在ThisWorkbook模块中:

Option Explicit

Private Sub Workbook_BeforeClose(Cancel As Boolean)
    Run "CloseWB"
End Sub

Private Sub Workbook_Open()
    Run "TimerStart"
End Sub

This works for me. 这对我有用。 Following scenarios have been tested: 已测试以下方案:

  • Run "TimerSet" manually > Wait for a few msgboxes > Run "TimerKill" manually. 手动运行“ TimerSet”>等待几个msgboxes>手动运行“ TimerKill”。
  • Run "TimerSet" manually > Wait for a few msgboxes > Close workbook. 手动运行“ TimerSet”>等待几个msgbox>关闭工作簿。
  • Open workbook > Wait for a few msgboxes > Close workbook. 打开工作簿>等待几个msgbox>关闭工作簿。
  • Open workbook > Wait for a few msgboxes > Close workbook using the CloseWB macro. 打开工作簿>等待几个msgbox>使用CloseWB宏关闭工作簿。

What I've found is: 我发现的是:

  • Running "TimerKill" from Workbook_BeforeClose does not work . 从Workbook_BeforeClose运行“ TimerKill” 不起作用 The workbook reopens. 工作簿重新打开。
  • Running "CloseWB" from Workbook_BeforeClose works . 从Workbook_BeforeClose works运行“ CloseWB”。

I'm sorry I can't explain why this is. 对不起,我无法解释为什么 However, it should work for you now. 但是,它现在应该对您有用。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM