Está en la página 1de 23

CURSO DE VB

CAPÍTULO 131

Índice de contenido
USO DE ETIQUETAS / CONTROL DE ERRORES .........................................................................2
PREPARANDO NUESTRA BD DE PRUEBAS............................................................................2
ETIQUETAS....................................................................................................................................2
ESTRUCTURA DE LAS ETIQUETAS. PROCESO DEL CÓDIGO........................................3
ETIQUETAS DENTRO DE UN BLOQUE...............................................................................6
CONTROL DE ERRORES.............................................................................................................7
MOSTRAR INFORMACIÓN DEL ERROR.............................................................................8
MANIPULANDO LOS ERRORES...........................................................................................9
UN ERROR HABITUAL QUE SE SOLUCIONA... HACIENDO NADA.............................11
LA PROPIEDAD SOURCE.....................................................................................................13
ON ERROR RESUME NEXT......................................................................................................15
GENERANDO NUESTROS PROPIOS ERRORES....................................................................16
ALGO MÁS SOBRE ERRORES..................................................................................................18
TIPOS DE ERRORES..............................................................................................................18
COMPILANDO EL CÓDIGO..................................................................................................21
DEPURACIÓN DE ERRORES................................................................................................22
UNOS BREVES TRUCOS.......................................................................................................22
PARA FINALIZAR.......................................................................................................................23

1 La BD donde están los ejemplos de este capítulo os la podéis bajar aquí.

1
Visítame en http://bit.ly/NckAccess
USO DE ETIQUETAS / CONTROL DE
ERRORES
Este capítulo estará dedicado, en primera instancia, al uso
de etiquetas para poder “dar saltos interestelares” a través
del código, y a continuación hablaremos de cómo controlar
los errores de código (y ver qué utilidades les podemos
dar).

Como siempre, vamos a prepararnos nuestra BD de


ejemplo.

PREPARANDO NUESTRA BD DE PRUEBAS


Vamos a crear una tabla, que llamaremos TClientes, que tendrá la estructura siguiente:

Rellenamos la tabla con algunos registros. Por ejemplo, yo la he rellenado así:

Vamos a crear otra tabla, que llamaremos TCientesNo. Para crearla vamos a copiar la tabla
TClientes, pero sólo pegamos su estructura (no los datos), y la pegamos con el nombre
propuesto.

En principio no necesitamos mucho más (y, si no, ya lo iremos añadiendo sobre la marcha).

ETIQUETAS
Las etiquetas son, por llamarlo de alguna manera, como “estaciones de servicio” en una
autopista. Es decir, lo normal sería ir conduciendo por dicha autopista, y hacer caso omiso a las
estaciones de servicio que van apareciendo. Sin embargo, si se produce algún evento en el
conducir (tenemos hambre, nos quedamos sin gasolina, queremos hacer un “pipí”...) pues
tenemos que pararnos en una estación de servicio.

Siguiendo con el símil, si programáramos lo anterior podríamos tener un esquema así (en
general):

2
Visítame en http://bit.ly/NckAccess

Private Sub...
Empieza a conducir
Ve por la autopista
Si <quedamos sin gasolina> entonces <Parar
en estación de servicio>
Llegamos a destino
Exit Sub
Parar:
Repostar gasolina
Seguir conduciendo
Llegamos a destino
End Sub

Para los que os suene algo de código, sería una especie de “GoSub” (que existe, pero como
hace el código difícil de leer prácticamente no se utiliza).

Evidentemente, si podemos “solventar” la condición dentro del propio código mejor hacerlo de
esta manera. Debemos recurrir a las etiquetas sólo cuando no tengamos otra solución mejor.

Ello implica que en el código anterior hubiera sido mejor escribir:


Private Sub...
Empieza a conducir
Ve por la autopista
Si <quedamos sin gasolina> entonces
<Parar en estación de servicio>
Continuar camino
End Si
Llegamos a destino
End Sub

Pensad que, en este capítulo, no voy a analizar si es mejor utilizar uno u otro sistema. Utilizaré
las etiquetas porque, obviamente, es lo que vamos a explicar.

También, para agudizar vuestro ingenio, no pondré los códigos comentados. Si habéis seguido
el curso ordenadamente hasta aquí deberíais ser capaces de entender perfectamente las
líneas. ¡Venga, que un poco de estímulo no está mal! ;)

ESTRUCTURA DE LAS ETIQUETAS. PROCESO DEL CÓDIGO


La estructura de las etiquetas es muy simple. Una etiqueta viene representada simplemente
por una palabra que a nosotros nos guste.

Para llamar a la etiqueta simplemente escribimos esa palabra elegida

Para indicar que es la etiqueta escribimos la palabra elegida seguida de dos puntos (:)

El código que debe ejecutarse, asociado a la etiqueta, lo escribimos a continuación de la


definición de la etiqueta.

