Probado en: Excel 365 v2509 · Excel 2021 · Excel 2019 · última verificación el 08/06/2026
En resumen — Cuando ocurre un error en tiempo de ejecución, VBA llena un único objeto global —Err— con todo lo que sabe del fallo. Lo lees dentro de un controlador para decidir qué hacer; también puedes escribir en él con Err.Raise para lanzar tu propio error:
Sub LeerPrecio()
On Error Resume Next
Dim precio As Double
precio = CDbl(Range("A1").Value) ' falla si A1 no es numérico
If Err.Number <> 0 Then
MsgBox "Error " & Err.Number & ": " & Err.Description
Err.Clear ' reinicia para que la próxima comprobación sea limpia
End If
On Error GoTo 0
End Sub
El objeto entero en un solo sitio:
Err.Number ' el código de error — 0 significa "sin error"
Err.Description ' el mensaje legible por humanos
Err.Source ' quién lo lanzó (nombre del proyecto / objeto)
Err.Raise 513 ' LANZA un error tú mismo
Err.Clear ' deja Err en estado limpio de nuevo
El modelo mental: Err es la caja negra del último choque
Err es un objeto único, global y siempre presente. Piénsalo como la caja negra de vuelo de tu macro: en cuanto ocurre un error en tiempo de ejecución, VBA escribe tres datos en él antes de que el control salte a tu controlador —
Err.Number— el código numérico (1004,13,9…).0significa «nada ha salido mal».Err.Description— el mismo texto que verías en el cuadro rojo («Tipos no coinciden», «Subíndice fuera del intervalo»).Err.Source— qué proyecto u objeto lo lanzó.
Solo hay un objeto Err para toda la sesión, y guarda el error más reciente. Por eso el cuándo lo lees importa tanto como qué lees — y por eso se borra automáticamente (más sobre esto abajo).
La única regla: Err.Number es el único «¿de verdad falló?» fiable
Tras On Error Resume Next, tu código sigue corriendo funcionara o no la línea. La única forma de saber qué pasó es leer Err.Number:
On Error Resume Next
Set libro = Workbooks("Presupuesto.xlsx") ' ¿ya está abierto este libro?
If Err.Number = 0 Then
MsgBox "Ya estaba abierto."
Else
Err.Clear
Set libro = Workbooks.Open("C:\Datos\Presupuesto.xlsx")
End If
On Error GoTo 0
Resume Next sin una comprobación de Err.Number es tiempo perdido: le has dicho a VBA que ignore los fallos, pero nunca te enteras de que ocurrió uno. La comprobación es el manejo. Esta es la regla compañera de On Error Resume Next — las dos solo funcionan en pareja.
También puedes ramificar según el código específico, porque cada número significa un problema distinto:
Select Case Err.Number
Case 0: ' sin error
Case 9: MsgBox "Esa hoja o índice no existe." ' Subíndice fuera del intervalo
Case 13: MsgBox "Ese valor no es del tipo correcto." ' Tipos no coinciden
Case 1004: MsgBox "Excel rechazó esa operación." ' error genérico de automatización
Case Else: MsgBox "Error inesperado " & Err.Number & ": " & Err.Description
End Select
La trampa: Err se borra solo cuando menos lo esperas
Err no permanece relleno hasta que termines con él. VBA lo reinicia a Number = 0 automáticamente ante cualquiera de estos:
- una instrucción
On Errorde cualquier tipo (incluidoOn Error GoTo 0) - un
ResumeoResume Next Exit Sub/Exit Function- el siguiente error en tiempo de ejecución (se sobrescribe, no se añade)
Así que si necesitas el número o la descripción después de cualquiera de esos —para registrarlo, mostrarlo más tarde o pasarlo hacia arriba— captúralo en tus propias variables en el instante en que arranca tu controlador:
ControlErrores:
Dim numError As Long, mensajeError As String
numError = Err.Number ' agárralo YA
mensajeError = Err.Description
On Error Resume Next ' ← esta línea borraría Err...
Application.ScreenUpdating = True ' ...así que la limpieza ya no puede leer Err
RegistrarEnHoja numError, mensajeError ' usa las copias guardadas, no Err.*
Este único detalle está detrás de la mayoría de los reportes de «mi registro de errores muestra error 0».
Lanzar tus propios errores con Err.Raise
Leer Err es la mitad del objeto. La otra mitad es escribir en él — lanzar un error a propósito cuando se violan tus reglas, no solo las de VBA:
Function PrecioNeto(bruto As Double, tasaImpuesto As Double) As Double
If tasaImpuesto < 0 Or tasaImpuesto > 1 Then
Err.Raise vbObjectError + 513, "PrecioNeto", _
"tasaImpuesto debe estar entre 0 y 1, llegó " & tasaImpuesto
End If
PrecioNeto = bruto / (1 + tasaImpuesto)
End Function
Err.Raise Number, Source, Description genera un error en tiempo de ejecución de verdad — el controlador On Error de quien llama lo atrapa igual que uno integrado. Usa vbObjectError + n (con n de 513 a 65535) para errores personalizados; esa constante te desplaza fuera del rango 0–512 que VBA reserva para los códigos del sistema, así nunca colisionas con uno real.
La opinión: devolver un código de error es esperanza; lanzarlo es exigencia
Mucho VBA «valida» devolviendo un centinela —-1, False, una cadena vacía— y confiando en que cada quien que llama se acuerde de comprobarlo. No lo harán. Seis meses después alguien llama a tu función, ignora el -1 y divide entre él.
Err.Raise elimina la elección. Un error lanzado no puede ignorarse en silencio — o topa con un controlador, o detiene la macro. De eso se trata. Leer Err.Number te hace competente manejando errores; lanzar los tuyos propios ante entradas y reglas de negocio incorrectas es lo que hace tu código defensivo en vez de meramente cortés. Si un valor corrompería el resultado más adelante, no devuelvas un indicador y reces — lánzalo.
Errores frecuentes con Err (y la solución)
| Síntoma | Causa | Solución |
|---|---|---|
| El registro siempre muestra «error 0» | Leíste Err después de que Resume/On Error/la limpieza lo borraran |
Guarda Err.Number/Err.Description en variables primero |
Resume Next «no atrapa» nada |
Nunca comprobaste Err.Number tras la línea de riesgo |
Añade If Err.Number <> 0 Then … |
| El error personalizado colisiona con uno del sistema | Usaste un número pequeño y pelado como Err.Raise 5 |
Usa Err.Raise vbObjectError + 513 en adelante |
| La segunda comprobación salta por un error rancio | Olvidaste Err.Clear tras manejar el primero |
Llama a Err.Clear una vez resuelto |
Err.Description sale en blanco |
Lo leíste tras Err.Clear o un reinicio |
Lee la descripción antes de borrar |
Deja de tejer fontanería de errores a mano — describe la regla y ya
La mitad del VBA robusto es esto: lee Err.Number, guarda la descripción, lanza tus propios errores ante datos malos, borra, repite. Es necesario y es tedioso. ExcelMaster Agent te deja decir «valida que la tasa de impuesto esté entre 0 y 1 y detente con un mensaje claro si no» en español sencillo — y el Python generado lanza y reporta el error por ti, con el archivo respaldado primero. Prueba gratis →
Guías relacionadas
- VBA On Error — Resume Next vs GoTo y por qué las macros esconden errores
- Manejo de errores en VBA — El único patrón que usa toda macro fiable
- VBA Function en Excel — Valores de retorno y funciones personalizadas
- VBA Bucle For en Excel — 8 ejemplos reales
Preguntas frecuentes
¿Qué es el objeto Err en VBA?
Err es un objeto global que guarda información sobre el error en tiempo de ejecución más reciente. Sus miembros principales son Err.Number (el código de error, 0 = sin error), Err.Description (el mensaje) y Err.Source (qué lo lanzó). Lo lees dentro de un controlador de errores para decidir qué hacer.
¿Cómo compruebo el número de error en VBA?
Lee Err.Number. Tras On Error Resume Next, comprueba If Err.Number <> 0 Then para ver si la línea anterior falló. Un valor de 0 significa que no ocurrió ningún error. Puedes usar Select Case Err.Number para reaccionar distinto ante códigos concretos como 9 (subíndice fuera del intervalo) o 13 (tipos no coinciden).
¿Cuándo se reinicia el objeto Err?
Automáticamente ante cualquier instrucción On Error, ante Resume/Resume Next, ante Exit Sub/Exit Function y cuando el siguiente error lo sobrescribe. Si necesitas los valores después, copia Err.Number y Err.Description en tus propias variables de inmediato. También puedes reiniciarlo a mano con Err.Clear.
¿Cómo lanzo un error personalizado en VBA?
Usa Err.Raise Number, Source, Description. Para errores personalizados, usa vbObjectError + n donde n está entre 513 y 65535, p. ej. Err.Raise vbObjectError + 513, "MiFuncion", "Entrada no válida". Esto evita el rango 0–512 reservado para errores del sistema y deja que el controlador de quien llama lo atrape como cualquier error integrado.
¿Cuál es la diferencia entre Err.Clear y On Error GoTo 0?
Err.Clear reinicia las propiedades del objeto Err a un estado limpio pero deja sin cambios tu modo de atrape de errores. On Error GoTo 0 reinicia el modo de atrape al valor por defecto (detenerse ante el error) — y, como efecto colateral, también borra Err. Usa Err.Clear para reutilizar Err dentro del mismo controlador; usa On Error GoTo 0 para dejar de ignorar errores.
