Vous ne trouvez pas de réponse à votre problème ? Alors posez la question dans le forum. Souvenez-vous qu'il n'y a jamais de question bête, mais rester dans l'ignorance parce que l'on n'ose pas poser une question, ça c'est une erreur !

ALTERNATIVE TIMER POUR VBA


Information sur la source

Catégorie :VBA Classé sous : timer, macro Niveau : Initié Date de création : 07/02/2007 Date de mise à jour : 10/02/2007 20:22:26 Vu / téléchargé: 8 436 / 831

Note :
9,25 / 10 - par 4 personnes
9,25 / 10

  • 1

  • 2

  • 3

  • 4

  • 5

  • 6

  • 7

  • 8

  • 9

  • 10

Commentaire sur cette source (19)
Ajouter un commentaire et/ou une note

Description

Cliquez pour voir la capture en taille normale
Bonjour,

Ce code défini une classe d'objet « Timer » permettant de créer des 'Timer' tournant sur de longues durées.
Il a vu le jour suite à un problème rencontré lors du développement d'une macro EXCEL nécessitant l'exécution d’une tâche à intervalle régulier. Le composant 'Timer' n'existant pas sous VBA, et une simple boucle faisant ramer le PC, j'ai créé le mien...

 

Source

  • 'Contenu de ma classe Timer
  • Option Explicit
  • Private localInterval As Long
  • Private localEnabled As Boolean
  • Private Type FILETIME
  • dwLowDateTime As Long
  • dwHighDateTime As Long
  • End Type
  • Private TimeOptions As FILETIME ' Durée transmise à la fonction SetWaitableTimer
  • Private Declare Function CreateWaitableTimer Lib "kernel32" Alias "CreateWaitableTimerA" (ByVal lpSemaphoreAttributes As Long, ByVal bManualReset As Long, ByVal lpName As String) As Long
  • Private Declare Function SetWaitableTimer Lib "kernel32" (ByVal hTimer As Long, lpDueTime As FILETIME, ByVal lPeriod As Long, ByVal pfnCompletionRoutine As Long, ByVal lpArgToCompletionRoutine As Long, ByVal fResume As Long) As Long
  • Private Declare Function CancelWaitableTimer& Lib "kernel32" (ByVal hTimer As Long)
  • Private Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long
  • Private Declare Function MsgWaitForMultipleObjects Lib "user32" (ByVal nCount As Long, pHandles As Long, ByVal fWaitAll As Long, ByVal dwMilliseconds As Long, ByVal dwWakeMask As Long) As Long
  • Private TimerhWait As Long
  • Private CancelTimer As Boolean
  • Private TimerRunning As Boolean
  • Public Event Timer()
  • '--------------------------------------------------------------
  • 'Routine de temporisation...
  • '<vdata> : milisecondes
  • '<vdata> : <= 0 Annuler l'attente
  • '<vdata> : > 0 Démarrer la boucle d'attente
  • Public Property Let interval(vdata As Long)
  • 'Si le Timer est activé
  • If localEnabled Then
  • 'Reset le drapeau d'annulation
  • CancelTimer = False
  • 'Si la durée est inférieur ou égale à zéro
  • If vdata <= 0 Then
  • 'Durée de la temporisation : <vdata> ms
  • TimeOptions.dwLowDateTime = -1
  • 'Mettre à jour la variable locale
  • localInterval = vdata
  • 'Sinon
  • Else
  • 'Si le timer tourne déjà
  • If TimerRunning Then
  • 'Annule le décompte en cours
  • CancelWaitableTimer TimerhWait
  • 'Convertir la nouvelle durée
  • TimeOptions.dwLowDateTime = CLng(vdata * -10000)
  • 'Programmer le déclenchement de l'évènement 'TimerhWait' dans 'TimeOptions' ms
  • SetWaitableTimer TimerhWait, TimeOptions, 0, 0, 0, 0
  • 'Mettre à jour la variable locale
  • localInterval = vdata
  • 'Sinon
  • Else
  • 'Définir localement le timer comme tournant
  • TimerRunning = True
  • 'Mettre à jour la variable locale
  • localInterval = vdata
  • 'Convertir la nouvelle durée
  • TimeOptions.dwLowDateTime = CLng(vdata * -10000)
  • 'Boucle infinie (jusqu'à annulation)
  • Do Until TimeOptions.dwLowDateTime = -1
  • 'Programmer le déclenchement du prochain évènement 'TimerhWait' dans 'Timeoptions' ms
  • SetWaitableTimer TimerhWait, TimeOptions, 0, 0, 0, 0
  • 'Boucle d'attente sans stress (Attendre le déclenchement de l'évènement 'TimerhWait')
  • Do While MsgWaitForMultipleObjects(1, TimerhWait, False, &HFFFF, &HFF) > 0
  • DoEvents
  • 'If CancelTimer Then Exit Do
  • Loop
  • 'Si annulation, sortir de la boucle infinie
  • If TimeOptions.dwLowDateTime = -1 Then Exit Do
  • 'Déclenchement de l'évènement 'Timer'
  • RaiseEvent Timer
  • Loop
  • 'Définir localement le timer à l'arrêt
  • TimerRunning = False
  • End If
  • End If
  • 'Sinon
  • Else
  • 'Mettre à jour la variable locale
  • localInterval = vdata
  • End If
  • End Property
  • Public Property Get interval() As Long
  • interval = localInterval
  • End Property
  • '--------------------------------------------------------------
  • Public Property Let Enabled(vdata As Boolean)
  • 'Si changement
  • If vdata <> localEnabled Then
  • 'Si activation
  • If vdata Then
  • 'Mettre à jour la variable locale
  • localEnabled = vdata
  • 'Si l'intervalle est supérieur à zéro
  • If localInterval > 0 Then
  • 'Mise en route du timer
  • Me.interval = localInterval
  • End If
  • 'Sinon
  • Else
  • 'Annulation
  • TimeOptions.dwLowDateTime = -1
  • 'Mettre à jour la variable locale
  • localEnabled = vdata
  • End If
  • End If
  • End Property
  • Public Property Get Enabled() As Boolean
  • Enabled = localEnabled
  • End Property
  • '--------------------------------------------------------------
  • Private Sub Class_Initialize()
  • 'Création de l'horloge
  • TimerhWait = CreateWaitableTimer(0, True, "Timer6RatsMorts")
  • 'Initialisation de la durée
  • TimeOptions.dwHighDateTime = -1
  • TimeOptions.dwLowDateTime = -1
  • End Sub
  • Private Sub Class_Terminate()
  • TimeOptions.dwHighDateTime = -1
  • TimeOptions.dwLowDateTime = -1
  • CloseHandle TimerhWait
  • End Sub
'Contenu de ma classe Timer

Option Explicit

Private localInterval As Long
Private localEnabled As Boolean

Private Type FILETIME
    dwLowDateTime As Long
    dwHighDateTime As Long
End Type

Private TimeOptions As FILETIME  ' Durée transmise à la fonction SetWaitableTimer

Private Declare Function CreateWaitableTimer Lib "kernel32" Alias "CreateWaitableTimerA" (ByVal lpSemaphoreAttributes As Long, ByVal bManualReset As Long, ByVal lpName As String) As Long
Private Declare Function SetWaitableTimer Lib "kernel32" (ByVal hTimer As Long, lpDueTime As FILETIME, ByVal lPeriod As Long, ByVal pfnCompletionRoutine As Long, ByVal lpArgToCompletionRoutine As Long, ByVal fResume As Long) As Long
Private Declare Function CancelWaitableTimer& Lib "kernel32" (ByVal hTimer As Long)
Private Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long
Private Declare Function MsgWaitForMultipleObjects Lib "user32" (ByVal nCount As Long, pHandles As Long, ByVal fWaitAll As Long, ByVal dwMilliseconds As Long, ByVal dwWakeMask As Long) As Long

Private TimerhWait As Long
Private CancelTimer As Boolean
Private TimerRunning As Boolean

Public Event Timer()

'--------------------------------------------------------------
'Routine de temporisation...
'<vdata> : milisecondes
'<vdata> : <= 0 Annuler l'attente
'<vdata> : > 0 Démarrer la boucle d'attente

Public Property Let interval(vdata As Long)
'Si le Timer est activé
If localEnabled Then
        
    'Reset le drapeau d'annulation
    CancelTimer = False
    
    'Si la durée est inférieur ou égale à zéro
    If vdata <= 0 Then
        'Durée de la temporisation : <vdata> ms
        TimeOptions.dwLowDateTime = -1
        'Mettre à jour la variable locale
        localInterval = vdata
    'Sinon
    Else
        'Si le timer tourne déjà
        If TimerRunning Then
            'Annule le décompte en cours
            CancelWaitableTimer TimerhWait
            'Convertir la nouvelle durée
            TimeOptions.dwLowDateTime = CLng(vdata * -10000)
            'Programmer le déclenchement de l'évènement 'TimerhWait' dans 'TimeOptions' ms
            SetWaitableTimer TimerhWait, TimeOptions, 0, 0, 0, 0
            'Mettre à jour la variable locale
            localInterval = vdata
        'Sinon
        Else
            'Définir localement le timer comme tournant
            TimerRunning = True
            'Mettre à jour la variable locale
            localInterval = vdata
            'Convertir la nouvelle durée
            TimeOptions.dwLowDateTime = CLng(vdata * -10000)
            
            'Boucle infinie (jusqu'à annulation)
            Do Until TimeOptions.dwLowDateTime = -1
                
                'Programmer le déclenchement du prochain évènement 'TimerhWait' dans 'Timeoptions' ms
                SetWaitableTimer TimerhWait, TimeOptions, 0, 0, 0, 0
                
                'Boucle d'attente sans stress (Attendre le déclenchement de l'évènement 'TimerhWait')
                Do While MsgWaitForMultipleObjects(1, TimerhWait, False, &HFFFF, &HFF) > 0
                    DoEvents
                    'If CancelTimer Then Exit Do
                Loop
                
                'Si annulation, sortir de la boucle infinie
                If TimeOptions.dwLowDateTime = -1 Then Exit Do
                
                'Déclenchement de l'évènement 'Timer'
                RaiseEvent Timer
            
            Loop
            
            'Définir localement le timer à l'arrêt
            TimerRunning = False
            
        End If
    End If
'Sinon
Else
    'Mettre à jour la variable locale
    localInterval = vdata
End If
End Property

Public Property Get interval() As Long
    interval = localInterval
End Property

'--------------------------------------------------------------
Public Property Let Enabled(vdata As Boolean)

'Si changement
If vdata <> localEnabled Then
    'Si activation
    If vdata Then
        'Mettre à jour la variable locale
        localEnabled = vdata
        'Si l'intervalle est supérieur à zéro
        If localInterval > 0 Then
            'Mise en route du timer
            Me.interval = localInterval
        End If
    'Sinon
    Else
        'Annulation
        TimeOptions.dwLowDateTime = -1
        'Mettre à jour la variable locale
        localEnabled = vdata
    End If
End If
End Property

Public Property Get Enabled() As Boolean
    Enabled = localEnabled
End Property

'--------------------------------------------------------------
Private Sub Class_Initialize()
    'Création de l'horloge
    TimerhWait = CreateWaitableTimer(0, True, "Timer6RatsMorts")
    'Initialisation de la durée
    TimeOptions.dwHighDateTime = -1
    TimeOptions.dwLowDateTime = -1
End Sub

Private Sub Class_Terminate()
    TimeOptions.dwHighDateTime = -1
    TimeOptions.dwLowDateTime = -1
    CloseHandle TimerhWait
End Sub

Fichier Zip

Pour les "Membres Club", vous pouvez télécharger directement un fichier contenu dans le zip sans télécharger le zip en entier !
  • Essai Timer.xlsTélécharger ce fichier [Réservé aux membres club]47 104 octets

Télécharger le zip

Historique

10 février 2007 20:08:30 :
RAS
10 février 2007 20:22:26 :
Correction de la présentation du code

Commentaires et avis

signaler à un administrateur
Commentaire de jean_marc_n2 le 07/02/2007 15:41:50

Très sympathique, tout simple, tout léger, parfait!
Utilisation simplissime mais suffisante, bref, c'est nickel!
Du code comme on aimerait à en voir plus souvent :-)
Je mets 10/10, bien sur!

