Pasa Programación, apuntes y soluciones con Access
Página principal Mis apuntes de Access Mis utilidades Mis ejemplos Mis agradecimientos Enlaces a otras Webs

Fallos en Access

  1. Índice.
  2. Usar palabras reservadas.
  3. Usar caracteres especiales.
  4. Módulo y función con el mismo nombre.
  5. Bucles recursivos.
  6. Dejar objetos abiertos.
  7. Bibliografía.

Bucles recursivos

Los bucles recursivos, o bucles sin fin, se producen cuando el código que estamos usando, entran en un ciclo que se repite indefinidamente. Si tenemos suerte, al cabo de cierto tiempo se producirá el error 6 (desbordamiento), o el error 28 (no hay suficiente espacio de pila). Pero si el código no hace que se dispare algún error, se seguirá ejecutando indefinidamente.

Veamos el siguiente código:

Function UnProcedimiento() As Long
    Dim i As Integer
    Dim l As Long

    Do While i < 2
        l = l + 1
    Loop

    UnProcedimiento = l
End Function

En esta función, se dimensionan dos variables, y después se usa un bucle del tipo Do While ... Loop para incrementar una de las variables, mientras que la otra no llegue a un determinado valor. Finalmente, se devuelve el valor de la variable que se ha incrementado. ¿Qué ocurrirá cuando ejecutemos la función? Que después de un tiempo, obtendremos el error 6: Desbordamiento. Esto se debe a que la variable que nos sirve para controlar el bucle, no modifica su valor en ningún momento: siempre vale cero. Y como cero es menor que dos, se ejecuta el bucle indefinidamente, o casi. Y es casi porque, como incrementamos el valor de la segunda variable constantemente, llega un momento en que la variable no puede almacenar el valor que queremos. Pero si no incrementaramos el valor, podríamos obtener un ciclo o bucle sin fin, que se ejecutase indefinidamente en el tiempo, y sin acabar nunca.

Veamos otro ejemplo, en el que usamos un objeto DAO.Recordset para recoger unos registros de una tabla y actualizarlos:

Public Sub MalaActualizacion()
    Dim rst As DAO.Recordset
    Dim strSql As String
    Dim strCampo As String

    strSql = "SELECT Campo2 FROM Tabla1"
    Set rst = CurrentDb.OpenRecordset(strSql)

    Do While Not rst.EOF
        strCampo = "Modificado"

        rst.Edit
        rst("Campo2") = strCampo
        rst.Update
    Loop

    rst.Close
    Set rst = Nothing
End Sub

En este código, cargamos un conjunto de registros para modificar uno de sus campos. En un principio, parece que está bien, pero no es así. Si ejecutamos el procedimiento, se ejecutará indefinidamente, y no se parará ni por error, hasta que nos cansemos y decidamos parar la ejecución mediante la combinación de teclas CTRL+INTER. ¿Y por qué? Porque entramos en el bucle, indicando que queremos estar dentro de él mientras no lleguemos al final del conjunto de registros (propiedad rst.EOF). Pero nunca cambiamos de registro dentro del bucle, con lo que siempre modificamos el primer registro. Si después de interrumpir el código, revisamos la tabla, veremos que, efectivamente, sólo se ha modificado el primer registro, pero no los demás. Cuando usamos bucles que se ejecutan mientras no se cumple la condición del bucle, tenemos que comprobar que dentro del bucle hemos colocado la instrucción necesaria para poder salir de el. En este caso, tenemos que usar la instrucción rst.MoveNext para cambiar de registro y poder llegar al final, mientras que en el primer ejemplo, hay que asignarle a la variable i un valor que sea mayor que dos.

Además de los bucles sin fin, también existen las funciones recursivas, o funciones que se llaman a sí mismas para realizar lo que deseamos. El ejemplo más manido de este tipo de funciones es la función para calcular el factorial de un número. El factorial es el número que se genera al multiplicar un número por los números menores que él, hasta llegar a uno. Es decir, el factorial de 4 es 4 x 3 x 2 x 1 = 24. Así, podemos crear una función que devuelva el resultado de multiplicar el número que reibe por el resultado de sí misma por el número menor:

Public Function Factorial(UnNumero As Long) As Long
    If UnNumero > 12 Then
        Factorial = -1
    ElseIf UnNumero < 0 Then
        Factorial = 0
    ElseIf UnNumero <= 1 Then
        Factorial = 1
    Else
        Factorial = UnNumero * Factorial(UnNumero - 1)
    End If
End Function

Si nos fijamos en esta función, lo primero que hacemos es controlar el número que se recibe: si el número es mayor que doce, se devuelve -1 directamente, porque el factorial que se genera es demasiado grande para almacenarlo en un número de tipo entero largo. Si el número es negativo (menor que cero), se devuelve cero directamente, ya que no se pueden calcular los factoriales de números negativos (restando de 1 en 1 a un número negativo, nunca se llega a 1 positivo). Cuando el número que se recibe es uno, se devuelve uno, porque hemos llegado al último número que sirve para generar el factorial. Y, para el resto de números, se multiplica el número recibido por el resultado de la propia función, enviándole el número menos uno. Es decir, cuando creamos una función que se llama a sí misma, al igual que con los bucles, debemos tener en cuenta más datos de los normales, para conseguir que en ninguna circunstancia, se que la función llamándose a sí misma indefinidamente. Si no tenemos en cuenta todos los datos, obtendremos el error 28: espacio de pila insuficiente. Y la pila no es una batería de 12 voltios. Es una zona de la memoria del ordenador, donde se almacenan las funciones que se están ejecutando, y en qué orden se ejecutan. Si nos aparece este error, es porque estamos usando tantas funciones, o una función se ha llamado a sí misma tantas veces, que llega un momento en que la pila no tiene espacio para almacenar todas las funciones que se están ejecutando, y por eso salta este error.

Bucle sin fin en formulario

Pero hay que tener en cuenta otra cosa: los bucles sin fin no se producen sólo cuando trabajamos con VBA: también se pueden producir cuando diseñamos una consulta, un formulario o un informe. Supongamos que tenemos un formulario (FormBucle en la base de datos de ejemplo), con 3 cuadros de texto. Y cada cuadro de texto recoge el dato que tiene el cuadro de texto anterior y, tras operar con él, devuelve el resultado. Si no cerramos el bucle (el primer cuadro de texto no toma el dato del último), no ocurrirá nada grave. Pero si el primer cuadro de texto toma el dato del tercero, obtendremos un #Error en todos los cuadros de texto, tal y como se ve en la imagen. Esto es debido a que cada cuadro de texto actualiza su valor dependiendo de otro y, como siempre se actualizan, siempre se generan nuevos valores y vuelven a actualizarse, con lo que Access detecta el error y muestra ese mensaje. Si a cualquiera de los 3 cuadros de texto le quitamos el valor que tiene en su propiedad Origen del registro, dejaremos de tener un bucle sin fin, y aparecerán los valores correctamente.

2008 Patxi Sanz
Libro de visitas
Hosted by www.Geocities.ws

1