|
Curso básico
de programación en Visual Basic
Lección
32.2
Cómo
detectar errores en Visual Basic
|
Realizamos
programas para la gestión de empresas. Empresas medianas y
pequeñas. Programas de contabilidad, cartera de pedidos
clientes proveedores, facturación control de albaranes,
tesorería cartera de cobros y pagos y estadísticas.
Nuestro
agradecimiento a todos los que por unas causas o por otras
visitan nuestra web. Gestión de empresas PYMES. Curso de
programación de Visual Basic.
|
Cuando quieras que el Visual Basic
"ignore" los errores que se produzcan en tu aplicación o
en parte de ella, usa:
On Error Resume Next
Esto hará que si se produce un
error, se continúe ejecutando el código como si nada hubiese
ocurrido.
Por supuesto que la recomendación es que compruebes si se ha
producido un error, ya que no es bueno dejar que los errores ocurran
sin más.
Para ello tendrás que chequear el valor de la propiedad Number
del objeto Err, (que al ser la propiedad por
defecto no es necesario especificarla), si ese valor es cero quiere
decir que no se ha producido un error; veamos un ejemplo:
On Error Resume Next
' Error 13 producirá un error de tipos (Type Mismatch)
Error 13
If Err.Number Then
MsgBox "Se ha producido el siguiente error:" & vbCrLf & _
Err.Number & ", " & Err.Description
End If
Pero si haces esto, procura hacer
un poco de limpieza... ya que, si desde este procedimiento llamas a
otros procedimientos que a su vez tienen la instrucción On
Error Resume Next y no has "limpiado" el valor
del número del error... cualquier comprobación que hagas de ese
valor dará como resultado que se muestre el mensaje.
Veamos un par de ejemplos:
Para crear el programa de pueba, crea un nuevo proyecto, añade
tresd botones (Command1, Command2 y Command3), y pega este código:
Private Sub Command1_Click()
' Ejemplo para detectar errores en Visual Basic
Dim i As Integer
On Error Resume Next
i = MsgBox("Pulsa SI para producir un error en este evento," & vbCrLf & _
"pulsa en NO para llamar al procedimiento _
Command2_Click" & vbCrLf & _
"pulsa en Cancelar para llamar al procedimiento Command3_Click", vbYesNoCancel)
If i = vbYes Then
' Error 13 producirá un error de tipos (Type Mismatch)
Error 13
ElseIf i = vbNo Then
' El error producido en el procedimiento Command2 está controlado,
' por tanto no se mostrará el mensaje del final
Command2_Click
Else
' Esto producirá un error en Command3, pero se detectará aquí
Command3_Click
End If
If Err Then
MsgBox "Se ha producido el siguiente error:" & vbCrLf & _
Err.Number & ", " & Err.Description, , "En Command1_Click"
End If
End Sub
Private Sub Command2_Click()
On Error Resume Next
' Error 76, (Path not found)
Error 76
If Err Then
' Este error está comprobado dentro de este procedimiento, por tanto no
' no mostrará nada
End If
' Limpiamos el valor del error
Err = 0
End Sub
Private Sub Command3_Click()
' Este procedimiento produce un error número 5
Error 5
' Este mensaje NUNCA se mostrará
MsgBox "El valor de Err.Number es: " & Err.Number & vbCrLf & _
"Aquí no se notará que se ha producido un error..." & vbCrLf, , _
"En Command3_Click"
End Sub
Veamos que es lo que hace este
código y porqué.
Cuando pulses en el Command1 te
mostrará un mensaje pidiendote que selecciones el tipo de prueba
que quieres hacer, para probar cada una de ellas, tendrás que
pulsar varias veces en ese botón, una para cada una de las tres
posibilidades.
Si pulsas en "SI", el
error se producirá en este mismo evento y el mensaje del final nos
indicará que se ha producido el error número 13.
Cuando pulses en "NO", se
llamará al procedimiento Command2_Click en el que se produce un
error 76, pero que el propio procedimiento se encarga de gestionar y
"limpiar", por tanto, no ocurrirá, al menos
aparentemente, nada.
Por último, al pulsar en
"Cancelar", se llama al procedimiento Command3_Click, el
cual produce el error 5, pero no detecta los errores; pero como el
Visual Basic "sabe" que aún hay una rutina
"interceptadora" de errores en funcionamiento, la del
Command1, deja de ejecutar el código erróneo y vuelve a la
siguiente instrucción que haya en el procedimiento Command1...
Después de estas tres pruebas,
pulsa en el Command2. Nada ocurre, ya que el código detecta los
posibles errores.
Cuando pulses en el Command3,
verás que el Visual Basic se detiene mostrandonos una ventana de
error, esto ocurre porque no hay ninguna rutina de detección de
errores en funcionamiento y cuando no la hay... el Visual Basic nos
muestra la suya propia y detiene el programa.
Ahora cambia el código del
Command3_Click por este otro:
'
Private Sub Command3_Click()
On Error Resume Next
' Este procedimiento produce un error número 5
Error 5
' Ahora si que se mostrará este mensaje
MsgBox "El valor de Err.Number es: " & Err.Number & vbCrLf & _
"Aquí no se notará que se ha producido un error..." & vbCrLf, , _
"En Command3_Click"
End Sub
Como verás, al no
"limpiar" el valor de la propiedad Err.Number,
el valor se mantiene; y a pesar de que se haya detectado el error en
ese evento, al volver de nuevo al código del Command1, se mostrará
el mensaje de que hay error... y además el mensaje que tenemos en
el evento Command2_Click, el cual antes no se mostraba.
Resumiendo:
Si detectas los errores con Resume
Next, acostumbrate a dejar el valor de Err.Number
a cero antes de que acabe y/o antes de salir del procedimiento.
Recuerda que para salir de un procedimiento puedes usar Exit
Sub, Exit Function o Exit Property.
También debes saber que, cuando
acaba un procedimiento, la rutina que gestiona los errores también
acaba, pero, como has podido comprobar, el valor del error permanece
asignado.
Otras formas de detectar errores
Acabamos de ver la forma más
"recomendable" de detectar errores, ya que al hacerlo de
esta manera, nos obligamos a chequear si se ha producido un error...
aunque esta no es la única, ya que existe otra forma:
On Error Goto NúmeroLínea
Si Visual Basic se encuentra con
esta instrucción y se produce un error, pasará a ejecutar el
código que esté en la línea indicada por NúmeroLínea, (no tiene
porqué ser un número, puede ser y de hecho es lo más
recomendable, una etiqueta), por tanto si se especifica ese formato,
NúmeroLínea debe existir... (ahora veremos un ejemplo)
Antes de continuar, recordaros que
la detección de errores se procesa en el último procedimiento en
el que se ha especificado una intrucción On Error... por tanto si
hay algún procedimiento con una "detección" de errores
activa y se produce un error en otro procedimiento, puede que nos
encontremos que el error "parece" que no se produce en el
procedimiento que "realmente" se ha producido... que lio
¿verdad?
Aclaremos este punto.
Supongamos que tenemos el siguiente
código:
'
Private Sub Command4_Click()
' Ejemplo para detectar errores en Visual Basic
Dim i As Integer
On Error Goto HayError
i = MsgBox("Pulsa SI para producir un error en este evento," & vbCrLf & _
"pulsa en NO para llamar al procedimiento Command5_Click", vbYesNo)
If i = vbYes Then
' Error 13 producirá un error de tipos (Type Mismatch)
Error 13
ElseIf i = vbNo Then
' Esto producirá un error en Command5, pero se detectará aquí
Command5_Click
End If
' Es conveniente NO entrar en la rutina de detección de errores por "error"
Exit Sub
' Etiqueta para cuando se produzca un error
HayError:
MsgBox "Se ha producido el siguiente error:" & vbCrLf & _
Err.Number & ", " & Err.Description, , "En Command4_Click"
End Sub
Private Sub Command5_Click()
' En este procedimiento no hay rutina de detección de errores
' Este procedimiento produce un error número 5
Error 5
End Sub
Al pulsar en el Command4, se muestra un cuadro de diálogo, si
pulsas "SI", se producirá un error dentro de ese
procedimiento y se "saltará" a la etiqueta indicada en On
Error Goto ..., en este caso HayError, y se mostrará el mensaje de
que se ha producido un error...
Si pulsas en "NO", se llamará al procedimiento
Command5_Click, se producirá un error y, como en ese procedimiento
no hay rutina de detección de errores, el Visual Basic pasa a la
anterior que hubiese activa, la de Command4_Click, y allí es donde
se muestra el mensaje de aviso.
Pero si pulsas directamente en el
Command5, verás que el error es detectado directamente por el
Visual Basic, mostrándonos un mensaje y, en caso de que fuese un
ejecutable, acabando la aplicación.
Esto es porque en el código del procedimiento Command5_Click no hay
ninguna rutina de detección de errores y tampoco hay ninguna otra
rutina "pendiente" que controle errores, cosa que si es
cierta cuando se llama al procedimiento Command5_Click desde el
Command4_Click.
Recuerda que esto sólo ocurre cuando se llaman a procedimientos
dentro de otros procedimientos.
Fíjate del Exit Sub que hay antes
de llegar a la etiqueta "HayError", esto es necesario
hacerlo para que, en caso de que no se produzca un error, no se
entre en la parte en la que se detectan los errores.
Dentro de la parte en la que se
detectan los errores, podemos usar instrucciones como:
Resume Next, con esto tendríamos algo parecido al On Error
Resume Next, ya que cuando el VB se encuentra con un Resume Next,
continúa en la siguiente instrucción a la que produjo el error.
Resume NúmeroLínea, en esta ocasión se continuará
con el código que haya a partir de la etiqueta (o número de
línea) NúmeroLínea...
Si Visual Basic se encuentra con una instrucción Resume y no hay un
error, mostrará una queja indicándones que se ha encontrado con un
Resume sin que haya error...
Cuando queramos
"dejar" de detectar errores en un procedimiento,
usaremos esta instrucción:
On Error Goto 0
Esto no indica que se vaya a la línea "0", (aunque
exista), sino que deje de detectar errores... en ese procedimiento,
ya que si hay algún procedimiento de nivel superior... si que se
detectará el error...
Veamos un ejemplo:
'
Private Sub Command6_Click()
' Esta variable se usará para mostrar mensajes en la rutina de detección
Dim Mensaje As String
' Controlamos los posibles errores
On Error GoTo HayError2 ' no puede haber dos etiquetas con el mismo nombre
' Producimos un error...
Mensaje = "Instrucción: Error 10"
Error 10
' Llamamos al procedimiento Command7_Click
Mensaje = "Instrucción: Command7_Click"
Command7_Click
Exit Sub
HayError2:
MsgBox "'" & Mensaje & "'" & vbCrLf & vbCrLf & _
"Se ha producido un error: " & vbCrLf & _
Err.Number & " - " & Err.Description
' Continuar por la siguiente instrucción
Resume Next
End Sub
Private Sub Command7_Click()
'
On Error Resume Next
' Este mensaje de error será ignorado, (por el On Error Resume Next anterior)
Error 13
' Dejamos de detectar errores
On Error GoTo 0
' A ver que pasa con este otro error
Error 15
' Este código nunca se ejecutará
MsgBox "Un mensaje desde Command7_Click" & vbCrLf & "que nunca se mostrará"
End Sub
Un detalle: Si en un mismo módulo
vamos a usar varias veces On Error Goto NúmeroLínea, no podemos
usar el mismo nombre para la etiqueta... si no lo tenemos en cuenta,
el Visual Basic nos lo recordará.
El código de Command6_Click no
debería tener ningún problema, así que pasamos al del
Command7_Click:
Al principio tenemos un On Error Resume Next, por tanto
cualquier error que se produzca será ignorado...
La prueba: producimos un Error 13 y no passa nada...
Nos encontramos ahora con On Error Goto 0, esto dejará de
"detectar" errores en este procedimiento, (este detalle es
importante saberlo, ya que sólo se dejan de detectar en este
procedimiento... no en el resto... cosa que puede producirnos algún
que otro quebradero de cabeza al pensar que se dejará de detectar
errores y será el propio Visual Basic el que se encargue de
mostrarnos el error; esto se usa sobre todo cuando se está
"debugueando" un programa, pero al final nos
encontramos que había una rutina "superior" en la que si
que se detectan los errores y... en fin... que puede que nos liemos
más de lo que yo ya te estoy liando... lo dicho... si te aclaras
con toda esta parrafada... ¡me lo explicas!)
Sigamos: tenemos que después de dejar de detectar los errores,
producimos un error: Error 15, pero como en este
procedimiento ya no hay rutina de detección de errores,
(¿recuerdas? la cancelamos con el On Error Goto 0), el Visual Basic
"busca" alguna rutina activa y si la hay la envía a esa
rutina, que en nuestro ejemplo está en el procedimiento
Command6_Click.
Por tanto el mensaje ese que hay al final del Command7_Click nunca
se ejecutará...
Ni siquiera si se pulsa directamente en el Command7, ya que al no
existir ninguna rutina a un nivel superior, será el propio Visual
Basic el que se encargue de detener el programa al encontrarse con
un error no detectado...
Una cosa más: No hay ninguna forma
de crear rutinas genéricas para detección de errores... es decir
no se puede crear un procedimiento genérico para detectar
errores... al menos hasta la versión 6 del Visual Basic, en futuras
versiones... puede ser que lo hagan... pero... eso ya se verá...
Confío que tengas claro todo
esto de la detección de errores... si no es así... pues... pero
para ti...
Nos vemos
|
|