Realizar diferentes filtros sobre un formulario

Estoy montando una base de datos para control de calidad.

Tengo una tabla con 60000 registros. He creado un formulario con una serie de botones de opción con el evento al hacer clic ejecutan una macro de filtro. Tengo dos problemas:

1. Cuando selecciono el primer botón de opción me realiza el filtro correctamente, pero cuando marco el siguiente botón de opción para filtrar por otro criterio no me realiza el filtro sobre lo ya filtrado anteriormente, me lo hace del total de registros. Necesitaría que los botones realizaran filtros sobre lo filtrado con el botón anterior, es decir, y reduciendo de 60000 registros hasta quedarme con unos pocos con características similares para poder analizarlo.

2. El formulario esta en modo formulario único, y al pasar de registro los botones de opción se quedan marcados con la selección que realicé en el registro anterior. Necesitaría que estos botones volvieran a estar desmarcados para poder realizar de nuevo los filtros que quisiera

Espero que se entienda la explicación porque es algo enrevesada. Seguramente el planteamiento sea muy deficiente pero mis conocimientos sobre Access no me han permitido encontrar una mejor solución.

1 Respuesta

Respuesta
2

Sin ver cómo tienes montado tu formulario, sólo te puedo dar unas indicaciones "generales".

Para resolver el primer problema, lo que has de hacer es encadenar los filtros. Para eso has de quitar las macros que tienes asociadas y hacer los filtros por código.

La mejor opción es que crees un procedimiento que analice el estado de cada botón de opción, y en función de eso crees el filtro. Sería algo así:

Private Sub Filtrar()
Dim miFiltro as String
'Inicias el Filtro
miFiltro=""
'Analizas los botones
If Me.Opcion1=-1 Then  'El -1 indica que el botón está activado
    miFiltro=miFiltro & " AND [Campo1]=Criterio"
End If
If Me.Opcion2=-1 Then  'El -1 indica que el botón está activado
    miFiltro=miFiltro & " AND [Campo2]=Criterio"
End If
....
'Eliminas el primer 'AND '
If len(miFiltro)> 0 Then
    miFiltro = Right(miFiltro, len(miFiltro) - 5)
End If
'Aplicas el filtro al formulario
Me.Filter = miFiltro
Me.FilterOn = True
End Sub

Este código lo pondrás en el módulo asociado a tu formulario, y en el evento "despues de actualizar" de cada botón de opción, le generas este otro código:

Private Sub ..._AfterUpdate()

        Filtrar

End Sub

Al código del procedimiento anterior le has de hacer los siguientes "ajustes":

1º/ Sustituir Opcion1, Opcion2... por los nombres de tus botones

2º/ Sustirtuir [Campo1]=Criterio, [Campo2]=Criterio... por el nombre del campo y el criterio que vayas usar para filtrar, teniendo en cuenta el tipo de datos del campo, por ejemplo:

[Edad]>=18  -> Campo de tipo numérico

[Sexo]='Varón'  -> Campo de tipo texto

[FechaBaja]>#01/06/2015#  -> Campo de tipo Fecha/Hora

Ups, me olvidé de la segunda parte...

Si no entendí mal, lo que intentas hacer y te da el problema 2 no tiene sentido:

Si filtras tus 60000 registros por los criterios que sean, sería mucho suponer que sólo te devuelva un registro, o que el que busques de los que te devuelva sea el primero, por lo que si al cambiar de registro se te "reinician" los botones de opción y con ellos el filtro, de poco te sirvió hacer el filtro.

Lo que puedes hacer para resetear el filtro y los botones es añadir un botón "Quitar filtro", con este código asociado:

Private Sub ..._Click()

Me.Opcion1=0

Me.Opcion2=0

...

Me.FilterOn=False

End If

Para que veas más clara la sistemática, te preparé este mini-ejemplo: http://www.filebig.net/files/C4GTQJrz4b

¡Gracias! 

Mil gracias por la rapidez de la respuesta y sobre todo por el contenido de ella. Es justo lo que necesito. 

Voy a montarlo en mi bbdd y te cuento que tal me funciona.

