2016-08-20 109 views
0

经过大量的文章搜索后,我仍然无法得到我的头。请告诉我如何停止Application.Ontime事件。我遇到过解释To cancel a pending OnTime event, you must provide the exact time that it is scheduled to run停止准时事件

现在我的问题是我应该提供第一次运行事件的时间,还是应该提供下一次触发事件的时间?

我在下面的代码都尝试版本StopTimer的他们都让我"Method OnTime of object _Application failed

Option Explicit 

Private Sub Workbook_Open() 
    count = 1 
    Call test 
End Sub 



Public runwhen As Double 
Public Const runwhat As String = "TheSub" 
Public firstrunTime As Double 
Public count As Integer 




Sub test() 
    If count = 1 Then 
     runwhen = Now + TimeSerial(0, 0, 5) 
     firstrunTime = runwhen 
    Else 
     runwhen = Now + TimeSerial(0, 0, 5) 
    End If 

    Application.OnTime runwhen, "TheSub" 
End Sub 

Sub TheSub() 
    MsgBox "Hi!!!!!!" 
    count = count + 1 
    Call test 
    If count = 5 Then 
     StopTimer 
    End If 
End Sub 

'First Version of StopTimer 
Sub StopTimer() 
    Application.OnTime firstrunTime, "TheSub", , False 

End Sub 

'Second Version of StopTimer 
Sub StopTimer() 
    runwhen=now+TimeSerial(0,0,5) 
    Application.OnTime runwhen, "TheSub", , False 
End Sub 

请的是,我很想念以下工艺试验和

我已经修改填写我现在用的STOPTIMER的第三个版本,但仍然是我的代码给了我在我的机器上同样的错误

Sub test() 
    If count = 1 Then 
     runwhen = Now + TimeSerial(0, 0, 5) 
     firstrunTime = runwhen 
    Else 
     runwhen = Now + TimeSerial(0, 0, 5) 
    End If 
    If count <> 5 Then 
     Application.OnTime runwhen, "TheSub" 
    Else 
     Call StopTimer 
    End If 
End Sub 

回答

1

要取消OnTime事件,您需要通知计划运行的时间。

您的第一次尝试是告诉它取消不再计划的预定事件 - 实际上它可能发生在几个小时前。

您的第二次尝试是告诉它取消预定的事件,该事件在您决定要取消事件后5秒内发生。你可能是幸运的,并设法决定取消它很快,你设置5秒是正确的时间,但你可能不会。 (这取决于时钟的准确度以及计算机执行代码的速度。)

您需要做的是告诉它在您设置的同一时间取消该事件,因此您的代码需要说:

'Third Version of StopTimer 
Sub StopTimer() 
    Application.OnTime runwhen, "TheSub", , False 
End Sub 

该版本将使用相同的时间(runwhen)在取消当您设置的测试子程序时使用。


更新重新新代码:

代码的最初版本会工作(与StopTimer的版本3),不过新版本失败,因为你已经改变了它设置runwhen你的时候不应该。

让我们逐步了解新版本代码中正在发生的事情。假设您在上午6:00:00打开工作簿,并且CPU速度非常慢,以便我们可以为各种事件分配各种时间。

06:00:00.000 - Workbook opens 
06:00:00.001 - Subroutine Test is called 
06:00:00.002 - Count is 1, so first If statement executes the first section 
06:00:00.003 - runwhen is set to 06:00:05.003 
06:00:00.004 - firstruntime is set to 06:00:05.003 
06:00:00.005 - Count is 1, not 5, so second If statement executes the first section 
06:00:00.006 - OnTime is set to run TheSub at 06:00:05.003 
06:00:00.007 - Subroutine Test finishes and control returns to TheSub 
06:00:00.008 - Count is 1, not 5, so If statement is not executed 
06:00:00.009 - Subroutine TheSub finishes and execution of macro stops 

06:00:05.003 - OnTime event triggers 
06:00:05.004 - Subroutine TheSub is called 
06:00:05.005 - MsgBox is displayed 
       The user is very slow to press the button this time. (Mainly because I had 
       written a lot of the following times, and then realised my Count was out 
       by 1, and I didn't want to have to rewrite everything - so I just added 
       a very slow response here.) 
06:00:12.000 - User presses OK 
06:00:12.001 - Count is set to 2 
06:00:12.002 - Subroutine Test is called 
06:00:12.003 - Count is 2, not 1, so first If statement falls into Else portion 
06:00:12.004 - runwhen is set to 06:00:17.004 
06:00:12.005 - Count is 2, not 5, so second If statement executes the first section 
06:00:12.006 - OnTime is set to run TheSub at 06:00:17.004 
06:00:12.007 - Subroutine Test finishes and control returns to TheSub 
06:00:12.008 - Count is 2, not 5, so If statement is not executed 
06:00:12.009 - Subroutine TheSub finishes and execution of macro stops 

