Tratamento de erros no Visual Basic.
|
Conteúdo
|
Introdução.
Você terminou de desenvolver aquele super projeto e esta ansioso para mostrar para
o seu chefe. Naturalmente você depurou o seu código e testou tudo antes de gerar
os discos de instalação , afinal o seu emprego está em jogo.
A instalação foi um sucesso , basta agora carregar a aplicação , então você clica
no ícone da aplicação e surge na tela a fatídica mensagem :
Data error event hit in D:\PROJETO1\TESTES\CLIENTES.MDB isn't a valid Path..."
, imediatamente você percebe que esqueceu de mudar o caminho para a abertura do
banco de dados, e agora... todos os olhos se voltam para você e... bem ai você
acorda suando frio , ainda bem que foi tudo um sonho ... ou um pesadelo.
Veja bem, quando ocorre um erro durante a execução de um programa Visual Basic , o
controle vai para uma lógica de tratamento de erros que consiste em exibir uma men-
sagem descrevendo a causa do erro e encerrando o programa a seguir.
Este é o procedimento padrão adotado pelo Visual Basic durante a execução de um
programa compilado ; não o leve a mal, ele apenas esta sendo gentil solicitando
a sua intervenção.
Você pode , e deve, intervir neste processo construindo uma lógica de interceptação
e tratamento de erros no seu código , que irá interceptar os possíveis erros e tra-
tá-los de uma forma mais elegante que a adotada pelo procedimento padrão do Visual
Basic.
Tudo isto se torna mais enfático quando se trabalha com banco de dados no VB , pois
neste caso, teremos muitas condições de erro durante a execução da aplicação.
Lembre-se, não existem nem aplicações nem programadores nem usuários perfeitos.
Conteúdo
Interceptando erros.
Para interceptar um erro no Visual Basic você usa a instrução On Error.
Quando uma instrução On Error está em vigor e ocorrer um erro o VB vai
executar as ações determinadas pela instrução.
Para estar em vigor a instrução On Error deve ser executada antes da
ocorrência de um erro na mesma função ou sub-rotina onde ocorreu o erro
ou em uma função ou sub-rotina que tenha chamado a função ou
sub-rotina onde o erro tiver ocorrido.
A instrução On Error tem a seguinte sintaxe:
On Error goto label
Traduzindo-a teremos:
Quando ocorrer um erro , transfira a execução para a linha após a etiqueta.
A etiqueta é um identificador alfanumérico que termina com dois pontos (:).
(Ex: Trataerro: )
Ela tem que começar na primeira coluna e tem que estar na mesma função ou
sub-rotina da instrução On Error, sendo exclusiva dentro de um módulo.
Após a etiqueta você fornece o código que vai tratar o erro ocorrido.
Vejamos um exemplo:
Public Sub Exemplo()
On error Goto Trata_Erro -> Inicia tratamento de erro
Print 1/0 -> Ocorreu um erro, a execução é
desviada para a o código que vem após a etiqueta
Exit sub Trata_Erro
Trata_Erro:
msgbox "Não existe divisão por zero !!!!" ------> Exibe a mensagem e encerra
a aplicação.
End Sub
Obs:Note que antes da etiqueta existe a instrução Exit Sub. Sem ela
o codigo após a etiqueta seria sempre executado , mesmo não
havendo ocorrência de erros.
Conteúdo
Cada erro gerado no Visual Basic esta associado a um número e tem uma descrição.
Para identificar um erro ocorrido , informando o seu número , a mensagem de erro,
de onde o erro procede, etc. usamos o Objeto Err.
O objeto Err foi introduzido na versão 4.0 do VB e incorpora a funcionalidade
da instrução Err, da função Err, da instrução e Função Error e da função Error$.
Utilizaremos então as propriedades do objeto Err para identificar o tipo de
erro e fazer o seu tratamento , se for o caso.
As principais propriedades do objeto Err que utilizaremos são:
Number |
Fornece Numero do erro gerado |
Description |
Fornece a descrição do erro. |
Source |
Identifica o nome do objeto que gerou o erro |
Raise |
Gera um erro de execução, usado para testar condições de erro. |
Quando ocorre um erro o VB coloca o número do erro na propriedade Number
do objeto Err , conhecendo o número do erro você pode determinar o tipo de
erro e tomar a decisão quanto ao seu tratamento.
Vejamos um exemplo prático:
Vamos definir uma tabela com o nome de erro que estará armazenada no
banco de dados Controle.mdb e que possuirá a seguinte estrutura:
---------------------------------------------------------
nome do campo Tipo de Dados Tamanho do Campo
---------------------------------------------------------
codigo Long 04
nome Caracter 30
---------------------------------------------------------
1-Defina um índice para o campo codigo
ativando as opções: Unique, Primary index. e Requerid
Desta forma estamos criando uma chave primária para o campo codigo.
Se tentarmos gravar um registro com um número de código que já foi gravado o Jet
retornará um erro, o erro de número de 3022 , poderemos portando interceptá-lo
e através do tratamento informar ao usuário que o código já foi utilizado
permitindo a seguir ao usuário informar outro código.
Tudo se passa como se estivessemos fazendo a critica da entrada de dados do
usuário, só que sem utilizar nenhum código a não ser a interceptação e o
tratamento do erro.
1-Ao iniciar a aplicação teremos tela da figura 1.0 abaixo
fig 1.0
|
2-Suponhamos que o usuário tente incluir um código que já foi utilizado , ao
clicar no botão gravar ocorrerá uma mensagem de erro, pois o Jet não permite
a duplicação de uma chave primária.
Prevendo tal ação iniciamos o tratamento de erros e interceptando-o retornamos
ao usuário a mensagem da figura 2.0 abaixo:
fig 2.0
|
Fazemos isto utilizando a instrução Resume Next colocada após a mensagem
de aviso ao usuário.
Private Sub Command5_Click()
On Error GoTo erro_mdb 'inicia o tratamento de erros
'verifica se esta incluindo ou editando caso contrário não faz nada
If rs.EditMode = dbEditAdd Or rs.EditMode = dbEditInProgress Then
grava_regs
rs.Update --> linha que irá gerar o erro.
limpa_regs
Form1.Caption = "Tratamento de Erros "
rs.Bookmark = rs.LastModified
load_regs
End If
Exit Sub
erro_mdb:
MsgBox "Erro número : " & Str$(Err.Number) & " --> Codigo já utilizado !!! "
Resume Next 'retorna a ação para a linha de código subsequente áquela que
'gerou o erro
End Sub
-Código do projeto para Tratamento de erros.
Option Explicit
Dim db As Database
Dim rs As Recordset
Dim dbname As String
Private Sub Command1_Click()
'Inicia processo de inclusao, limpa os controles e
'foca o textbox codigo
Form1.Caption = "Inclusao !!! "
rs.AddNew
limpa_regs
Text1.SetFocus
End Sub
Private Sub Command2_Click()
'encerra aplicação
End
End Sub
Private Sub Command3_Click()
'move para o próximo registro
rs.MoveNext
If rs.EOF() Then rs.MovePrevious
Form1.Caption = "Tratamento de Erros "
load_regs
End Sub
Private Sub Command4_Click()
'move para o registro anterior
rs.MovePrevious
If rs.BOF() Then rs.MoveNext
Form1.Caption = "Tratamento de Erros "
load_regs
End Sub
Private Sub Form_Load()
dbname = App.Path & "\controle.mdb"
Set db = DBEngine.Workspaces(0).OpenDatabase(dbname)
Set rs = db.OpenRecordset("erro")
If rs.RecordCount > 0 Then
load_regs
Else
MsgBox "Arquivo vazio"
limpa_regs
End If
End Sub
Public Sub load_regs()
'carrega os dados nos controles
Text1 = "" & rs("codigo")
Text2 = "" & rs("nome")
End Sub
Public Sub limpa_regs()
'limpa os controles
Text1 = ""
Text2 = ""
End Sub
Public Sub grava_regs()
'descarrega o conteúdo dos controles para gravação
rs("codigo") = Text1.Text
rs("nome") = Text2.Text
End Sub
Conteúdo
Após a interceptação do erro você faz o tratamento do mesmo e tem que terminar o
tratamento de erros com uma instrução que elimine o erro, caso contrário o próprio
tratamento de erros irá gerar um erro.
No caso anterior a instrução que eliminou o erro foi a instrução Resume Next,
pois devolveu a ação ao usuário.
Vejamos abaixo as principais instruções utilizadas para eliminar um erro.
Resume Next |
Retorna a execução na linha que vem logo após à linha que gerou o erro |
Resume |
Executa mais uma vez a linha que gerou o erro. |
Resume Label |
Retorna a execução da linha que vem após a etiqueta citada. |
Resume Number |
Retorna a execução na linha com o número indicado. |
Exit Sub |
Sai da sub rotina atual. |
Exit Function |
Sai da função atual. |
Exit Property |
Sai da propriedade atual. |
On Error |
Redefine a lógica de tratamento de erros. |
Err.Clear |
Elimina o erro sem afetar a execução do programa. |
End |
Encerra a execução do programa. |
Vejamos um exemplo onde simulamos várias situações de erro e utilizamos o
tratamento de erros para determinar o número do erro a linha onde ocorreu
o erro e que gerou o erro.
Obs: Cuidado ao usar Resume pois você pode ficar preso num loop infinito.
Note que utilizamos números de linha em nosso código para ser possível a
identificação do número da linha pelo tratamento de erros.
Private Sub Form_Load()
Dim db As Database
Dim dbName As String
Dim rs As Recordset
Dim s As String
On Error GoTo TrataErro 'ativa o tratamento de erros
dbName = app.path & "\controle.mdb"
10 Set db = DBEngine.Workspaces(0).OpenDatabase(dbName)
' Aqui ocorre um erro , pois a tabela não existe neste banco de dados
20 Set rs = db.OpenRecordset("erros", dbOpenTable)
' Aqui temos a abertura correta da tabela erro
30 Set rs = db.OpenRecordset("erro", dbOpenTable)
' Aqui ocorre mais um erro , pois não existe o campo endereço na
' tabela erro
40 s = rs![endereço]
' Aqui temos outro erro pois o código não aceita valores alfanuméricos
50 rs![código] = "XYZ"
' Encerra a aplicação
60 End
Exit Sub
LoadError:
MsgBox "Erro número #" & Str$(Err.Number) & " na Linha " & Str$(Erl) & " - "_
& Err.Description & " - gerado por " & Err.Source
Resume Next 'devolve a ação para a linha subsequente à que gerou o erro.
End Sub
Você dever obter, ao iniciar o projeto, a mensagem da figura 3.0 e a seguir
a mensagem de erro da figura 4.0 , e assim por diante.
fig 3.0
|
fig 4.0
|
Observe que a descrição utilizada é fornecida pela propriedade description
do objeto Err.
A instrução que eliminou o erro foi a instrução Resume Next, pois devolve a
ação para a linha subsequente à que gerou o erro permitindo assim que o aplicação
seja executada até o seu final.
Simulando um erro
Na rotina abaixo vemos como gerar um erro fornecendo o número do erro desejado:
On error GoTo Trata_Erro_divisao
Err.Raise Number:=11 'Gera um erro de divisão por zero
exit sub
Trata_Erro_divisao:
Select Case Err.Number
case 11
if MsgBox("Não Existe divisão por Zero. !!! ", vbYesNo) = vbYes Then
c=inputbox("Informe o valor do denominador ! ")
resume
else
exit sub
endif
End Select
Conteúdo
Naturalmente você deve estar preparado para prever os erros potenciais e planejar
o seu tratamento, para isso devera conhecer os principais erros relacionados ao
seu ambiente de trabalho.
Relacionar aqui todos os erros tratáveis do Visual Basic seria impossível , mas
vamos tentar listar os principais fornecendo o seu número e descrição, vamos lá:
-------------------------------------------------------------------------
número Mensagem
-------------------------------------------------------------------------
Erros genéricos.
3005 Database name' isn't a valid database name.
3006 Database 'name' is exclusively locked.
3008 Table 'name' is exclusively locked.
3009 Couldn't lock table 'name'; currently in use.
3010 Table 'name' already exists.
3015 'Index name' isn't an index in this table.
3019 Operation invalid without a current index.
3020 Update or CancelUpdate without AddNew or Edit.
3021 No current record.
3022 Duplicate value in index, primary key, or relationship.
Changes were unsuccessful.
3023 AddNew or Edit already used.
3034 Commit or Rollback without BeginTrans.
3036 Database has reached maximum size.
3037 Can't open any more tables or queries.
3040 Disk I/O error during read.
3044 'Path' isn't a valid path.
3046 Couldn't save; currently locked by another user.
Erros relacionados a bloqueio de registros
3027 Can't update. Database or object is read-only.
3158 Couldn't save record; currently locked by another user.
3167 Record is deleted.
3186 Couldn't save; currently locked by user 'name' on machine 'name'.
3187 Couldn't read; currently locked by user 'name' on machine 'name'.
3188 Couldn't update; currently locked by another session on this machine.
3189 Table 'name' is exclusively locked by user 'name' on machine 'name'.
3197 Data has changed; operation stopped.
3260 Couldn't update; currently locked by user 'name' on machine 'name'.
3261 Table 'name' is exclusively locked by user 'name' on machine 'name'.
3356 The database is opened by user 'name' on machine 'name'.
Erros relacionados a Permissões
3107 Record(s) can't be added; no Insert Data permission on 'name'.
3108 Record(s) can't be edited; no Update Data permission on 'name'.
3109 Record(s) can't be deleted; no Delete Data permission on 'name'.
3110 Couldn't read definitions; no Read Definitions permission for
table or query 'name'.
3111 Couldn't create; no Create permission for table or query 'name'.
3112 Record(s) can't be read; no Read Data permission on 'name'.
-------------------------------------------------------------------------
Coleção de Erros do DBEngine
O VB fornece um nível especial de proteção para erros de acesso aos dados
através da geração do objeto Error , o qual armazena as informações
de erro além do objeto Err. Existe portanto uma coleção Errors
que armazena esses erros.
Para visualizar a coleção de erros podemos usar a rotina:
For x=0 to DBEngine.Errors.Count -1
MsgBox DBEngine.Errors(x).Description
next
Conteúdo
Acho que acabei. Ate mais ver...