Me parece un auténtico lujo que alguien te ayude de forma desinteresada con esta calidad de respuesta.

Enhorabuena de verdad!!!

Buenas tardes, de nuevo por aquí. He empezado a montar tu código en mi base de datos.

Me encuentro algunos problemas, que serán por mi desconocimiento en la materia (estoy empezando con VBA).

En la base de datos que me envías todos los campos a filtrar son de tipo texto, pero ¿cómo sería si hubiera campos texto y campos numéricos a filtrar? Habría que definir distintas variables no? Perdona mi absoluto desconocimiento.

Tampoco entiendo muy bien la siguientes sintaxis:

'Eliminas el primer 'AND 'If len(miFiltro)> 0 Then    miFiltro = Right(miFiltro, len(miFiltro) - 5)End If

¿Qué es lo que realmente hace?

En cuanto a la segunda parte de la consulta que te hice, volviendo a leer, veo que me explique fatal. Lo siento.

Te explico:

Tengo una tabla con 60.000 registros, 

Un formulario con una serie de botones de opción y cuadros combinados para ir realizando filtros, para quedarme con un grupo determinado de registros que son 

los que voy a auditar. Sobre cada uno de esos registros estableceré una serie de puntuaciones, comentarios, etc.

Una vez terminada la auditoría de esos registros vuelvo de nuevo a la zona de filtros y me gustaría tener un botón para que además de quitar los filtros y volver a tener 60.000 registros (eso ya me funciona con tu código, mil gracias) haga que todos los botones de acción se queden desmarcados para no tener que ir uno por uno desmarcándolos para elegir de nuevo los filtros que desee. 

Mil gracias por todo de verdad

Si son distintos tipos de datos, lo tienes explicado en mi primera respuesta, y cito:

2º/ Sustituir [Campo1]=Criterio, [Campo2]=Criterio... por el nombre del campo y el criterio que vayas usar para filtrar, teniendo en cuenta el tipo de datos del campo, por ejemplo:

[Edad]>=18  -> Campo de tipo numérico

[Sexo]='Varón'  -> Campo de tipo texto

[FechaBaja]>#01/06/2015#  -> Campo de tipo Fecha/Hora

Eso implica que si el código que te puse los 3 botones sirvieran para filtrar por esos criterios, quedaría así:

Private Sub Filtrar()
Dim miFiltro as String
'Inicias el Filtro
miFiltro=""
'Analizas los botones
If Me.Opcion1=-1 Then  'El -1 indica que el botón está activado
    miFiltro=miFiltro & " AND [Edad]>=18"
End If
If Me.Opcion2=-1 Then  'El -1 indica que el botón está activado
    miFiltro=miFiltro & " AND [Sexo]='Varón'"
End If
If Me.Opcion3=-1 Then  'El -1 indica que el botón está activado
    miFiltro=miFiltro & " AND [FechaBaja]>#01/06/2015#"
End If
'Eliminas el primer 'AND '
If len(miFiltro)> 0 Then
    miFiltro = Right(miFiltro, len(miFiltro) - 5)
End If
'Aplicas el filtro al formulario
Me.Filter = miFiltro
Me.FilterOn = True
End Sub

pero no tienes que declarar ninguna variable nueva.

La parte del código que no entiendes, significa que al ir encadenando la variable miFiltro (se inicia vacía: miFiltro=""), se va haciendo como si ya hubiera un criterio de filtro, y por eso se encadena con un "AND" (miFiltro = miFiltro & " AND ...")

Si no le borramos el primer AND, y los espacios hasta llegar al campo que se va a filtrar, al aplicar el filtro al formulario dará un error de código, por eso es que se elimina con ese bloque IF.

Te dejo este enlace, donde puedes ver una explicación más detallada, para una sistemática de filtros similar. En esa web, además tienes excelentes manuales y ejemplos.

Mil gracias por la información ahora me queda mucho más claro. 

He reproducido tu código en mi  bbdd

Private Sub Filtrar()

Dim miFiltro As String

miFiltro = ""

If Me.opcion1101 = -1 Then

miFiltro = miFiltro & "And [motivo]=1101"