Por ejemplo, supongamos que creamos la etiqueta “Cerrar_proceso”

3
Visítame en http://bit.ly/NckAccess
El código, en abstracto, sería:


Private Sub...
'Código
'Condición: si se cumple → GoTo
Cerrar_proceso
'Código
Cerrar_proceso:
'Código
End Sub

En cuanto al proceso, dentro del código, es un proceso lineal (como habréis podido intuir a lo
largo de todos estos capítulos anteriores). Podemos introducir un punto de “escape” al código
antes de llegar a la etiqueta, si nos interesa. Si no introducimos ese punto de “escape” el
código llegará a la etiqueta y seguirá procesándose.

Es decir, si yo escribo:


Private Sub ...
Const vNum as Byte = 25
Dim vProd as Integer SENTIDO DE
vProd = vNum * 2 EJECUCIÓN DEL
MsgBox "El producto es: " & vProd CÓDIGO
If vProd < 50 Goto Salgo
Salgo:
MsgBox "El producto es inferior a 50"
End Sub

Me voy a encontrar con:

– Me sale el MsgBox dándome el producto


– No se cumple If
– Me sale el MsgBos diciéndome que el producto es inferior a 50

Vemos que, en este caso, el código me da un resultado erróneo, lo que indica que no puedo
permitir que el código se ejecute más allá del If. Para ello modificamos ligeramente el código,
así:


Private Sub ... SENTIDO DE
Const vNum as Byte = 25 EJECUCIÓN DEL
Dim vProd as Integer CÓDIGO
vProd = vNum * 2
MsgBox "El producto es: " & vProd
If vProd < 50 Goto Salgo
Exit Sub INTERRUPCIÓN
Salgo:
MsgBox "El producto es inferior a 50"
End Sub

Ahora el código me dirá:

4
Visítame en http://bit.ly/NckAccess
Si vNum >= 25 Si vNum < 25
El valor del producto El valor del producto
----INTERRUPCIÓN Y SALIDA---- El mensaje de que el producto es inferior a 50

Y, lógicamente, no se estará equivocando.

Vamos a ver otro ejemplo aplicado sobre nuestra BD de pruebas.

En un formulario en blanco añadimos un botón de comando. En el evento “Al hacer click”, el


siguiente código2:


Private Sub cmdEtiqueta_Click()
Dim rst As Recordset
Set rst = CurrentDb.OpenRecordset("TClientesNo", dbOpenSnapshot)
If rst.RecordCount = 0 Then GoTo Salida
rst.MoveFirst
MsgBox "El primer cliente de la tabla es " & rst.Fields(0).Value
GoTo Salida2
Salida:
MsgBox "La tabla está vacía", vbInformation, "SIN DATOS"
Salida2:
rst.Close
Set rst = Nothing
End Sub

Este código nos da el código del primer cliente de la tabla TClientesNo. Si no hay registros
salta a la etiqueta Salida.

¿Qué problema tenemos aquí con el punto de interrupción? Evidentemente podríamos haber
escrito un Exit Sub tras la línea de código: MsgBox "El primer cliente de la tabla es " &
rst.Fields(0).Value

Pero como queremos hacer las cosas bien queremos cerrar el recordset y liberar memoria. Si
dejamos que el código continúe con la etiqueta Salida nos saldrá un mensaje que, en caso de
haber registros, no será correcto.

¿Solución? He creado una segunda etiqueta que hace “saltar” el código por encima del
mensaje de que no hay registros y nos cierra el recordset y libera memoria.

De esta manera, haya o no haya registros, nos aseguramos que al final cerramos el recordset

2 Si utilizáis Access 2003 y el código os da error utilizad DAO

5
Visítame en http://bit.ly/NckAccess
y liberamos memoria.

¿Pillamos la mecánica?

ETIQUETAS DENTRO DE UN BLOQUE


No debemos pensar que las etiquetas sólo se utilizan para
“soluciones finales” del código. Podemos utilizar etiquetas
dentro de un bloque para evaluar condiciones y “saltar” a
un sitio u otro.

Vamos a crearnos una tabla, que llamaremos TContactos, con la siguiente estructura 3:

Rellenamos la tabla con algunos datos, pero debemos asegurarnos que dejamos alguno de los
contactos en blanco. Por ejemplo, yo la he rellenado así:

Vamos a crearnos un código en el evento “Al hacer click” de un botón de comando que nos
indicará, a través de un Msgbox, el nombre de la empresa y el contacto.

El código sería:


Private Sub cmdContactos_Click()
Dim rst As Recordset
Set rst = CurrentDb.OpenRecordset("TContactos", dbOpenSnapshot)
With rst
.MoveFirst
Do Until .EOF
If IsNull(.Fields("Contacto").Value) Then GoTo Siguiente
MsgBox "Código empresa: " & .Fields("Empresa").Value & vbCrLf _
& "Contacto: " & .Fields("Contacto").Value
Siguiente:
.MoveNext
Loop
End With
rst.Close
Set rst = Nothing
End Sub

