Traducir el blog

Reloj analógico en tiempo real

Posted on febrero 23, 2026 by Excel Pedro Wave

🔝To translate this blog post to your language, select it in the top left Google box.


Un reloj analógico en tiempo real

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

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


Características del reloj analógico en tiempo real

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:

  • SetTimer
  • KillTimer

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:

  • StartTimerAPI
  • StopTimerAPI

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 Tick después del cierre.
  • El flujo es limpio, seguro y totalmente automático.

Contenido generado con la ayuda de:


Administrador de nombres

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.

No Response to "Reloj analógico en tiempo real"

Leave A Reply

Comenta este artículo, critícalo o avisa si detectas algún error que haya que corregir.

Mi lista de blogs