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

VBA Workbook_BeforeClose en Excel — cancela el cierre, pide guardar y dónde debe vivir el código

|

VBA Workbook_BeforeClose en Excel — cancela el cierre, pide guardar y dónde debe vivir el código

TL;DRWorkbook_BeforeClose es un evento que Excel dispara en el instante en que alguien intenta cerrar el libro — antes de que se desmonte ninguna ventana. Te entrega un único argumento, Cancel, y ese argumento lo es todo: pon Cancel = True y el cierre se aborta, el archivo sigue abierto. Así que esto no es una nota de despedida que ejecutas al salir — es un puesto de control que puede dar media vuelta al usuario en la puerta. El código debe vivir en ThisWorkbook, y si quieres ejecutar tu propio aviso de guardado sin que Excel también pregunte, pon ThisWorkbook.Saved = True para silenciar su cuadro de diálogo incorporado.

' Vive en ThisWorkbook, NO en un Module.
Private Sub Workbook_BeforeClose(Cancel As Boolean)
    If ThisWorkbook.Sheets("Form").Range("Approved").Value <> "Yes" Then
        MsgBox "Set Approved = Yes before closing this file.", vbExclamation
        Cancel = True          ' <-- aborta el cierre; el libro sigue abierto
    End If
End Sub

La mayoría de las macros se ejecutan cuando el usuario lo pide — un botón, un atajo. Workbook_BeforeClose se ejecuta cuando el usuario intenta marcharse, y ese momento es lo que la hace útil y peligrosa a partes iguales. Es el evento detrás de «tienes cambios sin guardar», los cierres de sesión obligatorios, la limpieza al salir y «registra quién cerró el archivo». Es también el evento que la gente conecta mal más a menudo — porque lo tratan como una notificación cuando en realidad Excel les ofrece un veto.

Lo que aprenderás

  • El modelo mental — un evento portero que te entrega un veto con Cancel, no solo un aviso
  • Cómo detener de verdad un cierre (y por qué un aviso con vbYesNo por sí solo no lo hace)
  • La trampa del doble aviso — y la palanca ThisWorkbook.Saved = True que la soluciona
  • Por qué BeforeClose nunca debe ser tu red de seguridad para la integridad de los datos (los fallos se lo saltan)
  • Cerrar un libro frente a salir de Excel — y dónde tiene que vivir el código

El modelo mental: un portero, no una nota de despedida

Workbook_BeforeClose se dispara en el momento en que se solicita un cierre — la X de la ventana, Archivo ▸ Cerrar, Application.Quit, u otra macro que llame a .Close — y se dispara antes de que Excel haga nada irreversible. Y algo crucial: pasa un único Boolean por referencia llamado Cancel. Tú nunca llamas a este Sub; Excel te llama a ti, espera a que termines y luego mira en qué está puesto Cancel.

Ese único argumento le da la vuelta a todo. Si dejas Cancel en paz, el cierre continúa con normalidad. Si pones Cancel = True, Excel abandona el cierre y el libro sigue abierto exactamente como estaba. Así que el manejador es un portero: puede dejar pasar al usuario, o puede detenerlo y mandarlo de vuelta a arreglar algo. Léelo como «avísame antes de cerrar» y te perderás todo el poder del evento.

La firma es fija y la ubicación no se negocia: Private Sub Workbook_BeforeClose(Cancel As Boolean), en el módulo de código de ThisWorkbook — haz doble clic en ThisWorkbook bajo «Objetos de Microsoft Excel» en el Explorador de proyectos. Ponlo en un Module estándar y no se disparará nunca, que es la misma regla de «dónde vive el código» que Workbook_Open.

La regla que más importa: un aviso sin Cancel es puro teatro

Este es el error que casi todo el mundo comete primero. Quieres confirmar antes de cerrar, así que escribes:

Private Sub Workbook_BeforeClose(Cancel As Boolean)
    MsgBox "Are you sure you want to close?", vbYesNo   ' pregunta... e ignora la respuesta
End Sub

Aparece el cuadro de diálogo, el usuario hace clic en No — y el libro se cierra igualmente. Nada en ese código toca Cancel, así que Excel continúa. El aviso era puro teatro. La regla: una decisión que quieras imponer tiene que escribirse de vuelta en Cancel. Captura la respuesta y actúa en consecuencia:

Private Sub Workbook_BeforeClose(Cancel As Boolean)
    If MsgBox("Close without exporting the report?", vbYesNo + vbQuestion) = vbNo Then
        Cancel = True          ' el usuario dijo No -> aborta el cierre
    End If
End Sub

Ahora «No» de verdad mantiene el archivo abierto. Esta es la diferencia entre un evento que informa y un evento que protege: la protección solo es real cuando se puede llegar a Cancel = True.

La trampa que molesta a los usuarios: Excel pide guardar dos veces

El segundo bug clásico aparece en cuanto tu manejador guarda. Añades un paso de «guarda antes de irte», y ahora cerrar un libro modificado produce dos cuadros de diálogo: tu aviso y después el propio «¿Quieres guardar los cambios?» de Excel. El motivo es que tanto tú como Excel intentáis gestionar el mismo estado sin guardar.

La palanca es la propiedad Saved del libro. Saved es el indicador de Excel para «no hay cambios sin guardar». Cuando la pones en True, le estás diciendo a Excel que el archivo está limpio — así que se cierra sin mostrar su propio aviso de guardado, aunque de verdad haya ediciones. Encárgate tú del guardado y luego cambia Saved:

Private Sub Workbook_BeforeClose(Cancel As Boolean)
    Dim answer As VbMsgBoxResult
    answer = MsgBox("Save changes before closing?", vbYesNoCancel + vbQuestion)

    If answer = vbCancel Then
        Cancel = True                 ' no cierres en absoluto
    ElseIf answer = vbYes Then
        ThisWorkbook.Save             ' guarda y luego deja que el cierre continúe
    Else ' vbNo
        ThisWorkbook.Saved = True     ' descarta: dile a Excel que está limpio para que no vuelva a preguntar
    End If
End Sub

Poner Saved = True no guarda nada — suprime el aviso afirmando que el libro ya está guardado. Úsalo a propósito: es el interruptor que hace que tu propia lógica de guardado sea la única que ve el usuario.

La regla que mantiene tus datos a salvo: BeforeClose no es una red de seguridad

Workbook_BeforeClose se dispara en cada cierre ordenado — la X, Archivo ▸ Cerrar, .Close, Application.Quit. No se dispara cuando Excel se cuelga, cuando se mata el proceso o ante un corte de luz. Eso vuelve peligrosa una tentación: nunca hagas que BeforeClose sea lo único que guarda tus datos. Si la lógica de «guardar la única copia» vive aquí y Excel muere, la copia se pierde. Trata BeforeClose como una cortesía (avisar, ordenar, registrar), y mantén la persistencia de verdad en un guardado explícito o un autoguardado programado, no en la ruta de salida.

Un caso límite más que conviene conocer: cuando el usuario está saliendo del propio Excel con varios libros abiertos, cada libro recibe su propio BeforeClose. Poner Cancel = True en uno de ellos impide que ese libro se cierre, pero los libros hermanos que ya ejecutaron su manejador pueden quedar en un estado a medio cerrar. Si necesitas «todo o nada» al salir, coordina desde Workbook_BeforeClose con moderación y prueba el caso de varios archivos.

La distinción que hace tropezar a la gente: BeforeClose frente a BeforeSave

BeforeClose protege la salida; su hermano Workbook_BeforeSave protege el guardado y te entrega la misma clase de veto con Cancel (más un indicador SaveAsUI). Forman pareja de manera natural — validar al guardar, confirmar al cerrar — y ambos comparten la regla de oro de la familia de eventos: si un manejador escribe en celdas o guarda, envuelve esa acción en Application.EnableEvents = False … = True y restáurala en un manejador de errores, exactamente como hace Worksheet_Change, para que tu propia escritura no pueda volver a disparar la maquinaria.

Cómo ayuda ExcelMaster

Una protección de cierre son cuatro pequeñas decisiones fáciles de equivocar por poco: el código en ThisWorkbook (no en un Module), la escritura de Cancel que de verdad detiene el cierre, el cambio a Saved = True que evita el doble aviso, y el criterio sobre qué es lo que no debes confiar a la ruta de salida.

ExcelMaster te deja describir el comportamiento en su lugar. Di «antes de que este archivo se cierre, si la celda Approved no es Yes, detén el cierre y avisa al usuario», y escribe un Workbook_BeforeClose en ThisWorkbook que pone Cancel correctamente, gestiona el aviso de guardado sin duplicarlo y protege cualquier escritura. Te quedas con el libro y el código; te ahorras el ensayo y error de aprender qué palanca hace qué.

Preguntas frecuentes

¿Cómo impido que un libro se cierre en VBA?

Pon el argumento Cancel en True dentro de Workbook_BeforeClose: Private Sub Workbook_BeforeClose(Cancel As Boolean)Cancel = True. Excel pasa Cancel por referencia y lo comprueba después de que se ejecute tu manejador; True aborta el cierre y el archivo sigue abierto. Un MsgBox por sí solo no hace nada — tienes que escribir la decisión de vuelta en Cancel.

¿Por qué Excel me pide guardar dos veces al cerrar?

Porque tu manejador de BeforeClose avisa para guardar y Excel sigue creyendo que hay cambios sin guardar, así que muestra también su propio cuadro de diálogo. Encárgate tú del guardado y luego pon ThisWorkbook.Saved = True para decirle a Excel que el libro está limpio — eso suprime su aviso incorporado de «¿Quieres guardar?».

¿Dónde va el código de Workbook_BeforeClose?

En el módulo de código de ThisWorkbook — haz doble clic en ThisWorkbook bajo «Objetos de Microsoft Excel» en el Explorador de proyectos y pega ahí Private Sub Workbook_BeforeClose(Cancel As Boolean). No se dispara desde un Module estándar, y las macros deben estar habilitadas.

¿Se ejecuta Workbook_BeforeClose si Excel se cuelga?

No. Solo se dispara en un cierre ordenado — la X de la ventana, Archivo ▸ Cerrar, .Close o Application.Quit. Un cuelgue, un proceso terminado a la fuerza o un corte de luz se lo saltan por completo. Nunca confíes en BeforeClose como lo único que guarda tus datos.

¿En qué se diferencia BeforeClose de Workbook_BeforeSave?

BeforeClose se dispara cuando el archivo se está cerrando y te deja cancelar el cierre; Workbook_BeforeSave se dispara cuando el archivo se está guardando y te deja cancelar el guardado. Cerrar un archivo modificado normalmente provoca un aviso de guardado, así que ambos suelen aparecer juntos, pero son eventos distintos con indicadores Cancel distintos.

Probado en

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

Guías relacionadas: VBA Workbook_BeforeSave · VBA Worksheet_Activate y Deactivate · VBA Workbook_Open · VBA Worksheet_Change · VBA On Error