43

i want to repeat an event after a certain duration that is less than 1 second. I tried using the following code

Application.wait Now + TimeValue ("00:00:01")

But here the minimum delay time is one second. How to give a delay of say half a seond?

Community
  • 1
  • 1
Rito
  • 431
  • 1
  • 5
  • 5

10 Answers10

34

You can use an API call and Sleep:

Put this at the top of your module:

Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)

Then you can call it in a procedure like this:

Sub test()
Dim i As Long

For i = 1 To 10
    Debug.Print Now()
    Sleep 500    'wait 0.5 seconds
Next i
End Sub
Doug Glancy
  • 27,214
  • 6
  • 67
  • 115
  • 7
    If the code is in 64bit OS, you will need to use `PtrSafe` See https://support.microsoft.com/en-us/kb/983043 – Antony Oct 26 '15 at 15:05
20

I found this on another site not sure if it works or not.

Application.Wait Now + 1/(24*60*60.0*2)

the numerical value 1 = 1 day

1/24 is one hour

1/(24*60) is one minute

so 1/(24*60*60*2) is 1/2 second

You need to use a decimal point somewhere to force a floating point number

Source

Not sure if this will work worth a shot for milliseconds

Application.Wait (Now + 0.000001) 
Mertinc
  • 793
  • 2
  • 13
  • 27
graham nelson
  • 225
  • 1
  • 2
  • 17
    Your half-second example is correct, but the millisecond example is not. One millisecond = 1/(1000 * 24 * 60 * 60) of a day, which comes to 0.000000011574 of a day. To get a millisecond in code as a constant: `Const ms As Double = 0.000000011574` So for example, to wait a quarter second, `Application.Wait Now + ms * 250` – WizzleWuzzle Jan 05 '16 at 21:24
16

call waitfor(.005)

Sub WaitFor(NumOfSeconds As Single)
    Dim SngSec as Single
    SngSec=Timer + NumOfSeconds

    Do while timer < sngsec
        DoEvents
   Loop
End sub

source Timing Delays in VBA

Community
  • 1
  • 1
user4232305
  • 179
  • 1
  • 4
6

I have try this and it works for me:

Private Sub DelayMs(ms As Long)
    Debug.Print TimeValue(Now)
    Application.Wait (Now + (ms * 0.00000001))
    Debug.Print TimeValue(Now)
End Sub

Private Sub test()
    Call DelayMs (2000)  'test code with delay of 2 seconds, see debug window
End Sub
JTG
  • 8,587
  • 6
  • 31
  • 38
Nam
  • 69
  • 1
  • 1
  • This answer ist WRONG regarding the initial question "Ho to give a time delay of less thna one second in excel VBA". This function will NOT work for delays less then 1000 miliseconds! You can check it out yourself by trying the following code snippet: `Dim lngIdx As Long 'newline' For lngIdx = 0 To 5000 'newline' Application.Wait (Now + (100 * 0.00000001)) 'newline' Next lngIdx 'newline'` – Semjon Mössinger Nov 08 '16 at 10:03
5

Everyone tries Application.Wait, but that's not really reliable. If you ask it to wait for less than a second, you'll get anything between 0 and 1, but closer to 10 seconds. Here's a demonstration using a wait of 0.5 seconds:

Sub TestWait()
  Dim i As Long
  For i = 1 To 5
    Dim t As Double
    t = Timer
    Application.Wait Now + TimeValue("0:00:00") / 2
    Debug.Print Timer - t
  Next
End Sub

Here's the output, an average of 0.0015625 seconds:

0
0
0
0.0078125
0

Admittedly, Timer may not be the ideal way to measure these events, but you get the idea.

The Timer approach is better:

Sub TestTimer()
  Dim i As Long
  For i = 1 To 5
    Dim t As Double
    t = Timer
    Do Until Timer - t >= 0.5
      DoEvents
    Loop
    Debug.Print Timer - t
  Next
End Sub

And the results average is very close to 0.5 seconds:

0.5
0.5
0.5
0.5
0.5
Jon Peltier
  • 5,895
  • 1
  • 27
  • 27
2

Otherwise you can create your own function then call it. It is important to use Double

Function sov(sekunder As Double) As Double

starting_time = Timer

Do
DoEvents
Loop Until (Timer - starting_time) >= sekunder

End Function
JakeK
  • 76
  • 2
  • 18
VilhelmP
  • 21
  • 2
2

Obviously an old post, but this seems to be working for me....

