> ## Tratamento de erros no Visual Basic.

##### Conteúdo

- Introdução.
- Interceptando erros.
- Identificando o Tipo de Erro.
- Finalizando um tratamento de erros.
- Principais erros relacionados a Banco de dados.

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

    AGUARDEM CONTINUAÇÃO...

Conteúdo

Retorna