signaler à un administrateur
Commentaire de 6RatsMorts le 12/02/2007 01:16:41

Merci.

signaler à un administrateur
Commentaire de verlaat4show le 18/02/2007 12:08:51

Cool ton code

jai u un pb identique  sous vba, j'ai besoin de lancer plusieurs chrono et/ou compte à rebours en laissant la main à dautres processus
et vu qu'avec la fonction timer c'est just just. Jvais essayer ta classe Timer.

T'en as u besoin pour faire koi comme appli si pas indiscret...

Koi kil en soit CIMER, jessaie jte donne des news ou jaurais ptetre besoin de tes services pour utiliser le timer...

signaler à un administrateur
Commentaire de 6RatsMorts le 22/02/2007 14:48:36

verlaat4show :

Si tu as un soucis de prog demande, on ne sais jamais. J'essayerai de t'aider...

J'en ai eu besoin pour migrer une appli VB vers VBA...

signaler à un administrateur
Commentaire de mimiZanzan le 24/02/2007 00:22:17

J'ai déjà soumis récemment un code pour un timer pour VBA sous forme d'un contrôle activeX (code  "Timer pour VBA"), qui se manipule exactement comme le timer VB, et on peut mettre autant de ces timers que l'on veut dans une application VBA.

signaler à un administrateur
Commentaire de verlaat4show le 26/02/2007 13:53:27

               Application.onTime is Good

