Есть ли в VBA код, которым я могу обернуть функцию, которая сообщит мне, сколько времени потребовалось для запуска, чтобы я мог сравнить разное время работы функций?
Есть ли в VBA код, которым я могу обернуть функцию, которая сообщит мне, сколько времени потребовалось для запуска, чтобы я мог сравнить разное время работы функций?
Ответы:
Если ваши функции не очень медленные, вам понадобится таймер с очень высоким разрешением. Самый точный из известных мне QueryPerformanceCounter
. Google для получения дополнительной информации. Попробуйте вставить следующее в класс, назовите его CTimer
say, затем вы можете создать экземпляр где-нибудь в глобальном масштабе и просто вызвать .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
TimeElapsed()
дает результат в миллисекундах. Я не реализовал какую-либо компенсацию накладных расходов, потому что меня больше беспокоил эффект заикания в подсчете накладных расходов, чем безупречная точность.
GetTickCount
из kernel32).
StartCounter
And TimeElapsed
? Я сделал экземпляр Timer CTimer
в начале, и With StartCounter
я просто написал .StartCounter
после того, как моя подпрограмма началась, .TimeElapsed
и мне ответили Invalid use of property
. Когда я не говоря .StartCounter
уже о том, он говорит мне, что объект не установлен.
Declare PtrSafe Function
stackoverflow.com/questions/21611744/…
Функция таймера в VBA дает вам количество секунд, прошедших с полуночи, с точностью до 1/100 секунды.
Dim t as single
t = Timer
'code
MsgBox Timer - t
Если вы пытаетесь вернуть время как секундомер, вы можете использовать следующий 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 (поскольку timeGetTime в winmm.dll у меня не работал, а QueryPerformanceCounter был слишком сложен для поставленной задачи)
Public Declare Function ...
роль? Он создает ошибку при добавлении вашего кода внизу моего
Для новичков эти ссылки объясняют, как сделать автоматическое профилирование всех подписок, время которых вы хотите отслеживать:
http://www.nullskull.com/a/1602/profiling-and-optimizing-vba.aspx
http://sites.mcpher.com/share/Home/excelquirks/optimizationlink см. procProfiler.zip в 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
Вывод:
Время выполнения: 00:00:02
Мы уже много лет использовали решение на основе timeGetTime в winmm.dll для точности до миллисекунд. См. Http://www.aboutvb.de/kom/artikel/komstopwatch.htm.
Статья на немецком языке, но код в загружаемом файле (класс VBA, оборачивающий вызов функции dll) достаточно прост для использования и понимания, не имея возможности прочитать статью.
Секунды с двумя знаками после запятой:
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
Просто оставьте это здесь для всех, кто искал простой таймер, отформатированный с секундами до двух десятичных знаков, как и я. Я люблю использовать эти короткие и милые маленькие таймеры. Они занимают только одну строку кода в начале подпрограммы или функции и еще одну строку кода в конце. Они не должны быть безумно точными, меня обычно не волнует что-либо менее 1/100 секунды лично, но таймер миллисекунд даст вам наиболее точное время работы из этих 3. Я также читал вас может получить неправильные показания, если он сработает при переходе через полночь, что является редким случаем, но просто к сведению.