3 El campo [Empresa] es numérico porque almacena el código de la empresa, y está creado a través del asistente para búsquedas.

6
Visítame en http://bit.ly/NckAccess
Como podemos ver en el código, la condición que se evalúa
es si el campo [Contacto] esta vacío (IsNull). Si se cumple
esta condición lo que hacemos es “saltar” al registro
siguiente, a través de la etiqueta Siguiente:, a fin de no
obtener un mensaje de error por “uso no válido de null”.

Y también, como podéis ver, la etiqueta está inmersa dentro


del bloque DO UNTIL...LOOP.

CONTROL DE ERRORES
La estructura de un control de errores es extremadamente simple. Su inicio es el siguiente:


Private Sub …
On error GoTo <etiqueta>

Pensad que debemos situar lo anterior siempre en el principio del código, inmediatamente
después del Sub (o Function).

Lo que hace es que, en cualquier momento de la ejecución del código, cuando se produce un
error, lo reconduce a la etiqueta que nosotros hayamos definido.

Si ampliamos el código, en abstracto, nos encontraríamos la siguiente estructura:


Private Sub …
On Error GoTo sol_err
'Código
Exit Sub
sol_err:
'Código para gestionar el error
End Sub

Es decir, que a través del código de la etiqueta gestionamos el error y tomamos las medidas
oportunas.

Finalmente, de manera habitual se suele remitir el final del código de control del error a lo que
sería el final “normal” del código, y eso se hace a través de otra etiqueta. La palabra “mágica”
para remitir de nuevo la ejecución del código a lo que he llamado el “final normal” de código es
RESUME (para quien quiera palabras más técnicas, RESUME es una instrucción).

En definitiva, si intentáramos esquematizarlo en abstracto el resultado nos quedaría una cosa


así:


Private Sub …
On Error GoTo sol_err
'Código
Salida:
'Código para salir (por ejemplo, un simple Exit Sub)
sol_err:
'Código para gestionar el error

7
Visítame en http://bit.ly/NckAccess
Resume Salida
End Sub

¿Fácil, no?

MOSTRAR INFORMACIÓN DEL ERROR


Una manera de gestionar el error es, simplemente, mostrar
qué error se produce. Para capturar el error utilizamos el
objeto ERR

Las propiedades que utilizaremos para ello serán:

– NUMBER
– DESCRIPTION

Vamos a verlo con un ejemplo.

Sabemos que, en nuestra BD de pruebas, en la tabla TClientesNo no hay registros. Vamos a


crearnos un código en un botón de comando que intente leer los datos de un registro.
Evidentemente, si no hay registros activos, eso nos provocará un error.

El código sería:


Private Sub cmdErrorTClientesNo_Click()
Dim rst As Recordset
Set rst = CurrentDb.OpenRecordset("TClientesNo", dbOpenSnapshot)
rst.MoveFirst
MsgBox rst.Fields(1).Value
rst.Close
Set rst = Nothing
End Sub

y el error que devuelve Access es el siguiente:

Vamos a añadirle pues un control de errores, de manera que nos saldrá un mensaje
advirtiéndonos del error, pero el usuario ya no tendrá opción de pulsar el botón <Depurar> y
así no podrá acceder al código VB.

El nuevo código debería quedarnos así:


Private Sub cmdErrorTClientesNo_Click()

8
Visítame en http://bit.ly/NckAccess
On Error GoTo sol_err
Dim rst As Recordset
Set rst = CurrentDb.OpenRecordset("TClientesNo",
dbOpenSnapshot)
rst.MoveFirst
MsgBox rst.Fields(1).Value
Salida:
rst.Close
Set rst = Nothing
Exit Sub
sol_err:
MsgBox "Error número: " & Err.Number & vbCrLf & vbCrLf & _
"Descripción: " & Err.Description, vbCritical, "ERROR"
Resume Salida
End Sub

Ahora, el mensaje que obtendremos tendrá esta “pinta”:

Y, como vemos, no nos da ningún botón de acceso al código VB.

Fijaos cómo hemos manejado el error: a través de: Err.Number y de Err.Description

MANIPULANDO LOS ERRORES


Si tenemos el nombre del error y su número de error podemos manipular ese error en
concreto a nuestro antojo. Vamos a modificar el código para que nos salga un mensaje
“personalizado” para ese error. Por ejemplo, un usuario de Access que no tenga mucha idea
puede ser que no entienda qué significa esto de “registro activo”. Por ello vamos a poner un
mensaje algo más “legible” para este usuario.

El código que deberíamos escribir sería:


Private Sub cmdManipuloErrorTClientesNo_Click()
On Error GoTo sol_err
Dim rst As Recordset
Set rst = CurrentDb.OpenRecordset("TClientesNo", dbOpenSnapshot)
rst.MoveFirst
MsgBox rst.Fields(1).Value
Salida:
rst.Close
Set rst = Nothing
Exit Sub
sol_err:
If Err.Number = 3021 Then
MsgBox "No existe ningún dato dado de alta todavía. No se puede mostrar" _

9
Visítame en http://bit.ly/NckAccess
& " la información solicitada", vbInformation, "SIN DATOS"
End If
Resume Salida
End Sub

Ahora creo que el usuario sí sabrá por qué no obtiene


ningún dato, ¿verdad?

Profundicemos un poco más en este tema.

Vamos a copiar nuestra tabla TClientesNo y la vamos a pegar como


TClientesNo2. Vamos a añadir un registro, pero “olvidándonos” de
introducir el CIF del cliente. Por ejemplo, algo así:

En un botón de comando escribimos el anterior código, a ver qué resultados nos da


(adaptándolo, claro, al nuevo nombre de tabla).

En definitiva, escribimos:


Private Sub cmdErrorTClientesNo2_Click()
On Error GoTo sol_err
Dim rst As Recordset
Set rst = CurrentDb.OpenRecordset("TClientesNo2", dbOpenSnapshot)
rst.MoveFirst
MsgBox rst.Fields(1).Value
Salida:
rst.Close
Set rst = Nothing
Exit Sub
sol_err:
If Err.Number = 3021 Then
MsgBox "No existe ningún dato dado de alta todavía. No se puede mostrar" _
& " la información solicitada", vbInformation, "SIN DATOS"
End If
Resume Salida
End Sub

Si ahora ejecutamos el código, ¿qué pasa?

Pues que no nos salta ningún error, pero tampoco obtenemos ningún MsgBox con la
información solicitada.

Conclusión: que debemos ir con sumo cuidado a la hora de gestionar el error, puesto que no
tendría que pasarnos lo de “por arreglar una cosa espachurramos otra”.

Si modificamos el código de la siguiente manera veremos los nuevos resultados:


Private Sub cmdErrorTClientesNo2_2_Click()

10
Visítame en http://bit.ly/NckAccess
On Error GoTo sol_err
Dim rst As Recordset
Set rst = CurrentDb.OpenRecordset("TClientesNo2",
dbOpenSnapshot)
rst.MoveFirst
MsgBox rst.Fields(1).Value
Salida:
rst.Close
Set rst = Nothing
Exit Sub
sol_err:
If Err.Number = 3021 Then
MsgBox "No existe ningún dato dado de alta todavía. No se puede mostrar" _
& " la información solicitada", vbInformation, "SIN DATOS"
Else
MsgBox "Error número: " & Err.Number & vbCrLf & vbCrLf & _
"Descripción: " & Err.Description, vbCritical, "ERROR"
End If
Resume Salida
End Sub

Ahora sí recibiremos una notificación de por qué no nos funcionaba el código: se producía otro
número de error.

Una vez vayamos detectando los diferentes errores que se puedan producir en nuestro código
podremos ir gestionándolos a nuestro gusto. Os recuerdo que si queremos gestionar más de
un error (por ejemplo, en el caso que acabamos de explicar) tenéis el bloque SELECT CASE
para ir identificando los errores y manipulándolos.

UN ERROR HABITUAL QUE SE SOLUCIONA... HACIENDO NADA


Como curiosidad os comentaré que hay una tipología de errores que responden a una
caracterización muy similar entre ellos y que la mejor solución es, precisamente, no hacer
nada.

Entended esto como una sugerencia, y no como una solución “única y cerrada” al problema.
Evidentemente ya sabemos cómo manipular los errores y cómo adaptarlos a nuestras
necesidades.

Me estoy refiriendo a aquellos errores que se producen al intentar ejecutar alguna acción que
depende de un parámetro, y que cuando se nos solicita el parámetro nos lo pensamos mejor y
cancelamos.

Vamos a ver dos ejemplos de este tipo (aunque en realidad serían “los mismos perros con
distintos collares”).

Vamos a crear una consulta CClientes parametrizada sobre la tabla TClientes. La estructura

11
Visítame en http://bit.ly/NckAccess
podría ser la siguiente:

Ahora queremos abrir esa consulta desde un


botón de comando. El código simple que
normalmente pondríamos a ese botón sería:


Private Sub cmdAbreCClientes_Click()
DoCmd.OpenQuery "CClientes"
End Sub

Si hacemos click sobre el botón nos saldrá la ventana con la petición del valor del parámetro.
¿Qué pasa si cancelamos?

Pues que obtenemos el siguiente mensaje:

Bastante molesto, por cierto.

La solución pasa por introducir, en el código, un control de errores que no haga nada. Es decir,
que el código nos quedaría así:


