jurassic pork
XLDnaute Accro
Hello,
EN VBA pour exécuter des routines à intervalles réguliers on a Application.OnTime mais hélas ceci est limité à un intervalle min de 1 seconde.
Il y a les API windows Timers mais elles peuvent faire planter Excel.
Il y a la classe stdTimer.cls du projet stdVBA qui utilise une autre instance d'Excel mais elle a deux inconvénients : 1 on crée un classeur et on
injecte du code dedans. Si cela se passe mal dans cette instance, elle reste dans le gestionnaire du tâche même après fermeture du classeur principal.
Alors, il m'est venu une idée : pourquoi ne pas ouvrir dans une nouvelle instance, un classeur avec le code d'un séquenceur.
et voici le code du classeur de démo :
On démarre le séquenceur en passant comme paramètres: l'intervalle de temps, l'objet Application , le classeur actif , la procédure à appeler.
Le CleanTimer ferme l'instance qui a été ouverte pour timerJP.xlsm
Si vous voyez des failles ou des améliorations à apporter, n'hésitez pas à le dire.
Ami calmant, J.P
EN VBA pour exécuter des routines à intervalles réguliers on a Application.OnTime mais hélas ceci est limité à un intervalle min de 1 seconde.
Il y a les API windows Timers mais elles peuvent faire planter Excel.
Il y a la classe stdTimer.cls du projet stdVBA qui utilise une autre instance d'Excel mais elle a deux inconvénients : 1 on crée un classeur et on
injecte du code dedans. Si cela se passe mal dans cette instance, elle reste dans le gestionnaire du tâche même après fermeture du classeur principal.
Alors, il m'est venu une idée : pourquoi ne pas ouvrir dans une nouvelle instance, un classeur avec le code d'un séquenceur.
Code:
Option Explicit
#If VBA7 Then
Private Declare PtrSafe Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
#Else
Private Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
#End If
Private tim As Boolean, ms_ As Long, app_ As Application, wbk_ As Workbook, fonction_ As String
Sub StartSeq(ms As Long, app As Application, wbk As Workbook, fonction As String)
ms_ = ms: Set wbk_ = wbk: fonction_ = fonction: Set app_ = app
Application.OnTime Now, "StartSequenceur" ' démarrage par événement pour ne pas avoir StartSeq bloquant
End Sub
Sub StopSeq()
tim = False
End Sub
Function StartSequenceur()
Dim x As Integer
tim = True
On Error Resume Next
Do While tim = True
' Pause pour réduire la charge processeur
x = 0
Do While x < ms_ / 20: x = x + 1: Sleep 20: DoEvents: Loop
' Appeler la fonction spécifiée
app_.Run fonction_
DoEvents
Loop
End Function
VB:
Private xlAppTimer As Application
Sub LaunchSequencer()
If xlAppTimer Is Nothing Then
Set xlAppTimer = CreateObject("Excel.Application")
xlAppTimer.Workbooks.Open "D:\Dev\Office\Excel\timerJP.xlsm"
xlAppTimer.Visible = False
End If
xlAppTimer.Run "StartSeq", 100, Application, ThisWorkbook, "TestProcedure" ' call "TestProcedure" toutes les 100 ms
End Sub
Sub StopSequencer()
xlAppTimer.Run "StopSeq"
End Sub
Sub CleanAppTimer()
If Not xlAppTimer Is Nothing Then
xlAppTimer.Run "StopSeq"
xlAppTimer.Workbooks("timerJP.xlsm").Close
xlAppTimer.Quit
Set xlAppTimer = Nothing
End If
End Sub
Public Sub TestProcedure()
[A1] = Time
End Sub
Le CleanTimer ferme l'instance qui a été ouverte pour timerJP.xlsm
Si vous voyez des failles ou des améliorations à apporter, n'hésitez pas à le dire.
Ami calmant, J.P