Você está na página 1de 27

Escola Técnica Machado de Assis

Curso Técnico em Informática

Linguagem de Programação III


Módulo IV

Professor: José Luís Schiavo


SUMÁRIO

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

Autor: Prof. José Luís Schiavo 1


8 – Formulários Mestre-Detalhe

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:

Pedidos.db (Mestre) Itens.db (Detalhe)


NUMERO I * NUM_PEDIDO I *
DATA D COD_PRODUTO I *
DATA_ENT D QUANTIDADE N
COD_CLIENTE I VLR_UNIT N
VLR_TOTAL N VLT_TOTAL N

1) Em um formulário ou DataModule, coloque um componente TTable, ligando-o com


a tabela de Pedidos (tabPedidos) e um TDataSource para esta tabela (dsPedidos).
Após, insira mais um TTable e ligue-o com a tabela de Itens (tabItens) e um
TDAtaSource para ela (dsItens)
2) O procedimento 1 é padrão, e tudo é feito como se estivéssemos configurando os
componentes para trabalharem isolados. Porém, para utilizarmos o relacionamento
existente entre as duas tabelas acima (1 para N) e criarmos um form mestre-
detalhe, vamos precisar relacionar os dois componentes TTable (tabPedidos e
tabItens) através das propriedades MasterSource e MasterFields do componente
table ligado à tabela detalhe. Para isso, faça o seguinte:

• Selecione o TTable “tabItens”


• Em sua propriedade MasterSource, selecione o TDataSource da tabela
Mestre (dsPedidos)
• Em sua propriedade MasterFields, clique no botão pontilhado apresentado
quando você selecionar propriedade. Será exibida a tela abaixo:

Autor: Prof. José Luís Schiavo 2


• Selecione o campo NUM_PEDIDO na coluna Detail Fields e o campo NUMERO na
coluna Master Fields, após clique no botão “Add” para adicionar. Veja o resultado
abaixo, a caixa “Joined Fields” mostra o relacionamento entre os campos.

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:

Autor: Prof. José Luís Schiavo 3


9 - TDataModule

Um DataModule é como se fosse um Form invisível, onde iremos inserir os


componentes de acesso a dados, como o Table e o Datasource. Para inserir um
DataModule em um projeto, escolha New DataModule do menu File. Os DataModules
não consomem recursos do sistema, servem apenas para “conter” os componentes de
acesso a dados. Funcionam como “Depósitos de Objetos”.

Uma das maiores vantagens no uso do TDataModule é a centralização dos


componentes de acesso a dados, ou seja, estes não ficarão espalhados pelos diversos
forms do projeto, o que facilita o gerenciamento e a manutenção de grandes projetos.

Todos os componentes deverão ser inseridos na guia “Components”, conforme


demonstrado na figura acima. À medida que os componentes forem inseridos e
configurados, é exibido na caixa da esquerda “Tree View” em forma de uma estrutura
em árvore, todas as tabelas com a definição dos campos, indices, etc. de cada uma
delas.

Mas você pode estar pensando: se os componentes como o TTable e o TDataSource


ficarão no TdataModule, como então iremos conectar estes componentes aos nossos
forms? A resposta é simples: Adicionando a Unit do TdataModule à cláusula USES do
form! Para fazer isso manulamente, vá para o editor de código do form desejado e,
logo no início da sessão implementation, logo após a palavra implementation,
acrescente a seguinte linha de código:
...
implementation
Uses UDataModule;

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;

Para acessar os métodos e propriedades dos objetos TTable do TdataModule a partir


de um form, você precisará colocar à frente(antes) do nome do objeto TTable o nome
do TdataModule mais um ‘.’ . por exemplo: suponha que você vá escrever o código
Autor: Prof. José Luís Schiavo 4
para o evento OnClick de um TButton, o qual terá a finalidade de inserir um registro na
tabela de Clientes (tabClientes):

DataModule.tabClientes.Insert;

9.1 – Diagramas de Dados

