🚀The world's best VBA AI has evolved. ExcelMaster is now an autonomous Agent.Read more →
Back to Blog

VBA Sleep en Excel — la llamada a la API de Windows, la trampa PtrSafe de 64 bits y Wait frente a Sleep

|

VBA Sleep en Excel — la llamada a la API de Windows, la trampa PtrSafe de 64 bits y Wait frente a Sleep

TL;DRSleep no forma parte de VBA. Es una función de la API de Windows que pausa tu macro un número de milisegundos, y tienes que declararla antes de poder llamarla. En Excel de 64 bits esa declaración debe llevar el atributo PtrSafe, envuelta en una guarda #If VBA7 para que siga compilando en todas partes:

#If VBA7 Then
    Public Declare PtrSafe Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
#Else
    Public Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
#End If

Sub PauseQuarterSecond()
    Sleep 250            ' 250 milisegundos = un cuarto de segundo
End Sub

La gente echa mano de Sleep cuando Application.Wait no basta — cuando necesita pausar una fracción de segundo, no uno entero. Y lo primerísimo que ocurre es un error de compilación, porque Sleep no es en absoluto un comando de VBA: vive en Windows. Esta guía se construye sobre una sola idea — Sleep es una pausa de milisegundos que tomas prestada del sistema operativo — porque explica la declaración, la trampa de los 64 bits, y por qué Sleep sigue sin poder darte una pausa receptiva.

Lo que aprenderás

  • El modelo mental — Sleep es una función kernel32 de Windows que tomas prestada, no una palabra clave de VBA
  • La trampa PtrSafe de 64 bits — el error de compilación exacto y el arreglo exacto con #If VBA7
  • Milisegundos, no segundos — la precisión por debajo del segundo que es toda la razón para usar Sleep
  • Por qué «milisegundos» no es «preciso» — el suelo de ~15 ms del planificador del sistema operativo
  • Por qué Sleep sigue congelando Excel, y cuándo usar Wait o un bucle DoEvents en su lugar

El modelo mental: una pausa que tomas prestada de Windows

Application.Wait es la herramienta propia de Excel. Sleep no lo es — pertenece a Windows, en una biblioteca del sistema llamada kernel32. Para usarla, sales fuera de VBA con una instrucción Declare que dice, en esencia: «hay una función llamada Sleep allá en kernel32; esta es su forma; déjame llamarla». Solo entonces puedes escribir Sleep 250.

Ese «tomarlo prestado de Windows» es el modelo mental, y todo lo incómodo de Sleep se deriva de ahí. Una palabra clave nativa de VBA simplemente funcionaría. Una función de API prestada hay que declararla, tiene que coincidir con la convención de llamada del sistema operativo y — esto es lo crucial — hay que declararla de forma distinta en Windows de 32 y de 64 bits. Ese último punto es donde casi todo el mundo se atasca.

La trampa PtrSafe de 64 bits: el error y el arreglo

Este es el problema número uno de Sleep, y es la razón por la que una macro que «funcionaba en el ordenador viejo» de repente se niega a arrancar. La declaración clásica que encontrarás en código viejo y en posts de foros antiguos es:

Public Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)   ' estilo anterior a 2010

Ejecútala en un Excel de 64 bits moderno y, antes de que se ejecute una sola línea, VBA se detiene con:

Compile error: The code in this project must be updated for use on 64-bit systems. Please review and update Declare statements and then mark them with the PtrSafe attribute.

El arreglo tiene dos partes. Primero, añade la palabra clave PtrSafe, que le dice a VBA que la declaración se ha revisado para la seguridad de punteros de 64 bits. Segundo, envuélvela en un bloque de compilación condicional #If VBA7 para que el mismo archivo siga compilando en versiones antiquísimas de Excel anteriores a PtrSafe:

#If VBA7 Then
    ' Excel 2010 y posteriores - seguro en 64 bits
    Public Declare PtrSafe Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
#Else
    ' Excel 2007 y anteriores - no existe la palabra clave PtrSafe
    Public Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
#End If

#If VBA7 se comprueba en tiempo de compilación, no de ejecución, así que cada versión de Excel solo ve la única declaración que entiende. Pon este bloque al principio de un módulo estándar, por encima de cualquier procedimiento, y Sleep compila y corre en todo Excel moderno. Si solo vas a apuntar a Excel 365 de 64 bits, basta con la línea PtrSafe sola — pero la versión protegida es el copiar-y-pegar seguro.

Milisegundos, no segundos — la razón de ser de Sleep

Sleep toma milisegundos. Sleep 250 es un cuarto de segundo; Sleep 1000 es un segundo; Sleep 50 es una cincuentava parte. Esta es toda la razón para preferir Sleep sobre Application.Wait, que solo puede pausar en segundos enteros. Si necesitas moderar un bucle a unas pocas veces por segundo, espaciar peticiones de API o esperar un instante corto a que algo se asiente, Sleep es la herramienta con la resolución adecuada.

Do
    ' ... comprueba si el archivo de exportacion ha aparecido ...
    If Dir(exportPath) <> "" Then Exit Do
    Sleep 200        ' sondea cinco veces por segundo en vez de machacar el disco
Loop

Pero «milisegundos» no es «preciso»

No confundas unidades finas con precisión fina. Windows planifica los hilos en un tick de aproximadamente 15,6 milisegundos, así que Sleep 1 no duerme un milisegundo — duerme hasta el siguiente tick del planificador, normalmente unos 15 ms. Sleep garantiza «al menos este tiempo», nunca «exactamente este tiempo», y la pausa real se redondea hacia arriba a la granularidad del planificador. Eso está bien para moderar y marcar el ritmo, donde solo quieres «más o menos con esta frecuencia». Es la herramienta equivocada si necesitas temporización precisa o medición exacta — para medir el tiempo transcurrido, usa Timer; para temporización de alta precisión bajarías a QueryPerformanceCounter.

