🔝To translate this blog post to your language, select it in the top left Google box.
En el artículo anterior publiqué un reloj analógico que mostraba manualmente la hora actual, presionando la tecla para calcular el libro, ya que no era automático por no tener macros:
Tenía la ventaja de poder usarlo en Excel para la Web y de insertarlo en el blog, por si alguien quería probarlo sin tener instalado Excel.
Ahora publico un reloj analógico en tiempo real, pues es automático y mueve la aguja de los segundos cada segundo, gracias a las macros VBA.
NOTA: Haga clic en el reloj analógico para iniciar o detener el temporizador de un segundo.
Descarga el reloj analógico en tiempo real desde este enlace:
Las macros del archivo descargado están bloqueadas por defecto. Para desbloquear las macros debes modificar las Propiedades del archivo siguiendo estas instrucciones:
Abre el archivo y presiona el botón: Habilitar edición cuando aparezca el aviso de VISTA PROTEGIDA.
Presiona el botón: Habilitar contenido cuando aparezca la ADVERTENCIA DE SEGURIDAD Las macros se han deshabilitado o se deshabilitó parte del contenido activo.
Las macros no están protegidas para poder analizar fácilmente el código VBA. Las hojas están protegidas sin contraseña, para poder analizarlas y para evitar que los usuarios alteren las fórmulas.
ATENCIÓN: Se puede modificar este libro de Excel respetando esta licencia:
Creative Commons — Atribución-NoComercial-CompartirIgual-No portada — CC BY-NC-SA 4.0
Estas son las principales características del reloj analógico en tiempo real.
⭐ Módulo del temporizador API
Este módulo implementa un temporizador de alta precisión en
Excel usando las funciones de Windows SetTimer y
KillTimer.
Está diseñado para funcionar en 32 y 64 bits, sincronizarse exactamente con el reloj del sistema y actualizar el rango nombrado "miHora" cada segundo sin bloquear Excel.
🧩 1. Compatibilidad total 32/64 bits
Incluye declaraciones API con #If VBA7 Then para:
SetTimerKillTimer
Esto garantiza compatibilidad con:
- Excel 2010 (32/64 bits)
- Excel 2013 → Excel para Microsoft 365
- Windows 7 → Windows 11
⏱️ 2. Temporizador real basado en Windows (no OnTime)
A diferencia de Application.OnTime, este temporizador:
- No se retrasa cuando Excel está ocupado
- No se acumula
- No depende del motor de Excel
- No se rompe al cerrar libros
- Tiene precisión de milisegundos
Usa:
TimerID = SetTimer(0, 0, intervalo_ms, AddressOf Tick)
🎯 3. Sincronización exacta con el segundo del sistema
El módulo calcula cuántos milisegundos faltan para el próximo segundo exacto:
msRestantes = 1000 - (Timer * 1000 Mod 1000)
Esto permite:
- Primer tick perfectamente alineado con el reloj
- Ticks posteriores cada 1000 ms exactos
- Evitar desvíos acumulados
🔄 4. Tick inteligente: solo actualiza si el segundo cambia
Evita trabajo innecesario:
If segundoActual <> UltimoSegundo Then
Range("miHora").Value2 = Now()
End If
Beneficios:
- Menos carga
- Más estabilidad
- No repite operaciones dentro del mismo segundo
🧱 5. Protección contra errores (incluido el 50290)
El procedimiento Tick incluye:
On Error GoTo SalirTick
Esto evita que:
- Excel detenga el temporizador si está ocupado
- Se produzcan errores al cerrar libros
- El temporizador quede “colgado”
🖱️ 6. Cursor dinámico de reloj
Al iniciar:
Application.Cursor = xlWait
Al detener:
Application.Cursor = xlDefault
Esto da feedback visual claro al usuario.
🛑 7. Inicio/parada conmutado
El módulo incluye un interruptor:
Sub StartStopTimerAPI()
que alterna entre:
StartTimerAPIStopTimerAPI
Ideal para botones o accesos rápidos.
🧹 8. Limpieza segura del temporizador
Al detener:
KillTimer 0, TimerID
Esto garantiza:
- No quedan temporizadores huérfanos
- No se ejecutan ticks después de cerrar el libro
- No se producen cierres inesperados de Excel
📌 9. No bloquea Excel
El temporizador API:
- No usa bucles
- No usa
DoEvents - No congela la interfaz
- Permite trabajar en otros libros sin interferencias
🎁 Resumen del Temporizador API
Temporizador API de alta precisión para Excel, compatible con 32/64 bits, sincronizado al segundo del sistema, con actualización inteligente, cursor dinámico, protección contra errores y control seguro de inicio/parada. No bloquea Excel y mantiene estabilidad incluso con múltiples libros abiertos.
🧩 DIAGRAMA DE FLUJO—Temporizador API de un segundo
┌──────────────────────────┐
│ StartStopTimerAPI() │
└──────────────┬───────────┘
│
¿RunClk = False? ────┤
│Sí
▼
┌────────────────────┐
│ StartTimerAPI() │
└───────┬────────────┘
│
▼
┌──────────────────────────────┐
│ Cursor = xlWait │
│ RunClk = True │
│ SyncPhase = True │
│ UltimoSegundo = -1 │
└───────────┬──────────────────┘
│
▼
┌────────────────────────────────────────┐
│ Calcular msRestantes hasta el próximo │
│ segundo exacto │
└───────────────┬────────────────────────┘
│
▼
┌────────────────────────────────────────┐
│ SetTimer( intervalo = msRestantes ) │
│ → llama a Tick() │
└────────────────────────────────────────┘
──────────────────────────────────────────────────────────────────────────────
TICK() — Cada disparo del temporizador
──────────────────────────────────────────────────────────────────────────────
┌────────────────────────────────────────┐
│ Tick() │
└───────────┬────────────────────────────┘
│
▼
┌────────────────────────────────────────┐
│ ¿SyncPhase = True? │
└───────────┬────────────────────────────┘
│Sí
▼
┌────────────────────────────────────────┐
│ SyncPhase = False │
│ KillTimer (primer timer) │
│ SetTimer( intervalo = 1000 ms ) │
│ (sincronizado al segundo exacto) │
└───────────┬────────────────────────────┘
│
▼
┌────────────────────────────────────────┐
│ segundoActual = Second(Now) │
└───────────┬────────────────────────────┘
│
¿segundoActual = UltimoSegundo? ─────────┤
│No
▼
┌────────────────────────────────────────┐
│ UltimoSegundo = segundoActual │
│ Range("miHora") = Now() │
└────────────────────────────────────────┘
│
▼
┌────────────────────────────────────────┐
│ Fin Tick() │
└────────────────────────────────────────┘
──────────────────────────────────────────────────────────────────────────────
STOP — Detener temporizador
──────────────────────────────────────────────────────────────────────────────
┌──────────────────────────┐
│ StopTimerAPI() │
└──────────────┬───────────┘
│
▼
┌──────────────────────────┐
│ RunClk = False │
│ KillTimer TimerID │
│ Cursor = xlDefault │
└──────────────────────────┘
🎯 Qué representa este diagrama
- El flujo completo desde que el usuario inicia o detiene el temporizador.
- La sincronización exacta al segundo del sistema.
- El comportamiento del primer tick (sincronización) y los siguientes (intervalo fijo).
- La actualización inteligente de
miHora. - La gestión del cursor de reloj.
- La detención limpia del temporizador API.
⭐ Eventos en ThisWorkbook
Este módulo conecta el ciclo de vida del libro con el temporizador API, de modo que el temporizador:
- se inicia automáticamente cuando se abre el libro
- se detiene automáticamente cuando el libro intenta cerrarse
Así se evita que el temporizador quede activo en memoria o siga ejecutándose después de cerrar el archivo.
🧩 Comportamiento detallado
✔ Al abrir el libro
Private Sub Workbook_Open()
StartTimerAPI
End Sub
Cuando el archivo se abre:
- Se ejecuta
StartTimerAPI - Se activa el temporizador API
- Se inicia la sincronización al segundo exacto
- Se cambia el cursor a modo reloj (
xlWait) - Comienza la actualización periódica (Tick)
Resultado: el temporizador arranca automáticamente sin intervención del usuario.
✔ Al intentar cerrar el libro
Private Sub Workbook_BeforeClose(Cancel As Boolean)
StopTimerAPI
End Sub
Cuando el usuario pulsa:
- La X
- Alt+F4
- Ctrl+W
- O cierra desde menú
Excel ejecuta Workbook_BeforeClose, que:
- Llama a
StopTimerAPI - Mata el temporizador con
KillTimer - Restaura el cursor (
xlDefault) - Limpia el estado interno
Resultado: el temporizador se detiene siempre antes de que el libro se cierre, evitando temporizadores huérfanos o errores 50290.
🎯 En una frase
Este código garantiza que el temporizador API se inicia automáticamente al abrir el libro y se detiene de forma segura al cerrarlo, evitando que quede activo en segundo plano.
⭐ Diagrama de flujo — Eventos del libro + temporizador API
┌────────────────────────────┐
│ El usuario abre el libro │
└───────────────┬────────────┘
│
▼
┌──────────────────────────┐
│ Workbook_Open() │
└─────────────┬────────────┘
│
▼
┌──────────────────────────┐
│ StartTimerAPI │
│ • Inicia temporizador │
│ • Activa cursor reloj │
│ • Sincroniza primer tick │
└─────────────┬────────────┘
│
▼
┌──────────────────────────┐
│ Temporizador en marcha │
│ (Tick cada segundo) │
└─────────────┬────────────┘
│
▼
┌────────────────────────────┐
│ El usuario intenta cerrar │
│ (X, Alt+F4, Ctrl+W, menú) │
└───────────────┬────────────┘
│
▼
┌──────────────────────────┐
│ Workbook_BeforeClose() │
└─────────────┬────────────┘
│
▼
┌──────────────────────────┐
│ StopTimerAPI │
│ • Mata el timer API │
│ • Restaura cursor normal │
│ • Limpia estado interno │
└─────────────┬────────────┘
│
▼
┌──────────────────────────┐
│ El libro se cierra sin │
│ temporizadores activos │
└──────────────────────────┘
🎯 Qué expresa este diagrama
- El temporizador se inicia automáticamente al abrir el libro.
- El temporizador se detiene siempre antes de que el libro se cierre.
- Se evita que queden temporizadores huérfanos en memoria.
-
Se garantiza que Excel no siga ejecutando
Tickdespués del cierre. - El flujo es limpio, seguro y totalmente automático.
Contenido generado con la ayuda de:
Estos son los nombres definidos en el Administrador de nombres, necesarios para diseñar el Reloj analógico en tiempo real.
Descarga el Reloj analógico en tiempo real, pruébalo y te agradeceré cualquier sugerencia que me hagas tendente a mejorarlo.






