Application.Wait (Now + TimeValue("0:00:01") / 1000)

Divide by whatever you need. A tenth, a hundredth, etc. all seem to work. By removing the "divide by" portion, the macro does take longer to run, so therefore, with no errors present, I have to believe it works.

  • If you wait for a time that's less than one second, VBA will wait for anything between 0 and 1 seconds, usually closer to zero. I ran a quick test of `Application.Wait Now + TimeValue("0:00:00") / 2` (half a second), and the average wait was 0.00156 seconds. – Jon Peltier Oct 23 '19 at 01:21
2

No answer helped me, so I build this.

'   function Timestamp return current time in milliseconds.
'   compatible with JSON or JavaScript Date objects.

Public Function Timestamp () As Currency
    timestamp = (Round(Now(), 0) * 24 * 60 * 60 + Timer()) * 1000
End Function

'   function Sleep let system execute other programs while the milliseconds are not elapsed.

Public Function Sleep(milliseconds As Currency)

    If milliseconds < 0 Then Exit Function

    Dim start As Currency
    start = Timestamp ()

    While (Timestamp () < milliseconds + start)
        DoEvents
    Wend
End Function

Note : In Excel 2007, Now() send Double with decimals to seconds, so i use Timer() to get milliseconds.

Note : Application.Wait() accept seconds and no under (i.e. Application.Wait(Now())Application.Wait(Now()+100*millisecond)))

Note : Application.Wait() doesn't let system execute other program but hardly reduce performance. Prefer usage of DoEvents.

karkael
  • 431
  • 2
  • 9
2

To pause for 0.8 of a second:

Sub main()
    startTime = Timer
    Do
    Loop Until Timer - startTime >= 0.8
End Sub
S.S. Anne
  • 15,171
  • 8
  • 38
  • 76
0
Public Function CheckWholeNumber(Number As Double) As Boolean
    If Number - Fix(Number) = 0 Then
        CheckWholeNumber = True
    End If
End Function

Public Sub TimeDelay(Days As Double, Hours As Double, Minutes As Double, Seconds As Double)
    If CheckWholeNumber(Days) = False Then
        Hours = Hours + (Days - Fix(Days)) * 24
        Days = Fix(Days)
    End If
    If CheckWholeNumber(Hours) = False Then
        Minutes = Minutes + (Hours - Fix(Hours)) * 60
        Hours = Fix(Hours)
    End If
    If CheckWholeNumber(Minutes) = False Then
        Seconds = Seconds + (Minutes - Fix(Minutes)) * 60
        Minutes = Fix(Minutes)
    End If
    If Seconds >= 60 Then
        Seconds = Seconds - 60
        Minutes = Minutes + 1
    End If
    If Minutes >= 60 Then
        Minutes = Minutes - 60
        Hours = Hours + 1
    End If
    If Hours >= 24 Then
        Hours = Hours - 24
        Days = Days + 1
    End If
    Application.Wait _
    ( _
        Now + _
        TimeSerial(Hours + Days * 24, Minutes, 0) + _
        Seconds * TimeSerial(0, 0, 1) _
    )
End Sub

example:

call TimeDelay(1.9,23.9,59.9,59.9999999)

hopy you enjoy.

edit:

here's one without any additional functions, for people who like it being faster

Public Sub WaitTime(Days As Double, Hours As Double, Minutes As Double, Seconds As Double)
    If Days - Fix(Days) > 0 Then
        Hours = Hours + (Days - Fix(Days)) * 24
        Days = Fix(Days)
    End If
    If Hours - Fix(Hours) > 0 Then
        Minutes = Minutes + (Hours - Fix(Hours)) * 60
        Hours = Fix(Hours)
    End If
    If Minutes - Fix(Minutes) > 0 Then
        Seconds = Seconds + (Minutes - Fix(Minutes)) * 60
        Minutes = Fix(Minutes)
    End If
    If Seconds >= 60 Then
        Seconds = Seconds - 60
        Minutes = Minutes + 1
    End If
    If Minutes >= 60 Then
        Minutes = Minutes - 60
        Hours = Hours + 1
    End If
    If Hours >= 24 Then
        Hours = Hours - 24
        Days = Days + 1
    End If
    Application.Wait _
    ( _
        Now + _
        TimeSerial(Hours + Days * 24, Minutes, 0) + _
        Seconds * TimeSerial(0, 0, 1) _
    )
End Sub
matan justme
  • 371
  • 3
  • 15