Tag Archives: OnTime

VBA – Agendando a execução de macros com a função OnTime

Introdução

Uma necessidade muito comum em aplicativos é utilizar critérios de tempo para execução de algumas rotinas. Esta é uma tarefa trivial em várias linguagens, mas poucos pensam em utilizá-la no VBA por achar muito complexo, tendo que envolver chamadas de API e outros recursos mais avançados da linguagem

Porém, o VBA do Microsoft Excel disponibiliza um método que facilita esse tipo de trabalho, o método OnTime().

O que é

O método OnTime programa um procedimento para ser executado em um momento especificado no futuro (seja em uma determinada hora do dia ou após uma quantidade específica de tempo decorrido).

A estrutura de chamada à função OnTime se faz da seguinte forma:

Application.OnTime([EarliestTime], [Procedure], [LatestTime], [Schedule])

Argumentos da função:

EarliestTime

Variant necessário. Especifica quando você deseja que esse procedimento seja executado.

Procedure

String necessário. O nome do procedimento a ser executado.

LatestTime

Variant opcional. Especifica até quando o procedimento pode ser executado. Por exemplo, se LatestTime estiver definido como EarliestTime + 30 e o Microsoft Excel não estiver em modo Pronto, Copiar, Recortar ou Localizar em EarliestTime devido a um outro procedimento estar sendo executado, o Microsoft Excel esperará 30 segundos para que o primeiro procedimento termine. Se o Microsoft Excel não estiver em modo Pronto dentro de 30 segundos, o procedimento não será executado. Se esse argumento for omitido, o Microsoft Excel esperará até que o procedimento possa ser executado.

Schedule

Variant opcional. True para programar um novo procedimento OnTime. False para limpar um procedimento definido anteriormente. O valor padrão é True.

Exemplo

Para informar ao VBA um valor de data válido para execução do método OnTime, usa-se a propriedade Now do VBA juntamente com a função TimeValue( . Somando as duas, é possível programar o procedimento para ser executado quando uma quantidade de tempo específica (contando a partir de agora) tiver decorrido.

Caso seja necessário informar uma hora específica, por exemplo, 3 da tarde (ou 15:00), usa-se TimeValue(time) onde time é um valor de hora informado através de uma String.

Veja os exemplos de código abaixo:

Public Sub ExecutaOnTime()
MsgBox "Opa! Executou."
End Sub
Public Sub TesteOnTime()
Call Application.OnTime(Now +
TimeValue("00:00:10"), "ExecutaOnTime")
End Sub

Execute a função TesteOnTime, deixando o cursor do mouse sobre ele (linha 5 a 6) e clicando em F5. Se tudo der certo, em 10 segundos você deverá ver esta mensagem:

Pronto! Conforme configuramos o OnTime para executar 10 segundos após a hora atual (linha 6) pois, Now retorna a data e hora atual e TimeValue(“00:00:10”) representa para o VBA 10 segundos, após executar a função TesteOnTime, ela programa a função ExecutaOnTime (linha 1) para ser executada neste tempo.

Para efeitos de teste, configure outros valores de tempo, mas tome o cuidado que sejam pequenos pois, se configurar para executar daqui a 24 horas (“24:00:00”), vai ter que esperar um bom tempo.

Para fazer outro teste interessante do OnTime, mude o código para ficar desta forma:

Public Sub ExecutaOnTime()
MsgBox "Opa!
Executou."
End Sub
Public Sub TesteOnTime()
Call Application.OnTime(TimeValue("13:00:00"),
"ExecutaOnTime")
End Sub

Da forma que está, o código irá configurar a função ExecutaOnTime (linha 1) para ser executada às na próxima 13:00 do computador em que está sendo executada. Como este é apenas um exemplo, configure uma hora que estiver mais próxima para não esperar muito.

É possível também cancelar a execução de uma macro agendada com o OnTime. O exemplo de código abaixo cancela a definição de OnTime do exemplo anterior, ou seja, caso a execução da função ExecutaOnTime estiver agendada, executar a função CancelaOnTime fará com que esta programação seja cancelada. isso é feito passando o valor False para o parâmetro Schedule (linha 10):

Public Sub</span> ExecutaOnTime()
MsgBox "Opa! Executou."
End Sub
Public Sub TesteOnTime()
Call Application.OnTime(TimeValue("13:00:00"),
"ExecutaOnTime")
End Sub
Public Sub</span> CancelaOnTime()
Call Application.OnTime(EarliestTime:=TimeValue("13:00:00"),
Procedure:="ExecutaOnTime", Schedule:=False)
End Sub

Conclusão

Com este recurso em mãos, é possível atender a algumas necessidades que no contexto do Excel pareciam inviáveis. Um exemplo típico é uma tela de apresentação ou SplashScreen como é conhecida que apresenta o programa e fecha em alguns segundos. Este é um bom teste para experimentar o uso do OnTime. Fica aí um desafio.

How to implement sleep/wait with VBA

Excel-Sleep

Ok, everybody need this. Every single programmer that I’ve known once in his miserable life needed to do this in your programs. Alright, this is too dramatic, but it’s true. The problem is, in VBA, there is no easy going way to find a “how to do this”, like it is in other languages. But don’t worry. I’m here to save your lives, or something like that. Ok, too dramatic again.

With VBA, there are a couple of ways to do this.

First Method: Use an empty loop For… Next

The problem here is that you don’t have any control on how long it will take/sleep/wait/whatever. It’s just a way to make your program do nothing for a while. The code below runs for a while, given to the user the impression of be waiting.

1
2
3
4
Sub MyDelayMacro
 For iCount = 1 to 1000
 Next iCount
End Sub

Second Method: Use an API to call the Sleep method

Yes, there a Sleep method which can be called from VBA! This causes the same effect as the other programs, holding the process of the program for a defined amount of time, in milliseconds.

The kernel32 lib contains this method, so, you need to declare it in the top module to call it.

1
2
   Declare Sub Sleep Lib "kernel32" Alias "Sleep" _
 (ByVal dwMilliseconds As Long)

To call the Sleep method::

1
2
3
Sub Sleep()
 Sleep 1000   'Faz o código esperar por 1 segundo
 End Sub

Third Method: Use the OnTime Method

Actually, it’s my favourite. The OnTime method is embedded in VBA and the programmers are often used to it. The syntax is a bit weird, but it works!

expression .OnTime (when, name, fail tolerance)

It requires the name of the macro/method which will be called after some time, which is the first argument of the method. So, as it seems to be, you will need two macros. The first one will activate the OnTime, while the second will be called by the OnTime.

In the code below, the “MyMainMacro” activate the OnTime to call “MyDelayMacro” after 15 seconds.

1
2
3
4
5
6
7
8
Sub MyMainMacro()
 ' Pausa por 15 segundos.
 Application.OnTime Now + TimeValue("00:00:15"), "MyDelayMacro"
 End Sub
Public Sub MyDelayMacro()
 ' Macro executada sob o agendamento.
 MsgBox "Esta macro foi executada após 15 segundos."
 End Sub

Fourth Method: Call the Application.Wait method

It’s similar to Sleep, but instead of send the amount of seconds as an argument, you need to build a TimeValue variable to send as a parameter. You need to think a bit different to use, because the program will wait to the time you have defined. Let’s see take a look at the code:

1
2
3
4
5
6
7
Sub MyWaitMacro()
newHour = Hour(Now())
newMinute = Minute(Now())
newSecond = Second(Now()) + 3
waitTime = TimeSerial(newHour, newMinute, newSecond)
Application.Wait waitTime
End Sub

To read more about the OnTime method, check this post: https://www.tomasvasquez.com.br/blog/microsoft-office/vba-agendando-a-execucao-de-macros-com-a-funcao-ontime

Enjoy!