Tratando Erros de Execução no Delphi - Clube Delphi 10
Aprenda nesse artigo a tratar erros de execução no Delphi, como o OnException.
Atenção: por essa edição ser muito antiga não há arquivo PDF para download. Os artigos dessa edição estão disponíveis somente através do formato HTML.
Tratando Erros de Execução
Utilizando o evento OnException paratratar todos os erros de execução
Uma boa prática a se aplicar aos projetos de sistemas informatizados, é a adoção de um mecanismo para tratamento de erros. Desta forma, seu aplicativo não exibiria mensagens indecifráveis para o usuário, tornando claro todo o ocorrido ao longo do processo e uso.
Geralmente, uma linguagem de desenvolvimento não fornece uma boa interface para interceptar ocorrências de erros, identificá-las e posteriormente tratá-las, considerando as diversas possibilidades.Mas em se tratando das ferramentas Inprise-Borland, todo esta tarefa fica minimizada ao contexto do desenvolvimento na linguagem adotada, pela simples utilização da estrutura de objetos da Classe Exception.
Nas operações com Banco de Dados, onde os erros originados de tentativas de quebra de integridade, violação de chave primária e outros, podem ocorrer com grande probabilidade, seria muito interessante se pudéssemos criar uma procedure única para o tratamento de todos os erros - ao invés de usar um try..except para cada situação.
Felizmente, este é um recurso de fácil implementação no Delphi - o objeto Tapplication possui o evento OnException - que é disparado quando qualquer erro é gerado pela aplicação, em qualquer formulário.
Uma das novidades do Delphi 5, é o objeto TapplicationEvents - que herda a funcionalidade do objeto Tapplication e permite a manipulação de seus eventos de forma visual (o objeto Tapplication é não visual).
Vamos agora criar um aplicativo exemplo, que irá utilizar o evento OnException para centralizar o tratamento de erros:
Interface principal do sistema e código fonte:
unit Principal;
interface
uses
Windows, Messages,SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
Menus, AppEvnts, ComCtrls;
type
TFrmPrincipal = class(TForm)
MainMenu1: TMainMenu;
Mdulos1: TMenuItem;
Geral1: TMenuItem;
ApplicationEvents1: TApplicationEvents;
StatusBar1: TStatusBar;
procedure ApplicationEvents1Exception(Sender: TObject; E: Exception);
private
{ Private declarations }
public
{ Public declarations }
end;
var
FrmPrincipal: TFrmPrincipal;
implementation
{$R *.DFM}
procedure TFrmPrincipal.Geral1Click(Sender: TObject);
begin
Try
Application.CreateForm(TFrmTesta Erros, FrmTestaErros);
FrmTestaErros.ShowModal;
Finally
FrmTestaErros.Free;
End;
end;
procedure TFrmPrincipal.ApplicationEvents1 Exception(Sender: TObject;
E: Exception);
var mensagem: string;
Pos1, Pos2: integer;
begin
If Pos(UpperCase('is not a valid date'), UpperCase(E.Message)) > 0 then
showmessage('Data inválida, proceda a correção.')
else
if Pos(UpperCase('must have a value'), UpperCase(E.Message)) > 0 then
begin
Pos1:=Pos('''', E.Message);
mensagem:=E.Message;
Delete(mensagem, Pos1, 1);
Pos2:=Pos('''', mensagem);
mensagem:=copy(E.Message, Pos1 + 1, Pos2 - Pos1);
showmessage('É obrigatório o preenchimento do campo '+ mensagem + '.');
end
else
If Pos(UpperCase('key violation'), UpperCase(E.Message)) <> 0 then
showmessage('Houve violação de Chave. Registro já incluido.')
else
If Pos(UpperCase('Input value'), UpperCase(E.Message)) <> 0 then
showmessage('Campo preenchido com valor não válido. Procedaa correção.')
else
If Pos(UpperCase('is not a valid time'), UpperCase(E.Message)) <> 0 then
showmessage('Hora inválida, proceda a correção.')
else
showmessage('Ocorreu o seguinte erro: '+UpperCase(E.Message));
end;
end.
Detalhando passo-a-passo o evento OnException:
O que o procedimento faz nada mais é do que comparar qual a string de erro que foi gerada. Esta string é passada como parâmetro através do objeto E (Exception), dentro de sua propriedade message.
If Pos(UpperCase('is not a valid date'), UpperCase(E.Message)) > 0 then
A primeira comparaçào se refere a um erro de data. A função Pos, indica se a substring passada como parâmetro existe dentro da mensagemde erro. Se existir, a função irá retornar um valor maio que 0 (zero).
Outros erros, testados pelos seus trechos significativos ('key violation', 'Input value', 'is not a valid time') podem ser tratados da mesma forma, diminuindo o trabalho e a manutenção do aplicativo.
Isto é só uma demonstração do que você pode fazer para prever todos os erros possíveis em seu projeto. Basta conhecer qual a mensagem de erro retornada pelo objeto Exception - e tratá-la neste evento.
Algumas situaçòes irão pedir uma maior habilidade do desenvolvedor com a linguagem. Por exemplo, se tentarmos capturar o erro gerado por um campo unique. Veja na figura ao lado um exemplo:
Poderíamos indicar ao usuário qual a coluna que gerou o erro. Observe abaixo como este problema pode ser resolvido:
if Pos(UpperCase('must have a value'), UpperCase(E.Message)) > 0 then- Testa a ocorrência do erro 'must have a value'.Caso positivo, investe na captura de qual coluna.
Pos1:=Pos('''', E.Message);
Atribui a variável Pos1, a posição do primeiro delimitador(') que envolve o nome do campo ( exemplo'Moeda').
mensagem:=E.Message;
Atribui o conteúdo da propriedade message(a própria mensagem de erro natural) a variável mensagem.
Delete(mensagem, Pos1, 1);
Usa-se a função Delete para excluir da string(variável mensagem) a ocorrência do primeiro delimitador(') que envolve o campo('Moeda').
Pos2:=Pos('''', mensagem);
Atribui a variável Pos2, o valor numérico da posição do segundo delimitador que envolve o nome do campo causador da exceção.
mensagem:=copy(E.Message, Pos1 + 1, Pos2 - Pos1);
Atribui um novo valor a variável mensagem, utilizando-se a função copy para extrair da propriedade message a sub-string que representa o nome do campo.
showmessage ('É obrigatório o preenchimento do campo '+ mensagem + '.');
Por último, é exibido a constante 'É obrigatório o peenchimento do campo', mais a concatenação da string que representa o nome da coluna.
Dica: Conforme apresentado no projeto que se segue, a tabela utilizada é Country do banco de dados de exemplo do Interbase.Porém o nome da coluna desta tabela não é MOEDA e sim CURRENCY. Aí vai umadica: O que a classe exception expõe, não é exatamente o nome da coluna, mas sim o conteúdo da propriedade DisplayLabel (quando tornada objeto). Fica assim explicado porque MOEDA e não CURRENCY conforme o original.
Caso a mensagem de erro não tenha sido prevista, exibimos uma janela padrão: showmessage('Ocorreu o seguinteerro: '+UpperCase(E.Message));
Interface de teste da captura de erro
Configuração dos Objetos:
TDATABASE
AliasNameIBLocal
ConnectedTRue
DatabasenameBDIB
NameDatabase1
TABLE1
Active True
DatabasenameBDIB
NameTableCountry
TableNameCountry
DATASOURCE1
DatasetTableCountry
NameDSTableCountry
DBGRID1
DataSourceDsTableCountry
CÓDIGO DA UNIT:
unit TestaErros;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
Db, Grids, DBGrids, DBTables;
type
TFrmTestaErros = class(TForm)
Database: TDatabase;
TableCountry: TTable;
DSTableCountry: TDataSource;
DBGrid1: TDBGrid;
TableCountryCOUNTRY: TStringField;
TableCountryCURRENCY: TStringField;
private
{ Private declarations }
public
{ Public declarations }
end;
var
FrmTestaErros: TFrmTestaErros;
implementation
{$R *.DFM}
A tela em execução provoca a entrada de um novo registro.Na sequência, o usuário tenta avançar para a próxima linha, que provoca de imediato o método Post.
Desta forma, o Servidor reage com uma exceção indicando o não preenchimento do campo Moeda. Como temos um tratamento específico, não é exibido a caixa de diálogo(figura 2) e sim a mensagem da nossa última tela.
Laercio Guerço Rodrigues é membro da DigiData Informática, resposável pela implementação de cursos voltados as áreas de desenvolvimento de Sistemas Client Server, atualmente empenhado em divulgar e implemtar cursos e aplicativos no modelo Objeto Distribuido(CORBA e D-COM), Internet(Web DataBase) e literatura específica em Delphi.
Artigos relacionados
-
Artigo
-
Artigo
-
Artigo
-
Artigo
-
Artigo