2014-10-30 3 views
2

Я пытаюсь отменить таймер в процедуре Workbook_Close в модуле ThisWorkbook. Может кто-нибудь объяснить следующее поведение ?:Application.OnTime не исполнено

Закрытие Рабочему вручную функции Application.OnTime, как ожидается, и отменяет таймер. Если я пытаюсь убить этот же таймер более чем один раз, или несуществующий таймер, я получаю сообщение об ошибке

ERROR: 1004: Method 'OnTime' of object '_Application' failed

Для меня это поддерживает доказательства того, что функция правильно работает.

Закрытие рабочей книги с помощью ThisWorkbook.Close Таймер не убит, о чем свидетельствуют факты, что:

  1. Учебное пособие повторно открывается, когда таймер истекает
  2. VBA не бросает любая ошибка, если один и тот же таймер убит более одного раза
  3. VBA не выдает ошибку при попытке убить несуществующий таймер

Далее Context

Application.Run пожары, как ожидается, в обоих случаях. Для меня это указывает на то, что объект приложения все еще загружен и VBA Runtime все еще функционирует должным образом.

Код проверки

В стандартном модуле под названием 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 

В 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 

трассировки для ручного закрытия (ошибки, возникающие, как и ожидалось) ...

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 

трассировки для закрытия с .close запустив 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 

ответ

0

Я сделал некоторые изменения. Для целей тестирования нам нужен только msgbox, чтобы узнать, правильно ли запущена/остановлена ​​процедура.

В стандартном модуле:

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 

В ThisWorkbook модуле:

Option Explicit 

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

Private Sub Workbook_Open() 
    Run "TimerStart" 
End Sub 

Это работает для меня.Следующие сценарии были протестированы:

  • Запустить «TimerSet» вручную> Подождите несколько msgbox> Запустите «TimerKill» вручную.
  • Запустить «TimerSet» вручную> Подождите несколько msgbox> Закрыть книгу.
  • Открыть книгу> Подождите несколько msgbox> Закрыть книгу.
  • Открыть книгу> Подождите несколько msgbox> Закрыть книгу, используя макрос CloseWB.

Что я нашел:

  • Запуск "TimerKill" из Workbook_BeforeClose не работает. Книга снова открывается.
  • Запуск «CloseWB» из Workbook_BeforeClose работы.

Прошу прощения, я не могу объяснить , почему это. Тем не менее, он должен работать для вас сейчас.

+0

testTimerKill действительно был ошибочной пастой ... спасибо, что указал, что сейчас исправлено. Я перепроверю оставшуюся часть вашего анализа и отчитаюсь. –

+0

Ваш ответ не распространяется на режим сбоя, который происходит, когда рабочая книга закрыта с помощью кода 'ThisWorkbook.Close' –

+0

@CoolBlue Я обновил свой ответ, включая решение для вашего запроса. Пожалуйста, попробуйте и отчитайтесь. Как-то, убивая таймер перед запуском таймера снова, решает эту проблему. Вид фанки, поскольку таймер уже прошел, однако это был единственный способ остановить таймер из макроса CloseWB. – TAKL

Смежные вопросы