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
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!!
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.
- Compartir respuesta