Usando o evento OnFilterRecord para filtrar ClientDataSets



Documentos relacionados
ETEC DR. EMÍLIO HENRNANDEZ AGUILAR PROGRAMAÇÃO DE COMPUTADORES II PROFESSOR RAFAEL BARRETO DELPHI FORMULÁRIO COM ABAS E BUSCAS DE REGISTROS

CRIAÇÃO DE RELATÓRIOS EM DELPHI

MANUAL DE UTILIZAÇÃO SISTEMA DE CADASTRO INTRANET

Display de 7. PdP. Autor: Tiago Lone Nível: Básico Criação: 16/12/2005 Última versão: 18/12/2006. Pesquisa e Desenvolvimento de Produtos

ETEC DR. EMÍLIO HENRNANDEZ AGUILAR PROGRAMAÇÃO DE COMPUTADORES II PROFESSOR RAFAEL BARRETO

Inserindo Dados no Banco de Dados Paradox.

&XUVRGH,QWURGXomRDR (GLWRUGH3ODQLOKDV([FHO

Listando itens em ComboBox e gravando os dados no Banco de Dados MySQL.

Entradas Digitais. PdP. Autores: Luís Fernando Patsko e Tiago Lone Nível: Intermediário Criação: 27/12/2005 Última versão: 18/12/2006

Cálculo utilizando variáveis do tipo DATA

Sumário: Fluxo Operacional... 3 Contatos Agenda Online Reservas de Salas Tarefas... 42

Memória Flash. PdP. Autor: Tiago Lone Nível: Básico Criação: 11/12/2005 Última versão: 18/12/2006. Pesquisa e Desenvolvimento de Produtos

USANDO O ROUNDCUBE WEBMAIL

ETEC DR. EMÍLIO HENRNANDEZ AGUILAR PROGRAMAÇÃO DE COMPUTADORES I PROFESSOR RAFAEL BARRETO

Fluxo de trabalho do Capture Pro Software: Indexação de código de barras e separação de documentos

Despachante Express - Software para o despachante documentalista veicular DESPACHANTE EXPRESS MANUAL DO USUÁRIO VERSÃO 1.1

Universidade Federal do Mato Grosso - STI-CAE. Índice

Parte 5 LibreOffice Base

Validando dados de páginas WEB

4 O Workflow e a Máquina de Regras

Lição 1 - Criação de campos calculados em consultas

Barra de ferramentas padrão. Barra de formatação. Barra de desenho Painel de Tarefas

AMBIENTE. FORMULÁRIO: é a janela do aplicativo apresentada ao usuário. Considere o formulário como a sua prancheta de trabalho.

TUTORIAL DO ACCESS PASSO A PASSO. I. Criar um Novo Banco de Dados. Passos: 1. Abrir o Access 2. Clicar em Criar um novo arquivo

INSTALAÇÃO DO SISTEMA CONTROLGÁS

Trabalhando com conexão ao banco de dados MySQL no Lazarus. Prof. Vitor H. Migoto de Gouvêa Colégio IDESA 2011

Introdução a Banco de Dados em Delphi

Gerenciamento de Contatos

Manual do Painel Administrativo

Primeiros Passos para o Simulador de Ações do FinanceDesktop. Parte A INICIANDO E CONFIGURANDO (5 passos)

ÍNDICE... 2 INTRODUÇÃO... 4

Tutorial de Matlab Francesco Franco

Como funciona? SUMÁRIO

A barra de menu a direita possibilita efetuar login/logout do sistema e também voltar para a página principal.

WF Processos. Manual de Instruções

Manual do Sistema "Vida Controle de Contatos" Editorial Brazil Informatica

PdP. Autor: Luís Fernando Patsko e Tiago Lone Nível: Intermediário Criação: 26/12/2005 Última versão: 18/12/2006

Table of Contents. PowerPoint XP

Impressão de Código de Barras Uma abordagem prática ZEBRA ZPL2

Fortes Report Parte 1 Desenvolvendo o Primeiro Relatório

JavaScript (Funções, Eventos e Manipulação de Formulários)

Tutorial do módulo Carteira Nacional de Militante

Tela Inicial: O Banco de Dados e seus objetos:

MANUAL DO USUÁRIO. Guia de orientações e conceitos para manipulação da plataforma Miraklon. VERSÃO Vigência

Autor: Tiago Lone Nível: Básico Criação: 19/12/2005 Última versão: 18/12/2006. PdP. Pesquisa e Desenvolvimento de Produtos

Podemos agora ver no IDE do Morfik os objetos que já incorporamos ao nosso projeto :

Banco de Dados BrOffice Base

Trecho retirando do Manual do esocial Versão 1.1

Status. Barra de Título. Barra de Menu. Barra de. Ferramentas Padrão. Caixa de nomes. Barra de. Ferramentas de Formatação. Indicadores de Coluna

SMS Corporativo Manual do Usuário

Bem- Vindo ao manual de instruções do ECO Editor de COnteúdo.

Fluxo de trabalho do Capture Pro Software: Indexação de OCR e separação de documentos de código de correção

CRIANDO TEMPLATES E LEGENDAS

A Estação da Evolução

MANUAL DO ANIMAIL Terti Software

Manual de utilização do sistema de envio de sms marketing e corporativo da AGENCIA GLOBO. V

Gerenciador de Congressos de Iniciação Científica Manual de Instruções

ALBUM DE FOTOGRAFIAS NO POWER POINT

Acesso à Dados ZEOS x Delphi. Professor Anderson

Instruções de uso do TABNET. Linha, Coluna e Conteúdo

INTRODUÇÃO AO WINDOWS

Portal Sindical. Manual Operacional Empresas/Escritórios

Atalhos da Web. Krishna Tateneni Yves Arrouye Tradução: Lisiane Sztoltz

ÍNDICE... 3 INTRODUÇÃO A série... 4

Como incluir artigos:

1) Como acessar a aplicação

Microsoft Excel Macros aula 1

Tutorial - DVD Flick

Manual do Publicador. Wordpress FATEA Sistema de Gerenciamento de Conteúdo Web

Pesquisa e organização de informação

www. inf.br Outubro/2008 5www.habisp.inf.br TREINAMENTO HABISP VERBA DE ATENDIMENTO

Manual de configuração do sistema

Clique no botão novo

Criando um script simples

Controle do Arquivo Técnico

Microsoft Access: Criar consultas para um novo banco de dados. Vitor Valerio de Souza Campos

PÓS-GRADUAÇÃO EM MATEMÁTICA COMPUTACIONAL INFORMÁTICA INSTRUMENTAL

MANUAL C R M ÍNDICE. Sobre o módulo de CRM Definindo a Campanha... 3

Banco de Dados Microsoft Access: Criar tabelas. Vitor Valerio de Souza Campos

CAPÍTULO 3 - TIPOS DE DADOS E IDENTIFICADORES

ROTINAS PADRÕES DO SISTEMAS

Manual SAGe Versão 1.2 (a partir da versão )

CRIANDO BANCOS DE DADOS NO SQL SERVER 2008 R2 COM O SQL SERVER MANAGEMENT STUDIO

Manual do Almoxarifado SIGA-ADM

Vamos criar uma nova Página chamada Serviços. Clique em Adicionar Nova.

Índice: Nitgen do Brasil

Gerenciamento de Projetos

Revisando sintaxes SQL e criando programa de pesquisa. Prof. Vitor H. Migoto de Gouvêa Colégio IDESA 2011

Ambiente Virtual de Aprendizagem C.S.G. M anual do Professor

Microsoft Excel Macro V. Índice 16-) Formulários ) Gerando código para o Formulário... 49

