Varios Filtros para Subformulario desde Formulario

Buenos días Neckkito.
Te hago una consulta a ver si me puedes ayudar.
Tengo una base de datos de Proyectos en los que tengo muchos registros.
Necesito hacer un formulario que funcione como filtrador de proyectos y la idea que tengo es:
Quiero tener un formulario que contenga un subformulario en forma de hoja de datos.
Quiero que inicialmente me aparezcan en el subformulario todos los proyectos y quiero poner 4 combos en el formulario principal de forma que conforme voy seleccionado criterios me va filtrando la hoja de datos y elimando proyectos que no cumplan.
Por ejemplo, abro el formulario y tengo los 4 combos vacíos, y en el subformulario hoja de datos aparecen todos los proyectos. En el combo 1 selecciono empeado 1 y entonces en el subformulario desaparecen los proyectos que no gestiona el empleado 1. Ahora en el combo 2 selecciono "proyecto activo" en el el subformulario desaparecen todos los proyectos del empledo 1 que no están activos, etc.
¿Es posible hacerlo?
Muchas gracias de antemano por tu ayuda.
Un saludo.

1 Respuesta

Respuesta
1
Si fuera un sólo combo la cosa sería muy sencilla. Al estar involucrados cuatro combos se multiplican las posibilidades de que te aparezcan errores por todas partes.
Déjame un poco de tiempo para que pueda encontrar alguna solución óptima (si puedo).
Te digo cosas lo más rápido posible.
Muchas Gracias Neckkito
Si se te ocurre alguna forma alternativa de montarlo no tengo inconveniente a plantearlo de otra forma.
Creo que sería sencillo pidiendo a la consulta en la que se basa el subformulario que filtre cada campo por el dato del combo que le corresponda. Lo único que se me escapa ahí es que a falta de dato en el combo no aplique filtro. Al probar esta forma si no pongo ningún dato en el combo la consulta no arroja ningún dato.
En cualquier caso espero tu respuesta.
Gracias.
Te explico cómo hacer lo que me pides a través de un ejemplo. Así podrás ver el tratamiento si el tipo de dato es numérico, texto o booleano. El sistema de selección es progresivo. Esto significa que la selección de los combos funciona según el orden combo1, combo2, combo3 y combo4. No creo que tengas ningún problema en adaptar el ejemplo a lo que tú tengas en tu BD.
Vamos allá:
He creado una tabla con estos campos:
Id: autonumérico
Empleado: numérico
Jefe: numérico
Proyecto: texto
Aprobado: Sí/No
He creado un formulario y dentro he metido un subformulario (llamado subFrmResultado) que recoge los datos de la tabla anterior. En ese mismo formulario he creado los siguientes combos:
CboEmpleado-> Recoge el número de empleado
cboJefe-> Recoge el número de jefe
cboProyecto-> Recoge el valor del campo proyecto
cboAprobado-> Recoge dos valores: -1 para Sí y 0 para No
Sacas las propiedades de los tres últimos y, en la pestaña Datos, le asignas
el valor NO a la propiedad "Activado"
También he creado un botón de comando en el formulario, de titulo "Restablecer valores", y de nombre cmdRestablece.
Para evitar comportamientos de teclado inesperados le he quitado el punto de tabulación al subformulario.
Ok. Seleccionas el cboEmpleado y al evento "Después de actualizar" le he puesto el siguiente código:
---
Private Sub cboEmpleado_AfterUpdate()
Dim valorEmpleado As Variant
Dim miFiltro As String
valorEmpleado = Me.cboEmpleado.Value
If IsNull(valorEmpleado) Then Exit Sub
miFiltro = "[Empleado] = " & valorEmpleado
Me.subFrmResultado.Form.Filter = miFiltro
Me.subFrmResultado.Form.FilterOn = True
Me.subFrmResultado.Form.Requery
Me.cboJefe.Enabled = True
Me.cboJefe.SetFocus
End Sub
---
Ahora seleccionamos el cboJefe y al evento "Después de actualizar" le asignas el siguiente código
---
Private Sub cboJefe_AfterUpdate()
Dim valorEmpleado, valorJefe As Variant
Dim miFiltro As String
valorEmpleado = Me.cboEmpleado.Value
valorJefe = Me.cboJefe.Value
If IsNull(valorJefe) Then Exit Sub
miFiltro = "[Empleado] = " & valorEmpleado & _
" And [Jefe] = " & valorJefe
Me.subFrmResultado.Form.Filter = miFiltro
Me.subFrmResultado.Form.FilterOn = True
Me.subFrmResultado.Form.Requery
Me.cboProyecto.Enabled = True
Me.cboProyecto.SetFocus
End Sub
---
Le toca el turno a cboProyecto (ojo con el filtro -miFiltro-, que este es un valor String)
---
Private Sub cboProyecto_AfterUpdate()
Dim valorEmpleado, valorJefe As Variant
Dim valorProyecto As Variant
Dim miFiltro As String
valorEmpleado = Me.cboEmpleado.Value
valorJefe = Me.cboJefe.Value
valorProyecto = Me.cboProyecto.Value
If IsNull(valorProyecto) Then Exit Sub
miFiltro = "[Empleado] = " & valorEmpleado & _
" And [Jefe] = " & valorJefe & _
" And [Proyecto] = '" & valorProyecto & "'"
Me.subFrmResultado.Form.Filter = miFiltro
Me.subFrmResultado.Form.FilterOn = True
Me.subFrmResultado.Form.Requery
Me.cboAprobado.Enabled = True
Me.cboAprobado.SetFocus
End Sub
---
Lo mismo para cboAprobado
---
Private Sub cboAprobado_AfterUpdate()
Dim valorEmpleado, valorJefe As Variant
Dim valorProyecto, valorAprobado As Variant
Dim miFiltro As String
valorEmpleado = Me.cboEmpleado.Value
valorJefe = Me.cboJefe.Value
valorProyecto = Me.cboProyecto.Value
valorAprobado = Me.cboAprobado.Value
If IsNull(valorAprobado) Then Exit Sub
miFiltro = "[Empleado] = " & valorEmpleado & _
" And [Jefe] = " & valorJefe & _
" And [Proyecto] = '" & valorProyecto & "'" & _
" And [Aprobado] = " & valorAprobado
Me.subFrmResultado.Form.Filter = miFiltro
Me.subFrmResultado.Form.FilterOn = True
Me.subFrmResultado.Form.Requery
End Sub
---
Finalmente nos queda el botón de comando. El siguiente código lo aplicamos al evento "Al hacer click":
---
Private Sub cmdRestablece_Click()
Me.subFrmResultado.Form.FilterOn = False
Me.subFrmResultado.Form.Requery
Me.cboEmpleado.Value = Null
Me.cboEmpleado.SetFocus
Me.cboJefe.Value = Null
Me.cboJefe.Enabled = False
Me.cboProyecto.Value = Null
Me.cboProyecto.Enabled = False
Me.cboAprobado.Value = Null
Me.cboAprobado.Enabled = False
End Sub
---
Y eso es todo. Ahora en teoría te debería ir filtrando en función de los valores que, secuencialmente, vayas eligiendo.
Si tienes algún problema o quieres que te explique alguna cosa con más detalle me lo comentas.
Por cierto, mañana parto de viaje hasta el viernes. Si me volvieras a consultar y ves que no contesto te pido un poquito de paciencia.
Estimado Neckkito,
Una vez más me sorprendes con tu respuesta. Gracias.
Una duda: ¿Sólo funcionaría si voy seleccionado combo por combo?
¿Si quiero dejar un combo en blanco para que no filte por él se pararía el código verdad?
De nuevo muchas gracias por tu ayuda.
Saludos.
Mejor me presento: me llamo Miguel ;)
Efectivamente, como comentas, el código no te funcionaría porque está pensado para ser ejecutado de forma secuencial.
Ya me había planteado el tema de realizar las consultas "jugando" con los diferentes combos, pero la solución que he llegado a pensar requiere un trabajo enorme. El problema está en que las combinaciones posibles de cuatro elementos son elevadas.
De todas maneras te comento la solución que yo había pensado, por si te animas a desarrollarla.
En el evento "Después de actualizar" de cada combo se debería poner un procedimiento que "codificara" la situación de los combos, y tener una variable que guardara esa codificación. Por ejemplo:
- Si combo1 vacío / combo2 vacío / combo3 vacío y valor en combo 4 la combinación podría ser "0001". Y así para todas las combinaciones posibles. En código esto vendría a ser:
---
Dim combinación As String
If IsNull(cbo1) And IsNull(cbo2) And IsNull(cbo3) Then
     combinación = "0001"
