Escolar Documentos
Profissional Documentos
Cultura Documentos
8 Formulários Mestre-Detalhe....................................................................... 02
8.1 Exercício..................................................................................................... 03
9 TdataModule............................................................................................... 04
9.1 Diagramas de Dados.................................................................................. 05
9.2 Exercício .................................................................................................... 06
10 Implementando Filtros em Tabelas............................................................ 07
10.1 Exercício..................................................................................................... 08
11 Indexação de Tabelas................................................................................ 08
11.1 Exercício..................................................................................................... 09
11.2 Ativando um Indice Secundário para uma Tabela...................................... 10
11.3 Exercício..................................................................................................... 10
12 Localizando Registros................................................................................ 10
12.1 Método FindKey.......................................................................................... 12
12.2 Método FindNearest....................................................................................12
12.3 Método Locate............................................................................................ 12
12.4 Exercício..................................................................................................... 13
13 Verificando Alterações................................................................................ 16
14 Valores Default .......................................................................................... 16
15 Percorrendo uma Tabela........................................................................... 16
16 Fields Editor............................................................................................... 17
17 TField......................................................................................................... 17
18 Conversão de Tipos................................................................................... 19
19 Validação de Campos................................................................................ 20
20 Formatação Personalizada ....................................................................... 20
21 Campos Calculados .................................................................................. 21
22 Campos LookUp........................................................................................ 21
23 Tratamento de Exceções - Aplicações Robustas...................................... 22
23.1 Blocos Protegidos..................................................................................... 22
23.2 Blocos de Finalização............................................................................... 23
23.3 Principais Classes de Exceções Disponíveis .......................................... 24
23.4 Erros de Bancos de Dados....................................................................... 25
24 Bibliografia................................................................................................. 26
Nos relacionamentos de 1 para N, uma tabela pode estar ligada a outra em uma
relação Mestre/Detalhe, nesse tipo de relação os registros da tabela de ordem N são
filtrados pelo campo de relacionamento com a tabela de ordem 1. Por exemplo, se o
relacionamento de Clientes com Pedidos for mestre/detalhe, só serão acessados em
pedidos, os registros cujo campo CodCli seja igual ao CodCli da tabela de Clientes.
Para utilizar esse tipo de relacionamento, considerando a estrutura das duas tabelas de
exemplo, siga os passos abaixo:
8.1 - Exercício:
Æ Com base nos passos descritos acima, crie as tabelas de Pedidos e Itens propostas
no exemplo e construa um form mestre-detalhe conforme modelo abaixo:
Caso já exista uma cláusula uses, apenas acrescente a unit do DataModule junto com
as demais, separando por vírgula:
...
implementation
Uses UClientes, UCidades, UDataModule;
DataModule.tabClientes.Insert;
Mas isso ainda não é tudo, temos também a possibilidade de visualiza os campos de
cada tabela, veja abaixo:
9.2 - Exercício:
Exemplos:
TabPedidos.Filter := ‘DATA >= ‘’01/03/2004’’ AND DATA <= ‘’10/03/2004’’’;
tabPedidos.Filtered := True;
Neste caso, a condição do filtro fica fixa, e só terá efeito quando a propriedade Filtered
estiver ativada. No exemplo abaixo é usado o evento OnClick de um Button para ativar
o filtro:
Para tornar este filtro dinâmico, em vez de especificar as datas literalmente no código,
podemos nos utilizar de variáveis, ou então, ler a data diretamente de um componente
MaskEdit.
Æ Utilizando-se dos conhecimentos adquiridos sobre o uso dos filtros, implemente com
base no exercício anterior um filtro capaz de filtrar os registros da tabela de pedidos
com base no campo DATA. Veja um modelo abaixo:
A indexação é usada para ordenar os registros da tabela, com base em uma ou mais
colunas (campos). A forma mais prática para a criação dos índices é através do
DataBase Desktop que utilizamos para criar as tabelas do banco de dados. Com ele,
um índice pode ser criado no momento da criação da tabela ou após.
Siga os passos abaixo para criar um índice para a tabela de pedidos usada nos
exemplos anteriores, que permita ordenar seus registros pela DATA de emissão, e
outro para ordenar pelo código do cliente (COD_CLIENTE).
11.1 – Exercício
Æ Repita os mesmos passos para criar o índice pelo campo COD_CLIENTE.
tabPedidos.IndexName := ‘indDATA’;
Comp. TcomboBox
da paleta Standard Comp. Tbevel da
paleta Additional
12 - Localizando Registros
Para localizar registros você pode usar vários métodos do objetop TTable dentre eles o
FindKey, FindNearest e Locate, mas o mais prático deles é o Locate. Vamos ver um
exemplo de cada.
FindKey é uma função que procura por registros cujos valores indicados coincidam
com o(s) respectivos campos, retornando TRUE se a busca foi bem sucedida ou
FALSE caso contrário. A pesquisa é sempre exata. Para tabelas Paradox e dBase,
FindKey requer sempre um índice ativo na tabela.0
Sintaxe:
function FindKey(const KeyValues: array of const): Boolean;
KeyValues deverá conter um vetor de valores separados por vírgula os quais irão
compor a chave de pesquisa. A ordem dos valores informados no vetor deve obedecer
a composição do índice a ser usado. Por exemplo: supondo que o indice de uma
determinada tabela seja composto pelos campos COD_CLIENTE+DATA_VENDA a
linha de código ficaria assim:
FindNearest Realiza uma pesquisa aproximada (não exata). Pode ser utilizada por
exemplo para localizar um cliente quando tivermos à mão apenas o primeiro nome do
mesmo. Também requer que a tabela possua um índice ativo.
Sintaxe:
procedure FindNearest(const KeyValues: array of const);
KeyValues deverá conter um vetor de valores separados por vírgula os quais irão
compor a chave de pesquisa. A ordem dos valores informados no vetor deve obedecer
a composição do índice a ser usado. Veja um exemplo supondo que a tabela esteja
indexada pelo campo NOME:
Table1.FindNearest([‘JOÃO’]);
O exemplo acima irá localizar o primeiro registro cujo o valor do campo NOME comece
com a string ‘JOÃO’.
Sem dúvida, este é o método mais prático e flexível para pesquisa. O mesmo não
requer que a tabela esteja indexada pelos campos a serem pesquisados. Por este fato,
este método quando usado em campos que não façam parte de índices, não possui a
mesma performance dos demais, mas esta queda de performance é quase
impercebível.
Você também pode fazer uma pesquisa parcial e/ou não case sensitive usando o
terceiro parâmetro, que é um conjunto de duas opções.
Se você precisar fazer uma pesquisa por mais de um campo, separe os nomes dos
campos por ponto e vírgula e use a função VarArrayOf para criar um array com os
valores que você quer procurar.
Caso os campos pesquisados sejam indexados, a pesquisa será muito mais eficiente,
senão será criado um filtro temporário da BDE para localizar os registros.
12.4 - Exercício
Æ Para praticar vamos incrementar um pouco mais nosso projeto exemplo. Siga os
passos abaixo:
Componente TmaskEdit
Name: medPesquisa
Text: ‘’
Componentes TButton
Name: btnFindKey, btnFindNearest, btnLocate
Onde for necessário a verificação de alterações feitas em uma Tabela, por exemplo no
evento OnClose de um Form de manutenção, você pode usar a propriedade Modified,
como mostrado no exemplo abaixo.
14 - Valores Default
Sempre que for necessário especificar valores Default (valores padrão) para os campos
de uma tabela, use o evento OnNewRecord, pois nesse evento o registro não é
marcado como modificado.
16 - Fields Editor
Para criar objetos para os campos de uma tabela clique duas vezes
no componente TTable ou escolha Fields Editor. Na janela do Fields
Editor, clique com o botão direito do mouse para acessar o menu de
contexto e escolha Add, na janela Add Fields, escolha os campos
que você vai querer usar e clique em Ok.
No Fields Editor podemos também remover os campos criados, alterar sua ordem de
apresentação e usar suas propriedades e eventos no Object Inspector. Para cada
campo é criado um objeto de um tipo descendente de TField, como TStringField,
TIntegerField, TFloatField. As principais propriedades dos objetos TField estão listadas
na tabela abaixo.
Se você não criar nenhum objeto TField, todos os campos da tabela estarão
disponíveis, mas caso você crie algum, somente os campos que você criar estarão
disponíveis.
Se você selecionar os campos no Fields Editor e arrastar para o Form, serão criados os
controles visuais para esses campos, Label, DBEdit e outros, mas antes coloque a
descrição dos campos na propriedade DisplayLabel, ou então, após, altere a
propriedade caption dos objetos TLabel criados na operação de arrastar e soltar os
campos sobre o Form.
17 - TField
A classe TField é usada como ancestral para todos as classes dos campos.
Geralmente iremos usar objetos de classes descendentes de TField, mas em todos
eles podemos encontrar os itens mostrados abaixo.
Propriedades Descrição
Alignment Alinhamento do texto do campo nos controles visuais
AsBoolean Valor do campo convertido para Boolean
AsCurrency Valor do campo convertido para Currency
AsDateTime Valor do campo convertido para DataTime
AsFloat Valor do campo convertido para Double
AsInteger Valor do campo convertido para Integer
AsString Valor do campo convertido para string
AsVariant Valor do campo convertido para Variant
Calculated Indica se o campo é calculado em tempo de execução
CanModify Indica se um campo pode ser modificado
Estão listadas abaixo algumas classes que realmente iremos manipular no tratamento
dos campos de uma tabela, são classes descendentes de TField.
TStringField TBlobField TTimeField
TSmallintField TIntegerField TBytesField
TFloatField TWordField TVarBytesField
TCurrencyField TAutoIncField TGraphicField
TBooleanField TBCDField TMemoField
TDateField TDateTimeField
Autor: Prof. José Luís Schiavo 18
Em alguns desses campos você pode encontrar as propriedades mostradas abaixo,
que não estão presentes em TField.
Propriedades Descrição
MaxValue Valor máximo para o campo
MinValue Valor mínimo para campo
DisplayFormatFormato de apresentação do campo, como ,0.00” %” ou ,0.##” Km”
EditFormat Formato de edição do campo
Currency Define se um campo é monetário
DisplayValuesUsado com campos Boolean, define o texto para True e False, como
Sim;Não
Métodos Descrição
LoadFromFile Carrega o conteúdo do campo de um arquivo
SaveToFile Salva o conteúdo do campo para um arquivo
Para acessar (ler ou gravar) os campo de uma tabela, existem várias abordagens,
como mostrado abaixo:
tabPedidosData.Value := Date;
tabPedidos['Data'] := Date;
tabPedidos.FieldByName('Data').Value := Date;
tabPedidos.Fields[1].Value := Date;
18 - Conversão de Tipos
A conversão de tipo de um campo pode ser feita através das propriedades tipo As...,
como AsDateTime, AsString, AsInteger, AsFloat, AsBoolean, AsCurrency, etc. Veja:
tabPedidosData.AsString := edtData.Text;
tabPedidoData.AsDateTime := StrToDate(edtData.Text);
20 - Formatação Personalizada
Caso queira-se fazer uma formatação personalizada para os campos da tabela, pode-
se usar os eventos OnGetText e OnSetText de cada campo. Por exemplo, se tiver um
campo chamado EstadoCivil definido para armazenar apenas 1 caracter, e quiser que
quando o valor do campo for ‘C‘ seja mostrado ‘Casado’ e quando for ‘S’, ‘Solteiro’, ou
seja, pode-se armazenar apenas 1 caracter mas quando o valor do campo for exibido,
será exibido o novo valor atribuido à variável Text, como no exemplo abaixo:
Como controle visual para o usuário escolher o valor do campo, você poderia usar o
componente DBComboBox, com Solteiro e Casado na propriedade Items, e no evento
OnGetText do campo o código do exemplo acima.
Campos Calculados, são campos que existem apenas em tempo de execução (no caso
das bases de dados padrão xBase: Paradox, dBase, etc), sendo assim, não há um
campo definido fisicamente na tabela do banco de dados.
Para criar campos calculados, clique com o direito no Fields Editor e escolha New
Field, no quadro NewField, digite o “nome” do campo a ser criado, o tipo do campo, seu
tamanho e escolha Calculated em Field type.
O código do evento OnCalcFields deve ser enxuto, pois este é chamado várias vezes
durante a edição de um registro e um procedimento pesado pode comprometer a
performance do sistema. Veja um exemplo:
Obs.:
- A tabela é aberta.
- a Tabela e colocada em modo de edição.
- o Foco é movido de um controle para outro, ou de uma coluna para outra no
caso de um TDBGrid e quando alterações são feitas no registro.
- Quando um registro é recuperado do banco de dados.
22 - Campos LookUp
Para criar um campo Lookup, siga os passos abaixo, tomando como exemplo o caso
do cadastro de livros:
• Abra o Fields Editor do Table “tabLivros”
Autor: Prof. José Luís Schiavo 21
• Clique com o direito e escolha New Field
• No quadro New Field, escolha as propriedades do campo como descrito em
campos calculados, mas em Field type, escolha Lookup
• Em Key Fields escolha o campo da tabela (detalhe - tabLivros) que faz parte do
relacionamento, CodAutor
• DataSet é a tabela de Autores (mestre – tabAutores)
• Em Lookup Keys, escolha o campo da tabela (mestre - tabAutores) que faz parte
do relacionamento, CodAutor
• Finalmente, escolha em Result field o campo da tabela mestre que vai ser
mostrado para o usuário, NomeAutor
Quando esses campo são exibidos em um DBGrid, por padrão é criado um botão de
lookup que mostrará os valores da outra tabela em uma lista. Para colocar esses
campos em um Form, devemos usar o DBLookupComboBox, apenas com as
propriedades padrão, ListSource, ListField, KeyField, DataSource e DataField. Quando
você arrastar o campo lookup para o Form isso será feito automaticamente.
Para que uma aplicação seja segura, seu código necessita reconhecer uma exceção
quando esta ocorrer e responder adequadamente a essa exceção. Se não houver
tratamento para uma exceção, será exibida uma mensagem padrão descrevendo o erro
e todos os processamentos pendentes não serão executados. Uma exceção deve ser
tratada sempre que houver perigo de perda de dados ou de recursos do sistema.
Exceções
Exceções são classes definidas pelo Delphi para o tratamento de erros. Quando uma
exceção é criada, todos os procedimentos pendentes são cancelados e, geralmente é
mostrada uma mensagem de erro para o usuário. As mensagens padrão nem sempre
são claras, por isso é indicado criar seus próprios blocos protegidos.
try
Soma := StrToFloat(EdtSoma.Text);
NumAlunos := StrToInt(EdtNum.Text);
ShowMessage(Format('Média igual a %f.', [Soma / NumAlunos]));
except
on EConvertError do
ShowMessage('Valor inválido para soma ou número de
alunos.');
on EZeroDivide do
ShowMessage('O nº de alunos tem que ser maior que zero.');
else
ShowMessage('Erro na operação, verifique os valores
digitados.');
end;
Blocos de finalização são executados sempre, haja ou não uma exceção. Geralmente
os blocos de finalização são usados para liberar recursos alocados previamente ou
restaurar alguma configuração, como o cursor do mouse por exemplo, veja:
Try
Screen.Cursor := crHourGlass; // ampulheta
// comando 1
// comando 2
// comando n
finally
Screen.Cursor := crDefault; // seta padão
end;
Try
Screen.Cursor := crHourGlass; // ampulheta
try
Tbl.Edit;
TblValor.AsString := EdtValor.Text;
except
on EDBEngineError do
ShowMessage('Alteração não permitida.');
on EConvertError do
ShowMessage('Valor inválido.');
end;
finally
Screen.Cursor := crDefault; // seta padão
end;
Autor: Prof. José Luís Schiavo 23
23.3 - Principais Classes de Exceções Disponíveis
O Delphi define muitasclasses de exceções, para cada tipo de erro existe uma classe
correspondente.
Classe Descrição
Exception Exceção genérica, usada apenas como ancestral de todas as
outras exceções
EAbort Exceção silenciosa, pode ser gerada pelo procedimento Abort e
não mostra nenhuma mensagem
EAccessViolation Acesso inválido à memória, geralmente ocorre com objetos não
inicializados
EConvertError Erro de conversão de tipos
EDivByZero Divisão de inteiro por zero
EinOutError Erro de Entrada ou Saída reportado pelo sistema operacional
EintOverFlow Resultado de um cálculo inteiro excedeu o limite
EinvalidCast TypeCast inválido com o operador as
EinvalidOp Operação inválida com número de ponto flutuante
EOutOfMemory Memória insuficiente
EOverflow Resultado de um cálculo com número real excedeu o limite
ERangeError Valor excede o limite do tipo inteiro ao qual foi atribuída
EUnderflow Resultado de um cálculo com número real é menor que a faixa
válida
EVariantError Erro em operação com tipo variant
EZeroDivide Divisão de real por zero
EDatabaseError Erro genérico de banco de dados, geralmente não é usado
diretamente
EDBEngineError Erro da BDE, descende de EDatabaseError e traz dados que
podem identificar o erro
Você também pode criar um procedimento que faça o tratamento do erro que possa ser
usado em toda a aplicação:
End;
end;
try
tabClientes.Post;
except
on E: EDBEngineError do
TrataErro(E);
end;
Note que a variável E, que vai identificar o erro, só precisa ser declarada no bloco de
tratamento da exceção. No help você pode consultar outras propriedades de
EDBEngineError que podem ser importantes.
Delphi 3 Total
Maurício B. Longo
Ronaldo Smith Jr.
Editora Brasport
Aplicações em Delphi
Adelize Generini de Oliveira
Editora Visual Books
Help do Delphi 5
Sites da Internet:
http://www.clubedelphi.com.br/
http://www.dugbr.com.br/
http://www.ramosdainformatica.com.br/
http://www.activedelphi.com.br/
http://www.delphibr.com.br/
http://www.borland.com.br/
Fórum de Discussão:
http://forum.abril.com.br/info/areas.php => Delphi