A1;A7 é o mesmo que A1 e A7 A1:A7 é o mesmo que A1 até A7 (abrange A1, A2, A3, A4, A5, A6, A7).

Iniciando o MySQL Query Brower

Manual GMI-Gabinete de Manutenção Informática

Como já foi dito anteriormente o Excel possui recursos que permitem alterar a aparência de nossas planilhas.

Assessoria Técnica de Tecnologia da Informação - ATTI. Projeto de Informatização da. Secretaria Municipal de Saúde do. Município de São Paulo

Windows Explorer. Prof. Valdir

Lista de operadores de comparação - > Maior que - < Menor que - <= Menor ou igual a - >= Maior ou igual a - === Igual a -!

Dicas para usar melhor o Word 2007

MANUAL DO USUÁRIO. Projeto/Software/Programa. CDAeM Cadastro de Artistas e Modelos JunioNet. Objetivo desse manual

MANUAL DO SISTEMA. Versão 6.04

Transcrição:

Usando o evento OnFilterRecord para filtrar ClientDataSets O objetivo mais importante no desenvolvimento de um programa é fornecer ao cliente maior liberdade para usar as interfaces e ao mesmo tempo tornar as rotinas bastante gerais, para que possam ser utilizadas por muitos tipos de clientes. Desta vez criei uma rotina para filtragem de dados através de um ClientDataSet, utilizando o evento OnFilterRecord. Outros métodos de filtragem sempre apresentaram problemas que me forçavam a modificar os ClientDataSets, ou restringiam os tipos de campo que eu normalmente coloco neles. Por exemplo, ao utilizar a propriedade Filter, não há como filtrar uma coluna de datas de um DBGrid para mostrar apenas o mês de julho, utilizandose os caracteres /07/. Isto acontece porque para configurar a propriedade Filter precisamos montar uma expressão com datas, e não com strings. Outros problemas também ocorrem, principalmente com campos lookup. Tudo isso pode ser resolvido com a técnica mostrada a seguir. Recursos A técnica desenvolvida permite ao cliente utilizar filtros em qualquer campo do ClientDataSet, seja ele exibido no DBGrid ou não. O cliente pode usar as operações igual, diferente, contendo, inicia com, maior, menor, e outras. Como as opções do filtro são colocadas em um ClientDataSet auxiliar, elas podem ser editadas livremente, excluídas, gravadas em arquivos XML ou recuperadas a partir deles. Requisitos A única exigência para utilizar a técnica é exibir os dados em um DBGrid associado a um ClientDataSet. A aplicação Comecemos por criar uma nova aplicação no Delphi 7. Vamos gra o formulário com o nome de uformfiltro e o projeto com o nome de ProjFiltro. No formulário vamos colocar dois ClientDataSets, um chamado cdslista e outro chamado cdsfiltro. Precisamos também de um DataSource chamado dslista apontando para cdslista e um DBGrid chamado dbglista, apontando para dslista. Para mostrar ao cliente as opções de filtragem, vamos colocar um BitBtn chamado Bfiltra. A figura 1 mostra a primeira etapa da aplicação. Como o ClientDataSet pode estar ligado a qualquer base de dados, vamos escolher um dos arquivos XML que já vêm com o Delphi. Aponte a propriedade Filename do cdslista para C:\Arquivos de programas\arquivos comuns\borland Shared\Data\employee.xml

