I know I'm doing something wrong here. I'm trying to use the sleep function to delay my code, but I get "Sub or Function not defined" error. Any tips?
7 Answers
VBA does not have a Sleep
function.
You can import it from Kernel32.dll like this:
Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
Note that this will freeze the application.
You can also call DoEvents
in a While
loop, which won't freeze the application.

- 868,454
- 176
- 1,908
- 1,964
-
Where in the code do I put that declaration? I've tried sticking it in outside and inside of the sub I'm working on, but get errors both times. – sooprise Apr 29 '10 at 13:39
-
Oh, oops, I was trying to put it into an excel object (silly me). I put it in a module and now it works. Thanks so much! I checked your answer. – sooprise Apr 29 '10 at 13:45
-
Despite the issue of hanging the application, I would prefer this method since the loop approach uses too much CPU. – KalenGi Aug 02 '13 at 12:44
-
@kalengi: You should be using async. – SLaks Aug 04 '13 at 23:36
-
@SLaks async with Sleep, or how do you mean? – KalenGi Aug 06 '13 at 10:15
-
@kalengi: Ideally, `Await Task.Delay()`. In VBA, I don't know whether there is any proper way to do it. – SLaks Aug 06 '13 at 14:03
-
This solution does not work in 64-bit Windows applications or on Mac. `DoEvents` in a while loop will cause excessive CPU usage. Look at [this solution](https://stackoverflow.com/a/74387976/12287457), which solves all of these issues. – GWD Nov 10 '22 at 12:08
Everything I've tried seems to hang the application, including Application.Wait. This seems to work though:
waitTill = Now() + TimeValue("00:15:00")
While Now() < waitTill
DoEvents
Wend

- 2,164
- 21
- 17
-
1I like this one and it is working great.. only one exception. I can't find a way to do 500 ms ... So 1 second is the minimum wait time. Is there a way to do less than 1 second? – BobNoobGuy Jul 06 '15 at 17:24
-
You can use GetSystemTime in kernel32.dll if you want higher resolution: http://www.freevbcode.com/ShowCode.asp?ID=1618 Or if in Excel, you can call the spreadsheet now() function (as [now()] from VBA) which also has higher resolution: https://groups.google.com/forum/#!topic/microsoft.public.excel.programming/-D6lkjJv2ew – Anthony Hayward Jul 08 '15 at 07:21
-
1In Excel you can use square brackets around the call to Now to get the Worksheet function version which has sub-second precision. `[Now()]` – HackSlash Jun 25 '18 at 22:34
-
2
-
This is not a good solution, it causes high CPU usage (1 thread gets maximum usage) and doesn't provide sub 1-second resolution. Use [this solution](https://stackoverflow.com/a/74387976/12287457), it solves both of these issues. – GWD Nov 10 '22 at 11:59
You can also pause the current macro context with Application.Wait T
which won't block the whole process.

- 171,639
- 30
- 264
- 288
-
4This only applies to `Excel.Application`. The `Wait` method does not exist for other Office application object models. – C Perkins Apr 07 '19 at 16:36
Application.Wait DateAdd("m", 10, Now) ' Wait for 10 Minutes
Application.Wait DateAdd("s", 10, Now) ' wait for 10 seconds

- 39,603
- 20
- 94
- 123

- 41
- 1
-
2Welcome to Stack Overflow! Thanks for posting your answer! Please be sure to read the [FAQ on Self-Promotion](http://stackoverflow.com/faq#promotion) carefully. Also note that it is *required* that you post a disclaimer every time you link to your own site/product. – Andrew Barber Feb 20 '13 at 11:03
-
@AndrewBarber: Looking at the link, it doesn't look like Babu's site, but rather like a useful read for the SO. Why would you want to delete it? – Peter Albert Feb 20 '13 at 11:16
-
@PeterAlbert It is Babu's site. They have been spamming it a lot lately (multiple of their answers were deleted as spam because they didn't even contain this much info), and it's in their profile here. – Andrew Barber Feb 20 '13 at 20:25
-
1@AndrewBarber - thanks for the info! I have to admit, I would not have noticed! – Peter Albert Feb 20 '13 at 20:29
-
With this code Excel not freeze and the CPU usage is low:
Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
Sub Delay(s As Single)
Dim TimeOut As Single
TimeOut = Timer + s
Do While Timer < TimeOut
DoEvents
Sleep 1 'With this line the CPU usage is 00 instead of 50 with an absolute error of +1ms and the latency of 1ms.
Loop
End Sub

- 775
- 5
- 15
-
**This solution has a severe bug:** when `Timer + s > 86400`, which can easily happen if called shortly before midnight, it will never stop sleeping! Also, this solution doesn't work on Mac or in 64bit Windows applications. For a solution that deals with both of these issues, look [here](https://stackoverflow.com/a/74387976/12287457). Also, note that the time resolution of `Sleep` is [not actually 1 millisecond](https://stackoverflow.com/q/9518106/12287457). – GWD Nov 10 '22 at 12:04
Pausing an application for 10 seconds:
Application.Wait (Now + TimeValue("0:00:10"))

- 57,590
- 26
- 140
- 166

- 139
- 1
- 4
-
Hi, is there any reason you can think of why this function would not be available in MS Outlook? For some reason, the Alt+F11 VBA editor does not seem to show it, and it won't work when I run it within functions on Outlook messages (from a Rule). Thanks! – Kalin Oct 18 '19 at 16:51
-
@Kalin look at [this solution](https://stackoverflow.com/a/74387976/12287457) for a cross-platform, cross-app solution that doesn't freeze the application and doesn't cause excessive CPU usage. – GWD Nov 10 '22 at 12:10
Here's what you need for cross compatability with 32-bit and 64-bit Windows machines. The delay is in milliseconds, so use 1000 for a 1 second delay.
First, put this above your other Subs/Functions in a module. On a 64-bit machine the line after "#Else" will be highlighted as if there is an error, but this isn't an issue. The code will compile and run.
#If VBA7 Then
Declare PtrSafe Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
#Else
Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
#End If
Now you can create a delay like this example with a 1.5 second delay:
Sub ExampleWithDelay()
Msgbox "This is a message before the delay."
Sleep 1500 ' delay of 1,000 milliseconds or 1.5 seconds
Msgbox "This is a message -AFTER- the delay."
End Sub
As noted by @SLaks, this freezes the application (preventing user input) but you can also call DoEvents
in a While
loop. See the example below. It runs for 10 seconds and allows user interaction.
Every 1/10th of a second it updates the Excel status bar with:
The address of the active cell
A countdown
Sub ExampleWithDelayInLoop() ' for MS Excel Dim thisMessage As String Dim countdownText As String Dim i As Long Const TOTAL_SECONDS As Byte = 10 For i = 1 To TOTAL_SECONDS * 10 countdownText = Excel.WorksheetFunction.RoundUp(TOTAL_SECONDS - (i / 10), 0) thisMessage = "You selected " & Excel.ActiveCell.Address & Space$(4) & countdownText & " seconds remaining" ' Show the address of the active cell and a countdown in the Excel status\ ' bar. If Not Excel.Application.StatusBar = thisMessage Then Excel.Application.StatusBar = thisMessage End If ' Delay 1/10th of a second. ' Input is allowed in 1/10th second intervals. Sleep 100 DoEvents Next i ' Reset the status bar. Excel.Application.StatusBar = False End Sub

- 3,024
- 5
- 35
- 61