Sleep sigue congelando Excel

Aquí está la trampa que Sleep comparte con Application.Wait: mientras pausa, Excel está congelado. Sleep aparca el único hilo de Excel durante todo ese tiempo y no procesa la cola de mensajes, así que la pantalla no se repinta, los clics no se atienden, y un Sleep lo bastante largo — o muchos cortos en un bucle — hace que la ventana pase a «No responde». La precisión por debajo del segundo no cambia esto; una pausa es una pausa, y un hilo bloqueado es un Excel congelado.

Así que Sleep, igual que Wait, es la herramienta equivocada cuando el objetivo de la pausa es dejar que el usuario vea algo o haga algo. Una pausa en la que Excel sigue vivo es un bucle que cede con DoEvents:

' Ritmo receptivo por debajo del segundo - Excel sigue vivo entre pulsos
Dim nextBeat As Double
nextBeat = Timer + 0.25
Do While Timer < nextBeat
    DoEvents
Loop

El veredicto honesto: Wait, Sleep o un bucle DoEvents

Alinea las tres según lo que de verdad necesitas:

  • Una pausa de segundos enteros, sin líosApplication.Wait Now + TimeValue(...). Sin Declare, sin PtrSafe, nada que se pueda equivocar. Echa mano de esto primero para «espera ~2 segundos».
  • Una pausa por debajo del segundoSleep, porque Application.Wait no puede bajar de un segundo. Acepta la ceremonia de Declare/PtrSafe como el precio de la resolución de milisegundos.
  • Una pausa en la que Excel debe seguir receptivo — un bucle DoEvents, porque tanto Wait como Sleep congelan la ventana. Esta es la que la gente más a menudo necesita y menos a menudo elige.

El reto: no añadas un Sleep «por si acaso» para ralentizar una macro. Si una macro se porta mal sin una pausa artificial, la pausa casi siempre esconde un bug real — un valor leído antes de estar listo, un evento que se disparó dos veces — y el arreglo honesto ataca eso, no un Sleep 500 espolvoreado por encima.

Cómo ayuda ExcelMaster

La declaración de Sleep es justo el tipo de código repetitivo que es fácil de equivocar y tedioso de acertar: la cadena Lib "kernel32", el argumento ByVal, el atributo PtrSafe, la guarda #If VBA7, y luego la decisión de criterio de si Sleep es siquiera la herramienta que querías en vez de Application.Wait o un bucle DoEvents.

ExcelMaster escribe por ti la declaración correcta y segura en 64 bits y, más importante aún, elige la construcción de espera adecuada para lo que describiste. Pídele «sondea un archivo cada 200 ms» y te da un bucle Sleep protegido; pídele «pausa pero déjame cancelar» y te da un bucle DoEvents en su lugar — así nunca publicas el Declare anterior a 2010 que revienta en Excel de 64 bits, ni congelas Excel cuando querías mantenerlo vivo.

Preguntas frecuentes

¿Cómo uso Sleep en Excel VBA?

Decláralo una vez al principio de un módulo estándar y luego llámalo con un valor en milisegundos. Usa la forma segura en 64 bits: #If VBA7 Then Public Declare PtrSafe Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long) (con un Declare normal en la rama #Else para Excel viejo). Entonces Sleep 250 pausa la macro 250 milisegundos — un cuarto de segundo.

¿Por qué mi Declare de Sleep provoca un error de compilación en Excel de 64 bits?

Porque el viejo estilo de declaración es anterior a Office de 64 bits. El Excel de 64 bits moderno exige el atributo PtrSafe en cada instrucción Declare, y sin él obtienes «The code in this project must be updated for use on 64-bit systems… mark them with the PtrSafe attribute». Añade PtrSafe después de Declare, y envuelve la línea en un bloque #If VBA7 para que también siga compilando en Excel más antiguo.

¿Cuál es la diferencia entre Sleep y Application.Wait?

Sleep es una llamada a la API de Windows que debes declarar; pausa un número de milisegundos y da precisión por debajo del segundo. Application.Wait viene integrado en Excel, no necesita declaración, y pausa hasta un momento del reloj con resolución de segundos enteros. Usa Sleep cuando necesites algo más fino que un segundo, y Application.Wait para pausas simples de segundos enteros. Ambos congelan Excel mientras esperan.

¿Sleep deja Excel sin responder?

Sí. Sleep bloquea el único hilo de Excel durante toda la pausa y no procesa mensajes, así que la ventana no puede repintarse ni atender clics y puede mostrar «No responde». Si necesitas que Excel siga receptivo durante una pausa — para mostrar progreso o un botón de Cancelar — usa un bucle que llame a DoEvents en vez de Sleep.

¿Es Sleep preciso al milisegundo?

No. Windows planifica los hilos en un tick de unos 15,6 ms, así que Sleep 1 en realidad pausa unos 15 ms, y Sleep solo garantiza «al menos este tiempo». Está bien para moderar y marcar el ritmo, pero no para temporización precisa. Para medir cuánto tarda un código, usa en su lugar la función Timer.

Probado en

Probado en: Excel 365 (Windows 11, 64 bits), VBA 7.1 — última verificación el 19/08/2026.

Guías relacionadas: VBA Wait · VBA Timer · VBA DoEvents · VBA On Error · VBA ScreenUpdating