Figura 1 primeira etapa da aplicação Para mostrar as opções de filtro, vamos construir um painel que fica oculto até ser disparado o evento OnClick do botão Bfiltra, simulando uma janela. Precisaremos de um GroupBox chamado GrupoFiltro, de um DBGrid chamado dbgfiltro, de um DataSource chamado dsfiltro para ligar o dbgfiltro ao cdsfiltro. Para controlar este painel, colocamos alguns BitBtns chamados respectivamente de BFNovo, BFExcluir, BFLimpar, BFCancelar, BFFiltrar, deixando a aparência semelhante à da figura 2. Figura 2 o painel de filtragem Os campos mostrados no dbgfiltro devem ser criados no cdsfiltro, todos do tipo string, com tamanhos suficientes para armazenar os operadores. No exemplo os campos foram chamados de: Campo, Operador, Valor e OpLogico, com os tamanhos 25, 10, 50 e 3, respectivamente. Não podemos esquecer de

executar a opção Create Dataset para gra estes campos no dbgfiltro. Depois de clicar duas vezes no dbgfiltro, adicionamos todos os campos e configuramos a propriedade PickList dos campos Operador e OperLogico veja o resultado nas figuras 3a e 3b. Figura 3a: valores do campo Operador Figura 3b: valores do campo OperLogico Como os desenvolvedores sempre querem apresentar aos seus clientes DBGrids bem configurados e com títulos sugestivos, podemos aproveitar estes títulos para configurar o primeiro campo do DBGrid dbgfiltro. Coloque o código abaixo no evento OnClick do botão BFiltra: Procedure TFormFiltro.BFiltraClick(Sender: TObject);

