Curso Básico de Programación
en Visual Basic

 

Apéndice a la entrega Treinta y dos (23/Ene/2000)
por Guillermo "guille" Som

Para volver a la entrega 32, pulsa este link.

 

¿Cómo detectar errores en 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 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.
Guillermo


 

Ir al índice principal del Guille