VBA Excel: Comptes à rebours imbriqués avec arrêt auto

Résolu
Aude -  
pijaku Messages postés 13513 Date d'inscription   Statut Modérateur Dernière intervention   -
Bonjour,

Je suis sous Excel 2007 et j"aimerais pouvoir me programmer un compte à rebours pour mes séances de sport, qui tiendrait compte de la durée de l'exercice, du temps de récupération et du nombre de séries.
Ces 3 données seraient à saisir dans une fenêtre, puis, à l'enclenchement du programme, le compte à rebours de l'exercice démarrerait. Une fois terminé, un bip sonnerait pour annoncer la fin de l'exercice et le début de la récupération dont le décompte se lancerait automatiquement, puis un nouveau bip et rebelotte pour l'exercice... et ce, autant de fois que de séries saisies.
J'ai commencé à faire des essais, pour l'instant non concluants: http://cjoint.com/?0Jjip7oFdRe
Quelqu'un pourrait-il m'aider??

Merci beaucoup!

5 réponses

  1. pijaku Messages postés 13513 Date d'inscription   Statut Modérateur Dernière intervention   2 773
     
    Bonjour,

    Voici deux fichiers (les mêmes) avec résolution du dernier bug :
    https://www.cjoint.com/c/DJojLZ0g5rT => format .xlsm
    https://www.cjoint.com/c/DJnikKBciRs => format .xls

    tu dis...

    EDIT : changement du fichier .xlsm

    🎼 Cordialement,
    Franck 🎶
    3
    1. Aude
       
      Bonjour Pijaku,

      C'est avec grand plaisir que je viens de prendre connaissance de tes messages! Je viens de tester les fichiers et le .xls me convient parfaitement!! Le .xlsm fonctionne aussi très bien mais j'ai une préférence pour les boutons "à l'ancienne" du .xls.

      Merci encore pour ton investissement!!
      0
    2. pijaku Messages postés 13513 Date d'inscription   Statut Modérateur Dernière intervention   2 773
       
      Salut,

      Tu as bien fait, d'autant plus que le .xlsm est une mauvaise version bourrée de bugs...... Je la change de suite.

      De rien et @++
      0
  2. pijaku Messages postés 13513 Date d'inscription   Statut Modérateur Dernière intervention   2 773
     
    Salut Aude,

    Mes tentatives avec Application.OnTime n'ont pas été concluantes. On arrive à un pseudo résultat ou les temps se chevauchent, avec une irrégularité du "rythme" des secondes.
    Donc il a fallut compliquer un peu le bouzin.

    Voici un exemple qui utilise un Timer plutôt que Application.OnTime :
    https://www.cjoint.com/c/DJjmGNSi4yG

    Tu m'en diras des nouvelles?
    2
    1. pijaku Messages postés 13513 Date d'inscription   Statut Modérateur Dernière intervention   2 773
       
      Ci-joint une seconde version : https://www.cjoint.com/c/DJjm6tDGJrA

      Améliorations : affichage du reste en hh:mm:ss + surprise finale
      0
    2. Aude
       
      Salut Pijaku,

      Un grand merci pour ton fichier qui tient parfaitement la route!

      Penses-tu qu'il soit possible:
      1. de pouvoir mettre le compte à rebours en pause?
      2. d'afficher le nombre de séries restantes pour savoir où on en est en cours d'exercice?

      Merci encore!
      0
    3. pijaku Messages postés 13513 Date d'inscription   Statut Modérateur Dernière intervention   2 773
       
      Un grand merci pour ton fichier qui tient parfaitement la route!
      Merci à toi.

      La pause je ne penses pas.
      Mais bon, je vais regarder quand même.
      Pour les séries, cela ne devrait poser aucun souci, je penses...
      0
  3. pijaku Messages postés 13513 Date d'inscription   Statut Modérateur Dernière intervention   2 773
     
    Pour la pause, c'est fait...
    A tester car ça ne me semble pas hyper stable.
    Pour le 2- aussi

    https://www.cjoint.com/c/DJjowWoh9R3

    Voili voilou
    0
    1. pijaku Messages postés 13513 Date d'inscription   Statut Modérateur Dernière intervention   2 773
       
      Pas très stable en effet.

      Il y aurait moyen d'améliorer tout ça avec l'api windows
      Private Declare Function GetInputState Lib "user32" () As Long


      Mais... Là je ne peux pas avant lundi.

      On s'en reparle.
      0
    2. Aude
       
      Merci, j'attends donc ton retour lundi.

      Bon week-end!
      0
  4. pijaku Messages postés 13513 Date d'inscription   Statut Modérateur Dernière intervention   2 773
     
    Salut,

    Un peu en avance : Le fichier .xlsm
    Les codes :
    Module :
    Option Explicit
    Private Declare Function GetInputState Lib "user32" () As Long
    Private Declare Function Beep Lib "kernel32" (ByVal Frequence As Long, ByVal Duree As Long) As Long
    Private Declare Function SetTimer Lib "user32" (ByVal hwnd As Long, ByVal nIDEvent As Long, ByVal uElapse As Long, ByVal lpTimerFunc As Long) As Long
    Private Declare Function KillTimer Lib "user32" (ByVal hwnd As Long, ByVal nIDEvent As Long) As Long
    
    Dim TempsInter()
    Dim NbSecondes As Long
    Dim Indic As Integer
    Dim Plage As Range
    Dim iCounter As Integer
    Dim lngTimerID As Long
    Dim BlnTimer As Boolean
    Dim pause As Boolean
    
    Sub TimerProc(ByVal hwnd As Long, ByVal uMsg As Long, ByVal idEvent As Long, ByVal dwTime As Long)
    Dim Reste As Long, Cel As Range
    
    'En cas d'erreur quitte proprement le Timer
    On Error GoTo Arret
    
    'coloriage
    For Each Cel In Plage
        If Cel.Address = TempsInter(2, Indic) Then Cel.Interior.ColorIndex = 3 Else Cel.Interior.ColorIndex = xlNone
    Next Cel
    
    'alimentation compteur si pas de pause
    If pause = False Then iCounter = iCounter + 1
    Reste = NbSecondes - iCounter
    Range("J" & CInt(Split(TempsInter(2, Indic), "$")(2))) = Format((TempsInter(1, Indic) - iCounter) / 86400, "hh:mm:ss")
    
    'FIN
    If iCounter = NbSecondes Then
        pause = False
        Call Arret_Timer
        Exit Sub
    End If
    'BEEP et autres actions à faire
    If iCounter = TempsInter(1, Indic) Then
        Call Beep(1500, 1000)
        Indic = Indic + 1
        iCounter = iCounter - 1
        If Indic Mod 2 = 0 Then Range("K" & CInt(Split(TempsInter(2, Indic), "$")(2))) = Range("K" & CInt(Split(TempsInter(2, Indic), "$")(2))) + 1
    End If
    Exit Sub
    
    Arret:
    pause = False
    Call Arret_Timer
    End Sub
    
    'La procédure de commencement du Timer
    Public Sub Lance_Timer()
    
    'permet de déclencher le clic sur un bouton en cas de pause:
    If GetInputState = 0 Then DoEvents
      
    '1000 = intervalle en millisecondes => 1s
    'TimerProc = nom de la procédure à relancer toutes les 1000ms
    lngTimerID = SetTimer(0, 0, 1000, AddressOf TimerProc)
    If lngTimerID = 0 Then
        MsgBox "Timer non créé. Fin du programme."
        Exit Sub
    End If
    BlnTimer = True
    End Sub
    
    'La procédure d'arrêt du Timer
    Public Sub Arret_Timer()
        lngTimerID = KillTimer(0, lngTimerID)
        If lngTimerID = 0 Then
            MsgBox "Timer déjà arrêté."
            Exit Sub
        End If
        BlnTimer = False
        Plage.Interior.ColorIndex = xlNone
        Range("J5:K14").ClearContents
        Sheets("Sheet1").CommandButton3.Caption = "Pause"
        Call Beep(2500, 2500)
        MsgBox "Fini!! Ouffff......"
    End Sub
    
    'Bouton Start
    Sub Lancement()
    Dim Lig As Integer, Col As Integer, Cpt As Integer
    Dim i As Integer
    
    i = 1
    NbSecondes = 0
    iCounter = 0
    pause = False
    Set Plage = Range("F4:I14")
    Plage.Interior.ColorIndex = xlNone
    Range("J5:K14").ClearContents
    
    ReDim Preserve TempsInter(1 To 2, 1 To i)
    TempsInter(1, i) = 0
    TempsInter(2, i) = "$F$4"
    For Lig = 5 To 14
        If Cells(Lig, 7) = "" Then Exit For
        Cpt = Cells(Lig, 9)
        Do While Cpt > 0
            For Col = 7 To 8
                NbSecondes = NbSecondes + Hour(Cells(Lig, Col)) * 3600 + Minute(Cells(Lig, Col)) * 60 + Second(Cells(Lig, Col))
                i = i + 1
                ReDim Preserve TempsInter(1 To 2, 1 To i)
                TempsInter(1, i) = TempsInter(1, i - 1) + Hour(Cells(Lig, Col)) * 3600 + Minute(Cells(Lig, Col)) * 60 + Second(Cells(Lig, Col))
                TempsInter(2, i) = Cells(Lig, Col).Address
            Next Col
            Cpt = Cpt - 1
        Loop
    Next Lig
    Indic = 2
    Range("K" & CInt(Split(TempsInter(2, Indic), "$")(2))) = 1
    Lance_Timer
    End Sub
    
    'Bouton pause
    Sub BtnPause()
        If Sheets("Sheet1").CommandButton3.Caption = "Pause" Then
            pause = True
            Sheets("Sheet1").CommandButton3.Caption = "Reprendre"
        Else
            Sheets("Sheet1").CommandButton3.Caption = "Pause"
            pause = False
        End If
    End Sub


    Feuille (3 boutons) :
    Private Sub CommandButton1_Click()
    Call Lancement
    End Sub
    
    Private Sub CommandButton2_Click()
    Call Arret_Timer
    End Sub
    
    Private Sub CommandButton3_Click()
    Call BtnPause
    End Sub


    Attention ne pas changer le nom de la feuille ni le texte du bouton pause. Sinon, adapter dans le code...

    Bon sport!

    A+
    0
    1. pijaku Messages postés 13513 Date d'inscription   Statut Modérateur Dernière intervention   2 773
       
      ERRATUM : l'utilisation ici d'un Timer rend inutile l'utilisation de GetInputState.
      Par conséquent,vous pouvez supprimer les trois lignes :
      dans l'entête :
      Private Declare Function GetInputState Lib "user32" () As Long

      dans la Public Sub Lance_Timer() :
      'permet de déclencher le clic sur un bouton en cas de pause:
      If GetInputState = 0 Then DoEvents


      Cordialement
      0
  5. Vous n’avez pas trouvé la réponse que vous recherchez ?

    Posez votre question
  6. pijaku Messages postés 13513 Date d'inscription   Statut Modérateur Dernière intervention   2 773
     
    Après réflexion, un problème subsiste. Si tu clic deux fois sur le bouton start tu va lancer 2 Timer et tu ne pourras en arrêter qu'un seul.
    Je rectifierais cela, mais, d'ici lundi, ne clic qu'une fois sur ce bouton.
    Sinon il faudra attendre la fin des décomptes ou fermer Excel de manière plus "sauvage"...
    0