Um TDataModule é muito mais do que um simples depósito de objetos. Um recurso


extra importantíssimo, incluído a partir da versão 5 do Delphi, permite a documentação
gráfica do modelo de dados utilizado. E isso pode ser obtido de maneira muito simples.

Observe a guia “Data Diagram” na figura abaixo:

Após a inserção e configuração dos componentes TTable e TDataSource, basta clicar


sobre o nome da tabela na Tree View à esquerda e arrastar para a caixa de edição da
guia Data Diagram e pronto, está criado o objeto gráfico para a tabela. No caso de os
componentes TTable estarem relacionados através de um relacionamento Mestre-
Detalhe, como na figura acima, ao arrastar a tabela detalhe do relacionamento, será
criado também a ligação entre os dois objetos, simbolizando o relacionamento
existente, exibindo inclusive o nome dos campos envolvidos no mesmo..

Mas isso ainda não é tudo, temos também a possibilidade de visualiza os campos de
cada tabela, veja abaixo:

Autor: Prof. José Luís Schiavo 5


Para adicionar os campos, clique com o botão direito do mouse sobre o objeto que
representa a tabela e escolha “Fields Editor”, no menu, clique em “Add Fields”, da
mesma forma como na adição dos campos nos objetos TTable. Após, se quiser
visualizar as definições de tipo para os campos, clique novamente com o botão direito e
marque a opção “Show field info”.

9.2 - Exercício:

Æ Com base no exercício anterior, adicione ao projeto um TdataModule e mova os


componentes TTable e TDataSource do form para o DataModule e reconfigure as
Propriedades DataSource dos objetos TDBGrid e TDBNavigator para que passem a
utilizar os objetos no DataModule. Execute também a criação do diagrama conforme
ilustrado na tela acima.

10 - Implementando Filtros em Tabelas

O uso de “FILTROS” em tabelas, permite-nos trabalhar com apenas um determinado


grupo de registros da mesma. Por exemplo, No caso de uma tabela de pedidos como a
usada nos exemplos anteriores, se quiséssemos apenas os pedidos de um
determinado período, poderíamos especificar um filtro o qual faria com que o nosso
componente TTable exibisse apenas os registros referentes ao período informado.

Um filtro na verdade é uma “CONDIÇÃO” , “REGRA” ou “EXPREESÃO LÓGICA” a ser


aplicada sobre os valores de um ou mais campos da tabela. Somente os registros que
satisfazem a condição são exibidos.

A propriedade Filter do objeto TTable deve receber a expressão a ser considerada,


após atribuir a expressão para a propriedade Filter, devemos atribuir True para a
propriedade Filtered, sendo que a partir deste momento o filtro imposto passará a surtir
efeito.

Exemplos:
TabPedidos.Filter := ‘DATA >= ‘’01/03/2004’’ AND DATA <= ‘’10/03/2004’’’;
tabPedidos.Filtered := True;

Autor: Prof. José Luís Schiavo 6


Uma outra maneira de trabalharmos com filtros, é utilizarmos o evento OnFilterRecod
do objeto TTable. Veja o exemplo:

Procedure TfrmExemplo.tabPedidosFilterRecord(DataSet: TDataSet; var


Accept: Boolean);
begin
Accept := (DataSet['DATA’] >= StrToDate(‘01/03/2004’)) AND
(DataSet['DATA'] <= StrToDate(‘10/03/2004’)) ;
end;

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:

procedure TfrmExemplo.btnFiltroClick(Sender: TObject);


begin
tabPedidos.Filtered := True;
end;

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.

Ao filtrar uma tabela, a propriedade RecordCount da TTable, só mostra o número de


registros que satisfazem ao filtro, como se os outros registros não existissem.
10.1 – Exercício:

Æ 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:

Autor: Prof. José Luís Schiavo 7


11 - Indexação de Tabelas

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).

1) Acesse o Database Desktop