Private Sub cmdAbreCClientesNoError_Click()
On Error GoTo sol_err
DoCmd.OpenQuery "CClientes"
sol_err:
Exit Sub
End Sub

Si ahora hacemos click y cancelamos la introducción del parámetro... pues el comportamiento


de Access parece “normal”.

12
Visítame en http://bit.ly/NckAccess
Vamos a realizar un segundo ejemplo: creamos un informe, que llamaremos RClientes, basado
en TClientes. Una vez creado situamos el informe en vista diseño y añadimos un cuadro de
texto en la cabecera, de manera que nos quede así:

El código “normal” de un botón de comando para abrir el informe sería:


Private Sub cmdAbreRClientes_Click()
DoCmd.OpenReport "RClientes", acViewPreview
End Sub

Nos pedirá la información del solicitante y... cancelamos. Nos saltará un mensaje así:

Como en el caso anterior, modificamos nuestro código para abrir el informe de la siguiente
manera:


Private Sub cmdAbreRClientesNoError_Click()
On Error GoTo sol_err
DoCmd.OpenReport "RClientes", acViewPreview
sol_err:
Exit Sub
End Sub

Si volvemos a probar el botón, y cancelamos, de nuevo ahora el comportamiento de Access


parecerá el lógico.

LA PROPIEDAD SOURCE
Si estamos utilizando varias bases de datos a la vez, gestionadas desde una sola aplicación, es
posible que nos encontremos con la aparición de un error pero no sepamos de qué BD
proviene (lo que implica que nos tendríamos que poner a buscar su origen).

Para facilitarnos esa labor tenemos la propiedad Source.

13
Visítame en http://bit.ly/NckAccess
El resultado de esa propiedad es la devolución del nombre del proyecto en el que estamos
trabajando. ¿Y cuál es ese nombre de proyecto? Buena pregunta...

Si abrimos, en nuestra aplicación, el editor de VB, y nos


fijamos en la ventana Proyecto, veremos ahí identificado
susodicho nombre. Por ejemplo, en la BD en la que estoy
trabajando ahora es “Nuevo Microsoft Office Access 2007
Base de datos”. Aunque no lo veáis entero, lo podéis intuir
en la imagen:

¡Qué nombre más feo! Vamos a cambiarlo. Clickamos con el botón de la derecha sobre el
nombre del proyecto, y en el menú emergente seleccionamos la opción “Propiedades de xxx”,
donde xxx es el nombre del proyecto. Nos aparecerá una ventana así:

Y ya podemos cambiarle el nombre del proyecto, además de configurar otras opciones que no
explicaremos aquí (aunque son bastante obvias).

Yo, de nombre, le he puesto CursoVB. Recordemos ese nombre porque vamos a ver cómo
funciona la propiedad Source a través de código.

Creamos un botón de comando y le asignamos este código, que intentará abrir un formulario
que no existe:


Private Sub cmdSource_Click()
On Error GoTo sol_err
DoCmd.OpenForm "NoExiste"
Exit Sub
sol_err:
MsgBox Err.Source
End Sub

14
Visítame en http://bit.ly/NckAccess

Si clickamos sobre ese botón obtendremos un MsgBox con


el nombre del proyecto que ha generado el error, y que,
lógicamente, en mi caso, será CursoVB. Algo así:

Claro, ¿verdad?

ON ERROR RESUME NEXT


Puede ocurrirnos que se produzca un error, pero que queramos hacer caso omiso de él, y que
queramos que el código se siga ejecutando.

Para ello tenemos la opción de escribir ON ERROR RESUME NEXT.

Lo que hace la anterior sentencia es decirle, como habréis intuido, que si se produce un error
que no le haga caso y siga con la siguiente línea de código.

Vamos a obtener una lista de los contactos de la tabla TContactos. Os pongo la línea del
control de error convertida en comentario para que no actúe. El código sería:


Private Sub cmdResumeNext_Click()
'On Error Resume Next
Dim rst As Recordset
Set rst = CurrentDb.OpenRecordset("TContactos", dbOpenSnapshot)
With rst
.MoveFirst
Do Until .EOF
MsgBox .Fields("Contacto").Value
.MoveNext
Loop
End With
MsgBox "Finalizó la lista de contactos", vbInformation, "FIN"
rst.Close
Set rst = Nothing
End Sub

Si ejecutamos el código veremos el “precioso” error que nos salta.

Si ahora “activamos” el control de errores y volvemos a ejecutar el código veremos la


diferencia de comportamiento.

Por si acaso, el código quedaría así:


Private Sub cmdResumeNext_Click()
On Error Resume Next
Dim rst As Recordset
Set rst = CurrentDb.OpenRecordset("TContactos", dbOpenSnapshot)

15
Visítame en http://bit.ly/NckAccess
With rst
.MoveFirst
Do Until .EOF
MsgBox .Fields("Contacto").Value
.MoveNext
Loop
End With
MsgBox "Finalizó la lista de contactos", vbInformation, "FIN"
rst.Close
Set rst = Nothing
End Sub

