vba - comando - ¿Necesitamos crear un controlador de errores para cada subrutina?
on error goto vba excel (2)
Exit Sub saldrá de la subrutina inmediatamente como return en Java
End Sub es solo el marcador para el final del bloque de sub rutina como} en Java
Una etiqueta es simplemente una marca en el código que se usa para definir un destino de salto. En caso de que no hayas saltado a la etiqueta pero haya llegado "regularmente", la etiqueta se ignorará, pero el código después de la etiqueta se ejecutará como si no hubiera una etiqueta, el código de tu ejemplo se ejecutará hasta el final. Salga de la instrucción Sub siempre que no se produzca ningún error. Si uno ocupa, saltará a ProcError
En este caso, Resume ejecutará ProcExit. Vea más aquí.
Copio un fragmento de código de SO como ejemplo. La subrutina contiene un controlador de errores. ¿Debería uno hacer un controlador de errores para todos los Subs?
Public Sub SubA()
On Error Goto ProcError
Connection.Open
Open File for Writing
SomePreciousResource.GrabIt
ProcExit:
Connection.Close
Connection = Nothing
Close File
SomePreciousResource.Release
Exit Sub
ProcError:
MsgBox Err.Description
Resume ProcExit
End Sub
Y, por cierto, ¿cómo funciona el flujo del control dentro de una subrutina cuando el ejecutor del código encuentra una Exit Sub
, End Sub
y Resume
? Y cuando encuentra una etiqueta como ProcError:
durante la ejecución, ¿la ejecuta o se salta?
La respuesta breve es: No, no solo no necesita tener un controlador de errores en cada procedimiento, sino que, de hecho, normalmente no querrá un manejador de errores en cada procedimiento.
Querrá hacer el manejo de errores donde tenga más sentido hacerlo. A menudo, solo querría un controlador de errores en el procedimiento de más alto nivel, es decir, el que llama a todos los demás; los procedimientos de nivel inferior deberían poner el problema en el piso de arriba y dejar que los errores "burbujeen" hasta el procedimiento de nivel superior. Algunas veces querrá algún tipo de manejo de errores en procedimientos de bajo nivel.
Para obtener más información, te remito a estas dos excelentes respuestas de @jtolle:
Además, una búsqueda en Internet revelará que hay toda una literatura en la web sobre el manejo de errores. ¡Algo de eso está bastante mal, en mi opinión! Pero si se apega a lo que escribí en los primeros dos párrafos, vale la pena considerarlo.
Exit Sub
y End Sub
son bastante intuitivos: el primero detiene la ejecución del Sub actual y devuelve el control al procedimiento que lo llamó (o detiene la ejecución por completo si el procedimiento no fue llamado por otro procedimiento). Este último es solo una indicación para el compilador de que aquí el código para este Sub particular termina - y si se ejecuta, End Sub
comporta como Exit Sub
.
Resume
especifica qué debe suceder a continuación, después de que finaliza una rutina de manejo de errores. Plain Resume
regresa a la misma declaración que causó el error e intenta ejecutarlo de nuevo. Resume Next
omite la afirmación que causó el error y, en su lugar, va a la declaración que lo sigue inmediatamente. Resume mylabel
va a etiquetar mylabel:
Si una etiqueta como su ProcError:
se encuentra en el curso de la ejecución, entonces no sucede nada especial, y la ejecución pasa a la siguiente instrucción después de la etiqueta. Por supuesto, en su ejemplo, ProcError:
nunca se ejecutará directamente (es decir, no, a menos que se ProcError:
un error) porque hay un Exit Sub
justo antes.
Por cierto, el bloque ProcExit:
probablemente debería comenzar con On Error Resume Next
(es decir, seguir cerrando todo y salir independientemente de cualquier error) o, alternativamente, como señala @Phydaux, un On Error Goto 0
(en caso de error, detener ejecución), de lo contrario, si algo allí desencadena un error, puede entrar en un ciclo infinito de ping-pong entre el manejador de errores y el código ProcExit:
.
ProcExit:
On Error Resume Next '' or, alternatively, On Error Goto 0
Connection.Close
Connection = Nothing
Close File
SomePreciousResource.Release
Exit Sub