VBA - Artigo 005 - Atualização de tela e uso da barra de status

Progredindo em VBA no Microsoft Excel

Atualização de tela e uso da barra de status


Muitas vezes, ao executar macros, a tela pode ficar piscando durante o processamento, devido às movimentações de células ou trocas de planilhas ativas. Para evitar esse efeito há um comando muito útil, que você deve ter visto nas videoaulas do Alessandro Trovato:

Application.ScreenUpdating = False

Esse comando desabilita a atualização de tela, evitando essas piscadas incômodas, além de acelerar o processamento (pois o Excel não precisa mais ficar atualizando a tela). Porém, ao término do processamento, a atualização de tela deve ser novamente ativada, caso contrário o usuário não irá conseguir fazer mais nada na planilha. Use este comando para ativar:

Application.ScreenUpdating = True

Deve-se tomar cuidado para não deixar a atualização de tela inativa quando houver caixas de mensagens ou de entrada. Caso tenha alguma dessas, o ideal é deixar o código relativo a essas caixas antes da inibição de atualização da tela. Veja o modelo abaixo:

Sub Processamento()

    MsgBox "O processamento será executado agora", vbOKOnly

    Application.ScreenUpdating = False
   
' Código do processamento
   
    Application.ScreenUpdating = True

End Sub

Desta forma, as mensagens aparecerão, permitindo a interação com o usuário. O ideal é ter o ScreenUpdating em apenas uma sub-rotina do processamento, de preferência na sub-rotina principal. Porém, há casos em que é necessário interagir com o usuário, com caixas de mensagem ou de entrada. Desta forma, é preciso estar bem atento com os posicionamento do ScreenUpdating, para que tudo corra conforme o desejado. Teste bastante antes de entregar o projeto.

Se o processamento for de curta duração, com no máximo alguns segundos, o usuário nem perceberá que a tela não está sendo atualizada. Porém, se levar alguns segundos ou mesmo minutos, o usuário poderá pensar que o computador travou. Portanto, precisamos usar um recurso que informe em que ponto do processo está. A barra de status é uma grande ajuda e relativamente fácil de ser usada. Analise o código abaixo:

Sub Processamento()

    Dim Iteracao        As Long
    Dim UltimaCelula    As Long
    Dim Percentual      As Double

    Application.ScreenUpdating = False
   
    UltimaLinha = Cells(ActiveSheet.Rows.Count, 1).End(xlUp).Row

    For Iteracao = 2 To UltimaLinha
        Percentual = (Iteracao - 1) / (UltimaLinha - 1) * 100
        Application.StatusBar = "Processando... " & Percentual & "%"
        '
        ' Código do processamento
        '
    Next
   
    Application.ScreenUpdating = True
    Application.StatusBar = False

End Sub

Neste exemplo é calculado o percentual do processamento e exibido na barra de status. Perceba que no código a estrutura de repetição inicia no valor 2, supondo que a primeira linha seja de título da coluna. Por isso que no cálculo de percentual foi subtraído 1 da célula atual e da última célula, caso contrário o cálculo não daria os valores corretos. Se for preciso processar com outro número inicial será preciso adaptar os valores.

Note também que ao final do processo é preciso desabilitar a barra de status, dando o valor de False a ela. Se esquecer de fazer isso, ela ficará com o valor fixo "Processando... 100%" ao término da execução.

Há quem prefira usar a forma "Processando linha ## de ##". Usando o exemplo acima, o código seria:


Application.StatusBar = "Processando... " & Iteracao - 1 & " de " & UltimaLinha - 1

Entretanto, se o processamento for longo demais, pode acontecer da própria barra de status também parecer "travar", parando em um valor intermediário e o Excel exibir a temerosa frase "não está respondendo". É possível evitar isso, acrescentando um comando simples na estrutura de repetição: DoEvents. Ele executa eventos pendentes, evitando que o Excel pareça travado. Ele é muito útil em estruturas de repetição demoradas, embora nada impeça de colocar em estruturas menores.

O uso é simples: basta adicionar uma linha no código dentro da estrutura de repetição. Pode ser no início ou no fim, tanto faz, mas o importante é que o comando seja colocado uma única vez para não gastar muito tempo, pois o processamento irá demorar um pouco mais. Pode tanto ser imperceptível como durar alguns segundos a mais, varia de caso para caso. Usando o DoEvents no exemplo anterior:

Sub Processamento()

    Dim Iteracao        As Long
    Dim UltimaCelula    As Long
    Dim Percentual      As Double

    Application.ScreenUpdating = False
   
    UltimaCelula = Cells(ActiveSheet.Rows.Count, 1).End(xlUp).Row

    For Iteracao = 2 To UltimaCelula
        Percentual = (Iteracao - 1) / (UltimaCelula - 1) * 100
        Application.StatusBar = "Processando... " & Percentual & "%"
        '
        ' Código do processamento
        '
        DoEvents
    Next
   
    Application.ScreenUpdating = True
    Application.StatusBar = False

End Sub

Aqui ele foi colocado no final da estrutura de repetição, logo antes do fechamento dela. Desta forma, a cada ciclo executado, serão processados os eventos pendentes, evitando a aparência de "travado". É possível melhorar ainda mais, executando o DoEvents a cada determinada quantidade de processamento. Pode-se usar o número da linha ou o percentual exibido na barra de status como "gatilho". Atualizando o mesmo exemplo:

Sub Processamento()

    Dim nteracao        As Long
    Dim UltimaCelula    As Long
    Dim Percentual      As Double

    Application.ScreenUpdating = False
   
    UltimaCelula = Cells(ActiveSheet.Rows.Count, 1).End(xlUp).Row

    For Iteracao = 2 To UltimaCelula
        Percentual = (Iteracao - 1) / (UltimaCelula - 1) * 100
        Application.StatusBar = "Processando... " & Percentual & "%"
        '
        ' Código do processamento
        '
        If Iteracao mod 100 = 0 Then
            DoEvents
        End If
    Next
   
    Application.ScreenUpdating = True
    Application.StatusBar = False

End Sub

Iteracao mod 100 = 0 verifica se o número da iteração é múltiplo de 100. Caso seja, executará os eventos pendentes. O custo de processamento do If é muito pequeno se comparado ao DoEvents, portanto esta solução evita que se perca muito tempo processando eventos sem necessidade. Neste exemplo está sendo feito a cada vez que a linha processada seja múltipla de 100, mas pode-se colocar outro valor qualquer. Tudo vai depender do quanto tempo está sendo gasto durante a execução da estrutura de repetição. Se demorar muito, é melhor reduzir a quantidade de linhas; se for muito rápido, é melhor aumentar.

Use esses comandos dependendo da necessidade, teste sempre o processo antes de codificar estes comandos. Por exemplo, não há necessidade de colocar a barra de status quando o processo todo leva menos de 3 segundos, o usuário mal perceberá a diferença. Da mesma forma, se a tela sequer pisca não há necessidade de usar o ScreenUpdating. Por fim, só use o DoEvents quando o processamento for longo e o Excel parecer travado.


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