En definitiva, que si vemos que en nuestro código se producen errores que no “bloquean” el
código (por decirlo de alguna manera) haciéndolo “inservible”, sino que son errores que no
tienen una influencia importante sobre el mismo, y que si los obviamos conseguimos sin
problemas los resultados esperados, podemos recurrir al ON ERROR RESUME NEXT.

GENERANDO NUESTROS PROPIOS ERRORES


Hemos visto que los errores que nos lanzaba Access iban identificados por un número (que
capturábamos con Err.Number). En un alarde de altruismo Access nos deja libres los números
que van del 513 al 65535 para que podamos asignarles un “error personalizado” (del 0 al 512
están reservados para los errores de sistema). Para ello podremos utilizar un método
denominado RAISE.

Por ejemplo, imaginemos que lo que queremos es lo contrarío de lo que queríamos hace unas
páginas antes: que ante una determinada circunstancia nos salga un mensaje de error con la
posibilidad de depurar el código.

Como tenemos los números de error reservados que os comentaba antes imaginemos que,
como programadores de la BD, nos hacemos una categorización de errores. Algo así como:

– Error 700: recordset vacío


– Error 705: valor nulo
– Error 710: etc...

He cogido el error 700 como hubiera podido coger el error 800... esto ha sido porque me gusta
el 7... je, je...

La idea subyacente no es “esperar que se produzca el error”, sino prever dónde se puede
producir el error con alguna probabilidad y establecer un control, sin resolverlo. Con
posterioridad ya aplicaremos las medidas oportunas para corregirlo como nos plazca (esto ya
sería un tema de “gustos propios sobre programación”).

Dicho lo anterior, y antes de ver el ejemplo con código, os indicaré que la sintaxis de RAISE es:

Err.Raise <NúmeroError>, <Source>, <TextoDelError>, <RutaDelFicheroDeAyuda>,


<IdentificadorDeAyuda>.

Lo que os he marcado en negrita constituye la expresión mínima obligatoria; el resto de


argumentos son opcionales.

Si aprovechamos para ir construyendo mi error escribiríamos: Err.Raise 700

<Source> ya os debería “sonar”... Es la misma “Source” que veíamos en el apartado anterior.

16
Visítame en http://bit.ly/NckAccess
Y mi error se completaría con: Err.Raise 700, “CursoVB”

<TextoDelError> es una simple descripción del error, que


aparecerá en pantalla.

Seguimos: Err.Raise 700, “CursoVB”, “Recordset vacío”

Los otros dos argumentos se refieren a si hemos construido


un fichero de ayuda (un *.chm), y nos sirve para poder
mostrar una ayuda más detallada del error. Indicaríamos la
ruta del fichero de ayuda y un identificador, que es
simplemente un marcador que, dentro del fichero de ayuda,
nos lleva al apartado donde se trata ese error.

Como podemos ver, la posibilidad de incluir un fichero de ayuda con la descripción del error
aumenta las posibilidades de “mostrar más información” y más personalizada que si se tratara
de un error “normal” propio de Access.

Y por fin vamos al ejemplo... Reutilizaremos el código que, en este ejemplo, yo empleaba para
manipular el error devuelto por TClientesNo, al no haber registros en la tabla.

Vamos a ver el mismo código, pero con “dos caras”.

El primer código sería el siguiente:


Private Sub cmdRaise_Click()
'On Error GoTo sol_err
Dim rst As Recordset
Set rst = CurrentDb.OpenRecordset("TClientesNo", dbOpenSnapshot)
'-----PREVEO QUE PUEDA NO HABER REGISTROS----
If rst.RecordCount = 0 Then
Err.Raise 700, "CursoVB", "Recordset sin registros. Contacte con el administrador"
Else
rst.MoveFirst
'-----PREVEO QUE PUEDA HABER VALORES VACÍOS
If IsNull(rst.Fields(1).Value) Then
Err.Raise 705, "CursoVB", "Campo vacío. Contacte con el administrador"
Else
MsgBox rst.Fields(1).Value
End If
End If
'Salida:
rst.Close
Set rst = Nothing
Exit Sub
'sol_err:
' MsgBox Err.Number & " - " & Err.Description
' Resume Salida
End Sub

Fijaos que he convertido en comentario todas las líneas referentes al control de errores
“normal”. En definitiva, es como si hubiera escrito el código sin control de errores.

17
Visítame en http://bit.ly/NckAccess
Os animo a ejecutarlo, para que veáis el comportamiento del mensaje de error.

A continuación volvemos al código y eliminamos los


comentarios de las líneas correspondientes al control de
errores. Es decir, que el código debería quedarnos así:


