2008-10-13 15 views

Répondre

67

À moins que vos fonctions ne soient très lentes, vous aurez besoin d'une minuterie à très haute résolution. Le plus précis que je connaisse est QueryPerformanceCounter. Recherche le sur Google pour plus d'informations. Essayez de pousser ce qui suit dans une classe, appelez-le CTimer dire, alors vous pouvez faire une instance quelque part juste et globale appeler .StartCounter et .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

Je dans Excel implémenté VBA (en ajoutant dans les frais généraux, comme mentionné dans ce KB article: http://support.microsoft.com/kb/172338. Ça a bien marché. Merci. –

+1

Merci, cela fonctionne bien pour moi aussi. 'TimeElapsed()' donne le résultat en millisecondes. Je n'ai pas mis en place de compensation pour frais généraux parce que j'étais plus préoccupé par l'effet d'un bégaiement dans le calcul des frais généraux qu'une précision parfaite. – Justin

+1

C'est beaucoup d'overheard (dans les lignes de code à gérer) - si vous pouvez vivre avec une précision de ~ 10ms, la réponse de Kodak ci-dessous donne la même chose dans une ligne de code (importer 'GetTickCount' de kernel32). – BrainSlugs83

2

Nous avons utilisé une solution basée sur timeGetTime en winmm.dll pour la milliseconde pendant de nombreuses années. Voir http://www.aboutvb.de/kom/artikel/komstopwatch.htm

L'article est en allemand, mais le code dans le téléchargement (une classe VBA enveloppant l'appel de fonction dll) est assez simple à utiliser et à comprendre sans être capable de lire l'article.

39

La fonction Minuterie dans VBA vous indique le nombre de secondes écoulées depuis minuit à 1/100 de seconde.

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

Si vous avez besoin d'une plus grande résolution, j'exécuterais simplement la fonction 1,000 fois et diviserais le temps total par 1,000.

+15

Cela ne fonctionnerait pas - vous ne pouvez pas obtenir plus de résolution de prendre la moyenne comme ça. –

+2

Néanmoins, si vous mesurez les performances dans VBA, obtenir une résolution de 1/100ème de seconde n'est pas mauvais. - Invoquer les appels de chronométrage seul pourrait prendre quelques ms. Si l'appel est si rapide que vous avez besoin de beaucoup de résolution pour le chronométrer, vous n'avez probablement pas besoin de données sur les performances de cet appel. – BrainSlugs83

+10

+1 pour l'utilisation de la fonction native. – RubberDuck

25

Si vous essayez de retourner le temps comme un chronomètre, vous pouvez utiliser l'API suivante qui retourne le temps en millisecondes depuis le démarrage du système:

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 

après http://www.pcreview.co.uk/forums/grab-time-milliseconds-included-vba-t994765.html (comme dans timeGetTime winmm.dll n'a pas été travaillant pour moi et QueryPerformanceCounter était trop compliqué pour la tâche nécessaire)

+0

Ceci est une excellente réponse. A noter: la * précision * des données renvoyées est en millisecondes, cependant, le compteur est seulement * précis * à environ 1/100ème de seconde (c'est-à-dire qu'il peut être désactivé de 10 à 16 ms) via MSDN: http : //msdn.microsoft.com/en-us/library/windows/desktop/ms724408 (v = vs.85) .aspx – BrainSlugs83

+0

hmm, si la résolution est la même ici qu'avec le temporisateur alors j'irais avec le temporisateur – Kodak

+0

Qu'est-ce que la partie 'Public Declare Function ...'? Il crée une erreur lors de l'ajout de votre code au bas de la mienne – Marine1