End If
---
Como te puedes imaginar, deberías poner todos los IF necesarios para conseguir todas las combinaciones: 0001 / 0010 / 0100 / 1000/ 0011 / 0101 / 1001 / etc
Una vez obtenida la combinación de combos pasar esa variable "combinación" a un procedimiento alojado en un módulo (por ejemplo, "Call subCombinacion (combinación)"
En el módulo se tendría que dictaminar el comportamiento para cada una de las combinaciones. Algo así como:
---
Public Sub subCombinacion(ValorCombinacion As String)
Select Case ValorCombinación
   Case "0001"
       'Código
   Case "0010"
       'Código
   Etc
End Select
---
La parte de código sería muy parecida al código que te he pasado antes, pero adaptado a cada circunstancia y a que estás operando desde un módulo, y no desde el propio formulario (el Me. Ya no funcionaría!).
Como podrás ver (o intuir) el "currete" que llevaría esto sería importante.
Pero, como siempre, si quieres intentarlo y tienes problemas me lo comentas y le echamos un vistazo.
Un gran saludo, y ánimo!
Buenas Noches Miguel,
Me alegro mucho de conocerte, mi nombre es Joaquín.
Ya se que me estoy poniendo un poco pesado, pero con esta ultima aclaración ya cierro la pregunta.
Tu última explicación abre un nuevo mundo pero como dices me parece demasiado laborioso.
He pensado una forma que haría que fuese muy sencillo pero no sé si se puede. Te lo planteo y si puedes me contestas y no doy más la vara con este tema.
Hago una consulta con los campos que me interesan como origen del subformulario.
En el formulario pongo los 4 combos que me interesan y ahora en el campo criterio de la consulta en la que se basa el subformulario quería poner una función SiInm con los valores:
Expresión: Forms! Subformulario!Combo1 Es Negado Nulo (Si hay algún dato en combo1)
Parte Verdadera: Forms! Subformulario!Combo1 (si lo hay aplicar el dato de combo 1 como filtro)
Parte Falsa: Es Negado Nulo (No sé qué poner aquí pero quiero que si en el combo 1 no hay ningún dato que la consulta muestre todos los datos de ese campo).
Lo intento pero cuando en el combo1 no hay ningún dato la consulta no arroja ningún valor, en lugar de todos.
Bueno, ahí dejo eso.
Muchas gracias por tu ayuda Miguel, eres un Crack!
Un Saludo!
¡Eres un iluminado! ;)
Por deformación profesional uno sólo piensa en código VBA, y a veces te olvidas de que Access tiene otras herramientas que pueden facilitarte la vida, como es el caso. Me acabo de dar un par de coscorrones contra la pared por tonto :)
Lo que comentas no sólo es una fantástica idea, sino que lo acabo de testear con dos combos y funciona de maravilla. Imagino que con cuatro funcionará igual de bien.
Te explico (la explicación sigue en base al ejemplo que te ponía en una de las respuestas) cómo hacerlo (aunque tú ya lo sabes mejor que yo!) ;)
Creas una consulta con los campos que quieres, incluidos los que vas a filtrar con los combos. El subformulario estará basado en esa consulta.
El código que debes poner en los combos, en el evento "después de actualizar", es, simplemente:
---
Private Sub cboEmpleado_AfterUpdate()
    Me.subFrmResultado.Form.Requery
