Error 2471 al usar la función DCount

Al hacer un informe que genera problemas de matemáticas, quiero que se imprima solamente un registro, escogido de forma aleatoria. Para ello utilizo el siguiente código, pero me da error en la función DCount. En concreto el error 2471 (la expresión que ha especificado como parámetro de la consulta produjo el error 'aleatorio') .

La tabla tiene un campo autonumérico [Id], y otros campos más de texto: [primero], [segundo], [tercero]

Private Sub Report_Load()
Dim total As Integer            'Número total de registros en la tabla
Dim i As Integer                'Variable a usar en For Next
Dim aleatorio As Long           'Valor aleatorio que se generará
Dim registro As Integer         'total de registros donde [Id]=aleatorio
Dim Filtro As String            'Filtro que voy a utilizar
DoCmd.GoToRecord , , acLast
total = [Id]                    'total=valor del último registro
For i = 1 To 3000               'Repito muchas veces hasta que la variable "aleatorio" coincida con el valor de un campo [Id]
    Randomize
    aleatorio = Int(Rnd * total + 1)
    registro = DCount("[Id]", "Problemas_resta", "[Id] = aleatorio")
    If registro <> 0 Then
        Exit For
    End If
Next
MsgBox aleatorio
'Filtramos el registro donde el campo [Id]=aleatorio
    Filtro = "id LIKE aleatorio"  ' Asignamos el filtro a la variable
    Me.Filter = Filtro            ' Asignamos la varaible a la propiedad Filter del subformulario
    Me.FilterOn = True
End Sub

Por más vueltas que le doy, no consigue adivinar dónde está el problema. Sobre los filtros que hay más adelante, no sé si funcionan o tienen algún error.

Respuesta
1

Le recomiendo hacer el filtro antes de abrir el reporte desde el formulario, excepto si es una macro. Igualmente, no debe utilizar acLast si no está abierto un Rercordset . Pruebe con lo siguiente:

Cambie

total=Dmax("[id]","Problemas_resta")

¿Por qué, antes de abrir el reporte? Porque imagínese si su reporte tuviera 1 millón de registros tendría que cargar este número de registros, en cambio, si lo hace en origen de datos con una sentencia SQL o el la instruccion DoCmd OpenReport sería muchísimo más ágil.

Gracias Eduardo. He hecho el cambio que me ha dicho. Quitar

DoCmd.GoToRecord , , acLast

Y poner

total=Dmax("[id]","Problemas_resta")

No he podido probar si funciona, porque cuando ejecuto el informe me sale el "Error de compilación. No se ha definido el Sub o Function". Y ahí me he quedado bloqueado. Este error es nuevo y creo que no he tocado nada.

De todas formas, creo que la propuesta que me hace no me soluciona el problema. Voy a intentar expresarme mejor.

Tengo una tabla "problemas_resta" que contiene plantillas (textos) de problemas de matemáticas para generar fichas de forma aleatoria. Esa tabla la tengo cargada en la hoja de propiedades del informe, en "origen del registro".

Lo que quiero es que, si tengo, por ejemplo, 20 registros de posibles problemas hechos, escoja uno de ellos y lo imprima en una hoja.

Los registros tienen un campo autonumérico [Id], que es por donde haré el filtro para que solo ese registro esté activo y se imprima un único registro en la hoja. Tengo el problema de que el campo [Id] no va seguido del 1 al último registro porque, si borro alguno, ya no quedan consecutivos. Por ejemplo, la tabla puede estar así después de borrar algunos registros:

Registro 1: [Id]=1
Registro 2: [Id]=2
Registro 3: [Id]=5
Registro 4: [Id]=8

Por ello, lo que hago es calcular el valor más alto de [Id], luego busco un número aleatorio entre 1 y el valor más alto (en este caso 8) y hago un bucle for...next hasta que el valor aleatorio que se ha creado coincida con el valor de un campo [Id]. Es ahí donde uso

    registro = Dtotal("[primero]", "Problemas_resta", "[Id] = aleatorio")

Pero me da el error mencionado.

Una vez que tengo un valor que existe en la tabla, hago el filtro.

Sobre la construcción de los filtros, no sé si están bien hecha o no, porque access se ha parado en ese error.

Espero haberme explicado mejor.

Sobre el problema de compilación, ya lo he solucionado. Era una tontería. Pero el problema principal que estaba consultanto, sigue presente. Me sale error en:

    registro = DCount("[primero]", "Problemas_resta", "[Id] = aleatorio")

Hay algo que aclarar, si va a retirar registros no se puede tomar el id más alto, porque de acuerdo con su aclaración, si el más alto es id=8 y no hay sino 4 registros se generaría un número aleatorio superior a la cantidad de registros, entonces, se debe utilizar Dcount(). Algo como:

total=Dcount("*","Problemas_resta")

Ahora, no es necesario ejecutar 3000 veces un ciclo, puede reemplazarlo por un Do .. Loop

Do
Randomize
aleatorio = Int((total*Rn) + 1) 'Nro aleatorio entre el total de registros
registro = DCount("[Id]", "Problemas_resta", "[Id] =" & aleatorio)
Loop registro>0

Observe que tenía mal el condicional del [id], la variable aleatorio se debe concatenar

Igualmente sobra el LIKE porque no tiene sentido en valores numéricos, en este caso quedaría asi:

'Filtramos el registro donde el campo [Id]=aleatorio
Filtro = "id=" & aleatorio ' Asignamos el filtro a la variable
Me.Filter = Filtro ' Asignamos la variable a la propiedad Filter del subformulario
Me.FilterOn = True

Observe que tenía mal el Filtro. El valor de aleatorio no puede ir dentro se debe concatenar. De todas maneras personalmente no haría el filtro sobre el reporte sino antes.

Muchas gracias Eduardo. No sabe cuánto tiempo he dedicado buscando la solución hasta que me decidí a preguntar. Ahora sí funciona. Solo aclarar que me he dado cuenta que en el loop es

Loop until registro>0

La verdad es que mucho mejor que utilizar for... next. No se me había ocurrido.

En fin, muchas gracias por su ayuda.

Si que pena me falto la palabra until, me alegro le haya funcionado.

Añade tu respuesta

Haz clic para o

Más respuestas relacionadas