El On Error Resume Next que ocultó tres archivos perdidos
Un procedimiento nocturno llamado ImportarPartes recorre con Dir los 30 archivos .csv de C:\Partes\Entrada, abre cada uno, vuelca sus filas en el libro de consolidación y lo cierra. En la tercera línea hay un On Error Resume Next que cubre todo el cuerpo y, al final, un MsgBox «Proceso completado». La semana pasada uno de los archivos estaba bloqueado por otro usuario: la ejecución continuó, el consolidado salió con 27 de las 30 líneas esperadas y nadie lo detectó hasta el cierre mensual. Además, dentro del bucle el programador añadió un manejador con la etiqueta ErrorAlAbrir que termina en Resume en lugar de Resume Next; con el archivo bloqueado, el procedimiento reintenta la misma instrucción indefinidamente y Excel deja de responder hasta que se fuerza el cierre.
1. ¿Por qué la ejecución siguió sin avisar y por qué `Resume` dentro del manejador deja Excel sin responder? Rediseña el manejo de errores para que un archivo fallido no detenga los demás pero quede registrado.
Read the worked answer
On Error Resume Next en la cabecera es un interruptor de ámbito de procedimiento. No se desactiva solo: sigue vigente en todas las líneas posteriores. Cualquier error -archivo bloqueado, ruta inexistente, formato inesperado- se ignora y la ejecución continúa en la línea siguiente. El resultado es que el archivo se salta sin dejar rastro y el MsgBox final afirma que todo fue bien. Un mensaje de éxito que no comprueba nada es peor que no tener mensaje.
Por qué Resume cuelga. Resume vuelve a ejecutar la instrucción que provocó el error. Si el archivo sigue bloqueado, el error se reproduce, se vuelve al manejador y otra vez a la misma línea: bucle infinito. Resume Next continúa en la línea posterior a la que falló, que es lo que se busca aquí.
Diseño correcto, por archivo:
- Activar el manejador justo antes de la operación crítica:
On Error GoTo ErrAbrir. - En el manejador, registrar
Err.NumberyErr.Descriptionjunto al nombre del archivo, incrementar un contador de fallos, hacerResume Nextpara pasar al siguiente fichero yErr.Clear. - Colocar un
Exit Sub(oExit For) antes de la etiqueta del manejador para que la ejecución normal no caiga dentro de él. - Al terminar, mostrar o escribir un resumen real: procesados, omitidos y motivo, en lugar de un mensaje fijo.
2. ¿Cómo dejarías constancia de los archivos fallidos en un proceso desatendido y por qué no sirve el MsgBox final?
Read the worked answer
Por qué no sirve el MsgBox. El proceso se lanza de noche, probablemente desde el Programador de tareas o un script. Un MsgBox en ese contexto bloquea la ejecución hasta que alguien pulse Aceptar: la tarea queda colgada y el resumen no llega a nadie. Además, el mensaje desaparece al cerrarse; no hay evidencia consultable al día siguiente.
Qué registrar. Por cada fallo: marca de tiempo, nombre completo del archivo, Err.Number, Err.Description y la acción tomada (omitido / reintentado). Eso permite distinguir un archivo bloqueado de uno corrupto sin volver a reproducir el problema.
Dónde registrarlo.
- En una hoja «Log» del propio libro de consolidación, añadiendo una fila por evento; es lo más cómodo si el libro se abre para revisarlo.
- En un archivo de texto con
Open ... For Appendcuando el libro pueda estar protegido o el fallo afecte al propio libro. - En ambos: hoja para el usuario y texto para el soporte técnico.
Qué devolver al proceso. Convertir el procedimiento en una función que devuelva el número de archivos omitidos, o un Boolean de éxito global. El lanzador puede entonces decidir si avisa por correo o relanza la tarea. Además, el resumen final debería escribirse siempre, incluso cuando no haya fallos, para demostrar que el proceso se ejecutó.
Detalle práctico: escribir en el log también puede fallar (libro de solo lectura, disco lleno). Ese punto necesita su propio On Error Resume Next muy acotado, no uno que cubra todo el procedimiento.
3. El programador defiende el `On Error Resume Next` diciendo que así puede depurar. ¿Qué ajustes y técnicas de depuración usarías en su lugar?
Read the worked answer
El argumento es una trampa. Resume Next oculta precisamente la información que se necesita para depurar: la línea, el número y la descripción del error. Depurar a ciegas con la esperanza de que el código siga adelante alarga el problema en lugar de resolverlo.
Ajustes de entorno. En Herramientas > Opciones > General, la opción «Interrumpir al producirse errores» permite elegir entre interrumpir solo en errores no controlados (lo habitual) e «Interrumpir en todos los errores», que rompe también cuando existe un manejador. Al depurar un procedimiento con On Error, esta segunda opción es la que revela el fallo real.
Técnicas concretas.
- Puntos de interrupción (F9) en la línea sospechosa y ejecución paso a paso con F8.
Debug.Print nombreArchivo & " | " & Err.Number & " | " & Err.Descriptionantes delResume Next, revisando la ventana Inmediato.- En la ventana Inmediato,
?Err.Number, Err.Descriptionpara inspeccionar el error sin detener la ejecución. - Expresiones de Inspección con condición, por ejemplo detenerse cuando
nombreArchivo = "parte_017.csv". Debug.Assertpara detener la ejecución cuando una condición que debería ser cierta no lo es, yStopcomo punto de ruptura temporal (eliminándolo antes de entregar).
Conclusión: el manejo de errores debe capturar lo previsto y registrar lo imprevisto, no silenciar todo. Para la fase de desarrollo, dejar el manejador fuera o comentado y añadirlo cuando el flujo base ya funciona.