End If

If Me.opcion1102 = -1 Then

miFiltro = miFiltro & "And [motivo]=1102"

End If

If Me.opcion1103 = -1 Then

miFiltro = miFiltro & "And [motivo]=1103"

End If

If Len(miFiltro) > 0 Then

miFiltro = Right(miFiltro, Len(miFiltro) - 5)

End If

Me.Filter = miFiltro
Me.FilterOn = True

pero me da el siguiente error:

Error de sintaxis en la expresion de consulta 'motivo]=1101AND[motivo]=1102'

Perdona mi torpeza pero como te dije soy un novato en VBA

Gracias!!!

Tienes que dejar un espacio en blanco entre las comillas y el AND. Fíjate bien en el código del ejemplo.

De nuevo aquí, ya me funciona!!! Por fin!!!!

El problema estaba en la longitud del filtro -5

Sigo montando.... ya te contaré!!!

Buenas de nuevo, me da un poco de vergüenza escribir otra vez, pero al intentar crear el código para otros botones que tengo me da error. El código es el siguiente:

Private Sub Filtrar()

Dim miFiltro As String

miFiltro = ""

If Me.opcion1101 = -1 Then

miFiltro = miFiltro & " AND [motivo]=1101"

End If

If Me.opcion1102 = -1 Then

miFiltro = miFiltro & " AND [motivo]=1102"

End If

If Me.opcion1103 = -1 Then

miFiltro = miFiltro & " AND [motivo]=1103"

End If
If Me.opcion1104 = -1 Then

miFiltro = miFiltro & " AND [motivo]=1104"

End If

If Me.opcion1105 = -1 Then

miFiltro = miFiltro & " AND [motivo]=1105"

End If

If Me.opcion1106 = -1 Then

miFiltro = miFiltro & " AND [motivo]=1106"

End If

If Me.opcion1107 = -1 Then

miFiltro = miFiltro & " AND [motivo]=1107"

End If

If Me.opcion1108 = -1 Then

miFiltro = miFiltro & " AND [motivo]=1108"

End If

If Me.opcion1109 = -1 Then

miFiltro = miFiltro & " AND [motivo]=1109"

End If

If Me.opcion1110 = -1 Then

miFiltro = miFiltro & " AND [motivo]=1110"

End If

If Me.opcion1111 = -1 Then

miFiltro = miFiltro & " AND [motivo]=1111"

End If

If Len(miFiltro) > 0 Then

miFiltro = Right(miFiltro, Len(miFiltro) - 13)

End If

Me.Filter = miFiltro
Me.FilterOn = True

End Sub

Se ha producido el error 3709 en tiempo de ejecución:

La clave de búsqueda no se encontró en ningún registro

Gracias por todo!!

Solucionado, acabo de entender el valor de Len(miFiltro) en mi caso es -4

Perdona loas molestias

No hay nada que disculpar, lo interesante es que aprendas de las soluciones propuestas para que lo puedas ir adaptando a tus necesidades.

¡Gracias

Para terminar de comprender la sintaxis completa, que significa exactamente el valor -4?

Seguro que tendré que recurrir más veces a ti, porque lo que quiero montar es bastante complejo

Te explico brevemente:

La función Len() devuelve el número de caracteres de lo que está entre paréntesis, en el código la longitud de la cadena de texto miFiltro.

La función Right() recorta una cadena de texto los x caracteres que le indiques por la derecha. La expresión: Right(miFiltro, Len(miFiltro) - 4), significa que cojas, de la variable "miFiltro" los caracteres de la derecha que resultan de la totalidad de caracteres de dicha cadena -4, o lo que es lo mismo, elimina los 4 primeros caracteres de la izquierda.

Si en el editor de VBA pones el ratón sobre una palabra y pulsas F1, te saldrá la ayuda, con una explicación y ejemplos de uso (normalmente bastante buenos).

Estupendo, todo entendido!!!! Muchas gracias.

Otra pregunta, para que al hacer clic en un botón de opción me pregunte por que valor quiero filtrar, sería correcta esta sintaxis?

If Me.opcion_fecha_cierre = -1 Then

