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.