VBA Access: Usar dos criterios para filtrar en diferentes combinaciones

Ampliando la respuesta en
VBA Access: DCOUNT con dos criterios
Ahora me surge la necesidad de filtrar bajo estos dos criterios en sus combinaciones posibles. De acuerdo a cómo desarrollé el código, ahora se me complica lograrlo.
Paso un link al ejemplo más claro de lo que tengo y necesito lograr.
El problema viene que, si filtro por un USUARIO muestra todos los tipos de acceso (DESCR) PEEEEROO, cuando intento filtrar un tipo de acceso (DESCR) para ese x usuario, me filtra solamente los tipos de acceso omitiendo el filtrado previo del usuario.
Y lo que necesito es que funcionen por separado pero si hay un valor en el otro filtro, se aplique a los resultados del primero (si muestro todos los tipos DESCR y luego quiero ver los DESCR de un usuario en particular, se añada dicho último filtro y lo mismo al revés. Espero que se entienda.
https://mega.nz/#!EJwgRQiT!hUR2Sq8fgRLcNCnKWK-v03fw1BrN_WtvtpBjH-9WRiY 
Para muestra basta un botón.

1 respuesta

Respuesta
1

Ahora no puedo revisar tu archivo, por problemas de compatibilidad con mi access y el archivo (no lo abre en 2007). Pero te doy un par de indicaciones a ver si logras solucionarlo:

1º/ Estas construcciones que haces:

Me.txt1.Value = DCount("*", "[US_HISTORIAL]", "[USUARIO] = txtUsuarioSelect And [DESCRIP] = 'Normal'")

son un tanto extrañas y no creo que te acaben de funcionar correctamente. Si txtxUsuarioSelect es un cuadro de texto de tu formulario, o lo pones:

"[USUARIO]='" & txtUsuarioSelect & "' And..."    'Suponiendo que sea un valor de texto, por eso las comillas simples

o lo pones:

"[USUARIO]= Forms.NombreFormulario.txtUsuarioSelect And..."

2º/ Si con el primer combo aplicas ya el filtro, es decir haces algo como:

Me.Filter="Usuario='" & Me.cboUsuario & "'"

En el segundo combo has de encadenar el filtro al ya existente, pues de otra forma te lo cargas:

If Me.Filter<>"" Then  'Si ya hay algun filtro, encadenas

Me.Filter=Me.Filter & " AND [OtroCampo]=" & Me.otroCombo

Else  'Si no lo hay, lo aplicas

Me.Filter="[OtroCampo]=" & Me.otroCombo

End If

Esto lo harías en todos los combos, para que de igual el orden en que los eliges.

Echa también un vistazo a este ejemplo de Neckkito, igual te da nuevas ideas: http://siliconproject.com.ar/neckkito/index.php/component/content/article/93-ejemplos-explicados/ejemplos-de-formularios/194-crear-un-filtro-multiple 

He logrado hacerla funciona, aunque cuando añado consultar por fechas, me arroja "No coinciden los tipos".

Dim vUsuario As String, vTipo As String, vFecha1 As Variant, vFecha2 As Variant, miFiltro As String
'Cogemos los valores que hayamos seleccionado como filtro
vUsuario = Nz(Me.lstFiltro1.Value, "")
vTipo = Nz(Me.lstFiltro2.Value, "")
vFecha1 = Nz(Me.txtFiltro3.Value, "")
vFecha2 = Nz(Me.txtFiltro4.Value, "")
'Inicilizamos el filtro
miFiltro = ""
'Creamos la 1 parte del filtro
If vUsuario <> "" Then
    miFiltro = "AND [USUARIO]='" & vUsuario & "'"
End If
'Creamos la 2 parte del filtro
If vTipo <> "" Then
    miFiltro = miFiltro & " AND [DESCRIP]= '" & vTipo & "'"
End If
'Creamos la 3 parte del filtro
If vFecha1 <> "" And vFecha2 <> "" Then
    miFiltro = miFiltro & " AND [INGRESO] BETWEN #" & Format(vFecha1, "mm/dd/yyyy") & "# AND #" & Format(vFecha2, "mm/dd/yyyy") & "#"
End If
'Ahora cogemos la longitud del filtro
vLargo = Len(miFiltro)
'Recomponemos el filtro eliminando el primer 'AND '
If vLargo > 0 Then
    miFiltro = Right(miFiltro, vLargo - 4)
End If
    MsgBox miFiltro
'Aplicamos el filtro al formulario
Me.Filter = miFiltro
Me.FilterOn = True

Supongo que es por las fechas, pero no sé cómo resolverlo.

Para filtrar 2 fechas, el operador es BETWEEN, y no betwen como tienes en el código.

Otra cosa que puedes probares convertir a fecha el valor variant de vfecha a tipo fecha, con la función cdate.

Apliqué la corrección sugerida y ha funcionado a la perfección.

'Asignamos los valores iniciales a las variables
    vUsuario = Nz(Me.lstFiltro1.Value, "")
    vTipo = Nz(Me.lstFiltro2.Value, "")
    vFecha1 = txtFiltro3 'Nz(Me.txtFiltro3.Value, "")
    vFecha2 = txtFiltro4 'Nz(Me.txtFiltro4.Value, "")
    If IsNull(vFecha1) Or IsNull(vFecha2) Then
    Else
        vFecha1 = CDate(vFecha1)
        vFecha2 = CDate(vFecha2)
    End If
'Inicilizamos el filtro
    miFiltro = ""
'Creamos la 1 parte del filtro
    If vUsuario <> "" Then
        miFiltro = "AND [USUARIO]='" & vUsuario & "'"
    End If
'Creamos la 2 parte del filtro
    If vTipo <> "" Then
        miFiltro = miFiltro & " AND [DESCRIP]='" & vTipo & "'"
    End If
'Creamos la 3 parte del filtro
    If IsNull(vFecha1) And IsNull(vFecha2) Then
    Else
        miFiltro = miFiltro & " AND [INGRESO] BETWEEN #" & vFecha1 & "# AND #" & vFecha2 & "#"
    End If
'Ahora cogemos la longitud del filtro
    vLargo = Len(miFiltro)
'Recomponemos el filtro eliminando el primer 'AND '
    If vLargo > 0 Then
        miFiltro = Right(miFiltro, vLargo - 4)
    End If
'Aplicamos el filtro al formulario
    Me.Filter = miFiltro
    Me.FilterOn = True
    Me.cmdLimpia.Visible = True
' Llama a otras partes
Call RECUENTO_INGRESOS
Call INFORMA

Ahora lo que debo revisar nuevamente es el conteo de los tipos (DESCR)  cuando está filtrado.
¿Hay alguna forma de basar el conteo en los resultados de los filtros?
Porque llamo al conteo y no me devuelve el recuento sino como si no hubiera filtrado nada o con resultados generales basados en USUARIO y/o DESCRIP solamente.

if isnull(lstfiltro1) then
    vuser = 0
else
    vuser = 1
end if
if isnull(lstfiltro2) then '.value = "" then
    vtipo = 0
else
    vtipo = 1
end if
if vuser = 1 and vtipo = 1 then
'    msgbox "usuario: sí / filtro: sí"
    vnor = dcount("*", "[us_historial]", "[usuario] = txtusuarioselect and [descrip] = 'normal'")
    vaut = dcount("*", "[us_historial]", "[usuario] = txtusuarioselect and [descrip] = 'autorizado'")
    vact = dcount("*", "[us_historial]", "[usuario] = txtusuarioselect and [descrip] = 'actualización'")
    vden = dcount("*", "[us_historial]", "[usuario] = txtusuarioselect and [descrip] = 'denegado'")
    vfal = dcount("*", "[us_historial]", "[usuario] = txtusuarioselect and [descrip] = 'fallido'")
    vfor = dcount("*", "[us_historial]", "[usuario] = txtusuarioselect and [descrip] = 'forzado'")
elseif vuser = 1 and vtipo = 0 then
'    msgbox "usuario: sí / filtro: no"
    vnor = dcount("*", "[us_historial]", "[usuario] = txtusuarioselect and [descrip] = 'normal'")
    vaut = dcount("*", "[us_historial]", "[usuario] = txtusuarioselect and [descrip] = 'autorizado'")
    vact = dcount("*", "[us_historial]", "[usuario] = txtusuarioselect and [descrip] = 'actualización'")
    vden = dcount("*", "[us_historial]", "[usuario] = txtusuarioselect and [descrip] = 'denegado'")
    vfal = dcount("*", "[us_historial]", "[usuario] = txtusuarioselect and [descrip] = 'fallido'")
    vfor = dcount("*", "[us_historial]", "[usuario] = txtusuarioselect and [descrip] = 'forzado'")
elseif vuser = 0 and vtipo = 1 then
'    msgbox "usuario: no / filtro: sí"
    vnor = dcount("*", "[us_historial]", "[descrip] = 'normal'")
    vaut = dcount("*", "[us_historial]", "[descrip] = 'autorizado'")
    vact = dcount("*", "[us_historial]", "[descrip] = 'actualización'")
    vden = dcount("*", "[us_historial]", "[descrip] = 'denegado'")
    vfal = dcount("*", "[us_historial]", "[descrip] = 'fallido'")
    vfor = dcount("*", "[us_historial]", "[descrip] = 'forzado'")
else 'vuser = 0 and vtipo = 0
'    msgbox "usuario: no / filtro: no"
    vnor = dcount("*", "[us_historial]", "[descrip] = 'normal'")
    vaut = dcount("*", "[us_historial]", "[descrip] = 'autorizado'")
    vact = dcount("*", "[us_historial]", "[descrip] = 'actualización'")
    vden = dcount("*", "[us_historial]", "[descrip] = 'denegado'")
    vfal = dcount("*", "[us_historial]", "[descrip] = 'fallido'")
    vfor = dcount("*", "[us_historial]", "[descrip] = 'forzado'")
end if
    me.txt1.value = vnor
    me.txt2.value = vaut
    me.txt3.value = vact
    me.txt4.value = vden
    me.txt5.value = vfal
    me.txt6.value = vfor

(He cambiado el código a TODO MINUSCULAS para que no me rechace el posteo por tener demasiadas mayúsculas)

He puesto msgbox con las combinaciones para ver 'cuál caso' es el que arroja el resultado. Por algún motivo algunos no se muestran como combinación posible por ende no cuenta los registros.
¿Cómo podría hacer el código?

EL formulario es este:

¿No se te ocurrió probar así: =DCount("*","[us_historial]",Me.Filter) ?

Lo acabo de probar pero el tema es que son 6 valores a obtener por cada combinación:
Normal, Autorizado, Actualización, Denegado, Fallido y Forzado.

Al aplicar eso me cuenta por cada DESCRIP la totalidad de registros y no importa como los combine, siempre me muestra la totalidad:

Como puedes ver, me cuenta 1 por cada ingreso posible (DESCRIP) en vez de 1 Autorizado para USER Admin.

Vale, te había entendido mal, y por eso la propuesta no te funciona...

No veo cómo puedes hacer el conteo dependiendo del filtro, pues el filtro tendrá un determinado valor de tipo de ingreso, y por eso siempre te suma lo mismo en todos.

Se me ocurre (es un proceso largo y complicado que igual no te merece la pena) que analices el valor del filtro (Me.Filter) con InStr() para buscar coincidencias de los distintos tipos de acceso. Si encuentras uno en el filtro, querrá decir que has seleccionado ese valor en el combo, por lo que solo has de sumar ese tipo de acceso y el resto serán 0. Si en el filtro no lo encuentras, tendrás que hacer un conteo para cada tipo de ingreso y además, para el filtro (por ejemplo: DCount(...."descrip='normal' AND " & Me.Filter) y así con todos)

La otra opción es montar el criterio del DCount igual que el filtro, es decir, analizas si se ha seleccionado algo en los combos, y montas cada caso, salvo que en el combo correspondiente elijas un tipo de accesso, que solo tendrás que contar ese accesso (con el resto de filtros) y el resto de conteos serán cero (se lo has de poner por código)

Añade tu respuesta

Haz clic para o

Más respuestas relacionadas