Private Sub cmdRaise2_Click()
On Error GoTo sol_err
Dim rst As Recordset
Set rst = CurrentDb.OpenRecordset("TClientesNo",
dbOpenSnapshot)
'-----PREVEO QUE PUEDA NO HABER REGISTROS----
If rst.RecordCount = 0 Then
Err.Raise 700, "CursoVB", "Recordset sin registros. Contacte con el administrador"
Else
rst.MoveFirst
'-----PREVEO QUE PUEDA HABER VALORES VACÍOS
If IsNull(rst.Fields(1).Value) Then
Err.Raise 705, "CursoVB", "Campo vacío. Contacte con el administrador"
Else
MsgBox rst.Fields(1).Value
End If
End If
Salida:
rst.Close
Set rst = Nothing
Exit Sub
sol_err:
MsgBox Err.Number & " - " & Err.Description
Resume Salida
End Sub

Y, si lo ejecutamos ahora, podréis ver la diferencia de respuesta del mensaje.

Pues... en función de nuestras necesidades ya sabemos cómo elegir uno u otro.

ALGO MÁS SOBRE ERRORES

TIPOS DE ERRORES
Podemos encontrarnos diversos tipos de error, y cada uno tiene un tipo diferente de
tratamiento.

Los diferentes tipos de error que podemos encontrarnos son:

– Errores en tiempo de diseño


– Errores en tiempo de diseño que se detectan en tiempo de ejecución
– Errores en tiempo de ejecución
– Errores de programación

Los errores en tiempo de diseño son muy fáciles de detectar porque es el propio Access quien
nos indica el error.

18
Visítame en http://bit.ly/NckAccess
Por ejemplo, si en cualquier procedimiento de los que hemos estado utilizando escribimos lo
siguiente:

If variable=0

y pulsamos Enter para acceder a una nueva línea, nos


saldrá lo siguiente:

Así, es el propio Access quien nos indica que hay error de “diseño”, y además nos proporciona
alguna sugerencia sobre lo que hemos omitido al escribir la línea de codigo.

¿Cómo se solventan? Fácil: escribiendo correctamente la línea de código en cuestión.

Los errores de diseño que se detectan en tiempo de ejecución de producen cuando se está
ejecutando el código. Es decir, que sintácticamente el código está bien escrito, pero hay
errores precisamente de diseño que imposibilitan la ejecución del código.

Por ejemplo, si escribimos lo siguiente en un procedimiento:


Private Sub cmdErrorDiseño_Click()
MsgBox vCliente
End Sub

El diseño de este procedimiento es, en principio correcto a nivel sintáctico, pero si intentamos
ejecutarlo nos saldrá el siguiente mensaje (doy por supuesto que hemos activado la opción
“Requerir declaración de variables”).

¿Cómo se solventan? Fácil, también: escribiendo la línea o líneas de código que corrigen el
error.

Los errores en tiempo de ejecución son los que sintácticamente están totalmente correctos,
pero que, al ejecutarse el código, se derivan del mismo una serie de “situaciones” que generan
errores por expresiones o valores incorrectos.

Son en definitiva, los que hemos estado viendo en los apartados precedentes.

Por ejemplo, si yo escribo el siguiente código:


Private Sub cmdErrorEjecucion_Click()
Const vNumerador As Integer = 10

19
Visítame en http://bit.ly/NckAccess
Const vDenominador As Integer = 0
Dim vResultado As Double
vResultado = vNumerador / vDenominador
MsgBox vResultado
End Sub

Sintácticamente es correcto, todas las variables están bien


declaradas y definidas... y, al ejecutarlo, nos dará un error.
¿Por qué? Porque derivado del código se obtiene una
expresión incorrecta, que es intentar obtener un valor de
una división entre cero.

¿Solución? La solución más obvia es establecer un control de errores. Sin embargo, hay que
tener en cuenta que, en general, estos errores son más difíciles de solucionar, porque aquí
entra en juego nuestra capacidad de “ponernos en lugar del usuario” e imaginar todas las
opciones posibles que puede realizar.

Porque si el código anterior fuera bastante más complicado, y vDenominador dependiera de un


valor introducido por el usuario que además se originara por operaciones aritméticas
posteriores, o somos capaces de “intuir” que vDenominador puede llegar a coger el valor cero
(que podría ser nunca) o en la trigésima ejecución por parte del usuario... ¡zas! Error al canto.

Finalmente, los errores de programación ya sí dependen totalmente de nosotros, porque no


hay errores de diseño ni errores en tiempo de ejecución y, sin embargo, no obtenemos los
resultados esperados.

Por ejemplo, si escribimos este código:


Private Sub cmdErrorProgramacion_Click()
Dim rst As Recordset
Set rst = CurrentDb.OpenRecordset("TContactos", dbOpenSnapshot)
MsgBox "Lista de contactos"
With rst
.MoveFirst
Do Until .EOF
MsgBox .Fields(1).Value
.MoveNext
Loop
End With
End Sub

