停止正常运行事件

时间:2016-08-20 18:58:26

标签: excel vba excel-vba event-handling

在搜索了很多帖子之后,我仍然无法理解它。请告诉我如何停止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

请填写我缺少的内容

我已对下面的程序TEST进行了更改,现在我正在使用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

3 个答案:

答案 0 :(得分: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

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

答案 1 :(得分:1)

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

您的第一次尝试是告诉它取消不再安排的预定活动 - 它可能实际上已在几个小时前发生。

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

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

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

该版本将在取消中使用与在Test子例程中设置时间时使用的相同时间(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事件。然后你去取消活动,但不能取消。

在设置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

答案 2 :(得分:0)

我在尝试停止Ontime事件时遇到错误,这对我来说很奇怪,因为我有3个计时器,其中2个工作正常,第三个有时无法停止。我的观察结果如下:当我尝试从计划/重复本身的子程序或从初始计划子程序调用的任何子程序中调用StopTimer时,出现错误。仅当我从其他子程序调用StopTimer时,它才能正常工作。 在TS示例命令中,从“ TheSub”本身的主体运行停止计划的子“ TheSub”。 这是我的示例:

public nextTime1 as Date
public nextTime2 as Date

sub StartTimer()
   call Repeat1 'the first scheduled sub
end sub

sub StopRepeat1
   Application.OnTime nextTime1, "Repeat1", , False
end sub

sub StopRepeat2
   Application.OnTime nextTime2, "Repeat2", , False
end sub

sub Repeat1()
 nextTime1 = Now + TimeSerial(0, 0, 5)
 if condition = true then
   call Repeat2
   call StopRepeat1 '< here gives error because I try to stop this sub from itself
 end if 
 Application.OnTime nextTime1, "Repeat1"  
end sub

sub Repeat2()
  nextTime2 = Now + TimeSerial(0, 0, 1)
  call StopRepeat1 '< also gives error because this sub Repeat2 was called from Repeat1, and thus I also try to stop Repeat1 from itself
  'do something
  Application.OnTime nextTime2, "Repeat2"
end sub

当我从另一个子菜单中调用StopRepeat1和StopRepeat2时-具有StopRepeat1和StopRepeat2的按钮,或者从用户窗体“ close”按钮(其中一个或多个子节点都停止了)-它正常停止而没有错误。 因此,我避免了一个错误,但是我仍然不知道为什么我不能停止自己的Repeat1(因为它的唯一目的-是启动Repeat2,而当启动Repeat2时,我不需要重复1以继续运行)。 也许以上信息对某些人会有帮助。