Existe código em VBA com o qual posso encapsular uma função que me avisará quanto tempo levou para ser executado, para que eu possa comparar os diferentes tempos de execução das funções?
Existe código em VBA com o qual posso encapsular uma função que me avisará quanto tempo levou para ser executado, para que eu possa comparar os diferentes tempos de execução das funções?
Respostas:
A menos que suas funções sejam muito lentas, você precisará de um cronômetro de resolução muito alta. O mais preciso que conheço é QueryPerformanceCounter
. Pesquise no Google para mais informações. Tente empurrar o seguinte para uma classe, chame-a por CTimer
exemplo, então você pode fazer uma instância em algum lugar global e apenas chamar .StartCounter
e.TimeElapsed
Option Explicit
Private Type LARGE_INTEGER
lowpart As Long
highpart As Long
End Type
Private Declare Function QueryPerformanceCounter Lib "kernel32" (lpPerformanceCount As LARGE_INTEGER) As Long
Private Declare Function QueryPerformanceFrequency Lib "kernel32" (lpFrequency As LARGE_INTEGER) As Long
Private m_CounterStart As LARGE_INTEGER
Private m_CounterEnd As LARGE_INTEGER
Private m_crFrequency As Double
Private Const TWO_32 = 4294967296# ' = 256# * 256# * 256# * 256#
Private Function LI2Double(LI As LARGE_INTEGER) As Double
Dim Low As Double
Low = LI.lowpart
If Low < 0 Then
Low = Low + TWO_32
End If
LI2Double = LI.highpart * TWO_32 + Low
End Function
Private Sub Class_Initialize()
Dim PerfFrequency As LARGE_INTEGER
QueryPerformanceFrequency PerfFrequency
m_crFrequency = LI2Double(PerfFrequency)
End Sub
Public Sub StartCounter()
QueryPerformanceCounter m_CounterStart
End Sub
Property Get TimeElapsed() As Double
Dim crStart As Double
Dim crStop As Double
QueryPerformanceCounter m_CounterEnd
crStart = LI2Double(m_CounterStart)
crStop = LI2Double(m_CounterEnd)
TimeElapsed = 1000# * (crStop - crStart) / m_crFrequency
End Property
TimeElapsed()
dá o resultado em milissegundos. Não implementei nenhuma compensação de overhead porque estava mais preocupado com o efeito da gagueira no cálculo do overhead do que com a precisão perfeita.
GetTickCount
do kernel32).
StartCounter
And TimeElapsed
? Eu fiz uma instância Timer de CTimer
no início e With StartCounter
só escrevi .StartCounter
depois que meu sub começou .TimeElapsed
e ele me respondeu Invalid use of property
. Quando eu o deixo .StartCounter
sozinho, ele me diz que um objeto não está definido.
Declare PtrSafe Function
stackoverflow.com/questions/21611744/…
A função Timer em VBA fornece o número de segundos decorridos desde a meia-noite até 1/100 de segundo.
Dim t as single
t = Timer
'code
MsgBox Timer - t
Se você está tentando retornar o tempo como um cronômetro, pode usar a seguinte API, que retorna o tempo em milissegundos desde a inicialização do sistema:
Public Declare Function GetTickCount Lib "kernel32.dll" () As Long
Sub testTimer()
Dim t As Long
t = GetTickCount
For i = 1 To 1000000
a = a + 1
Next
MsgBox GetTickCount - t, , "Milliseconds"
End Sub
depois de http://www.pcreview.co.uk/forums/grab-time-milliseconds-included-vba-t994765.html (já que timeGetTime em winmm.dll não estava funcionando para mim e QueryPerformanceCounter era muito complicado para a tarefa necessária)
Public Declare Function ...
parte? Ele cria um erro ao adicionar seu código na parte inferior do meu
Para novatos, esses links explicam como fazer um perfil automático de todos os subs que você deseja monitorar:
http://www.nullskull.com/a/1602/profiling-and-optimizing-vba.aspx
http://sites.mcpher.com/share/Home/excelquirks/optimizationlink veja procProfiler.zip em http://sites.mcpher.com/share/Home/excelquirks/downlable-items
Sub Macro1()
Dim StartTime As Double
StartTime = Timer
''''''''''''''''''''
'Your Code'
''''''''''''''''''''
MsgBox "RunTime : " & Format((Timer - StartTime) / 86400, "hh:mm:ss")
End Sub
Resultado:
Tempo de execução: 00:00:02
Há muitos anos, usamos uma solução baseada em timeGetTime em winmm.dll para precisão de milissegundos. Veja http://www.aboutvb.de/kom/artikel/komstopwatch.htm
O artigo está em alemão, mas o código no download (uma classe VBA que envolve a chamada de função dll) é simples o suficiente para usar e entender sem ser capaz de ler o artigo.
Segundos com 2 casas decimais:
Dim startTime As Single 'start timer
MsgBox ("run time: " & Format((Timer - startTime) / 1000000, "#,##0.00") & " seconds") 'end timer
Milissegundos:
Dim startTime As Single 'start timer
MsgBox ("run time: " & Format((Timer - startTime), "#,##0.00") & " milliseconds") 'end timer
Milissegundos com separador de vírgula:
Dim startTime As Single 'start timer
MsgBox ("run time: " & Format((Timer - startTime) * 1000, "#,##0.00") & " milliseconds") 'end timer
Só deixando isso aqui para quem estava procurando um cronômetro simples formatado com segundos para 2 casas decimais como eu. Estes são pequenos temporizadores curtos e doces que eu gosto de usar. Eles ocupam apenas uma linha de código no início da sub ou função e uma linha de código novamente no final. Eles não foram feitos para serem extremamente precisos, geralmente não me importo com nada menos que 1/100 de segundo pessoalmente, mas o cronômetro de milissegundos dará a você o tempo de execução mais preciso desses 3. Eu também li para você pode obter a leitura incorreta se acontecer de ser executado durante a passagem da meia-noite, um caso raro, mas apenas para sua informação.