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