Você está na página 1de 10

Delphi Resumo 07

Instrutor.: Luciano Ribeiro de Castro Validao e Pesquisas Exemplo: Cliente por Estado Iremos realizar algumas alteraes no formulrio "formConsClienteEstado", portanto , abra este formulrio. Atualmente este formulrio mostra todos os clientes cadastrados, vamos realizar uma procura onde iremos mostrar os Clientes por um determinado Estado escolhido pelo usurio. Altere a propriedade Caption para 'Cliente por Estado' e modifique tambm a propriedade Align do DBGrid para 'alBottom' e aumente o tamanho do fomulrio para acrescentar um Componente GroupBox( propriedade Caption para "Parmetros", como na figura abaixo: ) . Altere sua

Altere o nome do controle de edio para 'editEstado'e sua propriedade CharCase para 'ecUpperCase', deixe a propriedade Text vazia. Isso faz com que todas as letras digitadas sejam convertidas em maisculas. Chame o boto de 'btnProcurar' e mude sua propriedade Default para True. No evento OnClick do boto 'btnProcurar', vamos alterar a propriedade Filter do componente Table dinamicamente,com esta propriedade iremos definir um filtro que ir procurar os clientes que pertencem ao estado indicado.Digite o seguinte: tblCliente.Filter := 'Estado = ''' + editEstado.text + tblCliente.Filtered := true; tblCliente.Open; '''';

Note que para modificar a propriedade Filter, usamos vrios apstrofos na sintaxe. Cada dois apstrofos na string representam um apstrofo na string resultante. Por exemplo, se editEstado = 'GO' a string do Filter vai conter : Estado = 'GO' Mas a propriedade Filter funciona somente se a propriedade Filtered for True.Aps a alterao da propriedade necessrio abrir o componente Table novamente para ver o resultado. Salve o formulrio e execute. Para testar informe alguns estados e clique no boto 'Procurar'.

Notas: O paradox "case sensitive", portanto ele faz diferenciao entre letras maisculas e minsculas. Exceo somente quando cria um ndice secundrio para o campo e a opo "case sensitive" deve estar desmarcada. Exemplo: Clientes - Alterando Neste captulo, faremos vrias alteraes no formulrio "formCadCliente". Portanto, abra esse projeto. Note que ainda faltam no formulrio controles de dados para os novos campos que foram acrescentados por ltimo: CPF, Cidade e Estado. Os objetos foram criados , falta criar os controles de dados. Clique duas vezes em 'tblCliente' (o nico componente Table do formulrio) para abrir o editor de campos. Agora arraste, um de cada vez, os campos CPF, Cidade e Estado para o formulrio. Deixe o formulrio com a aparncia semelhante a figura abaixo:

Mantenha o editor de campos aberto. Validao de Campos e Registros Uma mscara de edio proporciona uma forma automtica de validao de campos, mas voc pode tambm adicionar seu prprio cdigo de validao, executado pelo Delphi quando for necessrio. Existem duas formas de validao: Validao de Campo: feita logo quando o usurio alterna para outro campo, no mesmo registro ou em outro. Se a validao falha, o usurio no consegue mudar de campo. Validao de Registro: feita apenas quando o usurio muda de registro, e se a validao falha, o usurio no pode mudar de registro. Pode ser usada para fazer uma verificao que envolva mais de um campo. Validando Campos Para fazer a validao de campo, voc deve tratar o evento OnValidate. Esse um evento do componente TField associado ao campo. Vamos adicionar uma validao ao campo CPF. Para este projeto foi criado uma unit independente chamada GeralVenda que contm uma funo para fazer a verificao do CPF, a idia no explicar como funciona a verificao de CPF , mas de como fazer esse tipo de verificao no Delphi, segue tambm nesta unit uma rotina para verificao de CGC.Ento iremos utiliz-la para verificar se um determinado CPF foi informado corretamente.O nome da funo ValidaCPF ela retorna true se o CPF estiver correto, temos que passar como parmetro um valor do tipo 'String'. Notas:Para verificar se um cpf vlido ou no, primeiro certifique que ele tenha 11 dgitos. Os dois ltimos dgitos so utilizados para verificao.

Declare algumas variveis: var soma, somaDig, pos, resto : smallint; A constante ordZero contm a posio do nmero 0 na tabela Ascii. A verificao do penltimo dgito feita atravs da soma dos dgitos at a posio , cada dgito necessrio multiplicar por 11 e subtrair pela sua posio, necessrio tambm ter a soma de todos os dgitos at a posio 9.. for pos := 1 to 9 do begin soma := soma + (ord(textoCPF[pos]) - ordZero) * (11 - pos); somaDig := SomaDig + (ord(textoCPF[pos]) - ordZero); end; Verificao do Penltimo Dgito: Divida o contedo da varivel soma por 11,faa a subtrao do resto pelo nmero 11 e atribua a uma varivel, se o contedo desta varivel for maior que 9, altere o contedo da variavel para 0, em seguida verifique se o contedo desta varivel diferente do penltimo digito do CPF, se for CPF invlido, caso contrrio necessrio verificar o ltimo dgito.

resto := 11 - soma mod 11; if resto > 9 then resto := 0; if resto <> ord(textoCPF[10] - ordZero then exit; {DV errado} Para verificar o ltimo dgito nessrio somar os resultados encontrados nos calculos anteriores. Ento Soma + SomaDig + 2 * resto , dividir este resultado por 11, o resto subtrair por 11 , se o resultado obtido for maior que 9 , atribuir 0 a esse resultado, em seguida verificar se o resultado encontrado igual ao ltimo dgito verificador , se for igual CPF Vlido. soma := soma + somaDig + 2 * resto; resto := 11 - soma mod 11; if resto > 9 then resto := 0; if resto <> ord(textoCPF[11]) - ordZero then exit; { segundo DV errado } Result := True; { tudo certo } No formulrio "formCadCliente" abra o editor de campos para tblCliente e clique no campo CPF na lista. No Object Inspector, abra a pgina de eventos e crie um procedimento de evento para OnValidate. Neste procedimento de eventos, adicione o seguinte: begin if not ValidaCPF(tblClienteCpf.value) then begin ShowMessage('CPF Invlido!'); Abort; end; end; A funo ValidaCPF verifica se o CPF esta correto.Caso esteja errado, o procedimento mostra uma mensagem, com ShowMessage e gera uma exceo com o procedimento Abort. Qualquer exceo gerada faz com que o Delphi cancele a movimentao de campo ou de registro, mas melhor usar Abort porque ele gera uma exceo silenciosa, da classe EAbort, que no mostra nenhuma mensagem de erro alm das mensagens do seu programa.

Antes de executar o programa na seo Implementation da Unit CADCLIENTE acrescente uma clausula uses para a unit independente: uses GeralVenda; Para adicionar a Unit ao projeto , no menu Project|Add to Project ( seguida clique no boto "Abrir". ), escolha a unit "GERALVENDAS.PAS" em

Execute o programa e veja o que acontece. Altere um registro existente, digitando um valor para o CPF, Invlido e tecle [Tab] para tentar mudar de campo. Voc deve digitar um valor vlido ou teclar [Esc] para retornar ao valor anterior do campo. importante notar que a validao de campo s acontece quando o usurio edita o campo. Um registro j existente, que tenha um valor invlido, no passar pela validao a no ser que o usurio altere o valor do campo CPF. Nota: Quando vrios controles esto associados ao mesmo campo, as alteraes de propriedade afetam todos eles. Validando Registros Para fazer uma validao de registro, voc pode utilizar o evento BeforePost do componente Table. Esse evento executado logo antes do registro ser gravado, seja um novo registro ou um registro j existente. Essa gravao pode ocorrer quando o usurio clica no boto do DBNavigator ou quando ele muda de registro, se o registro foi alterado.

Selecione o componente 'tblCliente', e na pgina de eventos, clique duas vezes no valor de BeforePost. Neste evento vamos fazer o seguinte: begin if tblClienteNome.IsNull then begin ShowMessage('O nome obrigatrio'); tblClienteNome.FocusControl; Abort; end; if tblClienteCidade.IsNull then begin ShowMessage('A cidade obrigatrio'); tblClienteCidade.FocusControl; Abort; end; end;

A propriedade IsNull de um componente TField retorna True se ele tem um valor nulo, isto , vazio, no informado. Se o campo estiver vazio, o procedimento mostra uma mensagem e chama o mtodo FocusControl do componente. Esse mtodo coloca o foco no controle de dados associado (com isso no preciso saber o nome do controle DBEdit ligado ao campo). Depois de fazer isso, o procedimento chama Abort para cancelar a gravao do registro. Com a validao de registro, o usurio s tem duas opes: ou digitar valores vlidos, ou cancelar a edio do campo, com o boto do DBNavigator. Execute o programa e note que agora essa validao tambm feita se voc incluir um registro e tentar grav-lo. Salve e execute o programa. Para testar crie um novo cliente , no informe seu nome , mas coloque o nome da cidade onde ele mora, ao salvar o cliente , o cliente no ser salvo enquanto no informar o seu nome. Notas: A verificao se um campo ou no obrigatrio pode ser no banco de dados e no Delphi podemos fazer a verificao atravs de erros.Veremos nos prximos captulos. Tratamento de Excees

Desmarque a opo " Stop on Delphi Exceptions" no menu Tools | Debugger Options | Language Exceptions. Mas tarde iremos entender o motivo. Observe que ao digitar uma data invlida , ocorre a seguinte mensagem:

Esta mensagem que aparece um erro de execuo, ou seja, uma mensagem do Delphi avisando de uma condio de erro.O termo usado no Delphi para essas situaes exceo.Uma exceo[exception] uma condio anormal que ocorre durante a execuo do programa, que interrompe o seu funcionamento. Quando ocorre uma exceo, o Delphi mostra uma mensagem padro e termina a execuo do procedimento de evento atual, mas continua a responder a eventos e executar o programa.Para qualquer exceo, voc pode fazer seu prprio tratamento, interceptando o tratamento do Delphi. Para tratar essa exceo voc tem que utilizar um evento que ocorra antes da mensagem de erro. Como o componente est associado a um objeto de campo , podemos fazer este tratamento nos eventos do objeto de campo. Clique duas vezes no componente tblCliente ( ) para abrir o editor de campos. Clique no campo "DataNasc" e crie um procedimento para o evento OnSetText . Esse evento executado todas as vezes que alterado o contedo do objeto de campo. Neste procedimento o parmetro "Text" contm o valor da data informada. Coloque o cdigo a abaixo: var Data : TDateTime; begin try data := strtodate(text); tblClienteDataNasc.asDatetime := data; except on EConvertError do begin showmessage('Data Invlida!'); abort; end; end; end; O comando try (tentar) um comando de tratamento de excees. Os comandos entre o try e o except so executados, mas se ocorre alguma exceo nesse bloco, o Delphi sai do bloco e entra na parte except[exceto]. Ento o Delphi procura uma clusula on correspondente classe da exceo gerada. Se ele encontra um on correspondente, ele executa o comando de tratamento associado. Depois de executar o tratador, o Delphi no termina a execuo do procedimento de evento, mas continua a execuo com o prximo comando depois do end do try. A funo strtodate converte uma varivel do tipo string para data, caso ocorra algum erro gera uma exceo da classe 'EConvertError', se ocorrer a exceo mostramos a mensagem 'Data Invlida' , em seguida o comando abort executado ,es este comando cancela o procedimento, se ele no for colocado a mensagem do Delphi ir continuar aparecendo. Quando colocamos algum procedimento para este evento , ao sair do procedimento a data informada no ser colocada no objeto de campo, por isso que atribuimos o valor da data ao objeto 'tblClienteDataNasc'.

Visualizando Informaes sobre Excees Se a opo " Stop on Delphi Exceptions" estiver marcada , o Delphi mostra uma mensagem mais detalhada sobre cada exceo e mostra exatamente qual a linha que causou a exceo. Para verificar esta opo no menu Tools | Debugger Options | Language Exceptions e marque a opo " Stop on Delphi Exceptions". Agora execute o programa e provoque uma exceo, cadastrando um data invlida para a data de nascimento'. Nesse caso a mensagem ser:

ou seja , o projeto causou uma exceo da classe 'EConvertError'. O nome da classe de exceo uma informao importante quando voc fizer o tratamento da exceo no programa. Para continuar a execuo, tecle[F9] ou clique no boto (Run). Depois ir aparecer a mensagem que colocamos ( caso no tenha tratado a exceo aparece a mensagem do Delphi). Classes de Excees Quando voc faz o tratamento de excees, pode trat-las a nvel especfico de cada exceo ou voc pode tratar uma classe de exceo mais geral. As classes fazem parte de uma hierarquia de excees, como a seguinte: Exception (qualquer exceo) EIntError (erros de nmeros inteiros) EDivByZero (diviso por zero de inteiro) EIntOverflow (transbordo inteiro) ERangeError (valor ou ind. vetor fora de faixa) EMathError (erros de matemtica real) EOverflow (transbordo de real) EUnderflow (valor muito peq. de real) EZeroDivide (diviso por zero de real) Se voc criar uma clusula de tratamento para uma exceo mais geral, como 'EMathError', ela ser acionada para qualquer uma das classes abaixo na hierarquia, seja diviso por zero (EZeroDivide), transbordo de valor (EOverflow) ou qualquer outra. A classe Exception o nvel mais geral de tratamento e intercepta qualquer exceo.

Se num conjunto de tratadores, voc colocar um tratador primeiro para uma exceo mais geral e depois para uma exceo especfica, o tratador mais especfico nem vai chegar a ser executado. Notas: O tratamento de exceo pode ser feito em qualquer procedimento que julgar necessrio. Pesquisas na Tabela Uma caracterstica fundamental de um programa permitir que o usurio faa uma pesquisa em uma tabela, fornecendo o valor a ser pesquisado. Na tabela de clientes, vamos facilitar a pesquisa pelo nome do cliente. Adicionando um DBGrid

Para isso vamos adicionar ao formulrio um controle DBGrid, que vai mostrar toda a lista de clientes, permitindo selecionar qualquer um deles. Abra um espao adicional direita do formulrio e acrescente um componente Label, com o texto "Procura:" e um componente Edit (no use um DBEdit), com o nome de "editProcura". Abaixo deles acrescente um componente DBGrid (cone da pgina Data Controls). O formulrio deve ficar como o seguinte:

Agora associe a grade (DBGrid) com a tabela, alterando sua propriedade DataSource para 'dsCliente'. Com isso, se a tabela estiver ativa, ele vai automaticamente mostrar todos os campos e todos os registros da tabela. No vamos permitir que o usurio altere os dados usando o grid. Para isso basta mudar a sua propriedade ReadOnly para True. Vamos restringir os campos mostrados apenas ao campo "Nome". Para isso, clique duas vezes em 'tblCliente' para abrir o editor de campos, selecione todos os campos menos Nome e altere a propriedade Visible para False. Se preciso, reduza o DisplayWidth para que o valor do campo aparea todo no Grid. Algumas caractersticas de visualizao do DBGrid no so necessrias aqui, como as linhas divisrias de registros e campos, ou os ttulos da parte de cima. Vamos desativar essas caractersticas, alterando a propriedade Options.

Expanda essa propriedade no Object Inspector e altere as seguintes opes: Opo Valor Finalidade dgEditing False no permite incluir ou excluir dgTitles False desativa os ttulos dgIndicator False desativa o indicador de registro dgColLines False desativa as linhas verticais dgRowLines False desativa as linhas horizontais dgTabs False no usa [Tab] para mudar de campo dgAlwaysShowSelection True sempre mostra a linha selecionada Se a opo 'dgAlwaysShowSelection' estiver desativada, o grid s mostra qual a linha selecionada (a do registro atual) quando ele tem o foco de teclado. Ns devemos ativ-la para que o usurio saiba qual o nome selecionado na lista a qualquer momento. Execute o programa e verifique. Voc pode clicar na grade a qualquer momento para selecionar um dos registros, ou usar o DBNavigator para percorrer os registros. Nota: existem duas opes parecidas: dgAlwaysShowEditor e dgAlwaysShowSelection. Para visualizar melhor as opes, aumente a largura do Object Inspector.

Utilizando um ndice Secundrio Mas h um problema: a grade mostra os dados ordenados pelo ndice principal da tabela, que no caso o ndice no campo CodCliente. Para facilitar a pesquisa, eles deveriam estar ordenados por nome. Para mudar a ordem dos registros, podemos usar um ndice diferente. Para ordenar por nome, que o necessrio, precisamos usar o ndice criado para o campo Nome. Para isso, basta alterar a propriedade IndexName do componente Table. Se ela estiver vazia, a ordem dos registros ser determinada pelo ndice primrio da tabela. Se voc colocar o nome de um ndice secundrio, a ordem ser de acordo com esse ndice. Essa propriedade afeta tanto a ordem virtual dos registros, quanto as pesquisas que voc fizer, como veremos. Clique na propriedade IndexName e selecione o nome "IndNome" da lista. Esse o nome do ndice secundrio criado. Note como a ordem dos registros alterada no controle DBGrid. Se voc apagar o valor de IndexName, a ordem volta a ser a do campo CodCliente. Alm da propriedade IndexName, existe outra chamada IndexFieldNames, que tem a mesma funo. O valor desta propriedade a lista dos campos que compem o ndice. Por exemplo, voc poderia colocar "Nome" em IndexFieldNames e teria o mesmo efeito. Isto til se voc no souber o nome do ndice, mas se souber quais os campos que fazem parte dele. As duas propriedades so mutuamente exclusivas: se voc altera uma, a outra ter seu valor eliminado. Pesquisando pelo Nome Os controles acima do DBGrid sero usados para permitir pesquisa na tabela pelo nome do cliente. A cada digitao do usurio, vamos posicionar a tabela no nome mais prximo. Para isso, vamos usar o mtodo FindNearest do componente Table. Esse mtodo procura um valor na tabela utilizando o ndice atual. Se o valor no for encontrado exatamente, ele posiciona no registro mais prximo. Selecione o controle 'editProcura' e crie um procedimento para o evento OnChange. Esse evento executado toda vez que o usurio altera o valor do controle, digitando ou apagando caracteres. No procedimento basta colocar o seguinte:

begin tblCliente.FindNearest([editProcura.Text]); end; Execute e verifique o resultado. Quando voc digita um nome em 'editProcura', o valor mais prximo selecionado. Isso chamado de busca incremental. Nota: se o ndice tiver mais de um campo, coloque em IndexFieldNames os nomes de campos separados por ponto-evrgula ";", sem espaos. Nota: quando voc clica num cone da paleta de componentes e depois em cima de um componente, aquele que voc criou fica contido no primeiro, isto , restrito rea do componente e os dois so movimentados em conjunto. Pesquisando pelo Cdigo Agora vamos dar ao usurio a opo de procurar um registro pelo valor do campo cdigo, que tambm tem um ndice definido (o ndice primrio da tabela). Para isso, abra um espao na parte inferior do formulrio. Vamos colocar nesse espao um componente GroupBox, que usado para agrupar visualmente outros componentes. Selecione o cone do GroupBox na pgina standard e coloque-o no formulrio. Coloque na sua propriedade Caption o texto "Procura por cdigo". Dentro do componente GroupBox, crie um label, um quadro de edio e um boto, como na figura abaixo:

Mude o Caption do label para "Cdigo:". Mude o Name do componente Edit para 'editProcCodigo' , a propriedade Text deixe vazia e o nome do boto para 'btnProcCodigo' e altere a propriedade caption para "Procurar". Agora clique duas vezes no boto Procurar. Neste procedimento, vamos usar o valor digitado para pesquisar na tabela, usando o mtodo FindKey. Como vamos pesquisar por um campo diferente, devemos alterar a propriedade IndexName do componente dinamicamente, e depois retorn-la ao original. Isso gera um pequeno problema ao alterar essa propriedade, os controles do formulrio vo mudar para refletir o novo ndice. Isso pode ser evitado com o mtodo DisableControls do componente Table. Quando ele chamado, os controles de dados no atualizam mais seus valores at que o mtodo EnableControls seja chamado. Com isso, coloque o seguinte no cdigo do procedimento:

var codigo: integer; begin codigo := StrToInt(editProcCodigo.Text); with tblCliente do try DisableControls; IndexName := ''; {usando ndice primrio} if not FindKey([codigo]) then ShowMessage('Codigo no encontrado'); finally IndexName := 'IndNome'; {usando ndice por Nome} EnableControls; end; end; O mtodo FindKey uma funo que retorna True se encontrou o registro. Caso ele encontre, ele posiciona no registro, seno mantm posicionado no registro atual. Blocos Protegidos Os tratamentos de erros no Delphi podem ser feitos para uma exceo especfica. As vezes , no necessrio tratar um exceo especfica , mas preciso realizar uma ao de finalizao, O finally utilizado quando uma determinada exceo ocorre , e necessitamos executar de qualquer forma um determinado comando ou vrios comandos antes de interromper o procedimento. Esses comandos devem ser colocados no trecho finally..end. Em geral , blocos protegidos podem ser usados em qualquer situao que envolva uma alocao e liberao de recursos(como um arquivo , por exemplo). No procedimento de evento do OnClick observe que a alterao de IndexName e a chamada de EnableControls so feitas no bloco finally. Isso significa que mesmo que acontea uma exceo, esses comandos so executados. Isso importante, pois se esse tipo de tratamento no for feito, os controles de dados podem ficar num estado desabilitado, e o usurio no conseguiria mais utilizar o programa. Execute e verifique o resultado. Se voc digitar um cdigo e clicar no boto Procurar, o programa vai tentar procurar o registro.

Usando Outros Controles de Dados Alm dos controles DBEdit e DBGrid, que j utilizamos, a pgina Data Controls contm vrios outros que so teis nos programas. Usando o DBComboBox

Os controles DBListBox (

) e DBComboBox (

) so equivalentes, respectivamente, aos controles padro

) e ComboBox ( ), da pgina Standard. Ambos mostram uma lista de nomes (definida pela ListBox ( propriedade Items) e permitem que o usurio escolha um dos itens da lista. Os controles ComboBox e DBComboBox mostram a lista fechada, com um boto de seta que permite o usurio selecionar um valor, enquanto que ListBox e DBListBox mostram a lista sempre aberta. Os controles da pgina Data Controls, alm da mesma funo que seus equivalentes na pgina Standard, ainda tm a capacidade de ler e gravar um valor no banco de dados.

O campo Estado da tabela pode utilizar uma lista de valores, com os nomes de estados possveis. Para isso, vamos utilizar um controle DBComboBox. Apague o controle DBEdit relacionado ao Estado e substitua por um DBComboBox ( ), na mesma posio do anterior.

A propriedade Style de uma combo box determina se ela permite digitao de um valor que no est na lista. O valor padro 'csDropDown', que permite digitar, alm de escolher da lista. O valor 'csDropDownList' probe digitao o usurio s pode escolher um valor da lista. Altere para 'csDropDownList. Associe o controle com o campo da tabela: em DataSource, selecione 'dsCliente' e em DataField selecione "Estado". Agora vamos preencher a lista dos valores possveis da combo box. Para isso, clique na propriedade Items e abra o seu editor. Agora, em cada linha, digite uma sigla de estado (para simplificar, digite apenas as que estiverem presentes nos seus dados de teste). No preciso se preocupar com a ordem alfabtica: AM, PA, RR, RO, AC, GO, TO, MT, MS, SE, SP, RJ, MG, ES, BA, AL, MA, CE, PI, RS, SC,DF. Para colocar todos os itens da lista em ordem alfabtica, altere a propriedade Sorted para True. Execute o programa e veja a diferena. Agora o usurio, ao invs de digitar a sigla do estado, pode selecionar a partir da lista. Para usar a combo box pelo teclado, sem usar o mouse, use as setas [ ] e [ ] para se movimentar pelos itens, ou digite [Alt+ ] ou [Alt+ ] para abrir ou fechar a lista. Quando a lista est aberta, use as setas para escolher um item e tecle [Enter] para selecionar, ou [Esc] para fechar a lista. Se voc teclar uma letra, a combo box seleciona o primeiro item que comea com essa letra e, se voc continuar repetindo a tecla, seleciona os prximos. Em alguns casos, a lista de valores no fixa no programa, mas deve ser criada dinamicamente. Nesse caso, preencha a propriedade Items em tempo de execuo, usando o mtodo Add: cboEstado.Items.Add(sigla); Nota: quando os dados vm de outra tabela, existe uma forma mais fcil, que utilizar o controle DBLookupComboBox ( ), como veremos mais tarde.

Você também pode gostar