666ratsmorts Merci. ton code fonctionnent avec de toutes pitites modifications, Jvais surement utiliser ta classe car elle evite d'utiliser des fichiers en plus : contrôle timer vb à importer

juste une petite question toi qui semble gérer dans l'utilisation des dll, dans ta classe tu fais appel à user32 et à kernell32,
à la ligne :
Private Declare Function CancelWaitableTimer& Lib "kernel32"...
la fonction CancelWaitableTimer& dans mon fichier kernel32.dll n'apparait que sans le '&', j'ai essayé avec et sans le '&' pour mon timer, les 2 fonctionnent. Peux tu me renseigner sur ce '&'?

Merci quand même MiZanMizan j'ai testé ta façon d'opérer, c'était ce que je pensais faire ; vu que je n'ai pas ms VB , dégouté de constater que ce contrôle Timer n'appparaisse pas dans la liste des contrôles sous vba d'office sans le récupérer ailleurs au préalable. M'enfin ...

Sinon pour ce qui concerne le besoin de Timer(s) avec vba, je trouve que la fonction Application.onTime est simple, très simple. A utiliser sans modération !

signaler à un administrateur
Commentaire de mimiZanzan le 26/02/2007 15:07:34

Cher Verlaat4Show, je te précise que ce n'est pas la peine d'avoir VB pour utiliser mon timer: il suffit d'enregistrer le controle .OCX présent dans mon code dans le registre et il apparaitra dans la liste des contrôles sous VBA.

signaler à un administrateur
Commentaire de verlaat4show le 26/02/2007 15:23:10

Je répète pour mimizanzan:
le contrôle Timer n'appparait pas dans la liste des contrôles sous vba d'office sans le récupérer ailleurs au préalable, soit, il faut télécharger 'ton' timer et aller le charger dans la liste des controles supplementaires pour pouvoir l'utiliser.

M'enfin, cette manière d'opérer n'est pas satisfaisante car d'un poste à un autre, il faut transporter à la fois l'application excel et le controle timer.ocx, surtout que les droits d'utilisation de contrôles sont souvent sécurisés (en entreprise...)


Vive Application.onTime, et encore bravo à 6ratsmorts pour sa classe !!!

signaler à un administrateur
Commentaire de mimiZanzan le 26/02/2007 19:35:46

Je ne voudrais pas insister, mais une fois que l'on a enregistré 1 fois le timer ocx sur un PC et que on l'a chargé 1 fois à partir de la liste des contrôles supplémentaires dans VBA, il est toujours dispo à chaque ouverture de Excel par ex directement dans la boite à outils, et on peut en mettre autant que l'on veut dans une application avec des paramètres différents.
Quant à la sécurité d'utilisation de cet ocx, je le garantis sain, et il y a bien d'autres raisons de se faire du souci au niveau de la sécurité en entreprise.
Enfin si il y en a qui préfèrent des lignes de codes et des API pour gérer un timer (et un seul à la fois), tant pis pour eux!

signaler à un administrateur
Commentaire de 6RatsMorts le 27/02/2007 20:36:31

verlaat4show,
Le '&' de ...Timer&...' indique au compilateur que la fonction retournera un entier long (variable de type 'Long').

Dans l'aide MS VB :
"Le caractère de déclaration de type Long est le signe &."

Mais dis moi, tu le mets en pièces mon code. Tu le décode à fond! Ca fait plaisir!

signaler à un administrateur
Commentaire de 6RatsMorts le 27/02/2007 20:51:54

mimiZanzan a mis le doigt sur un problème minim pour mon cas et que j'avais donc mis de coté :
Il n'est pas possible de faire fonctionner 2 timer simultanément avec ce code. Je cherche la solution...

Une idée?

signaler à un administrateur
Commentaire de zeratul67 le 11/05/2008 14:18:45

Bon code, très pratique.

J'ai juste du effectuer une modification car parfois ma macro ne se terminait pas.
J'ai ajouté "CancelTimer = True" dans "Private Sub Class_Terminate()" et en dessous du seul "DoEvents" du code j'ai inséré "If CancelTimer Then Exit Do" (qui était commenté si mes souvenirs sont bons).

Merci pour ce code sympa :)

signaler à un administrateur
Commentaire de Cyrilooo63 le 30/05/2008 08:04:17

Très bon code qui prend peu de ressource!
par contre j'aimerais l'utiliser pour faire une mise à jour toutes les heures. Soit trop 3600000 millisecondes... le code me retourne un erreur de "overflow"... je ne sais pas comment corriger ca.

merci de votre aide

signaler à un administrateur
Commentaire de mimiZanzan le 30/05/2008 17:24:22

En effet, l'intervalle maximum accepté par le timer est de 65535 ms cad un peu plus d'une minute (c'est pareil pour le timer VB6 sur lequel est bâti le mien).
Mais ce n'est pas un pb, il suffit de mettre un intervalle de 1000 (1 seconde) pour le timer, et dans la procédure évenement _Click du  timer mettre une variable t que l'on incrémente chaque seconde (t=t+1).
Et ajouter dans la même procédure:
  If t mod 60 = 0 then 'procédure à déclencher toutes les heures
Il vaut mieux déclarer "Dim t as Integer" au début du module (pas dans la procédure!)

Et voilà!

signaler à un administrateur
Commentaire de Cyrilooo63 le 02/06/2008 16:14:43 7/10

Merci MimiZanzan ca marche super bien! un peu decu tout de meme de ne pas pouvoir trouver une solution aussi simple...
je vais encore devoir vous demander de l'aide: j'aimerais pouvoir utiliser mon excel tranquillement pendant que ma mise a jour tourne. Je penser faire en sorte que ce timer s'ouvre dans un nouvelle application excel. avez vous de meilleurs idée?
Merci!

signaler à un administrateur
Commentaire de mimiZanzan le 02/06/2008 17:19:59

Salut CYRIL00063!

Content de savoir que mon timer te convient.
Pour répondre à ta question, il suffit de mettre le timer directement sur une Autres contrôles), et dans la procédure timer_click de la feuille, mettre au début l'instruction Doevents.
Tu peux alors lancer le timer (par un bouton sur la feuille par ex) et ouvrir un autre classeur: le timer continuera de tourner dans son classeur...
Et revoilà!

signaler à un administrateur
Commentaire de Cyrilooo63 le 03/06/2008 11:15:26

Merci de ton aide, mais je dois dire que le bout de phrase incomplet (mettre le timer directement sur...) m'empeche de comprendre ce que tu me conseil...
Ce qui est bizarre c'est que je peux me servir d'excel à partir du moment où j'ouvre un autre fichier à partir d'excel (file/open) mais ca ne marche pas si je l'ouvre directement depuis windows (double clic).
merci!

signaler à un administrateur
Commentaire de mimiZanzan le 03/06/2008 12:25:27

Désolé CYRIL00063, un bout de phrase a sauté.
Il faut lire:
"mettre le timer directement sur une feuille de calcul(par la boite à outils VBA, autres contrôles)".
Pour que çà marche,il faut rester dans Excel et ouvrir ou créer un nouveau dossier par le menu.

signaler à un administrateur
Commentaire de Cyrilooo63 le 03/06/2008 15:45:31

Merci MIMIZANZAN pour toute ton aide! ca marche!

Ajouter un commentaire

Discussions en rapport avec ce code source dans le forum

peut t'on remplacer la fonction ontime par timer [ par eryk17 ] bonjourj'ai réaliser une macro sous outlook et jaimerai qu'il s'execute automatiquement ttes les 2h par exemple.J'ai vu qu'il y avait une fonction en Utilisation du timer [ par jems86 ] Bonjour tout le monde, Je vous explique mon problème: j'ai programmé une macro dans un module sous Excel (VBA) (macro de calculs et de comparaison.. macro enregistrement pdf sous autocad [ par Ricou36 ] Bonjour à tous,Je suis débutant en programmation sous AutoCAD et donc je vous demandes votre aide.Pour information, je travailles sous AutoCAD R13 ou Lancement automatique d'une macro [ par ChevalierPaul ] Bonjour,J'ai fait l'acquisition d'un PC portable dans une vente : appareil récent (1 an 1/2 environ) en excellent état technique. Les fichiers de trav Passage d'une variable d'une macro vers une feuille de calcul [ par Tity333 ] Bonjour, à tous,Je cherche depuis quelque temps à utiliser une variable définie selon les choix d'un set d'OptionButton directement dans mes formules Problème avec boucle If [ par likemonster ] Bonsoir tout le monde, j'ai un petit soucis pour réaliser une petite manip sous excel! J'ai une plage de valeurs sur une feuille excel qui se nomme Ma VBA: executer une macro depuis une fonction [ par edoo82 ] Bonjour à tous, j'ai un souci, j'arrive pas à exécuter une fonction (personnalisée) qui appelle une macro: dans la cellule B1 de la feuille "Control Macro word: obtenir le numéro de la ligne d'un mot selectionné [ par elliotttt ] Bonjour! Je me heurte à un problème que je ne saurais résoudre.! Je cherche une commande, une fonction ou je ne sais quoi qui pourr inputbox mettre plusieurs macro en mot de passe [ par patbl ] Bonjourj'ai encore besoin de votre aide je suis sur excel 2000 je crée des mots de passe pour mon fichier pour acceder a chaque fonction mais voila qu


Nos sponsors

Sondage...

CalendriCode

Juillet 2009
LMMJVSD
  12345
6789101112
13141516171819
20212223242526
2728293031  

Consulter la suite du CalendriCode

Téléchargements

Logiciels à télécharger sur le même thème :

Comparez les prix Nouvelle version


LG KP501

Entre 9€ et 159€


Photothèque Nouveau !



Développement réalisé par Nicolas SOREL (Nix) avec l'aide de : Cyril DURAND et Emmanuel (EBArtSoft), Merci à Vincent pour ses précieux conseils
CodeS-SourceS.com© Toute reproduction même partielle est interdite sauf accord écrit du Webmaster
CodeS-SourceS.com© est une marque déposée tous droits réservés
Temps d'éxécution de la page : 0,359 sec

Google Coop CodeS-SourceS Google Coop CodeS-SourceS


Certaines images présentes sur le site (notament certains avatars) sont issues des collections IconShock, donc si vous souhaitez utiliser ces icons vous devez les acheter, ne les copiez pas et ne utilisez pas dans vos sites et applications sans les avoir commandé.