dbgfiltro.columns[0].picklist.clear; for I := 0 to dbglista.columns.count - 1 do dbgfiltro.columns[0].picklist.add(dbglista.columns[i].title.caption); PainelFiltro.Visible := True; Posteriormente, isto vai implicar em algumas rotinas extras para determinar o nome do campo que deve ser filtrado, mas este sacrifício será compensado quando o cliente vir nomes que ele entende, em vez de REGPROD, NOMECLI, etc. Disparando o Filtro Para disparar a filtragem através do evento OnFilter, basta alterar a propriedade Filtered de cdslista para True. Se o ClientDataSet já estiver filtrado, devemos então alterar para False e em seguida para True. Coloque o código abaixo no botão BFFiltrar: procedure TFormFiltro.BFFiltrarClick(Sender: TObject); cdslista.filtered := False; PainelFiltro.Visible := False; cdslista.filtered := True; dbglista.setfocus; A filtragem registro a registro O evento OnFilterRecord do cdslista é onde tudo ocorre. Através dele podemos contornar todos os problemas e manipular todas as iações que os clientes ou os desenvolvedores quiserem. O código completo do evento encontra-se na listagem 1. Uma iável global foi criada para auxiliar o funcionamento do evento, portanto declare a iável como mostrado abaixo, antes da seção Implementation: FormFiltro: TFormFiltro; SinalExcecaoFiltro: Boolean; implementation Observe que para cada operador escolhido foi desenvolvida uma análise do tipo de dados que vai receber o filtro. Há casos que merecem maior destaque, como as datas. Para que o cliente possa escolher o operador Contendo, ou Inicia com e utilizar apenas uma parte da data, como /07/, precisamos nos certificar de que as datas estão sendo exibidas com 10 dígitos e que valores com apenas um dígito estejam completados com zeros. Este efeito é obtido simplesmente alterando a iável global ShortDateFormat para dd/mm/yyyy, o que pode ser feito adicionando a seguinte linha ao evento OnCreate do formulário:

ShortDateFormat := 'dd/mm/yyyy'; A função RetiraAcentos, em conjunto com a função AnsiUpperCase, nos permite digitar as expressões com ou sem cedilhas e acentos, e o filtro sempre fará a comparação como se eles não existissem. Confira na ajuda do Delphi a diferença entre as funções UpperCase e AnsiUpperCase. A função Analisa verifica o tipo de dados armazenado em um campo e retorna um valor correspondente. Os tipos numéricos e as datas foram tratados de maneira diferenciada, pois são os tipos que mais causam problemas durante a montagem das expressões de filtro. A função DefineTipo age de maneira semelhante, analisando um campo e transformando uma string em um tipo compatível com o campo passado. Esta string será justamente a expressão que o cliente vai digitar no campo Valor do dbgfiltro. Veja o código desta função e outras funções auxiliares na listagem 2. Quando os dados não forem inseridos corretamente Note o bloco try... except... end no evento OnFilterRecord. Caso ocorra algum problema com a expressão digitada no campo Valor, será levantada uma exceção e mostrada uma mensagem explicando qual a expressão que causou o problema. Como o evento OnFilterRecord re todos os registros do ClientDataSet, a exceção será levantada muitas vezes. Para evitar isto, usamos a iável SinalExcecaoFiltro, que foi criada anteriormente. Esta iável funciona como flag, bloqueando a análise dos demais registros, caso seu valor se torne verdadeiro. Outras ações O restante dos botões da janela de filtragem possui códigos bastantes simples, que servem para controlar a inserção e exclusão de registros no cdsfiltro e ocultar o PainelFiltro. Estes códigos podem ser vistos na listagem 3. Recursos extras Como todas as operações da filtragem são baseadas em valores de um ClientDataSet, podemos utilizar vários de seus recursos e oferecder ao cliente muitas outras opções. Por exemplo, através dos métodos SaveToFile e LoadFromFile, podemos gra os filtros em arquivos XML ou arquivos binários (cds) e recuperá-los posteriormente. Observe na figura 4 o filtro em ação. Considerações finais Com a liberdade para analisar todas as situações em um mesmo evento, além de poder criar vários tipos de operações para oferecer ao cliente (a operação ENTRE ficará como exercício para o leitor), o desenvolvedor pode avançar muito mais, com base no que já foi mostrado. A filtragem percorre todo o ClientDataSet, criando uma dependência entre a velocidade da máquina do cliente e a performance. Conseqüentemente, máquinas mais lentas vão demorar mais para executar uma filtragem. Apesar

