Filtros sequenciais – Alterações e comentários

Nesta página vou dar alguns detalhes sobre a função que permite criar os filtros sequenciais que podem ser usados em qualquer ordem.

Acredito que, desta maneira, quem desejar alterar a função terá uma idéia mais precisa do que pode ser alterado e onde essas alterações devem ser feitas.

VERSÃO DO PROGRAMA

A função foi criada com a versão 2000 do Access usando o modelo de acesso a dados : DAO (Data Access Objects).

Só recentemente instalei a versão 2007 em um outro computador e ainda tenho pouca (ou nenhuma) familiaridade com ela. Ou seja, não saberia responder dúvidas sobre quaisquer novas possibilidades relativas a filtros nessa versão ou na versão 2010.

Sempre usei o DAO e nunca precisei do ADO (ActiveX Data Objects). Por isso, não saberia responder dúvidas relativas à adaptação DAO -> ADO.

O QUE VOCÊ DEVE SABER PARA MEXER NA FUNÇÃO

1) Tenha em mente que a função é baseada em regras. Para modificá-la, ou você terá que alterar as regras ou então criar exceções a essas regras.

Uma dessas regras é que os filtros usam somente o operador “=”. Se você pretende usar outro operador (<; >; like etc) em algum dos filtros, terá que criar as exceções correspondentes a eles.

2) Você deve ler o código do começo ao fim e entender como ele funciona. É chato e gasta tempo, mas se não fizer isso provavelmente  será mal sucedido.

3) Você deve ter conhecimento básico da linguagem SQL.

A LÓGICA DA FUNÇÃO

Antes que algum filtro tenha sido usado, cada um deles tem como origem da linha a lista de itens únicos do campo que será filtrado por ele.

Genericamente, uma SQL como a abaixo:

SELECT “campo”

FROM “tabela que contém o campo”

GROUP BY “campo”

HAVING “campo”

ORDER BY “campo”;

Quando você seleciona um item de um dos filtros, você está introduzindo um critério (o item selecionado ) que deve ser passado para a origem da linha dos filtros ainda não usados.

Digamos que você selecionou algo no filtro1 (Critério1) . Para que os demais filtros (filtroN) incorporem o Critério do filtro1, a origem da linha dos filtroN será uma SQL como a abaixo:

– Primeira filtragem (SQL que será a origem da linha dos filtros ainda não usados)

SELECT “campo do filtroN”

FROM “tabela do filtroN”

GROUP BY “campo do filtro1” , “campo do filtroN”

HAVING “campo do filtro1” = Critério1

ORDER BY “campo do filtroN”;

Ao selecionar um item do filtro2 (Critério2) , a SQL para os demais filtros (filtroN) deverá ser:

– Segunda (e demais) filtragens (SQL que será a origem da linha dos filtros ainda não usados)

SELECT “campo do filtroN”

FROM “tabela do filtroN”

GROUP BY “campo do filtro1” , “campo do filtro2” , “campo do filtroN”

HAVING “campo do filtro1” = Critério1 AND “campo do filtro2” = Critério2

ORDER BY “campo do filtroN”;

Observe que as instruções SELECT, FROM são sempre iguais.

A cada filtragem, a instrução GROUP BY contém os campos dos filtros já usados e o campo do filtro ainda não usado ao qual a SQL se aplica (campo do filtroN)

A cada filtragem, a instrução HAVING vai incluindo os critérios dos filtros já usados.

Na instrução ORDER BY o “campo do filtroN” é sempre igual. (Veja mais abaixo a observação sobre classificação decrescente)

Esse é o modo como a SQL que é origem da linha de cada filtro é construída após cada filtragem.

COMO SÃO OBTIDOS OS ELEMENTOS DA INSTRUÇÃO SQL

Para construir essas SQL’s é necessário saber de cada filtro :

1) O nome do campo que será filtrado (filtroN)

A maneira que usei para descobrir o nome do campo (e seu tipo de dado) foi usar a SQL associada a cada um deles e a partir dela construir uma consulta temporária (“ConsultaTemp”). Analisando as propriedades dessa consulta é possível saber o nome e o tipo do campo que vai ser filtrado.

O nome é usado na criação da SQL e o tipo para adequar a string do critério ao tipo de campo filtrado.

2) O nome da tabela que contém o campo que será filtrado (tabela do filtroN)

Para permitir que a origem da linha dos filtros possa ser proveniente de diferentes tabelas, no evento ao abrir do formulário é criada uma consulta temporária chamada “FiltrosRowSource” que é um clone da origem dos registros do formulário e que na função é usada para obter a o nome da tabela referente ao campo do filtro.

3) O critério de cada filtro usado

É usada a instrução : Screen.ActiveControl.Value

COMO SABER QUAIS FILTROS FORAM USADOS

Após um filtro ser usado, a respectiva caixa de combinação é desabilitada. O estado habilitado dos demais filtros é usado para saber que eles ainda não foram usados.

