Conteúdo

Tratamento de erros no Visual Basic.


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

Identificando o tipo de erro..

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

Finalizando um tratamento de erros..

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

Principais erros relacionados a banco de dados.

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