您如何测试VBA代码的运行时间?


Answers:


81

除非您的功能很慢,否则您将需要一个非常高分辨率的计时器。我知道的最准确的是QueryPerformanceCounter。谷歌获取更多信息。尝试推动以下到一类,把它CTimer说,那么你可以让一个实例全球某处,只是打电话.StartCounter.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

2
我实现了在Excel VBA(添加,因为这样有知识库文章中提到的开销:support.microsoft.com/kb/172338它的工作十分感谢。
兰斯·罗伯茨

2
谢谢,这对我也很好。TimeElapsed()给出结果(以毫秒为单位)。我没有执行任何开销补偿,因为我更担心开销计算中的口吃而不是完美的准确性。
贾斯汀

2
这是很多听闻的内容(在要管理的代码行中)-如果您能够以〜10ms的精度生存,则下面的@Kodak答案将在一行代码中(GetTickCount从kernel32 导入)给出相同的结果。
BrainSlugs83 2014年

您如何使用StartCounterAnd TimeElapsed?我在一CTimer开始就做了一个实例Timer,With StartCounter我只是.StartCounter在我的潜艇开始后写了.TimeElapsed,它回答了我Invalid use of property。当我更不用说.StartCounter它告诉我未设置对象时。
莫妮卡(Monica)

对于Excel 2010:Declare PtrSafe Function stackoverflow.com/questions/21611744/…–
1:32的user3226167

48

VBA中的计时器功能使您自午夜起经过的秒数达到1/100秒。

Dim t as single
t = Timer
'code
MsgBox Timer - t

18
那是行不通的-从这样的平均值中获取更大的分辨率是不可能的。
Andrew Scagnelli 09年

2
不过,如果您要在VBA中测量性能,则获得1/100秒的分辨率也不错。-仅调用定时呼叫可能要花费几毫秒。如果呼叫是如此之快,以至于您需要足够的分辨率来计时,那么您可能不需要该呼叫的性能数据。
BrainSlugs83 2014年

注意:在Mac上,计时器只能精确到一秒-如果它在午夜之前开始并在午夜之后结束,则它可能会变成负数
TmTron 16'Aug4

32

如果您试图像秒表一样返回时间,则可以使用以下API,它返回自系统启动以来的时间(以毫秒为单位):

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

http://www.pcreview.co.uk/forums/grab-time-milliseconds-included-vba-t994765.html之后(由于winmm.dll中的timeGetTime对我不起作用,而QueryPerformanceCounter对于所需的任务来说太复杂了)


这是一个很好的答案。注意:通过MSDN ,返回的数据的精度以毫秒为单位,但是,该计数器的精度精确到大约1/100秒(即,它可能会偏离10到16毫秒):msdn.microsoft.com / zh-
CN

嗯,如果此处的分辨率与计时器相同,那么我将使用计时器
柯达

是什么Public Declare Function ...部分?它在矿井底部添加代码时创建了一个错误
革命报莫妮卡

您需要将此公共声明移至模块顶部
柯达


3
Sub Macro1()
    Dim StartTime As Double
    StartTime = Timer

        ''''''''''''''''''''
            'Your Code'
        ''''''''''''''''''''
    MsgBox "RunTime : " & Format((Timer - StartTime) / 86400, "hh:mm:ss")
End Sub

输出:

播放时间:00:00:02



1

秒,含2个小数位:

Dim startTime As Single 'start timer
MsgBox ("run time: " & Format((Timer - startTime) / 1000000, "#,##0.00") & " seconds") 'end timer

秒格式

毫秒:

Dim startTime As Single 'start timer
MsgBox ("run time: " & Format((Timer - startTime), "#,##0.00") & " milliseconds") 'end timer

毫秒格式

使用逗号分隔符的毫秒数:

Dim startTime As Single 'start timer
MsgBox ("run time: " & Format((Timer - startTime) * 1000, "#,##0.00") & " milliseconds") 'end timer

毫秒(带逗号分隔符)

只是将其留在这里,供任何正在寻找像我一样使用秒到2小数位格式的简单计时器的人使用。这些是我喜欢使用的简短而可爱的小计时器。它们在子或函数的开头仅占用一行代码,而在结尾处仅占用一行代码。这些并不意味着疯狂准确,我个人通常并不关心少于1/100秒的内容,但是毫秒计时器将为您提供这3种中最准确的运行时间。我也读过您如果它恰好在午夜时分运行时可能会得到不正确的读数,这种情况很少见,但仅供参考。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.