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.


Catálogo de aulas (NOVIDADE)

Criei um catálogo de aulas para ajudar você em seus estudos. Acesse clicando na imagem abaixo ou clique aqui.


Postagem Anterior Próxima Postagem