TL;DR —
Workbook_BeforeSavees un evento que Excel dispara en el momento en que se solicita un guardado — Ctrl+S, el botón Guardar o el.Savede una macro — antes de escribir en disco. Te entrega dos argumentos:SaveAsUI(¿está a punto de aparecer el cuadro Guardar como?) yCancel(ponlo enTruepara bloquear el guardado). Así que es un control de calidad sobre la acción de guardar: inspecciona el libro y, o bien dejas pasar la escritura, o bien la rechazas. Lo único que muerde a todo el mundo — si tu manejador llama aThisWorkbook.Save, ese guardado disparaBeforeSaveotra vez y entra en bucle infinito a menos que lo controles conApplication.EnableEvents.
' Vive en ThisWorkbook, NO en un Module.
Private Sub Workbook_BeforeSave(ByVal SaveAsUI As Boolean, Cancel As Boolean)
If ThisWorkbook.Sheets("Invoice").Range("Total").Value = "" Then
MsgBox "Enter a Total before saving.", vbExclamation
Cancel = True ' <-- bloquea el guardado; no se escribe nada
Exit Sub
End If
ThisWorkbook.Sheets("Invoice").Range("LastSaved").Value = Now ' sella la hora — sin llamada a .Save aquí
End Sub
Guardar parece lo más seguro que puede hacer un usuario, y justo por eso es el lugar
idóneo para imponer reglas. Workbook_BeforeSave es el evento detrás de «no puedes
guardar con un campo obligatorio en blanco», las celdas de «última modificación» selladas
automáticamente, los nombres de archivo obligatorios y los registros de auditoría en el
momento de guardar. Es también donde viven dos trampas sutiles: un guardado que en
silencio no hace nada, y un manejador que se guarda a sí mismo hasta caer en un bucle
infinito.
Lo que aprenderás
- El modelo mental — una compuerta sobre el guardado, con un veto
Cancely una señalSaveAsUI - Qué significa de verdad
SaveAsUI, y cómo usarlo para forzar un nombre de archivo o una carpeta - El patrón de sellado automático — escribe «quién y cuándo» dentro del archivo que se guarda
- La trampa de la recursión — por qué
.Savedentro deBeforeSaveentra en bucle, y el arreglo conEnableEvents - Por qué un
Cancel = Truesilencioso es un bug, no una función
El modelo mental: una compuerta sobre el guardado, no un recibo
Workbook_BeforeSave se dispara cuando se solicita un guardado y se ejecuta antes de
que Excel escriba el archivo. Tú no lo llamas — Excel te llama a ti, espera y luego decide
qué hacer según lo que hiciste. Pasa dos argumentos por referencia:
SaveAsUI As Boolean—Truecuando Excel está a punto de mostrar el cuadro Guardar como (el usuario eligió «Guardar como», o es un archivo nuevo sin guardar),Falsepara un guardado normal sobre el archivo existente. Es información: ¿qué tipo de guardado es este?Cancel As Boolean— tu veto. PonCancel = Truey Excel abandona el guardado; no se escribe nada.
Así que el manejador es una compuerta, no un recibo. Un recibo confirmaría que un
guardado ya ocurrió; este se ejecuta primero y tiene la última palabra para decir «no».
(Si quieres el recibo — saber que un guardado tuvo éxito — ese es el evento aparte
Workbook_AfterSave, que se dispara después con un indicador Success.)
La firma es fija y, como todo evento de libro, vive en ThisWorkbook:
Private Sub Workbook_BeforeSave(ByVal SaveAsUI As Boolean, Cancel As Boolean). En un
Module estándar no se dispara nunca.
La regla que lo hace útil: Cancel bloquea, SaveAsUI decide cómo
Los dos argumentos hacen dos trabajos distintos, y confundirlos es donde la gente se atasca.
Usa Cancel para imponer una condición previa — niégate a guardar hasta que los datos
sean válidos:
Private Sub Workbook_BeforeSave(ByVal SaveAsUI As Boolean, Cancel As Boolean)
If Sheets("Order").Range("CustomerID").Value = "" Then
MsgBox "Can't save: Customer ID is required.", vbExclamation
Cancel = True ' el guardado se detiene aquí
End If
End Sub
Usa SaveAsUI para controlar cómo se guarda el archivo — casi siempre para impedir
que los usuarios desperdiguen copias con nombres aleatorios, o para forzar una convención
de nombres:
Private Sub Workbook_BeforeSave(ByVal SaveAsUI As Boolean, Cancel As Boolean)
If SaveAsUI Then
MsgBox "Use File > Save only. This file must keep its name.", vbCritical
Cancel = True ' bloquea "Save As", permite "Save" normal
End If
End Sub
Ese manejador deja pasar un Ctrl+S normal pero rechaza «Guardar como» — una pequeña
política imposible sin saber qué guardado está en curso. La regla: SaveAsUI te dice la
intención, Cancel decide el resultado.
El patrón que vale la pena memorizar: sella el archivo antes de que se escriba
Lo más útil que hace BeforeSave es escribir metadatos dentro del archivo en el último
momento posible, para que la copia guardada los lleve consigo. Como tu código se ejecuta
antes de la escritura en disco, cualquier cosa que cambies queda capturada por el
guardado que está a punto de suceder:
Private Sub Workbook_BeforeSave(ByVal SaveAsUI As Boolean, Cancel As Boolean)
With Sheets("Log")
.Range("LastSavedBy").Value = Environ("Username")
.Range("LastSavedAt").Value = Now
End With
' Sin .Save aquí — el guardado que disparó este evento incluirá los sellos.
End Sub
Fíjate en lo que falta: no hay ninguna llamada a ThisWorkbook.Save. No necesitas una —
el guardado ya está ocurriendo; solo estás editando el libro un instante antes de que
aterrice en el disco. Añadir un .Save aquí no solo es redundante, sino que prepara el
terreno para la siguiente trampa.
La trampa que congela Excel: llamar a Save dentro de BeforeSave
Si tu manejador llama a ThisWorkbook.Save (un instinto natural — «séllalo y luego
guárdalo»), ese guardado dispara Workbook_BeforeSave otra vez, que guarda de nuevo,
que lo dispara de nuevo — la misma forma de bucle infinito que
Worksheet_Change escribiendo en una celda. El evento no
tiene ninguna protección incorporada contra reaccionar a su propia acción.
Cuando de verdad tengas que provocar un guardado desde dentro de un manejador de guardado — o desde cualquier evento que luego escriba — apaga los eventos a su alrededor y restáuralos siempre en un manejador de errores para que un fallo no pueda dejarlos atascados en apagado:
Private Sub Workbook_BeforeSave(ByVal SaveAsUI As Boolean, Cancel As Boolean)
On Error GoTo CleanExit
Application.EnableEvents = False ' nuestras propias acciones no volverán a disparar este evento
' ... trabajo que podría a su vez guardar o escribir ...
CleanExit:
Application.EnableEvents = True ' se ejecuta tanto si tuvimos éxito como si falló
End Sub
Application.EnableEvents es un único interruptor global de la aplicación que Excel
no restaura por ti. Si un manejador lo pone en False y falla antes de restaurarlo,
todos los eventos de Excel se quedan callados hasta que reinicies o ejecutes
Application.EnableEvents = True en la ventana Inmediato — el mismo modo de fallo descrito
en VBA On Error.
La regla que la gente olvida: no canceles en silencio
Un Cancel = True sin explicación es un bug de verdad. El usuario pulsa Ctrl+S, no ve
nada y se marcha creyendo que el archivo está guardado — pero BeforeSave lo bloqueó en
silencio y Workbook.Saved sigue siendo False. Horas de trabajo pueden evaporarse en el
siguiente cuelgue. Siempre que pongas Cancel = True, dile al usuario por qué con un
MsgBox, para que un guardado bloqueado sea una decisión visible, no una silenciosa. Una
compuerta que el usuario no puede ver es una trampa.
BeforeSave protege el guardado; su hermano Workbook_BeforeClose
protege el cierre con la misma clase de veto Cancel, y ambos pertenecen a la familia de
eventos de libro junto a Workbook_Open.
Cómo ayuda ExcelMaster
Una compuerta de guardado tiene un montón de pequeños detalles de correcto-o-roto: el
manejador en ThisWorkbook, Cancel usado para validar pero no en silencio, SaveAsUI
leído en el sentido correcto, el sello escrito sin una llamada a .Save, y una
protección con EnableEvents si algo llega a guardar.
ExcelMaster
te deja enunciar la regla en su lugar. Di «no dejes que este archivo se guarde si la celda
Total está vacía, y sella quién lo guardó y cuándo», y escribe un Workbook_BeforeSave que
bloquea el guardado con un mensaje claro, sella la hoja de registro antes de la escritura y
protege contra el bucle de autodisparo. Te quedas con el libro y el código; te ahorras el
congelón que provocarías, si no, enseñándote la regla a ti mismo.
Preguntas frecuentes
¿Cómo impido que un libro se guarde en VBA?
Pon el argumento Cancel en True dentro de Workbook_BeforeSave:
Private Sub Workbook_BeforeSave(ByVal SaveAsUI As Boolean, Cancel As Boolean) …
Cancel = True. Excel comprueba Cancel después de que se ejecute tu manejador; True
abandona el guardado y no escribe nada. Muestra siempre un mensaje que explique por qué,
para que el bloqueo no sea silencioso.
¿Qué significa el parámetro SaveAsUI?
SaveAsUI es True cuando Excel está a punto de mostrar el cuadro Guardar como —
porque el usuario eligió «Guardar como» o el archivo nunca se ha guardado — y False para
un guardado normal sobre el archivo existente. Léelo para tratar los dos casos de forma
distinta, por ejemplo para permitir Ctrl+S pero bloquear «Guardar como» de modo que el
archivo conserve su nombre.
¿Por qué mi macro BeforeSave provoca un bucle infinito?
Porque llama a ThisWorkbook.Save (u otro guardado), y ese guardado dispara
Workbook_BeforeSave de nuevo, sin fin. Normalmente no necesitas ningún .Save — las
ediciones que haces en el manejador quedan capturadas por el guardado que ya está en
curso. Si de verdad tienes que guardar, envuélvelo en
Application.EnableEvents = False … = True y restaura los eventos en un manejador de
errores.
¿Cómo añado una marca de tiempo de «última vez guardado» automáticamente?
En Workbook_BeforeSave, escribe el valor en una celda sin llamar a Save:
Sheets("Log").Range("LastSavedAt").Value = Now. Como el manejador se ejecuta antes de que
Excel escriba en disco, el guardado que disparó el evento incluye tu sello. Añade
Environ("Username") para saber quién lo guardó.
¿Dónde va el código de Workbook_BeforeSave?
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
Private Sub Workbook_BeforeSave(ByVal SaveAsUI As Boolean, Cancel As Boolean). No se
dispara desde un Module estándar, y las macros deben estar habilitadas.
Probado en
Probado en: Excel 365 (Windows 11), VBA 7.1 — última verificación el 05/08/2026.
Guías relacionadas: VBA Workbook_BeforeClose · VBA Worksheet_Activate y Deactivate · VBA Workbook_Open · VBA Worksheet_Change · VBA On Error