06:00:17.004 - OnTime event triggers 
06:00:17.005 - Subroutine TheSub is called 
06:00:17.006 - MsgBox is displayed 
06:00:18.000 - User presses OK 
06:00:18.001 - Count is set to 3 
06:00:18.002 - Subroutine Test is called 
06:00:18.003 - Count is 3, not 1, so first If statement falls into Else portion 
06:00:18.004 - runwhen is set to 06:00:23.004 
06:00:18.005 - Count is 3, not 5, so second If statement executes the first section 
06:00:18.006 - OnTime is set to run TheSub at 06:00:23.004 
06:00:18.007 - Subroutine Test finishes and control returns to TheSub 
06:00:18.008 - Count is 3, not 5, so If statement is not executed 
06:00:18.009 - Subroutine TheSub finishes and execution of macro stops 

06:00:23.004 - OnTime event triggers 
06:00:23.005 - Subroutine TheSub is called 
06:00:23.006 - MsgBox is displayed 
06:00:24.000 - User presses OK 
06:00:24.001 - Count is set to 4 
06:00:24.002 - Subroutine Test is called 
06:00:24.003 - Count is 4, not 1, so first If statement falls into Else portion 
06:00:24.004 - runwhen is set to 06:00:29.004 
06:00:24.005 - Count is 4, not 5, so second If statement executes the first section 
06:00:24.006 - OnTime is set to run TheSub at 06:00:29.004 
06:00:24.007 - Subroutine Test finishes and control returns to TheSub 
06:00:24.008 - Count is 4, not 5, so If statement is not executed 
06:00:24.009 - Subroutine TheSub finishes and execution of macro stops 

06:00:29.004 - OnTime event triggers 
06:00:29.005 - Subroutine TheSub is called 
06:00:29.006 - MsgBox is displayed 
06:00:30.000 - User presses OK 
06:00:30.001 - Count is set to 5 
06:00:30.002 - Subroutine Test is called 
06:00:30.003 - Count is 5, not 1, so first If statement falls into Else portion 
06:00:30.004 - runwhen is set to 06:00:35.004 
06:00:30.005 - Count is 5, so second If statement executes falls into the Else portion 
06:00:30.006 - Subroutine StopTimer is called 
06:00:30.007 - Code attempts to cancel Ontime event scheduled for 06:00:35.004 (the value of runwhen), 
       but fails because no such event is scheduled) 

的失败是因为你更新的runwhen值(在06:00:在我的例子30.004),但后来不设置导通时间的事件。然后你去取消这个活动,但它不能取消。

当您设置OnTime事件时,您应该设置runwhen只有,然后您将能够使用该变量取消该事件。

我建议你改变你的整个代码为:

'In your Workbook module 
Option Explicit 

Private Sub Workbook_Open() 
    count = 1 
    Call StartTimer 
End Sub 

'In your main code module 
Option Explicit 

Public runwhen As Double 
Public count As Integer 

Sub TheSub() 
    MsgBox "Hi!!!!!!" 
    count = count + 1 
    Call StartTimer 
End Sub 

Sub StartTimer() 
    If count <> 5 Then 
     runwhen = Now + TimeSerial(0, 0, 5) 
     Application.OnTime runwhen, "TheSub" 
    End If 
End Sub 

如果设置了这种方式,你不需要StopTimer子程序,因为你只启动定时器,你希望它的次数跑。

但是,您可能正试图设计一个系统,用户可以决定何时停止计时器,也许可以通过点击某个按钮。如果是这样,你只需要在按钮的代码,以包括以下语句停止定时器:

Application.OnTime runwhen, "TheSub", , False 
+0

如果在StopTimer的第三个版本中没有“On Error Resume Next”语句,Test子例程将继续运行。我在我的机器上试过了。 –

+0

@ Anastasiya-Romanova秀 - 没有错误处理程序,如果尝试取消OnTime事件失败,则会生成错误消息。错误处理程序只会导致执行继续而不会崩溃。您可能认为需要On Error的原因是,当OP将'runwhen'设置为新的不同时间时,会发生崩溃。你的最新答案删除了'runwhen'的重置,所以'On Error'也可以被删除。 – YowE3K

+0

如果我没有弄错,OP希望Test子例程必须在count = 5时结束,但如果没有On Error Resume Next,它将继续运行。 –

1

你的代码工作正常。在这里,我使用StopTimer子例程的第二个版本,并将所有代码放入标准代码模块中。我想在你的代码的罪魁祸首是你不声明全局变量:

Public runwhen As Double 
Public Const runwhat As String = "TheSub" 
Public firstrunTime As Double 
Public count As Integer 

您的代码模块的顶部。把它们放在Option Explicit的正下方,以使它们正常工作。

FWIW,我解决您的StopTimer子程序的第一个版本,以使其正常工作:

Sub StopTimer() 
    On Error Resume Next 
    Application.OnTime runwhen, "TheSub", , False 
End Sub 

现在这两个子程序中可以互换使用。

+0

我怀疑这是原因:) –

+0

@RohitSaluja好了,我跑测试子程序与建议在我的机器上面,MsgBox'Hi !!!!!!'只显示5次然后停止。 –

+0

@ Anastasiya-Ramanova请看看编辑过的帖子,我仍然得到相同的错误,同时将count声明为全局变量不会解决任何问题。 –