You can create a Timer at the module level. A simple Timer, but taking care of all necessary variable setting. Otherwise, Excel can crush. You can also create a very stable Timer but it is a whole project behind such an idea. Anyhow, I can use such a Timer without problems in my projects. What is nice is the fact that once started the Timer works even in cell edit mode...
Create a standard module (I all the time name it "Timer_module") with the next code:
Option Explicit
Declare PtrSafe Function SetTimer Lib "user32" (ByVal hWnd As LongPtr, _
ByVal nIDEvent As LongPtr, ByVal uElapse As Long, ByVal lpTimerFunc As LongPtr) As LongPtr
Declare PtrSafe Function KillTimer Lib "user32" (ByVal hWnd As LongPtr, ByVal nIDEvent As LongPtr) As Long
Private TimerID As LongPtr
Private xTimer As Long, howMany As Long
Sub StartTimer(TimerSeconds As Long, howManyTimes As Long)
howMany = howManyTimes
TimerID = SetTimer(0&, 0&, TimerSeconds * 1000, AddressOf T_Pr)
End Sub
Sub StopTimer()
On Error Resume Next
KillTimer 0, TimerID
xTimer = 0
End Sub
Sub T_Pr(ByVal hWnd As Long, ByVal uMsg As Long, _
ByVal nIDEvent As Long, ByVal dwTimer As Long)
xTimer = xTimer + 1: Debug.Print xTimer, Now
DoEvents
If xTimer = howMany Then StopTimer: Debug.Print "Timer stopped: " & Now
End Sub
In another module the Timer can be simple called like in the next code:
Sub testTimeer()
StartTimer 2, 4
End Sub
Were the first parameters means the number of seconds which must path until the timer function will do something. The code can be easily adapted to work for milliseconds. The second parameter means the number of timer function runs after the timer is stopped. It is just an example an it can be easily adapted in order to fulfill your need. So you can set it to act just once, you can call `StopTimer()' procedure whenever you need (from a loop, for instance) and so on...
P.S. Such a timer can be easily linked to a form. You have to take care of TimerID definition. It should be the form handle. For instance, in this way:
TimerID = GetActiveWindow
This piece of code must be part of the form initialize event and of course TimerID must be a Public declared variable...
And you must take care that when the Timer runs all the rest of the running code to be very stable and have error handlers able to stop Timer in case of errors.
DoEventsin the macro. - John Coleman