disto, a satisfação do cliente estará garantida, pois a fidelidade do resultado e a facilidade de uso levam vantagem sobre a queda de performance. Figura 4 Listagem 1 o evento OnFilterRecord procedure TFormFiltro.cdsListaFilterRecord(DataSet: TDataSet; Accept: Boolean); Condicao: Boolean; Aux: string; AuxField: Tfield; Accept := True; Condicao := True; if not cdsfiltro.isempty then cdsfiltro.first; // re os filtros digitados, a menos que uma exceção tenha ocorrido while not cdsfiltro.eof and not SinalExcecaoFiltro do try // Confira as duas funções abaixo na Listagem 2 Aux := AchaCampoPorRotulo(cdsLista, cdsfiltrocampo.asstring).asstring; AuxField := AchaCampoPorRotulo(cdsLista, cdsfiltrocampo.asstring); if AnsiUpperCase(cdsFiltroOperador.AsString) = 'CONTENDO' then Condicao := (pos(retiraacentos(cdsfiltrovalor.asstring), RetiraAcentos(Aux)) <> 0);

if AnsiUpperCase(cdsFiltroOperador.AsString) = 'INICIA COM' then Condicao := (pos(retiraacentos(cdsfiltrovalor.asstring), RetiraAcentos(Aux)) = 1); if cdsfiltrooperador.asstring = '=' then Condicao := (RetiraAcentos(cdsFiltroValor.AsString) = RetiraAcentos(Aux)); if cdsfiltrooperador.asstring = '<>' then Condicao := (RetiraAcentos(cdsFiltroValor.AsString) <> RetiraAcentos(Aux)); if cdsfiltrooperador.asstring = '<' then Condicao := (Analisa(AuxField) < DefineTipo(AuxField, cdsfiltrovalor.asstring)); if cdsfiltrooperador.asstring = '<=' then Condicao := (Analisa(AuxField) <= DefineTipo(AuxField, cdsfiltrovalor.asstring)); if cdsfiltrooperador.asstring = '>' then Condicao := (Analisa(AuxField) > DefineTipo(AuxField, cdsfiltrovalor.asstring)); if cdsfiltrooperador.asstring = '>=' then Condicao := (Analisa(AuxField) >= DefineTipo(AuxField, cdsfiltrovalor.asstring)); if cdsfiltrooperlogico.asstring = '' then cdsfiltro.edit; cdsfiltrooperlogico.asstring := 'E'; cdsfiltro.post; if AnsiUpperCase(cdsFiltroOperLogico.AsString) = 'E' then Accept := Accept and Condicao else Accept := Accept or Condicao; except SinalExcecaoFiltro := True; raise exception.create('expressão inválida digitada no filtro:' + #13 + #10 + '' + #13 + #10 + cdsfiltrovalor.asstring + #13 + #10 + '' + #13 + #10 + 'Campos numéricos devem ser digitados com vírgulas decimais,' + #13 + #10'separadores de milhar não são permitidos' + #13 + #10 + 'e datas devem ser digitadas no formato dd/mm/aaaa.'); cdsfiltro.next; {if} Application.ProcessMessages; Listagem 2 funções auxiliares Function AchaCampo(CDS: TClientDataSet; Nome: String): TField; Var Begin Result := Nil; For I := 0 To CDS.FieldCount - 1 Do If ansiuppercase(cds.fields[i].fieldname) = ansiuppercase(nome) Then Result := CDS.Fields[I]; Function AchaCampoPorRotulo(CDS: TClientDataSet; Rotulo: String): TField; Var Begin Result := Nil; For I := 0 To CDS.FieldCount - 1 Do If ansiuppercase(cds.fields[i].displaylabel) = ansiuppercase(rotulo) Then Result := CDS.Fields[I]; Function Analisa(Campo: TField): Variant;

Begin Result := RetiraAcentos(Campo.AsString); If Campo.datatype In [ftdatetime, ftdate] Then Result := Campo.asdatetime; If Campo Is tnumericfield Then Result := Campo.asfloat; Function DefineTipo(Campo: TField; VALOR: String): Variant; Begin Result := RetiraAcentos(VALOR); If Campo.datatype In [ftdatetime, ftdate] Then Result := strtodate(valor); If Campo Is tnumericfield Then Begin VALOR := stringreplace(valor, '.', ',', [rfreplaceall]); Result := strtofloat(valor); Function RetiraAcentos(S: String): String; Var Begin S := ansiuppercase(s); For I := 1 To Length(S) Do Begin If S[I] In ['Á', 'À', 'Â', 'Ã', 'Ä'] Then S[I] := 'A'; If S[I] In ['É', 'Ê', 'È', 'Ë'] Then S[I] := 'E'; If S[I] In ['Í','Ì', 'Ï'] Then S[I] := 'I'; If S[I] In ['Ó', 'Ô', 'Õ', 'Ò', 'Ö'] Then S[I] := 'O'; If S[I] In ['Ú', 'Ü', 'Ù'] Then S[I] := 'U'; If S[I] In ['Ç'] Then S[I] := 'C'; Result := S; procedure DropDown; keybd_event(vk_menu, 0, 0, 0); keybd_event(vk_down, 0, 0, 0); keybd_event(vk_down, 0, KEYEVENTF_KEYUP, 0); keybd_event(vk_menu, 0, KEYEVENTF_KEYUP, 0); Listagem 3 outras ações da janela de filtragem procedure TFormFiltro.BFNovoClick(Sender: TObject); cdsfiltro.app procedure TFormFiltro.BFExcluirClick(Sender: TObject); cdsfiltro.delete; procedure TFormFiltro.BFLimparClick(Sender: TObject); cdsfiltro.emptydataset; cdslista.filtered := False; PainelFiltro.Visible := False; dbglista.setfocus;

procedure TFormFiltro.BFCancelarClick(Sender: TObject); PainelFiltro.Visible := False; dbglista.setfocus; procedure TFormFiltro.cdsFiltroAfterInsert(DataSet: TDataSet); dbgfiltro.selectedindex := 0; procedure TFormFiltro.FormKeyDown(Sender: TObject; Key: Word; Shift: TShiftState); // para que o usuário possa navegar pela grid usando TAB em vez de ENTER if Key = VK_RETURN then keybd_event(vk_tab, 0, 0, 0); case Key of VK_F2: BFNovo.click; VK_F4: BFExcluir.click; VK_F8: BFLimpar.click; VK_F9: BFCancelar.click; VK_F10: BFFiltrar.click; procedure TFormFiltro.dbgFiltroColEnter(Sender: TObject); NomeCampo: string; NomeCampo := dbgfiltro.selectedfield.fieldname; if (NomeCampo = 'Operador') or (NomeCampo = 'Campo') or (NomeCampo = 'OperLogico') then dbgfiltro.selectedfield.focuscontrol; DropDown; {função auxiliar} Roselito Fávero da Silva Matemático Atualmente Supervisor do setor de Informática da EMBRAPA Pecuária Sudeste E-mail: roselito@cppse.embrapa.br