End Sub
---
OK. Y, volviendo a la consulta, los criterios que debes ponerle a cada uno de los campos que se relacionan con los combos del formulario son, en abstracto:
SiInm(EsNulo(Combo1); Todos los campos de la TABLA <NombreTabla>; Los campos filtrados de la tabla)
Te copio los dos criterios que he testeado yo. Te será muy fácil adaptarlos a tu BD:
Para el campo Empleado:
SiInm(EsNulo([Formularios]![Form2]![cboEmpleado]. [value]);[Tabla1]! [Empleado];[Formularios]![Form2]![cboEmpleado].[value])
Para el campo Jefe:
SiInm(EsNulo([Formularios]![Form2]![cboJefe]. [value]);[Tabla1]! [Jefe];[Formularios]![Form2]![cboJefe].[value])
Donde Form2 es el nombre del formulario principal, y Tabla1 es el nombre de la tabla que contiene la información que quieres.
Ya me dirás si te ha ido bien.
Ah! Por cierto, mi correo es [email protected], por si lo necesitas para "futuras experiencias" ;)
Un gran saludo.
Hola Miguel,
Anoche terminé el formulario de filtro de Proyectos con la solución de los filtros en la consulta, con lo 4 combos de filtrado como me indicabas.
Es una pasada!, inicialmente salen todos los proyectos y conforme vas seleccionando criterios en los combos va filtrando los datos. Y si no quieres filtrar por alguno de ellos lo dejas en blanco y arreglado.
Muchas Gracias Miguel por el interés que me has prestado y por las fantásticas soluciones que me planteas.
Me guardo tu correo aunque espero no ser demasiado plasta con las consultas. Insisto, ERES UN CRACK!

Añade tu respuesta

Haz clic para o

Más respuestas relacionadas