Desenvolvimento - Visual Basic

Tratamento de erros no Visual Basic

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

por José Carlos Macoratti



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 e nem usuários perfeitos.

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()
	"Inicia tratamento de erro	
	On error Goto Trata_Erro 
	
	"Ocorreu um erro, a execução é desviada para a o código que vem 
	"após a etiqueta Trata_Erro
   	Print 1/0
                               
	Exit sub
                                                 
Trata_Erro:                                          
	"Exibe a mensagem e encerra a aplicação.
	msgbox "Não existe divisão por zero !!!!"
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.

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:

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


Figura 1

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:


Figura 2

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

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.

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.


Fugura 3


Figura 4

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

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

Acho que acabei. Ate mais ver...

José Carlos Macoratti

José Carlos Macoratti