Traducir el blog

PA2 - Programación por Pares vs Programación Asistida

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



    Programación por Pares

    Con la Programación por Pares o Programación en Pareja (Pair Programming en inglés), no se puede aprender a programar, porque se trata de emparejar a dos expertos en un determinado lenguaje de programación para mejorar el código escrito por ambos.


    Programación Asistida

    Con la Programación Asistida por IA (Vibe coding) si se puede aprender a programar un nuevo lenguaje de programación, que es lo que acabo de hacer en dos días.

    He pasado de usar el lenguaje HTML como un aficionado a programarlo como un profesional, aunque sigo sin ser un experto en HTML, CSS y JavaScript.

    Con lo que he conseguido diseñar el código que muestro más abajo, y he podido incrustar la comparativa entre los dos métodos de programación dentro del artículo de Blogger que estás leyendo ahora mismo, justo debajo de estas líneas.


    Comparativa

    Con una pizca de HTML, otro poco de CSS y el resto de JavaScript he conseguido regenerar la comparativa animada, con botones para repetir la animación.

    Pero no lo habría sabido hacer sin la inestimable ayuda de la IA de Microsoft Copilot con la que, gracias a la Programación Asistida, he conseguido programar la siguiente comparativa.


    ATENCIÓN: Para poder ver bien la siguiente comparativa en el móvil o celular, gíralo en horizontal.


    Comparativa:
    Programación por Pares vs Programación Asistida
    Programación por Pares
    Programación Asistida
    Dos desarrolladores humanos
    Humano + IA (Asistente)
    Simétricos, cambio de roles
    Asimétricos, humano conduce, IA asiste
    Debate y negociación
    Sugerencias y correcciones
    Turnos de 15–30 minutos
    Asistencia rápida y continua
    Entorno compartido
    Limitación del contexto
    Ejecución y depuración en conjunto
    La IA no ejecuta el código
    Detectados entre ambos
    Riesgo de fallos sutiles
    Experiencia compartida
    Transferencia de conocimiento
    Colaboración con la Inteligencia Natural Asistencia de la Inteligencia Artificial


    Ventajas e inconvenientes de la comparativa animada

    Ventajas de usar animaciones Inconvenientes de usar animaciones
    Mejoran la comprensión: guían la mirada y ordenan la información. Pueden distraer: si se usan en exceso o sin un propósito claro.
    Aumentan la atención: el movimiento atrae la vista de forma natural. Requieren control de estados: si el estado final no está bien definido, el elemento puede quedar oculto.
    Dan sensación de profesionalidad: una entrada suave o un glow sutil elevan la calidad visual. Reiniciarlas no es trivial: a veces hay que usar trucos como forzar reflow para reiniciar la animación.
    Son ligeras: las animaciones CSS consumen pocos recursos y funcionan bien en móviles. Pueden afectar a la accesibilidad: usuarios sensibles al movimiento pueden necesitar animaciones más suaves o desactivadas.
    No requieren librerías externas: todo se hace con CSS y el propio navegador. Dependencia del orden de carga: en entornos como Blogger, si el script se carga antes que los elementos, los eventos pueden fallar.
    Fáciles de mantener: cambiar duración, suavidad o estilo no rompe la estructura. Compatibilidad variable: algunos efectos avanzados (como ciertos filtros) pueden verse distinto según el navegador.
    Escalables: se pueden añadir más elementos animados sin reescribir la base. Riesgo de saturación visual: si todo se mueve, nada destaca y el mensaje se diluye.


    Cómo programé la comparativa animada

    En el próximo artículo explicaré cómo he conseguido hacer la comparativa animada en dos días, para lo que necesito bastantes más días, pues tengo que recoger todas las ideas que he aprendido durante el proceso de aprendizaje con la Programación Asistida por IA.

    Por supuesto que publicaré las PROMPTS (SOLICITUDES en español) con las que he guiado a la IA Microsoft Copilot para obtener este resultado.


    Cómo programé el índice animado

    El índice animado, que aparece al principio de este artículo, lo he programado en dos horas y también lo explicaré en el próximo artículo, además de explicar cómo hacer los botones: Volver al índice, como el de aquí abajo, que al pulsarlo hace scroll suave hacia arriba hasta llegar al índice.


    Artículos sobre Programación Asistida del Mapamundi con relojes

    Sigue todo lo que escribo sobre Programación Asistida para mejorar el Mapamundi con relojes desde aquí:


    Me alegrará saber si este proyecto te parece interesante.

    Deja un comentario y te lo agradeceré.

    PA1 - Mapamundi con relojes en Excel

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


    DEDICATORIA:

    Dedico este y los próximos artículos a mi amigo Fernando, el mejor programador que he conocido en mi vida profesional, con quien he compartido muchas sobremesas y que, recién jubilado, se mudó a vivir a Pareja (pueblo de Guadalajara), escapando de los madriles.


    Cambios en el Mapamundi con relojes

    Para no perderte en el laberinto de los cambios de horario de invierno y de verano, lee estas páginas:

    O mejor aún, descarga la nueva versión del Mapamundi con relojes en Excel, que he diseñado a partir de las versiones anteriores que publiqué en mi blog:

    La nueva versión tiene este aspecto y permite saber la hora en cualquier ciudad del mundo:


    ¡La nueva versión del Mapamundi con relojes la he diseñado con la inestimable ayuda de Microsoft Copilot!, una IA generativa que permite la Programación Asistida (Vibe coding), de la que hablaré más adelante.


    Descarga el mapamundi con relojes

    Descarga la última versión del Mapamundi con relojes, en continua evolución, 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


    Vídeo: Mapamundi con relojes

    En este vídeo explico cómo usar el Mapamundi con relojes.

    Te agradecería que me comentaras cualquier sugerencia de mejora o los errores que deban corregirse en una próxima versión.


    Programación en Pareja

    Mi carrera profesional acabó en 2020 (año de la pandemia) sin haber usado la Inteligencia Artificial - IA, pues el uso generalizado de la IA comenzó en el año 2022, coincidiendo con la aparición y expansión de los modelos de IA generativa como ChatGPT.

    Lo que si conocí fue la Programación en Pareja o Programación por Pares (Pair Programming), que es una técnica de desarrollo ágil, especialmente con la Programación Extrema (Extreme Programming - XP)donde dos desarrolladores trabajan juntos en el mismo código al mismo tiempo, compartiendo pantalla, teclado y ratón. Uno escribe y el otro revisa, y ambos intercambian roles con frecuencia. Esto mejora la calidad del código, acelera el aprendizaje y reduce errores.

    La Programación en Pareja o Programación por Pares se denomina así porque siempre hay dos programadores, que intercambian sus roles regularmente:

    • Conductor/Piloto: es el que escribe el código.
    • Navegador/Copiloto: es el que revisa el código, detecta errores, propone mejoras y piensa en el diseño general.

    Siempre he creído que este tipo de programación es el mejor para generar código, aunque pocas veces la he practicado, pues hacen falta dos programadores para generar un único código, y los gestores de proyectos aún piensan que cada programador haga su tarea y se responsabilice de ella, sin contar con una pareja de programadores, cuando es más rápido y eficaz que dos programadores codifiquen juntos aprendiendo el uno del otro.

    Con el teletrabajo se creó la variante de Programación Remota en Pareja (Remote Pair Programming), donde ambos desarrolladores trabajan desde lugares separados usando herramientas de colaboración remota en tiempo real. Yo no la he probado, pues suelo programar habitualmente solo... ¡Hasta hace poco!


    Programación Asistida

    Este es el primer artículo sobre Programación Asistida por IA, que me ha servido para diseñar la última versión del Mapamundi con relojes en Excel, y para compartir mis experiencias de programación con los lectores de mi blog.

    Los títulos de cada uno de los artículos de esta serie comenzarán con PA y un número de artículo, para indicar que se refieren a la Programación Asistida (PA).

    La Programación Asistida por IA (Vibe coding) permite a programadores solitarios desarrollar software que antes requería un equipo de ingeniería.

    "La nueva relación entre los programadores y la inteligencia artificial será de colaboración, en la que las herramientas automatizadas incrementarán la productividad y la eficiencia, mientras que el conocimiento y la experiencia humana seguirán siendo esenciales para incrementar la calidad del software."


    ¿Cómo he programado el nuevo Mapamundi con relojes?

    Con la inestimable ayuda de Microsoft Copilot, una IA que permite codificar mediante Programación Asistida.

    Gracias a MS Copilot he podido encontrar bugs, mejorar y comentar el código VBA de la última versión del Mapamundi con relojes, que puedes descargar más arriba y que está en continua evolución, pues no me resisto a seguir consultando a la IA, que está activa 24x7 y deseando ayudarme.

      De momento, quédate con esta comparativa:


      En los próximos artículos de esta serie sobre Programación Asistida, os contaré cómo la IA me ha ayudado y sigue ayudándome a realizar cambios en el código VBA e incluso en las hojas de Excel.

      Podrás seguir los nuevos artículos desde aquí:


      Fernando, ¿ya has probado la Programación Asistida por IA?

      Relojes de 24 horas y de 12 horas AM/PM

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


      Cómo aprender a usar relojes de 24 horas

      He visto que quienes vienen de países con relojes que marcan la hora en formato de 12 horas con AM/PM tienen dificultad para aprender a usar relojes de 24 horas.

      En países como Colombia se dice: la una de la tarde en lugar de las 13 horas, pues no están acostumbrados a relojes de 24 horas.

      Con estos dos relojes se aprende a distinguir el formato de 12 horas AM/PM del formato de 24 horas.

      El reloj de la izquierda marca la una y 18 minutos en formato PM (después del mediodía).

      El reloj de la derecha marca las 13:18 horas en formato de 24 horas.

      TRUCO: Para convertir cualquier hora PM en 24 horas, se suman 12 horas. Por ejemplo, 01:18 PM se convierte en 13:18 horas. Si es 01:18 AM no se suma nada, por lo que es 01:18 horas.


      Vídeo para saber la hora

      En este vídeo de unos dos minutos explico cómo saber la hora en los relojes de 12 horas y de 24 horas.


      Pruébalo ahora mismo en tu teléfono

      Prueba en tu teléfono estos dos relojes analógicos, de 24 horas y de 12 horas con AM/PM, desde esta ventana en la nube de Microsoft OneDrive:

      ATENCIÓN: Para hacer zoom, coloca dos dedos sobre la pantalla del teléfono y muévelos, igual que cuando amplías o reduces una foto.

      En la barra de abajo hay varios iconos:

      Botón para actualizar los relojes: Actualizar todas las conexiones de datos

      Botón para descargar el archivo: Descargar

      Botón para: Información acerca de este libro. Aparece un Código para insertar que no funciona desde hace meses. Está denunciado a Microsoft, pero no da solución.

      Ayúdame a compartir los relojes, insertando el siguiente código en tu blog o página web:


      Pruébalo ahora mismo en tu PC

      Prueba en tu PC estos dos relojes analógicos, de 24 horas y de 12 horas con AM/PM, sin necesidad de descargar nada, incluso sin tener instalado Excel, desde esta ventana en la nube de Microsoft OneDrive:

      Para ajustar el zoom en la nube:

      • En el PC sitúa el cursor dentro del buscador y presiona la tecla <Control> girando la ruleta del ratón.

      Descarga el archivo haciendo clic en el botón: Descargar

      Si quieres ayudarme puedes compartir el nuevo reloj analógico, insertándolo en tu blog o página web con este código:

      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

      Dime si te ha sido útil saber usar los dos tipos de reloj.

      Reloj analógico en tiempo real

      🔝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 contener 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, que automáticamente 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.


      ACTUALIZACIÓN v1.12: Descarga la última actualización para elegir el tipo de reloj con un desplegable en la celda D6:

      • 12 Horas: De 1 a 12 horas.
      • 24 Horas: De 12 a 23 horas si la hora es después del mediodía. Si es antes del mediodía se comporta como el reloj de 12 Horas.
      • AM/PM: De 1 a 12 horas, indicando AM o PM si la hora es antes o después del mediodía, respectivamente.

      Con la última actualización el tipo de reloj que se muestra ya no está determinado por la configuración regional del sistema operativo, sino que depende de la elección del usuario.

      También he añadido eventos de la hoja para cambiar automáticamente el valor del tipo de reloj en la celda D6 cuando el usuario cambia el idioma del reloj.

      Además he añadido un microbenchmark, que escribe en la ventana Inmediato del editor VBA (denominada también ventana Ejecución) cuando el reloj se salta algún segundo, debido a que el recálculo tarda más de un segundo, o a que Excel o el sistema están ocupados en otras tareas y no responden en un segundo.


      Descarga el reloj analógico en tiempo real

      Descarga el reloj analógico en tiempo real v1.12 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

      ACTUALIZACIÓN v1.12: He ajustado el comportamiento del módulo con la ayuda de la IA de Microsoft, llevando a cabo pruebas y corrección de errores en 12 iteraciones del desarrollo del código del módulo VBA.

      ¡Realmente me lo he pasado "pipa" interactuando con la IA de Microsoft Copilot, intentando resolver los intríngulis del código!

      Este es el resultado de la última revisión del módulo:

      A continuación explicaré cuáles 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 - (CLng(Timer * 1000) Mod 1000)
      If msRestantes = 1000 Then msRestantes = 0
      

      Esto permite:

      • Primer tick comienza exactamente en 0 ms, no en un punto arbitrario
      • Ticks posteriores cada 1000 ms exactos
      • Evitar desvíos acumulados

      🔄 4. Crea el temporizador API

      RelojTimerID = SetTimer(0, 0, msRestantes, AddressOf Tick)
      

      El primer tick ocurre justo al inicio del siguiente 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 IniciarDetenerReloj()
      

      que alterna entre:

      • IniciarReloj
      • DetenerReloj

      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.



      Explicación técnica del módulo ModTempo

      A continuación explico técnicamente el módulo ModTempo, desarrollado con la ayuda de la IA.

      La estructura sigue el flujo real del código y explica qué hace, por qué lo hace, y cómo interactúan entre sí las partes críticas: API Win32, temporizador, corrección de (drift correction), modo híbrido y escritura inteligente.


      Módulo Temporizador

      ModTempo implementa un reloj de alta precisión dentro de Excel usando:

      • Temporizador API de Windows (SetTimer)
      • Corrección de deriva (drift correction)
      • Modo híbrido:
        • Actualiza la celda solo si Excel está activo y visible
        • Ahorra CPU cuando Excel está en segundo plano
      • Milisegundos reales mediante Now()
      • Escritura inteligente: solo escribe si el valor cambia
      • Sin interferir con cálculos ni edición

      El resultado es un reloj estable, eficiente y preciso, superior a cualquier implementación basada en Application.OnTime.


      🧩 Declaraciones API

      El módulo declara cuatro funciones de la API de Windows:

      1) SetTimer

      Crea un temporizador que ejecuta un procedimiento (callback) cada X milisegundos.

      • hWnd = 0 → temporizador asociado al proceso, no a una ventana
      • nIDEvent = 0 → Windows asigna un ID automáticamente
      • uElapse → intervalo en milisegundos
      • lpTimerFunc → dirección del procedimiento Tick

      Devuelve un ID de temporizador, que se guarda en RelojTimerID.

      2) KillTimer

      Detiene el temporizador usando su ID.

      3) IsWindowVisible

      Comprueba si la ventana de Excel está visible (no minimizada).

      4) GetForegroundWindow

      Devuelve el handle de la ventana que tiene el foco.


      🧩 Variables locales

      Private RelojCorriendo As Boolean
      Private RelojTimerID As LongPtr
      Private TickUltimo As Double
      Private contadorTicks As Long
      Private contadorSaltos As Long
      
      • RelojCorriendo: estado ON/OFF del reloj.
      • RelojTimerID: ID del temporizador API (obligatorio LongPtr en 64 bits).
      • TickUltimo: marca de tiempo del último tick para medir drift.
      • contadorTicks: contador de ticks del reloj.
      • contadorSaltos: contador de saltos del microbenchmark.

      Son Private porque solo deben ser accesibles dentro del módulo.


      🧩 IniciarDetenerReloj

      Alterna el estado del reloj:

      • Si estaba apagado → lo inicia
      • Si estaba encendido → lo detiene

      Es un interruptor simple para el usuario.


      🧩 IniciarReloj

      Este procedimiento:

      1) Cambia el cursor a reloj de arena
      Application.Cursor = xlWait
      

      Indica visualmente que el reloj está en marcha.

      2) Marca el reloj como activo
      RelojCorriendo = True
      
      3) Guarda el tiempo actual
      TickUltimo = Timer
      
      4) Sincroniza el primer tick con el siguiente segundo exacto
      msRestantes = 1000 - (CLng(Timer * 1000) Mod 1000)
      If msRestantes = 1000 Then msRestantes = 0
      

      Esto garantiza que el reloj empiece exactamente en 0 milisegundos, no en un punto arbitrario.

      5) Crea el temporizador API
      RelojTimerID = SetTimer(0, 0, msRestantes, AddressOf Tick)
      

      El primer tick ocurre justo al inicio del siguiente segundo.


      🧩 DetenerReloj

      • Marca el reloj como detenido
      • RelojCorriendo = False
        
      • Mata el temporizador API
      • If RelojTimerID <> 0 Then KillTimer 0, RelojTimerID
            RelojTimerID = 0
        
      • Restaura el cursor
      • Application.Cursor = xlDefault
        

      Evita fugas de temporizadores y el cursor indica que el reloj se ha detenido.


      🧩 Tick — el corazón del reloj

      Este procedimiento se ejecuta cada segundo (o antes, si hay corrección de deriva - drift correction).

      0) Evita error 50290 cuando Excel está ocupado
      On Error GoTo SalirTick
      1) Protección contra cálculos
      If Application.CalculationState <> xlDone Then GoTo SalirTick
      

      Evita interferir con cálculos pesados.

      2) Determina si Excel está activo
      ExcelActivo = (GetForegroundWindow() = hWndExcel) _
                    And (IsWindowVisible(hWndExcel) <> 0)
      

      Esto implementa el modo híbrido:

      • Si Excel está activo → modo precisión
      • Si Excel está en segundo plano → modo ahorro
      3) Si Excel no está activo → no escribir
      If Not ExcelActivo Then GoTo SalirTick
      

      Evita repintados innecesarios.

      4) Si la hoja no está visible → no escribir
      If Not ActiveSheet.Visible Then GoTo SalirTick
      

      Evita trabajo inútil. Es el modo ahorro para no gastar la batería de los portátiles.

      5) Corrección de deriva (drift correction)
      tNow = Timer
      delta = tNow - TickUltimo
      If delta < 0 Then delta = delta + 86400#
      
      6) Si el temporizador se desvía más de ±50 ms, corregir
      If Abs(delta - 1#) > 0.05 Then
          KillTimer 0, RelojTimerID
          RelojTimerID = SetTimer(0, 0, 1000, AddressOf Tick)
      End If
      

      Esto reancla el temporizador al segundo real del sistema.

      7) Una sola lectura del reloj del sistema
      vHora = Now()
      

      Excel soporta milisegundos en formato personalizado.

      8) Escritura inteligente del cambio de hora
      If celda.Value2 <> vHora Then
      

      Solo escribe si el valor cambia → evita repintados.

      9) Si Excel no está listo se salta el tick
      If Not Application.Ready Then GoTo Registrar
      

      Y registra el resultado del microbenchmark.

      10) Medir bloque de escritura
      tBloque = Timer
      

      Mide el bloque de escritura de la hora para registrarlo en el microbenchmark.

      11) Escritura optimizada del día y la hora del sistema
      On Error Resume Next
      Application.EnableEvents = False
      Application.ScreenUpdating = False
      celda.Value2 = vHora
      escribeHora = True
      Application.ScreenUpdating = True
      Application.EnableEvents = True
      On Error GoTo 0
      tBloque = Timer - tBloque
      

      Evita parpadeos y eventos innecesarios.


      🧩 Comportamiento final del módulo

      1. Se sincroniza con el siguiente segundo exacto.
      2. Cada tick:
        • Evita error 50290 cuando Excel está ocupado
        • Comprueba si Excel está calculando
        • Comprueba si Excel está activo
        • Comprueba si la hoja está visible
        • Mide la deriva (drift calculation) y corrige si es necesario
        • Lee la hora en milisegundos
        • Escribe solo si cambia el valor
        • Con microbenchmark que registra saltos de segundos

      El módulo ModTempo consigue:

      • Sincronización exacta con el segundo real
      • Milisegundos reales en cada actualización
      • Corrección automática de deriva (drift correction)
      • Ahorro de energía cuando Excel está en segundo plano
      • Cero parpadeos
      • Cero interferencias con cálculos
      • Cero repintados innecesarios
      • Compatibilidad total con 32 y 64 bits

      Es un reloj de precisión profesional dentro de Excel:

      • Preciso
      • Eficiente
      • Estable
      • Sin jitter
      • Sin parpadeos
      • Sin interferir con Excel



      🧩DIAGRAMA DE FLUJO—ModTempo

      
                                 ┌──────────────────────────┐
                                 │ IniciarDetenerReloj()    │
                                 └──────────────┬───────────┘
                                                │
                   ¿RelojCorriendo = False? ────┤
                                                │Sí
                                                ▼
                                     ┌────────────────────┐
                                     │ IniciarReloj()     │
                                     └───────┬────────────┘
                                             │
                                             ▼
                               ┌──────────────────────────────┐
                               │ Cursor = xlWait              │
                               │ RelojCorriendo = True        │
                               │ TickUltimo = Timer           │
                               └───────────┬──────────────────┘
                                           │
                                           ▼
                           ┌────────────────────────────────────────┐
                           │ Calcular msRestantes hasta el próximo  │
                           │ segundo exacto                         │
                           └───────────────┬────────────────────────┘
                                           │
                                           ▼
                           ┌────────────────────────────────────────┐
                           │ SetTimer( intervalo = msRestantes )    │
                           │ → llama a Tick()                       │
                           └────────────────────────────────────────┘
      
      
      ──────────────────────────────────────────────────────────────────────────────
                                 TICK() — Cada disparo del temporizador
      ──────────────────────────────────────────────────────────────────────────────
      
                           ┌────────────────────────────────────────┐
                           │ Tick()                                 │
                           └───────────┬────────────────────────────┘
                                       │
         ¿Error si Excel ocupado? ─────┤
                                       │No
                                       ▼
                           ┌────────────────────────────────────────┐
                           │ Continua si Excel no está calculando,  │
                           │ si está activo y si la hoja es visible │
                           └───────────┬────────────────────────────┘
                                       │Sí
                                       ▼
                           ┌────────────────────────────────────────┐
                           │ Mide la deriva del temporizador        │
                           │ KillTimer (primer timer)               │
                           │ SetTimer( intervalo = 1000 ms )        │
                           │ (sincronizado al segundo exacto)       │
                           └───────────┬────────────────────────────┘
                                       │
                                       ▼
                           ┌────────────────────────────────────────┐
                           │ Lee día y hora: vHora = Now()          │
                           └───────────┬────────────────────────────┘
                                       │
                 ¿Cambió la hora? ─────┤
                                       │Sí
                                       ▼
                           ┌────────────────────────────────────────┐
                           │ ¿Excel está listo?                     │
                           └───────────┬────────────────────────────┘
                                       │Sí
                                       ▼
                           ┌────────────────────────────────────────┐
                           │ Deshabilita eventos y refresco pantalla│
                           │ Range("miHora") = vHora                │
                           │ Habilita eventos y refresco pantalla   │
                           └────────────────────────────────────────┘
                                       │
                                       ▼
                           ┌────────────────────────────────────────┐
                           │ Fin Tick()                             │
                           └────────────────────────────────────────┘
      
      
      ──────────────────────────────────────────────────────────────────────────────
                                 STOP — Detener temporizador
      ──────────────────────────────────────────────────────────────────────────────
      
                                 ┌──────────────────────────┐
                                 │ DetenerReloj()           │
                                 └──────────────┬───────────┘
                                                │
                                                ▼
                                 ┌──────────────────────────┐
                                 │ RelojCorriendo = False   │
                                 │ KillTimer TimerID        │
                                 │ Cursor = xlDefault       │
                                 └──────────────────────────┘
      

      🎯 Qué representa este diagrama

      • El flujo desde que el usuario inicia el temporizador hasta que lo detiene.
      • 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.


      Explicación técnica de los eventos del reloj

      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()
          IniciarReloj
      End Sub
      

      Cuando el archivo se abre:

      • Se ejecuta IniciarReloj
      • 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)
          DetenerReloj
      End Sub
      

      Cuando el usuario pulsa:

      • La X
      • Alt+F4
      • Ctrl+W
      • O cierra desde menú

      Excel ejecuta Workbook_BeforeClose, que:

      • Llama a DetenerReloj
      • 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.


      🎯 Resumen de los eventos del reloj

      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 reloj

      
                         ┌────────────────────────────┐
                         │   El usuario abre el libro │
                         └───────────────┬────────────┘
                                         │
                                         ▼
                           ┌──────────────────────────┐
                           │ Workbook_Open()          │
                           └─────────────┬────────────┘
                                         │
                                         ▼
                           ┌──────────────────────────┐
                           │ IniciarReloj             │
                           │ • 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()   │
                           └─────────────┬────────────┘
                                         │
                                         ▼
                           ┌──────────────────────────┐
                           │ DetenerReloj             │
                           │ • 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.


      Administrador de nombres

      Estos son los nombres definidos en el Administrador de nombres, necesarios para diseñar el Reloj analógico en tiempo real.


      Reloj analógico traducido a 6 idiomas

      Selecciona tu idioma para disfrutar de una Excel-ente experiencia.

      En la siguiente imagen animada se ve un reloj analógico del tipo AM/PM, con el formato regional en inglés, y otro del tipo 24 horas en español.


      Videotutorial explicando las macros del reloj analógico

      En este vídeo he intentado explicar los intríngulis del reloj analógico.

      En el vídeo no he mencionado la colaboración con la IA de Microsoft Copilot, sin la cual no habría podido afinar tanto el código para lograr este resultado, aunque en los siguientes enlaces no he incluido el diálogo que mantuve con la IA durante muchas iteraciones, sino solo el resultado final:

      Descarga el Reloj analógico en tiempo real, pruébalo y te agradeceré cualquier sugerencia que me hagas tendente a mejorarlo.

      Mi lista de blogs