delsonk 23/10/2018, 00:16
Boa noite,
eu utilizo a função FiltrosSequencialV2, abaixo, em meu BD e funciona muito bem!
Chame a função (Call FiltrosSequencialV2) para executar a filtragem e crie um botão chamar a função (Call Removerfiltros) que já está incluída no código.
'---------------------------------------------------------------------------------------
' Projeto : Filtros Sequenciais
' Modulo : FiltrosSequenciaisV2
' Autor : Paulo R. Robilotta (www.accessporexemplo.wordpress.com/)
' Data : 15/3/12
' Função : Filtragem de registros e criação do RowSource (Origem da linha) dos filtros
' Access : 2000 (DAO 3.6)
' Versão : 2.03. Esta atualização incorpora a possibilidade de se ter um filtros com
' Classificação decrescente.
'---------------------------------------------------------------------------------------
' Veja os termos de uso no blog (www.accessporexemplo.wordpress.com)
'---------------------------------------------------------------------------------------
'
Option Compare Database
Global varFiAc As String ' Armazena os filtros já usados
Global varGroup As String 'Armazena os nomes de campo que já foram usados na instrução GROUP BY
'---------------------------------------------------------------------------------------
' Procedimento : FiltrosSequencialV2 [ 15/3/12]
' Atualização : 0.3
'
' Chamado por : "Após atualizar" das caixas de combinação usadas como filtro
'
' Funções : Após selecionar um valor em um filtro
' : 1) cria o RowSource para os filtros ainda não usados
' 2) filtra o formulário em função do valor selecionado.
'
'---------------------------------------------------------------------------------------
'
Public Function FiltrosSequencialV2()
Debug.Print "###### FUNCTION ###########################################################"
Debug.Print "-----------------------------------------------"
Debug.Print "varFiaAc INICIAL : " & varFiAc
Debug.Print "varGroup INICIAL : " & varGroup
Debug.Print "-----------------------------------------------"
Debug.Print ""
Debug.Print " >>> COLETA DE DADOS DO FILTRO SELECIONADO >>> INÍCIO #"
Debug.Print ""
'VARIÁVEIS
Dim dbs As Database 'O BD
Dim fldQueryDefClic As Field 'Campo da consulta
Dim prpLoopClic As Property 'Coleção fields de fldQueryDefClic
Dim qdfNewClic As QueryDef 'Consulta temporária usada para puxar os dados
Dim varClicCampo As String 'Campo da ccFiltro clicada
Dim varClicTipo As String 'Tipo de campo da ccFiltro clicada
Dim varClicSQL As String 'SQL da ccFiltro clicada
'PROPRIEDADES DO FILTRO CLICADO
Set dbs = CurrentDb
varClicSQL = Screen.ActiveControl.RowSource 'Define a variável
Debug.Print " RowSource original do filtro clicada (varClicSQL) [ " & Len(varClicSQL) & " ]" & ">> "
Debug.Print " >> " & varClicSQL
Set qdfNewClic = dbs.CreateQueryDef("ConsultaTemp", varClicSQL) 'Cria a consulta temporária da ccFiltro clicada
Set fldQueryDefClic = dbs.QueryDefs("ConsultaTemp").Fields(0) 'Definição do campo :Fields(0)
For Each prpLoopClic In fldQueryDefClic.Properties 'Ciclo pela coleção de fields
On Error Resume Next
If prpLoopClic.Name = "Name" Or _
prpLoopClic.Name = "Type" Or _
prpLoopClic.Name = "SourceField" Or _
prpLoopClic.Name = "SourceTable" Or _
prpLoopClic.Name = "Attributes" _
Then 'Se a propriedade for ...
Select Case prpLoopClic.Name 'Descobre o tipo, nome e tabela do campo que vai ser filtrado pela ccFiltro clicada
Case Is = "Type" 'Tipo do campo clicado
varClicTipo = prpLoopClic.Value 'Define a variável
Debug.Print " TIPO de campo do filtro clicado -Type-(varClicTipo): " & varClicTipo
Case Is = "SourceField" 'Nome do campo clicado
varClicCampo = prpLoopClic.Value 'Define a variável
Debug.Print " NOME do campo do filtro clicado -SourceField-(varClicCampo): " & varClicCampo
End Select
On Error GoTo 0
End If
Next prpLoopClic
'Informação : Verifica o tipo de consulta do filtro.
' O tipo deve ser = a zero >> (Select ...)
' Fica a informação para possível uso futuro !
Debug.Print " ** Tipo de consulta do filtro clicado : " & dbs.QueryDefs("ConsultaTemp").Type
dbs.QueryDefs.Delete qdfNewClic.Name 'Deleta a consulta temporária
Dim frm As Form ' O formulário atual
Dim ctrl As Control ' Controles do form
Dim varClicName As String ' Nome do controle no form
Dim varClicValue As String ' Valor do controle
varClicName = Screen.ActiveControl.Name 'Define a variável : Nome do filtro clicado no form
Debug.Print " NOME do controle filtro clicado no form (varClicName): " & varClicName
varClicValue = Screen.ActiveControl.Value 'Define a variável : Valor da ccFiltro clicada
Debug.Print " VALOR do filtro clicado (varClicValue): " & varClicValue
Dim varFiTemp As String 'Variável para a instrução HAVING da SQL que será RowSource dos filtros ainda não usados
'FILTRO CLICADO -> Define a variável: varFiTemp
'Faz a conversão de tipo em função do tipo de campo do filtro clicado
If Screen.ActiveControl.Name = varClicName Then
Select Case varClicTipo
Case Is = 1 'Tipo = "Sim/Não"
varFiTemp = varClicCampo & " = CBool('" & varClicValue & "')"
Case Is = 2 'Tipo = "byte"
varFiTemp = varClicCampo & " = CByte('" & varClicValue & "')"
Case Is = 3 'Tipo = "Inteiro"
varFiTemp = varClicCampo & " = CInt('" & varClicValue & "')"
Case Is = 4 ' Tipo = "Longo"
varFiTemp = varClicCampo & " = CLng('" & varClicValue & "')"
Case Is = 5 'Tipo = "Moeda"
varFiTemp = varClicCampo & " = Ccur('" & varClicValue & "')"
Case Is = 6 'Tipo = "Simples"
varFiTemp = varClicCampo & " = CSng('" & varClicValue & "')"
Case Is = 7 'Tipo = "Duplo"
varFiTemp = varClicCampo & " = CDbl('" & varClicValue & "')"
Case Is = 8 'Tipo = "Data/Hora"
varFiTemp = varClicCampo & " = CDate('" & varClicValue & "')"
Case Is = 10 'Tipo = "Texto"
varFiTemp = varClicCampo & " = '" & varClicValue & "'"
Case Is = 20 'Tipo = "Decimal"
varFiTemp = "CStr(" & varClicCampo & ") = '" & varClicValue & "'"
End Select
Debug.Print " Instrução HAVING -(varFiTemp)- : " & varFiTemp
End If
Debug.Print ""
Debug.Print " >>> COLETA DE DADOS DO FILTRO SELECIONADO >>> FIM #"
Debug.Print ""
Debug.Print " *** DESABILITA O FILTRO CLICADO *** INÍCIO #"
Debug.Print ""
'Esta rotina usa o Índice de tabulação como critério para enviar o foco do
'filtro clicado para um outro controle.
'Limitação : é necessário que o form tenha um controle que possa receber o foco.
Set frm = Screen.ActiveForm 'Atribui a referência ao form atual
For Each ctrl In frm.Controls 'Ciclo pelos controles do form 'Debug.Print frm(ctrl.Name).Name
If frm(ctrl.Name).Name <> varClicName Then 'Controles com nome diferente do filtro clicado 'Debug.Print frm(ctrl.Name).TabIndex
If IsEmpty(frm(ctrl.Name).TabIndex) Then 'TabIndex vazio
'Debug.Print " TabIndex -> Empty"
Else 'TabIndex tem valor 'Debug.Print " TabIndex -> " & frm(ctrl.Name).TabIndex
If frm(ctrl.Name).Enabled = True Then
frm(ctrl.Name).SetFocus
Debug.Print " Foco no controle: " & frm(ctrl.Name).Name
Exit For
End If
End If
End If
Next
frm(varClicName).Enabled = False 'Desabilita a caixa de combinação selecionada
Debug.Print ""
Debug.Print " *** DESABILITA O FILTRO CLICADO *** FIM #"
Debug.Print ""
Debug.Print " <<< COLETA DE DADOS DOS DEMAIS FILTROS <<< INÍCIO #"
Debug.Print ""
Debug.Print ""
For Each ctrl In frm.Controls 'Debug.Print "FOR EACH ctrl ..." 'Debug.Print "CONTROLE >> " & ctrl.Name
If Mid(ctrl.Name, 1, 6) = "filtro" Then 'O controle é um filtro (prefixo filtro...)
If frm(ctrl.Name).Enabled = True Then 'O controle está habilitado (Filtro não usado)
Debug.Print " === CONTROLE ==="
Debug.Print " varFiAc anterior >>> " & varFiAc
Debug.Print " varGroup anterior >>> " & varGroup
Debug.Print " Nome do controle filtro no form > " & ctrl.Name
Dim fSQL As String ' A SQL atual do controle
fSQL = frm(ctrl.Name).RowSource ' Define a variável
'Verifica se a SQL tem a string " DESC;" que indica a classificação Decrescente
If InStr(1, fSQL, " DESC;") <> 0 Then
Debug.Print "##### O campo " & ctrl.Name & " está em ordem DESC;"
varDESC = "Sim" 'Marcador para campo Decrescente (Usado abaixo)
End If
Dim fldQueryDefCCf As Field 'Campo do controle
Dim prpLoopCCf As Property 'Propriedades do controle
Dim qdfNewCCf As QueryDef 'Consulta temporária usada para puxar os dados
Set qdfNewCCf = dbs.CreateQueryDef("ConsultaTemp", fSQL)
'Limitação : Como a função só se aplica a controles originários
' de uma ÚNICA tabela e o form também tem que ter origem
' em uma ÚNICA tabela ,aqui, pode ser usado Fields(0)
'Para eliminar esta limitação, devia ser feita a contagem de fields (i) e usado
'"Fields(0) to (i)" para achar todos os SourceField e SouceTable possíveis.
'
Set fldQueryDefCCf = dbs.QueryDefs("ConsultaTemp").Fields(0)
'Coleta as propriedades
For Each prpLoopCCf In fldQueryDefCCf.Properties 'Debug.Print " Nome da propriedade: "; prpLoopCCf.Name & " >>" & prpLoopCCf.Value
On Error Resume Next
If prpLoopCCf.Name = "Name" Or _
prpLoopCCf.Name = "Type" Or _
prpLoopCCf.Name = "SourceField" Or _
prpLoopCCf.Name = "SourceTable" Or _
prpLoopCCf.Name = "Attributes" _
Then 'Se a propriedade for ...
Select Case prpLoopCCf.Name
Case Is = "Name"
Debug.Print " ** Nome do campo do controle no form: " & prpLoopCCf.Value 'Simples informação
Case Is = "Type"
'varTipoCCf = prpLoopCCf.Value 'Não é usada
Debug.Print " Tipo de dados do controle filtro: " & prpLoopCCf.Value 'Simples informação
Case Is = "SourceField"
varNomeCCf = prpLoopCCf.Value 'Define variável
Debug.Print " SourceField do controle filtro (varNomeCCf): " & varNomeCCf
'Verifica o marcador de Decrescente (só para conferir !)
If varDESC = "Sim" Then
Debug.Print "****** O campo " & varNomeCCf & " está em ordem DESC;"
End If
Case Is = "SourceTable"
varTabelaCCf = prpLoopCCf.Value
Debug.Print " SourceTable do controle filtro (varTabelaCCf): " & varTabelaCCf
Case Else
'Debug.Print " VALOR DA PROPRIEDADE: " & prpLoopCCf.Value
End Select
On Error GoTo 0
End If
Debug.Print " VALOR DA PROPRIEDADE: " & prpLoopCCf.Value
Next prpLoopCCf
dbs.QueryDefs.Delete qdfNewCCf.Name 'Deleta a consulta temporária
'------------------------------------------------------------------------------------
'PRIMEIRA FILTRAGEM ** PRIMEIRA FILTRAGEM ** PRIMEIRA FILTRAGEM ** PRIMEIRA FILTRAGEM
'------------------------------------------------------------------------------------
'Debug.Print "varFiAc anterior ("")>>> " & varFiAc
If varFiAc = "" Then
'Define a SQL do controle
filtroSQL = ""
filtroSQL = filtroSQL & "SELECT " & varNomeCCf
filtroSQL = filtroSQL & " FROM FiltrosRowSource" 'Atualização 0.2
filtroSQL = filtroSQL & " GROUP BY " & varClicCampo & "," & varNomeCCf
filtroSQL = filtroSQL & " HAVING " & varFiTemp
'Verifica o marcador de Decrescente
'Constroi a instrução SQL dependendo do caso
If varDESC <> "Sim" Then 'Crescente
filtroSQL = filtroSQL & " ORDER BY " & varNomeCCf
Else 'Decrescente
filtroSQL = filtroSQL & " ORDER BY " & varNomeCCf & " DESC;"
End If
'Redefine o marcador de Decrescente (para uso nos demais filtros)
varDESC = "Não"
frm(ctrl.Name).RowSource = filtroSQL 'Atribui a RowSource ao controle
dbs.QueryDefs.Delete qdfNewCCf.Name 'Deleta a consulta temporária
Debug.Print "### 1ª FILTRAGEM"
Debug.Print "1-SQL atual do controle(fSQL)>> "
Debug.Print "2-SQL aplicada ao controle(filtroSQL) [" & Len(filtroSQL) & "] >> "
Debug.Print ""
Debug.Print " 1 >> " & fSQL
Debug.Print " 2 >> " & filtroSQL
Debug.Print ""
'------------------------------------------------------------------------------------
'SEGUNDA FILTRAGEM ** SEGUNDA FILTRAGEM ** SEGUNDA FILTRAGEM ** SEGUNDA FILTRAGEM
'------------------------------------------------------------------------------------
Else
'Define a SQL do controle
filtroSQL = ""
filtroSQL = filtroSQL & "SELECT " & varNomeCCf
filtroSQL = filtroSQL & " FROM FiltrosRowSource" 'Atualização 0.2
filtroSQL = filtroSQL & " GROUP BY " & varGroup & "," & varClicCampo & "," & varNomeCCf
filtroSQL = filtroSQL & " HAVING " & varFiAc & " AND " & varFiTemp
'filtroSQL = filtroSQL & " ORDER BY " & varNomeCCf
'Verifica o marcador de Decrescente
'Constroi a instrução SQL dependendo do caso
If varDESC <> "Sim" Then 'Crescente
filtroSQL = filtroSQL & " ORDER BY " & varNomeCCf
Else 'Decrescente
filtroSQL = filtroSQL & " ORDER BY " & varNomeCCf & " DESC;"
End If
frm(ctrl.Name).RowSource = filtroSQL 'Atribui a RowSource ao controle
dbs.QueryDefs.Delete qdfNewCCf.Name 'Deleta a consulta temporária
Debug.Print "### 2ª FILTRAGEM"
Debug.Print "1-SQL atual do controle(fSQL)>> "
Debug.Print "2-SQL aplicada ao controle(filtroSQL) [" & Len(filtroSQL) & "] >> "
Debug.Print ""
Debug.Print " 1 >> " & fSQL
Debug.Print " 2 >> " & filtroSQL
Debug.Print ""
End If
End If
End If
Next
Debug.Print " <<< COLETA DE DADOS DOS DEMAIS FILTROS <<< FIM #"
Debug.Print ""
Debug.Print " --- FITRAGEM DO FORMULÁRIO --------------- INÍCIO - #"
If varGroup = "" Then
Debug.Print " -- 1ª FITRAGEM ----- INÍCIO - #"
varFiAc = varFiTemp 'Define varFiAc para a próxima filtragem
frm.Filter = varFiAc 'Atribui o filtro ao formulário
frm.FilterOn = True
varGroup = varClicCampo '
Debug.Print " Filtro aplicado ao form (varFiAc) >> " & varFiAc
Debug.Print " varGroup acumulado >> " & varGroup
Debug.Print " -- 1ª FITRAGEM ----- F I M - #"
Else
Debug.Print " -- 2ª FITRAGEM ----- INÍCIO - #"
varFiAc = varFiAc & " AND " & varFiTemp 'Define varFiAc para a próxima filtragem
frm.Filter = varFiAc 'Atribui o filtro ao formulário
frm.FilterOn = True
varGroup = varGroup & "," & varClicCampo
Debug.Print " Filtro aplicado ao form (varFiAc) >> " & varFiAc
Debug.Print " varGroup acumulado >> " & varGroup
Debug.Print " -- 2ª FITRAGEM ----- F I M - #"
End If
dbs.Close 'Fecha o BD
Debug.Print " --- FITRAGEM DO FORMULÁRIO --------------- F I M - #"
Debug.Print ""
Debug.Print "###### END FUNCTION #######################################################"
Debug.Print ""
Debug.Print ""
End Function
'---------------------------------------------------------------------------------------
' Procedimento : RemoverFiltros [ 07/1/12 00:07 ]
' Chamado por : Botão Remover filtros
' Funções : 1) Remove o filtro do form e
' : 2) Reconstroi a RowSource dos filtros
'---------------------------------------------------------------------------------------
'
Public Function RemoverFiltros()
varFiAc = "" 'Zera as variáveis globais
varGroup = ""
DoCmd.ShowAllRecords 'Remove o filtro
Dim frm As Form
Dim ctrl As Control
Set frm = Screen.ActiveForm
For Each ctrl In frm.Controls 'Ciclo pelos controles
If Mid(ctrl.Name, 1, 6) = "filtro" Then 'Verifica se é filtro
frm(ctrl.Name).Enabled = True 'Habilita o campo
Dim fSQL As String
fSQL = frm(ctrl.Name).RowSource 'Captura a SQL do filtro
'Verifica se a SQL tem a string " DESC;" que indica a classificação Decrescente
If InStr(1, fSQL, " DESC;") <> 0 Then
Debug.Print "##### O campo " & ctrl.Name & " está em ordem DESC;"
varDESC = "Sim" 'Marcador para classificação Decrescente (usado abaixo)
End If
Dim dbs As Database 'O BD
Dim fldQueryDef As Field 'Campo da consulta
Dim prpLoop As Property 'Propriedades
Dim qdfNew As QueryDef 'Consulta temporária usada para puxar os dados
Set dbs = CurrentDb
Set qdfNew = dbs.CreateQueryDef("ConsultaTemp", fSQL) 'Cria a consulta temporária
Set fldQueryDef = dbs.QueryDefs("ConsultaTemp").Fields(0)
For Each prpLoop In fldQueryDef.Properties
Dim varType As Variant 'Variável usada na "limpeza" do controle do filtro (veja no final)
Select Case prpLoop.Name
Case Is = "Type"
varType = prpLoop.Value 'Define variável para tipo
Case Is = "SourceField"
varCampo = prpLoop.Value 'Define variável para nome do campo
'Verifica o marcador de Decrescente (só para conferir)
If varDESC = "Sim" Then
Debug.Print "****** O campo " & varCampo & " está em ordem DESC;"
End If
Case Is = "SourceTable" 'Define variável para tabela do campo
varTabela = prpLoop.Value
End Select
Next prpLoop
Debug.Print " Tipo de dados : " & varType
Debug.Print " Campo fonte : " & varCampo
Debug.Print " Tabela fonte : " & varTabela
dbs.QueryDefs.Delete qdfNew.Name 'Deleta a consulta temporária
'Verifica se o filtro tem classificação Decrescente ou não
If varDESC <> "Sim" Then 'Crescente
'Define a SQL que será rowsource do filtro
ccFiltroSQL = "SELECT [" & varTabela & "].[" & varCampo & "]" _
& " FROM " & varTabela _
& " GROUP BY " & "[" & varTabela & "].[" & varCampo & "]" _
& " HAVING (((" & varTabela & "." & varCampo & ") Is Not Null))" _
& " ORDER BY " & "[" & varTabela & "].[" & varCampo & "]"
Else 'Decrescente
'Define a SQL que será rowsource do filtro com DESC
ccFiltroSQL = "SELECT [" & varTabela & "].[" & varCampo & "]" _
& " FROM " & varTabela _
& " GROUP BY " & "[" & varTabela & "].[" & varCampo & "]" _
& " HAVING (((" & varTabela & "." & varCampo & ") Is Not Null))" _
& " ORDER BY " & "[" & varTabela & "].[" & varCampo & "]" & " DESC;"
Debug.Print ccFiltroSQL
End If
'Redefine o marcador
varDESC = "Não"
frm(ctrl.Name).RowSource = ccFiltroSQL 'Aplica a SQL ao filtro
Debug.Print "SQL do controle : " & ccFiltroSQL
'Limpa o valor selecionado anteriormente no controle
If varType = 1 Then
frm(ctrl.Name) = 0
Else
frm(ctrl.Name) = ""
End If
End If
Next
dbs.Close 'Fecha o BD
End Function
Abraço, Delson