20
Visítame en http://bit.ly/NckAccess
Es un código “maravilloso”, sin errores de ninguna clase... hasta que lo ejecutamos, y vemos
que la información que nos muestra no tiene mucho sentido.

¿Dónde está el error? Pues descubrimos que nos hemos


equivocado en el índice de Fields, y que el campo donde
está el nombre del contacto no tiene el índice 1, sino que
tiene el índice 2.

¿Cómo solucionamos este tipo de errores? Quizá llevando


alguna vela a un santo... je, je... Si el código es muy
complicado no nos quedará más remedio que ir probando y
probando (a no ser que la solución sea muy evidente, claro)
hasta ir acotando el código hasta descubrir qué es lo que
hemos programado “mal” para que nos dé la información
incorrecta, y así poder subsanar el error.

COMPILANDO EL CÓDIGO
Si os habéis fijado en las imágenes que os he puesto para los errores de diseño y de ejecución,
veréis que Access nos indica que el error es un error “de compilación”.

Algunas veces podemos escribir un código (o muchos) y no testearlo inmediatamente. Para


estar seguros de que no tenemos errores podemos compilar el código.

Para ello:

1.- Nos situamos en el VBE

2.- Nos vamos a menú Depuración → Compilar xxx (donde xxx será el nombre de nuestro
proyecto)

3.- Si hay algún error de diseño (ojo, que los errores en tiempo de ejecución nos saltarán al
ejecutar el código, no al compilar), Access nos marcará el tipo de error y su ubicación.

4.- Corregimos los errores que nos vayan apareciendo. Cuando ya no haya más errores la
opción del menú mencionado nos saldrá atenuada en gris.

¡Y código compilado!

21
Visítame en http://bit.ly/NckAccess
DEPURACIÓN DE ERRORES
El editor de VB nos proporciona otras herramientas para
depurar el código. Prácticamente todas las podemos
encontrar en menú Depuración.

Sin embargo no las vamos a explicar aquí, porque no es


objeto del curso.

Si queréis más información en el menú de ayuda del VBE escribid


“menú Depuración” y ahí encontraréis todos los resultados para las
diferentes opciones de dicho menú.

UNOS BREVES TRUCOS


A veces nos salta un error insistentemente y no vemos el origen del mismo. Os explico un par
de trucos que yo utilizo para depurar errores:

a) Comentarios

Si en el VBE nos vamos menú Ver → Barras de herramientas → Edición nos aparecerá dicha
barra de herramientas. En ella encontraremos dos botones muy útiles:

De esta manera, si “sospechamos” que un bloque de código es el que nos causa problemas,
podemos seleccionarlo entero y clickar sobre el botón que aplica comentarios en bloque.
Ejecutamos el código y si se sigue produciendo el error querrá decir que nuestras sospechas
eran erróneas (o al revés); lógicamente teniendo en cuenta siempre que la “supresión
temporal” de ese bloque de código no imposibilite la ejecución del código, claro.

b) La función MsgBox

Cuando creemos que una variable no está obteniendo el valor deseado, o cuando una cadena
de texto no está devolviendo los valores esperados, podemos realizar una comprobación rápida
con un MsgBox. E incluso, para obviar el error, lo podemos combinar con un Exit Sub para
evitar que se siga ejecutando el código.

22
Visítame en http://bit.ly/NckAccess
Por ejemplo, si nuestra variable vVar nos da problemas podríamos hacer lo siguiente:


Private Sub...
'Código
Msgbox vVar
Exit Sub
'Código
End Sub

Al ejecutar el código nos saldrá un mensaje con el valor de la


variable, y así podremos comprobar qué valor ha cogido.

O, por ejemplo, si una Sql nos da error, podemos escribir lo siguiente:


Private Sub...
'Código
sql = “SELECT * FROM Tabla WHERE Tabla.var1=” & vVar1 & “ AND Tabla.var2=” & vVar2
Msgbox sql
Exit sub
'Código
End Sub

El resultado podría ser, por ejemplo:

SELECT * FROM Tabla WHERE Tabla.var1 = 12/05/11 AND Tabla.var2 = 25

E inmediatamente deberíamos darnos cuenta que la fecha debería ir entre almohadillas.

Para quienes les guste utilizar el VBE el MsgBox sería una especie de “sucedáneo” de

Debug.Print

Que nos mostraría lo mismo, pero en la ventana Inmediato del VBE.

PARA FINALIZAR
Hemos dado, en este capítulo, la mecánica para utilizar etiquetas, más un buen “repasón” al
tema de los errores, y hemos añadido, al final, algo que podríamos considerar un poco de
teoría sobre el tema.

Espero que, tras leer/estudiar este capítulo, en vuestros códigos “no se os escape ni uno”... je,
je...

Un saludo, y...

¡suerte!

23
Visítame en http://bit.ly/NckAccess

También podría gustarte