miFiltro = miFiltro & " AND [fecha_cierre]=[Introduce la fecha de cierre]"

End If

Muchas gracias!!!

Pues no sé si así te funcionaría o no (sería cuestión de que probaras...)

De todas formas, te comento cómo lo haría yo: usando un InputBox para preguntar el valor, algo así:

If Me.opcion_fecha_cierre = -1 Then

Dim miValor as Date 

miValor=InputBox("Introduce la fecha de cierre")

miFiltro = miFiltro & " AND [fecha_cierre]=#" & miValor & "#"  'Porque es una fecha lleva #

End If

¡Gracias! 

Alucino con la rapidez de tus respuestas!!!!

Me funciona perfectamente

No te imaginas lo mucho que me estás ayudando y lo mucho que estoy aprendiendo

Mil gracias de verdad

Acabo de probar tu código y me funciona correctamente, me aplica el filtro. El problema que surge es que tengo otro campo por el que tengo que filtrar de igual forma, y al clicar en el otro botón me sale el imputbox del anterior

If Me.opcion_fecha_cierre = -1 Then

Dim miValor As Date

miValor = InputBox("Introduce la fecha de cierre")

miFiltro = miFiltro & " AND [fecha_cierre]=#" & miValor & "#"

End If


If Me.opcion_fecha_apertura = -1 Then

Dim miFechaApertura As Date

miFechaApertura = InputBox("Introduce la fecha de apertura")

miFiltro = miFiltro & " AND [fecha_apertura]=#" & miFechaApertura & "#"

End If

Thanks!!!

Claro, te saldrá el inputbox siempre que se vayan cumpliendo las condiciones.

Para solucionarlo, se me ocurre esto, aunque implica que rehagas todo el código que hiciste hasta ahora sobre este tema...

1º/ En el encabezado del módulo, debajo de Option Compare Database Y Option Explicit (si te sale), escribe:

Public miFiltro As String

2º/ En el evento "Despues de actualizar" de cada botón, antes de llamar al procedimiento filtrar, pones el If que te crea la parte del filtro asociada a ese botón (los tienes en el procedimiento Filtrar), por ejemplo:

Private opcion_fecha_cierre_AfterUpdate()

If Me.opcion_fecha_cierre = -1 Then

Dim miValor As Date

miValor = InputBox("Introduce la fecha de cierre")

miFiltro = miFiltro & " AND [fecha_cierre]=#" & miValor & "#"

End If

Filtrar

End Sub

3º/ En el procedimiento Filtrar(), borra todo hasta la parte en que eliminas el primer AND, es decir, que te quede sólo así:

Private Sub Filtrar()

'Eliminas el primer 'AND '

If len(miFiltro)> 0 Then

    miFiltro = Right(miFiltro, len(miFiltro) - 5)

End If

'Aplicas el filtro al formulario

Me.Filter = miFiltro

Me.FilterOn = True

End Sub

A ver si así te resulta como quieres.

Buenas de nuevo, no te dejo en paz!!!

He intentado montarlo siguiendo tus instrucciones pero me da error. Seguro que es mucho pedir pero por no marearte más, sería posible que me enviaras un ejemplo del código con varios elementos diferentes para hacer filtros, por ejemplo un botón de opción que realice un filtro, luego un combox donde al elegir un valor me realice un nuevo filtro sobre el resultado anterior, y un botón de opción donde me salga un inputbox solicitandome que introduzca un valor para hacer un filtro sobre lo anterior.

Entiendo la sintaxis de forma individual pero creo que el problema lo tengo a la hora de encadenarlas todas.

Si puede ser te lo agradeceré de corazón, si no es posible, te doy las gracias por todo lo que me has ayudado y enseñado, para mi tiene un valor incalculable

http://www.filebig.net/files/RCNRfZkUng 

Yo de ti no usaría botones de radio para filtrar, a menos que puedas hacer esto: si está activado muestre un valor, si no lo está muestre todos. En mi opinión dan más juego para filtros los cuadros combinados.

Añade tu respuesta

Haz clic para o

Más respuestas relacionadas