Documentos de Académico
Documentos de Profesional
Documentos de Cultura
VBA1
ÍNDICE
INTRODUCCIÓN................................................................................................................................2
MECÁNICA DE TRABAJO................................................................................................................2
TIPOS DE ERRORES..........................................................................................................................2
ERRORES EN TIEMPO DE DISEÑO (ERROR DE COMPILACIÓN).......................................2
ERRORES EN TIEMPO DE DISEÑO QUE SE DETECTAN EN TIEMPO DE EJECUCIÓN
(ERROR DE COMPILACIÓN)......................................................................................................3
ERRORES EN TIEMPO DE EJECUCIÓN....................................................................................4
ERRORES DE PROGRAMACIÓN................................................................................................4
DEBUGGING THE CODE (O DEPURANDO EL CÓDIGO, PARA LOS AMIGOS).......................6
LA VENTANA INMEDIATO.........................................................................................................6
INFORMACIÓN EXPRESS...........................................................................................................9
DEBUG.PRINT.............................................................................................................................10
DEBUG.ASSERT..........................................................................................................................11
LA SENTENCIA STOP.................................................................................................................11
LA PILA DE LLAMADAS...........................................................................................................13
PUNTOS DE INTERRUPCIÓN...................................................................................................14
NUESTRO AMIGO SHERLOCK Y SU FAMILIA.....................................................................18
F8..............................................................................................................................................19
SHIFT+F8.................................................................................................................................20
CTRL+F8..................................................................................................................................21
CTRL+SHIFT+F8.....................................................................................................................22
VIGILANDO VARIABLES Y EXPRESIONES...........................................................................23
INSPECCIONANDO CONDICIONALMENTE.....................................................................27
VENTANA DE VARIABLES LOCALES....................................................................................28
PARA FINALIZAR ESTA MINI-GUÍA............................................................................................31
1
Visítame en http://bit.ly/NckAccess
INTRODUCCIÓN
Cuando aprendemos a programar en VBA con frecuencia
nos centramos más en lo que es la programación en sí, y
dejamos de lado todo lo que sería la parte de depuración de
código.
Ya advierto que, siguiendo en la línea de cómo redacto yo los manuales, esta guía no pretende
en absoluto ser un “texto académico”, por lo cual, en la medida de lo posible, voy a huir de
tecnicismos y voy a intentar explicar los contenidos de los diferentes apartados de la manera
más simple y pedestre, dado que lo que persigo es que entendáis los conceptos y los podáis
aplicar sin necesidad de ser unos “expertos informáticos” ;-)
MECÁNICA DE TRABAJO
Todo lo explicado aquí se basará en la estructura e información contenida en la base de datos
que acompaña a este ejemplo. Para no “cargaros” no voy a explicaros la estructura de dicha
base de datos, puesto que parto del supuesto de que tenéis ya algunos conocimientos de
Access y que, echando un vistazo rápido a la base de datos, la entenderéis “a la primera”. Sí
me detendré en los códigos, dado que voy a darme el gran “gustazo” de destrozarlos
(uhmmm…) para poder aplicar después las técnicas de depuración.
Así que, en base a lo anterior, mi recomendación es que tuvierais esa base de datos a mano
para poder consultar o intentar recrear lo que en esta mini-guía se explique.
TIPOS DE ERRORES
Antes de empezar a depurar debemos conocer los cuatro tipos de errores a los que debemos
enfrentarnos. Veamos:
Si nosotros empezamos a escribir un condicional, por ejemplo, y nos olvidamos del “then”,
Access nos avisará con un bonito mensaje, indicándonos asimismo lo que él cree que podría
ser una posible solución:
2
Visítame en http://bit.ly/NckAccess
Otra manera que tiene Access de avisarnos de que “hay algo mal” es marcar en rojo la línea de
código incorrecta. Por ejemplo, si yo no corrigiera el error anterior y siguiera escribiendo
código lo que vería sería lo siguiente:
Fijaos que Access me sigue marcando la línea del IF en rojo, dado que yo he seguido
escribiendo código pero no he corregido el error.
Finalmente, en ocasiones especiales, tenemos alguna línea de código mal escrita que, por los
motivos que sean, no está marcada en rojo. En ese caso una manera de detectar que “hay
algo mal” es darnos cuenta de que el Intellisense parece que “nos ha dejado de funcionar”.
Son casos, como comentaba, muy específicos y es difícil proporcionaros un ejemplo, por lo
que, para este supuesto, lo que me interesa es que os quedéis con la idea de que “si el
Intellisense falla, algo pasa”.
3
Visítame en http://bit.ly/NckAccess
ERRORES EN TIEMPO DE EJECUCIÓN
este tipo de errores se detectan en tiempo de ejecución, puesto ahí es cuando Access los
detecta y nos avisa. Y no solo nos avisa, sino que nos da la opción de depurar el código,
conduciéndonos al procedimiento o función que está dando el error y marcándonos en amarillo
la línea de código conflictiva.
El típico ejemplo de este tipo de errores es intentar realizar una división entre cero. Si yo
escribo el siguiente código, al ejecutarlo, obtendré el error marcado por Access:
ERRORES DE PROGRAMACIÓN
Posiblemente, y en función de nuestro código, los más difíciles de encontrar. El código está
perfecto, sin errores, y, sin embargo, los resultados no son los esperados. ¡Y encima Access no
nos dice nada! En este caso el error digamos que está en el propio programador, y una revisión
exhaustiva del código nos debería permitir encontrar el fallo.
4
Visítame en http://bit.ly/NckAccess
Por ejemplo, supongamos que si la variable vProducto tiene
valor “sólido” el precio final viene de multiplicar vCantidad x
vPrecioKilo, mientras que si tiene valor “líquido” el precio
final viene de multiplicar vCantidad x vPrecioLitro.
Al depurar el código no obtendremos ningún error, dado que todo está perfecto. Sin embargo,
la función no nos devuelve los valores correctos. Así pues, nos encontramos con un error de
programación, y el “fallo humano” está en que, en la parte de ELSE, calculamos el precio total
multiplicando la cantidad por el precio por kilo, mientras que deberíamos hacerlo multiplicando
por el precio por litro.
Resumiendo: ¿cómo detectamos este tipo de errores? Pues revisando el código de arriba a
abajo. Pero para ello tenemos algunas ayudas, que es lo que os contaré durante esta mini-guía
:-)
Permitidme poneros otro ejemplo no tan evidente a simple vista. Imaginaos que tengo una
llamada a una función que me devuelve el resultado de multiplicar dos variables.
La pregunta que os lanzo es: ¿devolverán los dos msgbox el mismo resultado?
Digo sorprendentemente porque el siguiente código, donde la variable tiene la parte decimal
separada por un punto, nos da 5, y funciona correctamente:
5
Visítame en http://bit.ly/NckAccess
Así que, en definitiva, este tipo de errores son los que nos
interesan realmente, y, como os comentaba, veremos en
esta guía qué herramientas tenemos para ayudarnos en su
detección.
Cuando hablamos de depurar código pensamos en un código que ya tenemos escrito y que
queremos analizar para detectar algún error. Eso, evidentemente, es totalmente correcto.
Sin embargo, también podemos utilizar alguna (la mayoría) de herramientas para ir
construyendo el código e ir probándolo, sin que este esté completo. Así, sobre todo si el código
final va a ser muy complejo, podemos ir construyéndolo poco a poco a la vez que depuramos,
para no “darnos la panzada” al final. Esta segunda idea es la que desearía que os quedara en
mente para tenerla en cuenta para ese “por si” que os comentaba al principio.
LA VENTANA INMEDIATO
La ventana inmediato, que podemos sacar pulsando la combinación de teclas CTRL+G o bien
utilizando el menú del editor de VB (VBE), deviene un espacio de trabajo sumamente útil.
Entre otras muchas cosas, en la ventana inmediato podemos acceder a valores de variables,
de expresiones, a sacar información sobre la base de datos, resetear variables, mostrar
información de otras herramientas de depuración de código, etc.
6
Visítame en http://bit.ly/NckAccess
Si ejecutamos el segundo procedimiento la consulta en la
ventana inmediato nos dará el siguiente valor:
De la misma manera, podemos obtener el valor de funciones incorporadas, como por ejemplo:
7
Visítame en http://bit.ly/NckAccess
Ojo, que también cuenta las tablas de sistema.
Ojo, que estamos manejando una colección de formularios, y, como colección, el índice de la
misma empieza por cero, de ahí que el segundo formulario sea el que tiene el índice 1.
✔ Resetear variables
Si retomamos nuestra variable pública miValor, podríamos forzar que tomara el valor que
quisiéramos (siempre y cuando nuestro código lo permitiera, claro), para forzar al código que
entrara en el bucle que queremos analizar.
Y por mucho que ejecutamos nuestros códigos no hay manera que el código nos entre en el
CASE ELSE, que es el que queremos testear. En ese caso, escribimos en la ventana inmediato
8
Visítame en http://bit.ly/NckAccess
✔ Mostrar información de los puntos que queramos de nuestro código
Y para hacer eso tenemos que pasar a explicar…
INFORMACIÓN EXPRESS
Podría resultar que, en ocasiones, al depurar el código nos
“hagamos la picha un lío” (perdón por la expresión, pero no
he podido evitarlo… je, je...) con las variables. Es decir, que
tras varias horas de darle al coco con nuestro código nos
preguntemos: “¿Y esta variable, de dónde sale? ¿Era
pública, privada? ¿Era un String o un Variant?
Imaginemos que he creado una variable pública (varPub) en un módulo estándar, una variable
a nivel de módulo de formulario (varForm) y una variable local dentro de un procedimiento
(varProc). Al repasar el código, si ando algo perdido, puedo situarme sobre las variables y
solicitar esa información rápida:
9
Visítame en http://bit.ly/NckAccess
De la misma manera podemos obtener otro tipo de información si nos situamos sobre los
diferentes elementos que componen nuestro código. A modo de ejemplo, ¿cómo eran los
parámetros de un msgbox?
DEBUG.PRINT
Al utilizar la sentencia Debug.Print lo que hacemos es mostrar en la ventana inmediato el valor
que queremos controlar.
Por ejemplo, imaginemos que queremos controlar los cambios de valor que sufre una variable
durante la ejecución de código. En ese caso nuestro código quedaría así:
Y, al ejecutar el código, veríamos los resultados en la ventana inmediato tal y como muestra la
anterior ilustración.
10
Visítame en http://bit.ly/NckAccess
Nota: en ocasiones me resulta más cómodo utilizar un
msgbox para mostrar los valores. Sin embargo, esa opción
la utilizo para lanzar uno (o unos pocos) mensajes; si
estamos dentro de un bucle que se repite cien veces os
aseguro que es un “peñazo” pulsar el botón de aceptar del
msgbox cien veces: mejor utilizar, en ese caso, un
debug.print.
DEBUG.ASSERT
La sentencia Debug.Assert lo que hace es detener el
código cuando alguna condición devuelve el valor
FALSE.
¿Qué intentamos controlar con Debug.Assert? Pues queremos asegurarnos de que miVar no
tome ningún valor que sea divisible entre 5. Si lo toma se fuerza la detención del código.
LA SENTENCIA STOP
Podemos forzar la interrupción del código con la sentencia STOP, que, como todo el mundo
sabe, significa “Siempre Tiene Obligación de Parar” (je, je…).
Imaginemos que queremos comprobar qué pasa con el valor de una variable de la cual
depende la ejecución de un condicional, dado que nunca parece ejecutarse ese condicional.
En consecuencia, podríamos realizar un debug.print seguido de un stop para ver qué valor está
tomando la variable.
11
Visítame en http://bit.ly/NckAccess
Fijémonos que el código se detiene en el STOP y nos lo marca en amarillo. En la ventana
inmediato vemos que el valor tomado es 6, por lo que por eso no entra en el bloque IF.
Nota: para examinar un solo valor, y si tenemos prisa, nos podemos evitar el uso de
debug.print. Si, cuando se produce la detención del código al llegar al stop, dejamos el puntero
del ratón sobre cualquier lugar donde aparezca miVar veremos cómo Access nos chiva su valor.
Otro ejemplo de la utilidad de lo anterior es utilizar el mismo sistema en bucles iterativos. Por
ejemplo, si ejecutamos el siguiente código:
12
Visítame en http://bit.ly/NckAccess
Y a continuación pulsamos F5 (o el botón de continuar) podremos controlar qué valor toma la
variable i en cada iteración…
LA PILA DE LLAMADAS
En ocasiones podemos tener un código que hace llamadas a un procedimiento, que a su vez
hace llamadas a otro procedimiento, y así sucesivamente.
Para examinar el camino recorrido por las diferentes llamadas tenemos una opción visual que
quizá nos pueda ser de ayuda, y que se denomina “pila de llamadas”. La podemos encontrar en
el menú Ver → Pila de llamadas
13
Visítame en http://bit.ly/NckAccess
La opción de “Pila de llamadas” se nos activará cuando se produzca algún error o forcemos la
interrupción del código.
Si en proc2 insertamos un STOP y hacemos clic sobre el botón del formulario se nos mostrará,
como ya sabemos, el STOP resalado en amarillo. Si en ese momento seleccionamos la opción
de pila de llamadas (o CRTL+L) podremos ver qué camino sigue todo el “meollo” (en orden
descendente):
PUNTOS DE INTERRUPCIÓN
El punto de interrupción es una figura muy similar a la sentencia STOP, dado que lo que hace
es forzar la interrupción de la ejecución del del código allí donde se encuentren. Entonces,
¿cuál es la diferencia?
14
Visítame en http://bit.ly/NckAccess
Pues que los puntos de interrupción, al cerrar Access, no
quedan guardados. Así que si por el motivo que sea lo
dejamos para ir a ver los anuncios de la tele (porque ya
sabéis que los malvados de televisión siempre nos cortan
los anuncios para poner una película… ¡desalmados!) y
queremos “guardar” dónde estábamos depurando el código
utilizad STOP.
Ni que decir tiene que podemos añadir tantos puntos de interrupción como queramos.
Así, cuando ejecutemos el código, este se nos parará en el IF en cada iteración del bucle FOR,
lo mismo que cada vez que vaya a cambiar el valor de la variable i, y finalmente se nos
detendrá antes de lanzar el msgbox.
15
Visítame en http://bit.ly/NckAccess
Si volvemos a hacer clic sobre el punto del margen
izquierdo eliminaremos ese punto de interrupción en
concreto. Si queremos eliminarlos todos podemos irnos a
menú → Depuración → Borrar todos los puntos de
interrupción, o pulsar la combinación de teclas
Crtl+Shift+F9
Pulsamos F5 (o botón Reanudar) y se repetirá el proceso tantas veces como sea necesario.
Sin embargo, imaginemos que queremos hacer pruebas “volviendo hacia atrás”, siguiendo con
el ejemplo anterior, de “qué pasaría si...” (o hemos encontrado un error y queremos “volver
atrás”). ¿Cómo lo hacemos?
16
Visítame en http://bit.ly/NckAccess
Si ejecutamos el procedimiento, en la ventana inmediato
solo nos debería aparecer un 1, dado que al ser un número
impar no se entraría en el IF por no cumplirse la condición.
La pregunta es: ¿qué pasaría si i tomara una unidad más?
17
Visítame en http://bit.ly/NckAccess
El primer i=1 viene de nuestra primera ejecución de código
Al haberle sumado una unidad a i vemos que sí el código entra en el bucle IF, porque i es
ahora 2 y eso es un número par, y por tanto, ahora sí podemos comprobar que, primero, var2
devuelve un valor y, segundo, cuál es ese valor que devuelve.
Aunque lo anterior puede parecer complicado a primera vista no os preocupéis, que con
utilizarlo un par de veces se le pilla el truco y parecerá que lo hemos hecho toda la vida.
De la misma manera, si nos situamos en cualquier punto del código, clic derecho del ratón →
Mostrar instrucción siguiente, el VBE nos llevará al punto de interrupción que está
deteniendo el código.
¿Para qué? Imaginaos que tenéis un código de 500 líneas, habéis ejecutado el código con
puntos de interrupción y os habéis desplazado por el código para examinar alguna cosa. En
lugar de ir con la rueda del ratón (o la barra de desplazamiento) hasta encontrar “la línea
amarilla” con este sistema dais el salto directamente. Cuestión de tiempo, en definitiva :-)
18
Visítame en http://bit.ly/NckAccess
F8
Pues para responder la pregunta anterior tenemos a
nuestro Sherlock, que es F8.
y como yo estoy haciendo la prueba el día 11, si volvemos a pulsar F8 comprobamos que el
código ejecuta el primer msgbox, y ya no entra dentro del ELSE.
19
Visítame en http://bit.ly/NckAccess
SHIFT+F8
Una variación sobre lo anterior constituiría si nuestro
procedimiento realiza llamadas a otros procedimientos. Si
vamos pulsando solamente F8 la depuración nos llevará a
ese procedimiento llamado y nos mostrará todas sus líneas,
y volverá a nuestro código original una vez se haya salido
del procedimiento llamado.
c) Y así sucesivamente F8 hasta que nos salte el mensaje de msgbox miMsg, tras lo cual se
20
Visítame en http://bit.ly/NckAccess
retorna al procedimiento llamante:
Si solo nos interesa ver el procedimiento en el que estamos trabajando, y no queremos ver lo
que ocurre en el resto de procedimientos llamados, lo que debemos hacer es pulsar Shift+F8.
CTRL+F8
Si lo que pulsamos es Ctrl+F8 lo que hace el código es llegar hasta donde tengamos situado el
cursor.
y sitúo el cursor sobre la línea del IF, y pulso Crtl+F8, el código se ejecutará hasta esa línea
del condicional.
21
Visítame en http://bit.ly/NckAccess
Aprovecho para comentaros que la mayoría de estas opciones también pueden realizarse con
el menú emergente del clic derecho del botón. Para este caso, por ejemplo,
De la misma manera, también tenemos esas opciones en el menú Depuración del VBE
CTRL+SHIFT+F8
Bueno… hemos pulsado un par de veces F8 y, visto el recorrido que nos interesaba y depurado
lo que se deba depurar, queremos continuar con la ejecución del código, pero sin ir a saltitos.
En ese caso basta con pulsar la combinación de teclas Ctrl+Shift+F8.
22
Visítame en http://bit.ly/NckAccess
Es decir, y partiendo de un punto de interrupción en la línea
de vHoy = Date , si en ese momento pulsamos susodicha
combinación de teclas veremos cómo el código se ejecuta y
llega, en este caso, al End Sub.
Como vemos, las variables a y b dependen de la fecha del sistema, y según se cumplan unos
requisitos marcados en el SELECT CASE, se realizan una serie de operaciones de adición y/o
multiplicación entre ellas o consigo mismas.
Para ir viendo qué valor están tomando en cada paso del código lo que haremos será añadir
una inspección. Así que nos iremos a menú → Depuración → Agregar inspección…
23
Visítame en http://bit.ly/NckAccess
También encontraremos esa opción en el menú emergente del clic derecho del ratón.
Se nos abrirá una ventana para configurar la inspección. Lo que haremos será controlar qué
pasa con la variable a, forzando la interrupción del código cada vez que se modifique su valor.
Tras eso veremos cómo nos aparece la ventana de inspección, que nos muestra información
sobre la variable a
Si ejecutamos el código veremos que se nos detiene y la ventana de inspecciones nos muestra
el valor 11, que es el día en que estoy escribiendo estas líneas.
Pulsamos F5 y nuestro código nos dice que, si es impar, a tiene que sumarse a sí misma.
24
Visítame en http://bit.ly/NckAccess
Y como es mayor que 10 pero menor que 25 entra en el
segundo select y se nos dice que a tiene que multiplicarse a
sí misma.
Ni que decir tiene que podemos añadir todas las inspecciones que queramos. Por ejemplo, tras
haber añadido la inspección de a puedo añadir la inspección de b.
Esa inspección puede hacerse tan compleja como deseemos. Supongamos que tenemos una
tabla con una lista de personas, y en nuestro código tenemos un recordset que las recorre.
Podríamos inspeccionar el valor que va tomando ese recordset, por ejemplo.
Agregamos una inspección sobre el recordset para saber qué valor está tomando como
identificador.
25
Visítame en http://bit.ly/NckAccess
Establecemos un punto de interrupción en rst.MoveNext, y ejecutamos el código
Si nos fijamos, vemos que el inspector nos dice que, en esta iteración, el identificador en la
tabla tiene el valor 1. Pero, además, a la derecha del icono de las “gafitas” podemos ver que
hay un signo “+”. Si hacemos clic y lo desplegamos podemos ver una gran cantidad de
información sobre el objeto recordset que estamos vigilando
26
Visítame en http://bit.ly/NckAccess
Y, a su vez, “Properties” permite su despliegue, y los elementos en su interior también
permiten despliegues, por lo que podemos analizar “hasta el último pelo” de nuestro recordset
(el último pelo porque los recordsets no se depilan, claro).
INSPECCIONANDO CONDICIONALMENTE
Finalmente, comentaros que podemos realizar una “inspección condicional” si pulsamos para
ello la opción correspondiente.
Podemos añadir una inspección condicional sobre la variable i y forzar la interrupción de código
si la condición es verdadera.
27
Visítame en http://bit.ly/NckAccess
Lógicamente, en nuestro bucle i sí pasa por el valor 8, así que al ejecutarlo obtendremos…
Si os fijáis, es más o menos la operación “al revés” que vimos utilizando debug.assert.
28
Visítame en http://bit.ly/NckAccess
Lo que hace esta ventana es mostrarnos qué valores están
tomando las variables locales, en primera instancia, pero
también nos permite cambiar su valor. Yo lo veo como una
especie de “qué pasaría si...”.
Sacamos la ventana de variables locales y ejecutamos el código. Veremos que tenemos estos
valores:
Seguimos con la ejecución de código (pulsando F5) y vemos que, tras el análisis del IF, sus
valores han cambiado a:
En función del apartado anterior, ya sabemos que el SELECT CASE hace que a se multiplique
por sí misma, obteniendo un valor de 484. De hecho, si continuáramos con la ejecución de
29
Visítame en http://bit.ly/NckAccess
código veríamos que la ventana de locales nos lo mostraría.
Pero, por los motivos que sean, yo quiero saber qué pasa si
a tomara un valor de 10. Para ello, me voy a la ventana
locales, hago clic sobre el valor 22 y lo cambio a 10.
Y si mi código hace lo que se espera de él, el resultado final de a debería ser 100. Pulsamos F5
para reanudar la ejecución del código y obtenemos:
Lo mismo puede decirse si queremos, también según el ejemplo del apartado anterior, vigilar
el recordset (pero eso es un poquito más trabajoso).
Si despliego el elemento “Fields”, y a su vez el segundo ítem (el campo 2, con índice 1), puedo
ver que el valor de persona que está tomando es “Coco”
30
Visítame en http://bit.ly/NckAccess
PARA FINALIZAR ESTA MINI-GUÍA
Bueno… Pues ya hemos finalizado esta mini-guía, donde he intentado mostrar algunas
herramientas que tenemos para ayudarnos en la depuración de nuestros códigos y en la
detección y subsanación de errores.
Poco más me queda por añadir. Solo desear que alguna de las cosas explicadas aquí os puedan
ser de utilidad.
Un saludo, y…
¡suerte!
31
Visítame en http://bit.ly/NckAccess