2) Abra a tabela de pedidos (Pedidos.db) e clique no botão “Restructure” para
editar sua estrutura
3) No combo “Table Properties” selecione “Secondary Indexes”, veja abaixo:

4) Clique no botão “Define” para definir / criar um novo índice

Autor: Prof. José Luís Schiavo 8


5) Selecione o campo DATA na coluna da esquerda e adicione-o à coluna da
direita usando a seta Æ, após clique em OK para dar um nome para o índice e
salválo

6) Após informar o nome clique em OK para confirmar.

Pronto, o índice secundário está criado.

11.1 – Exercício
Æ Repita os mesmos passos para criar o índice pelo campo COD_CLIENTE.

11.2 – Ativando um Indice Secundário para uma Tabela

para ativar um índice em uma tabela, pode-se em tempo de projeto, setar a


propriedade IndexName do objeto TTable, no Object Inspector, ou em tempo de
execução atribuir o nome do índice à propriedade IndexName, veja abaixo:

tabPedidos.IndexName := ‘indDATA’;

Autor: Prof. José Luís Schiavo 9


11.3 – Exercício

Æ Vamos agora acrescentar ao nosso projeto exemplo, um mecanismo que permita


alterar em tempo de execução o índice da tabela de pedidos. Para isso siga os passos
abaixo:

Comp. TcomboBox
da paleta Standard Comp. Tbevel da
paleta Additional

Componente TComboBox: Componente TBevel:


Name: cbxOrdem Tem como função apenas destacar a região
Itens: Código do Cliente que será ocupada pelo TComboBox
Data do Pedido Componente TLabel:
Style: csDropDownList Caption: Ordenar Por:

Programando o evento OnChange do Componente TcomboBox:


procedure TfrmExemplo.cbxOrdemChange(Sender: TObject);
begin
if cbxOrdem.ItemIndex = 0 then // Código
tabPedidos.IndexName := 'indCOD_CLIENTE'
else // Data
tabPedidos.IndexName := 'indDATA';
end;

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.

Autor: Prof. José Luís Schiavo 10


12.1 Método FindKey

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:

Table1.FindKey([ 1124, StrToDate(“10/01/2004”) ]);

• Como trata-se de uma função, pode testar o resultado da pesquisa assim:

if not( Table1.FindKey([ 1124, StrToDate(‘10/01/2004’) ])) then


ShowMessage(‘Registro não localizado!’);

12.2 – Método FindNearest

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’.

12.3 – Método Locate

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.

Autor: Prof. José Luís Schiavo 11


Sintaxe:
function Locate(const KeyFields: String; const KeyValues:
Variant; Options: TLocateOptions): Boolean;

KeyFields: Lista de campos, entre aspas e separados por “ponto e vírgula”.


KeyValues: Lista de valores, na mesma ordem dos campos informados em KeyFields.
Quando a pesquisa for feita em mais de um campo simultaneamente deve-se usra a
função VarArrayOf([...]) para a passagem dos parâmetros, separados por vírgulas.
TlocateOptions: Opções de pesquisa sendo:
* loCaseInsensitive -> Não faz distinção entre maiúsculas e minúsculas
* loPartialKey -> Executa uma pesquisa parcial

No exemplo abaixo é feita uma pesquisa exata.

if not table1.Locate('Nome', ‘JOÃO’, []) then


ShowMessage('Cliente não encontrado.');

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.

Table1.Locate('Nome', JOÃO’, [loPartialKey, loCaseInsensitive]);

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.