O PAPEL DAS VARIÁVEIS GLOBAIS

São usadas duas variáveis globais na função:

varGroup : sua função é guardar os dados usados na instrução GROUP BY sobre os filtros já usados

varFiAc : sua função é guardar os dados usados na instrução HAVING sobre os filtros já usados e na instrução que faz a filtragem do formulário.

COMO A FUNÇÃO “SABE” QUE A DEFINIÇÃO ORIGINAL DA ORIGEM DA LINHA DO FILTRO ESTÁ EM ORDEM DECRESCENTE

Quando se obtem a SQL de cada filtro (a variável fSQL no código abaixo) é feita a verificação se nessa SQL existe a string “DESC;”, que indica que a origem da linha está em ordem decrescente.

If InStr(1, fSQL, ” DESC;”) <> 0 Then

varDESC = “Sim” ‘Marcador para campo Decrescente (Usado abaixo)

End If

No momento da criação da origem da linha dos filtros, a instrução ORDER BY é escrita da maneira adequada dependendo do marcador da instrução acima.

SOBRE REGRAS E EXCEÇÕES

Como foi dito no início o exemplo, no estágio de desenvolvimento atual, só permite o uso da instrução HAVING como a do modelo abaixo, ou seja usando o operador ” = “. Essa é uma regra rígida (por enquanto)

HAVING “campo do filtro” = Critério

As instruções que permitem determinar se um filtro foi criado em ordem crescente ou decrescente podem ser vistas como a introdução de uma exceção a regra. (Essa é a diferença entre as atualizações 0.2 e 0.3 da versão 2).

OBSERVAÇÕES PARA QUEM QUISER MODIFICAR A FUNÇÃO

Eu, você e o mundo queremos poder criar filtros com outros operadores que permitam selecionar também intervalo de valores ou que usem caracteres curinga do tipo Like ou ainda, expressões regulares (REGEX).

Pessoalmente ainda não tentei essas possibilidades.

Intuitivamente, me parece que usando este exemplo como “esqueleto”, uma das possibilidades seria definir um prefixo diferente para o nome cada tipo filtro específico e construir as SQL’s adequadas para esse tipo de filtro.

Aqui no exemplo, é usado o prefixo FILTRO+nome da caixa de combinação e no código da função esse prefixo é usado para determinar que essas caixas de combinação são filtros (e as respectivas SQL’s são construídas em função disso).

A idéia seria criar outras caixas de combinação com o prefixo INTERVALO+nome da caixa de combinação e para as caixas com esse prefixo criar as instruções da SQL que selecionem intervalos de valores. Ou seja, cada prefixo determina o tipo de instrução HAVING da SQL criada.

Restaria ainda, no final, juntar todas as instruções HAVING dos filtros de tipos diferentes na SQL que é origem da linha dos filtros.

Outra possibilidade de obter os dados necessários para a construção das SQL’s é fazer a engenharia reversa da SQL original das caixas de combinação que são filtros e depois reconstruí-las introduzindo os critérios a cada filtragem. Foi isso que eu fiz parcialmente na primeira versão do programa. No entanto, dada a infinidade de possibilidades de escrita de uma SQL e o meu conhecimento relativamente restrito dessa linguagem, abandonei esse caminho e resolvi partir para a abordagem diferente desta versão 2.

UM COMENTÁRIO MEIO MAL HUMORADO SOBRE OS COMENTÁRIOS

Muitos comentários em algum momento apresentam a pergunta : É possível … ?

A minha resposta, a priori, é: provavelmente sim. Como agora você já sabe a minha resposta, procure fazer essa pergunta a si mesmo e tente implementá-la. Se deu certo, coloque um comentário mostrando como foi feito para compartilhar com todos. Se não deu certo descreva o que fez e mande o comentário, que estarei à disposição para responder.

Antes de postar um comentário, certifique-se de ter apertado a tecla F1 quando necessário ou pelo menos ter feito uma pesquisa básica na internet.

Se tiver algum problema, por favor, descreva minimamente o que aconteceu.

Já recebi perguntas do tipo:

Tentei adaptar o exemplo e não funcionou. Você pode me ajudar ?

Argh !!!!!!!

Histórico da função

1) Access exemplo – Filtros sequenciais em formulário (25/03/10)

2) Access exemplo – Filtros sequenciais para subformulários (14/06/10)

3) Access – Filtros sequenciais – Versão 2 (07/01/12)

Atualização 0.3 (15/3/2012)

Deixe uma resposta

Preencha os seus dados abaixo ou clique em um ícone para log in:

Logotipo do WordPress.com

Você está comentando utilizando sua conta WordPress.com. Sair / Alterar )

Imagem do Twitter

Você está comentando utilizando sua conta Twitter. Sair / Alterar )

Foto do Facebook

Você está comentando utilizando sua conta Facebook. Sair / Alterar )

Foto do Google+

Você está comentando utilizando sua conta Google+. Sair / Alterar )

Conectando a %s

%d blogueiros gostam disto: