VBA - Artigo 012 - Usando On Error para tratar erros


Usando On Error para tratar erros


Há vezes em que um erro imprevisto e não tratado acontece. Imagine que isso aconteça com um usuário da planilha que não tem conhecimento nenhum de VBA: uma mensagem de erro aparece, a janela do Editor VBA é aberta e todo o seu código fica visível para ele, que olha atônito e sem saber o que fazer. Essa cena não é nada agradável e certamente ele estará procurando onde você está para se queixar do ocorrido.

Para evitar isso temos a instrução On Error, que ativa o manipulador de erros. Assim você poderá lidar com o erro e evitar que o Excel mande uma mensagem e abra o Editor VBA (e que o usuário pegue no seu pé). As formas de usar são as seguintes:

- On Error GoTo [rótulo]: É a principal forma de uso. Assim que um erro ocorrer, a execução do programa será desviada para um ponto indicado pelo rótulo. É boa prática manter a área de tratamento de erros no final da sub-rotina, bem como colocar um Exit Sub antes do rótulo, para que as instruções do tratamento de erro não sejam executadas toda vez que passar pela sub-rotina.

- On Error GoTo 0: Desativa o manipulador de erros. É necessário desativar o que estiver vigente antes de iniciar um novo manipulador de erros.

 - On Error Resume Next: Ignora o erro atual e continua a execução na instrução posterior à que deu erro. Nenhum tratamento de erro é feito e o uso desta forma é altamente não recomendado, pois pode ocasionar erros ainda piores.

A instrução Resume Next (sem On Error na frente) direciona a execução à instrução seguinte à que deu erro. Ela deve ser utilizada na seção de tratamento de erros para retornar à execução caso o erro tenha sido tratado e seja possível continuar a execução. No caso do erro não ser tratável, o melhor a fazer é exibir uma mensagem ao usuário e encerrar o processamento. Nessa mensagem é bom escrever algo que amenize o impacto para o usuário e, se possível, informações que você possa usar para encontrar e lidar com o erro.

É possível desativar e reativar o manipulador de erros na própria seção de tratamento de erros, apontando para a própria seção. Desta forma, você poderá concentrar todo o tratamento de erros em um ponto da sub-rotina. Veja o exemplo abaixo:

Sub TesteOnError()

    Dim Calculo As Integer

    On Error GoTo TratarErro

    Calculo = "Texto"
    Calculo = 5 / 0

    Exit Sub

TratarErro:
    Debug.Print "Erro número " & Err.Number & " - " & Err.Description
    On Error GoTo 0
    On Error GoTo TratarErro
    Resume Next

End Sub

A instrução On Error foi colocada logo após a declaração de variável. Logo em seguida há duas instruções que acionarão o manipulador de erros. Use o depurador para acompanhar a execução desse código. Assim que passar pela primeira instrução, a execução irá para o rótulo TratarErro. A área de Verificação imediata irá exibir o número e a descrição do erro gerado. Em seguida, o manipulador de erros será desativado e reiniciado. Por fim, a execução irá para a linha seguinte à que gerou o erro. Esta linha também gera erro e o processo se repete. A área de Verificação imediata deverá exibir o seguinte texto:

Erro número 13 - Tipos incompatíveis
Erro número 11 - Divisão por zero

O erro 13 indica "tipos incompatíveis", pois enviamos texto para uma variável numérica. Já o erro 11 é bem autoexplicativo.

Observe que há um objeto Err na rotina de tratamento de erros, com duas propriedades sendo utilizadas: Number e Description, cujas finalidades estão bem claras no texto gerado. Há ainda dois métodos que podemos utilizar: Clear e Raise.

Err.Clear, como o nome sugere, zera o código de erro, o que também é feito pelo On Error GoTo 0. A diferença é que Err.Clear não desativa o depurador de código, sendo possível continuar apontando novos erros para a mesma rotina sem necessidade de colocar uma nova linha. Altere a seção TratarErro para o seguinte código:

TratarErro:
    Debug.Print "Erro número " & Err.Number & " - " & Err.Description
    Err.Clear
    Resume Next

Executando o código vemos que não foi necessário desativar e ativar novamente o manipulador de erros. Podemos até comentar a linha com o Err.Clear que irá funcionar. A instrução Resume Next também zera o código de erro, portanto também não precisamos nem da instrução Err.Clear neste exemplo. Porém, é importante conhecer a função dela porque pode haver casos em que é preciso zerar o código de erro e não dar sequência no processamento. Pelo mesmo motivo foram mostradas as diferentes formas de On Error.

Com Err.Raise é possível gerar seus próprios códigos de erros. Isso pode ser feito tanto para ajudar nos testes do código quanto para ajudar no próprio tratamento de erros da planilha. Também é possível colocar uma descrição, que pode ser usada como o texto a colocar em uma mensagem para o usuário. Veja o exemplo de código abaixo em que o erro está sendo gerado em uma sub-rotina diferente da que tem o tratamento de erro:

Sub TesteGerarErro()

    On Error GoTo TratarErro
    
    GerarErro (513)
    GerarErro (842)
    GerarErro (1059)
    
    Exit Sub

TratarErro:
    Debug.Print "Número: " & Err.Number & " - Descrição: " & Err.Description
    Resume Next

End Sub

Sub GerarErro(Erro As Long)

    Err.Raise Number:=Erro, Description:="Erro " & Erro & " gerado"

End Sub

Depure o código (tecla F8) para acompanhar a execução. Perceba que não importe quantos erros estão sendo gerados, a rotina de tratamento de erro exibe a mensagem com código e descrição e parte para a próxima linha de código. Em um caso de uso mais realista, pode-se colocar um Select Case para agir de acordo com a necessidade do erro, inclusive chamando outras sub-rotinas para simplificar o entendimento do código.

Imagine que esteja processando uma tabela longa e em uma linha aparece algum dado inválido. A sub-rotina que está lendo a linha pode efetuar uma consistência dos dados e gerar um código de erro diferente de acordo com a coluna onde estiver o dado. Por exemplo, se estiver na primeira coluna o código gerado é 601, se estiver na segunda é 602 e assim sucessivamente. Pode-se exibir uma mensagem diferente de acordo com o número do erro gerado, além de selecionar a célula com erro para apontar para o usuário, encerrando o processamento. Alternativamente, pode-se abrir um formulário mostrando os dados da linha que está sendo processada, apontando o campo onde está o erro e solicitar que o usuário coloque o valor correto para continuar o processamento. Outra possibilidade é não processar as linhas que contiverem erros e copiar seus valores para um arquivo de texto (ou CSV). Tudo depende da necessidade do projeto e da habilidade do desenvolvedor.

O intervalo de números de erro entre 0 e 512 é reservado para erros de sistema. Podemos utilizar os valores entre 513 e 65535 para erros específicos. Como há muitas possibilidades de valores, podemos definir uso de faixas no início do projeto, separando por exemplo de 1001 a 2000 para consistências de dados. Sempre deixe faixas de valores para poder usar um Select Case enviando faixas diferentes para tratar em rotinas diferentes.

Como pode-se perceber, é possível usar o manipulador de erros do VBA a seu favor, ajudando a evitar erros de sistema e criando códigos novos para direcionar o processamento de acordo com a necessidade. Combinando uma boa consistência de dados preventiva e o devido tratamento em caso de erros, a chance de algo dar errado torna-se bem próximo de zero. O usuário da sua planilha provavelmente nunca verá uma janela de erro junto com o Editor de VBA quando seu código estiver sendo executado.

Espero ter contribuído para melhorar o tratamento de erros de suas planilhas. Comentários e sugestões são bem vindos.

Pedro Martins


Formado em Tecnologia em Eletrônica Digital, já trabalhou como artefinalista, eletrotécnico, programador de CLP (para máquinas industriais) e analista de sistemas em sistema bancário, programando em COBOL.
Mexe com computadores e programação desde a segunda metade dos anos 1980, quando teve um MSX e aprendeu a programar em BASIC. É a favor da disseminação do conhecimento.




Postagem Anterior Próxima Postagem