if not tabVendas.Locate('Vendedor;Data', VarArrayOf([


[‘PEDRO DOS SANTOS’, StrToDate(10/10/2002’)]),
[loCaseInsensitive]) then
ShowMessage('O vendedor não realizou vendas nessa data');

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:

Autor: Prof. José Luís Schiavo 12


Comp. TMaskEdit
da paleta Additional

Componente TmaskEdit
Name: medPesquisa
Text: ‘’

Componentes TButton
Name: btnFindKey, btnFindNearest, btnLocate

Codificação dos Eventos

procedure TfrmExemplo.btnFindKeyClick(Sender: TObject);


begin
if cbxOrdem.ItemIndex = 0 then // Código
tabPedidos.FindKey(StrToInt(medPesquisa.Text))
else // Data
tabPedidos.FindKey(StrToDate(medPesquisa.Text));
end;

procedure TfrmExemplo.btnFindNearestClick(Sender: TObject);


begin
if cbxOrdem.ItemIndex = 0 then // Código
tabPedidos.FindNearest(StrToInt(medPesquisa.Text))
else // Data
tabPedidos.FindNeares(StrToDate(medPesquisa.Text));
end;

Autor: Prof. José Luís Schiavo 13


procedure TfrmExemplo.btnLocateClick(Sender: TObject);
begin
if cbxOrdem.ItemIndex = 0 then // Código
tabPedidos.Locate('COD_CLIENTE',StrToInt(medPesquisa.Text),
[])
else // Data
tabPedidos.Locate('DATA',StrToDate(medPesquisa.Text), []);
end;

Autor: Prof. José Luís Schiavo 14


Anotações

Autor: Prof. José Luís Schiavo 15


13 - Verificando Alterações

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.

procedure TfrmExemplo.FormClose(Sender: TObject; var Action:


TCloseAction);
begin
if tabPedidos.Modified then
if Application.MessageBox('Gravar alterações?', 'Dados
Alterados',MB_ICONQUESTION + MB_YESNO) = IDYES then
tabPedidos.Post
else
tabPedidos.Cancel;
end;

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.

procedure TfrmExemplo.tabPedidosNewRecord(DataSet: TDataSet);


begin
tabPedidosData.Value := Date;
end;

15 - Percorrendo uma Tabela

Dependendo da situação, algumas vezes precisamos percorrer todos os registros de


uma tabela e fazer testes com os valores de determinados campos, fazer somatórios,
etc. Não é o método mais indicado pois em tabelas com muitos registros pode
demandar muito tempo de processamento e recursos do sistema, mas, tem casos em
que este método se faz necessário. Utilize um código semelhante ao mostrado abaixo
para percorrer uma tabela do início ao fim.

procedure TfrmExemplo.btnTotalizaClick(Sender: TObject);


var Total : Real;
begin
tabPedidos.DisableControls;
Total := 0;
tabPedidos.First;
while not tabPedidos.EOF do
begin
Total := Total + tabPedidos Valor.Value;
tabPedidos.Next;
end;
tabPedidos.EnableControls;

Autor: Prof. José Luís Schiavo 16


ShowMessage('A Soma Total os pedidos é: '
FormatFloat('#,##0.00',Total);
end;

16 - Fields Editor

O Fields Editor ou Editor de Campos, permite criemos objetos para


cada um dos campos da tabela. Cada objeto, assim como qualquer
outro objeto visual do Delphi, possuirá um conjunto de
Propriedades, Métodos e Eventos que facilitam em muito a
manipulação dos campos.

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

Autor: Prof. José Luís Schiavo 17


ConstraintErrorMes Mensagem de erro se a condição de CustomConstraint não for
sage satisfeita
CustomConstraint Condição de validação do campo
DataSet DataSet onde está o campo
DataSize Tamanho do campo, em Bytes
DataType Propriedade do tipo TFieldType, que indica o tipo do campo
DefaultExpression Expressão com valor Default do campo para novos registros
DisplayLabel Título a ser exibido para o campo
DisplayText Texto exibido nos controles visuais associados ao campo
DisplayWidth Número de caracteres que deve ser usado para mostrar o
campo no controles visuais
EditMask Máscara de edição do campo
FieldKind Propriedade do tipo TFieldKind que indica o tipo do campo,
como Calculado ou Lookup
FieldName Nome do campo na tabela
FieldNo Posição física do campo na tabela
Index Posição do campo nos controles visuais
IsIndexField Indica se um campo é válido para ser usado como índice
IsNull Indica se o campo está vazio
KeyFields Campo chave da tabela no relacionamento com
LookupDataSet, usado em campos Lookup
Lookup Indica se um campo é Lookup
LookupCache Define se será usado cache para campos Lookup
LookupDataSet DataSet onde está definido o valor do campo Lookup
LookupKeyFields Campo chave do relacionamento em LookupDataSet
LookupResultField Valor do campo, que será mostrado nos controles visuais
ReadOnly Define se um campo é somente para leitura
Required Define se o campo é obrigatório
Size Tamanho físico do campo
Text Texto de edição do campo
Value Acesso direto ao valor do campo
Visible Define se um campo é visível
Eventos Descrição
OnChange Chamado quando o valor do campo é mudado
OnSetText Chamado pelos controles visuais para atribuir o texto digitado
pelo usuário ao campo
OnGetText Chamado para formatar o texto de exibição do campo
OnValidate Validação do valor atribuído ao campo, caso o valor não seja
válido, gere uma exceção
Método Descrição
Assign Atribui um valor de um campo a outro, inclusive nulo
FocusControl Seta o foco para o controle visual ligado ao campo nos Forms
Clear Limpa o conteúdo do campo

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:

• Usando o objeto TField ligado ao campo.

tabPedidosData.Value := Date;

• Usando a notação de colchetes. Se você não especificar nenhuma


propriedade, é assumida a propriedade Value por padrão.

tabPedidos['Data'] := Date;

• Através do método FieldByName

tabPedidos.FieldByName('Data').Value := Date;

• Usando a lista Fields do TTable

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);

Autor: Prof. José Luís Schiavo 19


19 - Validação de Campos

Para validar os valores de um campo, você pode usar a propriedade


CustomConstraint, na qual deve ser especificada uma “string SQL” válida a qual será
usada para criticar/validar o valor de um campo específico. Por exemplo para garantir
que a quantidade de um item seja maior que zero e menor que 100, use em
CustomConstraint: QUANTIDADE > 0 AND QUANTIDADE < 100, e, em
CustomConstraintMessage coloque a mensagem para o usuário caso a condição
seja falsa, exemplo: “Quantidade deve ser maior que zero e menor que 100”. Pelo fato
da condição ser uma expressão SQL, ao testar valores fracionários use sempo o ponto
(.) para separar as casas decimais. No exemplo acima “QUANTIDADE” é o nome de
um campo da tabela, deve-se tomar o cuidado de sempre referenciar os campos pelos
seus nomes tal e qual estão definidos na tabela.

Outra forma, mais flexível de se validar o valor de um campo, é usando o evento


OnValidate. Este evento ocorre imediatamente antes de o valor informado ser escrito
no buffer do respectivo campo. Para rejeitar o valor informado, deve-se lançar/gerar
uma exceção para cancelar a atribuição do valor ao campo. Veja o exemplo:

procedure TForm1.tabItensQuantidadeValidate(Sender: TField);


begin
if (tabItensQuantidade.Value <= 0) or
(tabItensQuantidade.Value >= 100) then
raise Exception.Create('Quantidade deve ser maior que zero e
menor que 100');
end;

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:

procedure TForm1.tabClientesEstadoCivilGetText(Sender: TField;


var Text: String; DisplayText: Boolean);
begin
if tabClientesEstadoCivil.Value = 'C' then
Text := 'Casado'
else if tabClientesEstadoCivil.Value = 'S' then
Text := 'Solteiro';
end;

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.

Autor: Prof. José Luís Schiavo 20


21 - Campos Calculados

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.

Para colocar um valor nesse campo deve-se usar o evento OnCalcFields do


componente TTable, em nenhuma outra parte do código os valores desses campos
podem ser alterados.

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:

procedure Form1.tabItensCalcFields(DataSet: TDataSet);


begin
tabItensTotalItem.Value := tabItensQuantidade.Value *
tabItensValorUnitario.Value;
end;

Obs.:

a) Quando a propriedade AutoCalcFields da tabela for igual a True, o evento


OnCalcFields é disparado sempre que:

- 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.

b) O evento OnCalcFields só é disparado automaticamente se a propriedade


AutoCalcFields estiver setada para True.

22 - Campos LookUp

Assim como os campos calculados, os campos LOOKUP só existem em tempo de


execução. Esse tipo de campo é muito útil quando queremos exibir por exemplo, em
um cadastro de livros, o nome do autor, mas só temos na tabela de livros o código do
autor, então, podemos nos utilizar o relacionamento existente entre a tabela de autores
e livros ( 1 p/ N) para criar um campo lookup na tabela de livros que referencie a tabela
de autores e nos disponibilize o nome do mesmo.

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

Essas opções correspondem a algumas propriedades do objeto TField gerado, que


podem ser alteradas no Object Inspector (KeyFields, LookupDataSet,
LookupKeyFields, LookupDataSet e LookupResultField).

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.

23 - Tratamento de Exceções - Aplicações Robustas

O tratamento de exceção é um mecanismo capaz de dar robustez a uma aplicação,


permitindo que os erros sejam manipulados de uma maneira consistente e fazendo
com que a aplicação possa se recuperar dos mesmos, se possível, ou finalizar a
execução quando necessário, sem perda de dados ou recursos.

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.

23.1 - Blocos Protegidos

Um bloco protegido é um grupo de comandos com uma seção de tratamento de


exceções. Veja:
try
A := StrToFloat(EdtA.Text);
B := StrToFloat(EdtB.Text);
ShowMessage(FloatToStr(A * B));
except
ShowMessage('Número(s) inválido(s).');
end;

Autor: Prof. José Luís Schiavo 22


Algumas vezes você pode precisar especificar quais exceções quer tratar, como
mostrado abaixo.

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;

Obs.: Caso não ocorram exceções nos comandos do bloco try, o


bloco except será ignorado.

23.2 - Blocos de Finalização

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;

Pode-se usar blocos de proteção e finalização aninhados

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

Autor: Prof. José Luís Schiavo 24


23.4 - Erros de Bancos de Dados

A Classe de exceções EDBEngineError permite a identificação de erros de bancos de


dados gerados pela BDE.

Você também pode criar um procedimento que faça o tratamento do erro que possa ser
usado em toda a aplicação:

procedure TrataErro(E: EDBEngineError);


var i : byte;
begin
for i:= 0 to E.ErrorCount –1 do
begin
case E.Errors[i].ErrorCode of
DBIERR_KEYVIOL : ShowMessage('Código já cadastrado.');
DBIERR_REQDERR : ShowMessage('Campo obrigatório não
preenchido.');
DBIERR_LOCKED : ShowMessage('Registro travado por outro
usuário.');
end;

End;
end;

Exemplo de como utilizar o procedimento acima:

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.

Alguns códigos de erro da BDE estão listados abaixo.


Constante Descrição
DBIERR_KEYVIOL Violação de chave primária
DBIERR_MAXVALERR Valor máximo excedido
DBIERR_FORIEGNKEYERR Erro de chave externa, como em integridade
referencial
DBIERR_LOCKED Registro travado
DBIERR_FILELOCKED Arquivo travado
DBIERR_NETMULTIPLE Mais de um diretório usado como NetFileDir
DBIERR_MINVALERR Campo com valor mais baixo que valor mínimo
DBIERR_REQDERR Campo obrigatório faltando
DBIERR_LOOKUPTABLEERR Erro em tabela Lookup

Autor: Prof. José Luís Schiavo 25


24 - Bibliografia

Delphi 5 Passo a Passo Lite


Editora MAKRON BOOKS

Delphi 3 Total
Maurício B. Longo
Ronaldo Smith Jr.
Editora Brasport

Dominando o Delphi 5 “A Bíblia”


Marco Cantù
Editora MAKRON Books

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

Autor: Prof. José Luís Schiavo 26

Você também pode gostar