Microsoft 365 Problème interférences entre macros

Boostez vos compétences Excel avec notre communauté !

Rejoignez Excel Downloads, le rendez-vous des passionnés où l'entraide fait la force. Apprenez, échangez, progressez – et tout ça gratuitement ! 👉 Inscrivez-vous maintenant !

Dégé59

XLDnaute Nouveau
Bonjour à tous!

Je me retrouve confronté à un problème assez gênant lorsque je tente de faire fonctionner 2 classeurs différents contenant chacun une macro liée à un application.ontime, et qui me fait me demander s'il est même simplement techniquement possible de faire tourner 2 tableaux avec des macros sur le même PC.

Ils ne se déclenchent pas du tout aux même heures, l'un est un Today + Timevalue, et l'autre est un Now + Timevalue (je mets les codes ci-dessous).

Ces 2 tableaux sont situés dans un répertoire commun, pas dans le même dossier cela dit. Ils sont ouverts sur un PC qui tourne 24/24.

Tableau 1 doit faire une impression .pdf de lui-même et l'expédier en pj d'un mail 2 fois par jour (à 08h00 et à 20h00). Il est opérationnel seul depuis des semaines sans problème.
Tableau 2 doit faire une extraction .csv de lui-même, et l'envoyer en pj à une autre liste de diffusion mail 1x par jour à 23h. Il est en phase de test pour le moment.

Les 2 automatismes fonctionnent très bien quand ils sont seuls.

Au début j'ai même fait des tests sur tableau 2 sans extraction csv ni pj, juste en lui faisant envoyer un mail test, donc avec un code vraiment très simple.

J'ai eu différents bugs en laissant les 2 tableaux tourner en même temps, mais en gros tableau 1 se retrouve bloqué (la macro ne fonctionne plus) parfois, ou fonctionne mais envoi une impression pdf de tableau 2 (chose que personne ne lui demande). Depuis que j'ai ajouté l'extraction .csv dans tableau 2, ce code qui fonctionne parfaitement seul, se retrouve à tout bloquer quand je le met en test sur le PC 24/24 suite erreur de compilation sur une des lignes de la partie extraction .csv. Et de fait, tableau 1 est bloqué dans son exécution aussi à cause de ça... j'ai également aussi eu des problèmes d'envoi multiples de mail (entre 3 et 8 dans la même minutes) sur tableau 1 et 2.

Enfin bref, c'est n'importe quoi.

Dans tous les cas ça fait que je n'ai malheureusement pas beaucoup de retour et donc de précision sur les bugs, car j'ai absolument besoin que tableau 1 fonctionne tout le temps, ce qui me limite dans les possibilité de tester les défaillances...

Est-ce que cela semble cohérent ou parlerait à quelqu'un? J'ai fait quelques recherches mais difficile de trouver les bons mots clés pour ça...

Pour les 2 codes:

Tableau 1
VB:
Sub MAIL_TABLEAU_1()


           '  Cadencement de la diffusion (pour activer, cliquer sur l'icône Email dans le tableau une première fois).
                  
       Application.OnTime Now + TimeValue("12:00:00"), "MAIL_TABLEAU_1"
      
    
           'Procédure rafraichissement des liaisons avec 2 autres tableaux data bases
        
            Dim NomFich$, Wsh As Worksheet
 
     NomFich = "chemin database 1"
 
     For Each Wsh In ThisWorkbook.Worksheets
          Wsh.Cells.Replace What:=NomFich, Replacement:=NomFich _
             , LookAt:=xlPart, SearchOrder:=xlByRows, MatchCase:=False, SearchFormat:=False, ReplaceFormat:=False
     Next
    
    
      Dim NomFichB$, WshB As Worksheet
 
     NomFichB = "Chemin data base 2"
 
     For Each WshB In ThisWorkbook.Worksheets
          WshB.Cells.Replace What:=NomFichB, Replacement:=NomFichB _
             , LookAt:=xlPart, SearchOrder:=xlByRows, MatchCase:=False, SearchFormat:=False, ReplaceFormat:=False
     Next
  

            '   Export du tableau en PDF:
    ActiveSheet.ExportAsFixedFormat Type:=xlTypePDF, Filename:= _
        "chemin extraction.pdf" _
        , Quality:=xlQualityStandard, IncludeDocProperties:=True, IgnorePrintAreas _
        :=False, OpenAfterPublish:=False

'

            'Création nouveau mail :
Dim Outapp As Object
Dim Outmail As Object
 
 
   Set Outapp = CreateObject("Outlook.Application")
   Set Outmail = Outapp.CreateItem(0)
 
    With Outmail
  
        .SentOnBehalfOfName = "mail@expéditeur.com"
      
        .To = "Liste@diffusion.com"
    
        .Subject = "Suivi mis à jour le " & Date & " à " & Time
          
      
        .HTMLBody = "Bonjour," & "<br><br>" & _
                    "Veuillez trouver ci-joint le suivi tel que connu au " & Date & " à " & Time & "<br><br>" & _
                
          .Attachments.Add "chemin pièce jointe.pdf"
'
        .Send 
          
    End With
  
          'Nettoyage
    Set Outmail = Nothing
    Set Outapp = Nothing
'


End Sub


TABLEAU 2
Code:
Sub Tableau_2()


        '  Cadencement (pour activer, cliquer une première fois sur l'icône flèches dans le tableau).
          Application.OnTime Today + TimeValue("23:00:00"), "Tableau_2"
           
    
      'Mise à jour des liaisons
     Dim NomFichA$, WshA As Worksheet
 
     NomFichA = "Chemin data base 1"
 
     For Each WshA In ThisWorkbook.Worksheets
          WshA.Cells.Replace What:=NomFichA, Replacement:=NomFichA _
             , LookAt:=xlPart, SearchOrder:=xlByRows, MatchCase:=False, SearchFormat:=False, ReplaceFormat:=False
     Next
  
       Dim NomFich$, Wsh As Worksheet
 
     NomFich = "Chemin data base 2"
 
     For Each Wsh In ThisWorkbook.Worksheets
          Wsh.Cells.Replace What:=NomFich, Replacement:=NomFich _
             , LookAt:=xlPart, SearchOrder:=xlByRows, MatchCase:=False, SearchFormat:=False, ReplaceFormat:=False
     Next
    
    
          '   Export du tableau en CSV :
        Dim Chemin As String, Fichier As String

        Application.ScreenUpdating = False
        Chemin = "Chemin extraction" & "\"
        Fichier = "BILAN" & Format(Now, "yyyymm")
        ThisWorkbook.Worksheets("Feuille 1").Copy
        Application.DisplayAlerts = False
        ActiveWorkbook.SaveAs Filename:=Chemin & Fichier, FileFormat:=xlCSV, Local:=True
        ActiveWorkbook.Close
        'Application.DisplayAlerts = True

    
    
    
       'Création nouveau mail:
Dim Outapp As Object
Dim Outmail As Object
 
 
   Set Outapp = CreateObject("Outlook.Application")
   Set Outmail = Outapp.CreateItem(0)
 

     With Outmail
  
           'Choix adresse mail expéditeur:
        .SentOnBehalfOfName = "Mail@expéditeur.com"
     
        
        .To = "Liste@destinataires.com"

        .Subject = "TEST Tableau 2 " & Date & " à " & Time
          
      
        .HTMLBody = "Bonjour," & "<br><br>" & _
                    "Fonction diffusion du tableau 2 validée OK le " & Date & " à " & Time & "<br><br>"
                               
         .Attachments.Add Chemin & "\" & Fichier & ".csv"
      
'
       .Send
      
          
    End With
  
          'Nettoyage
    Set Outmail = Nothing
    Set Outapp = Nothing
    
    

End Sub

Je pense qu'il y a beaucoup d'éléments pas forcément utile pour cibler le problème, mais je laisse plus ou moins tel qu'utilisé au cas où un expert d'ici verrais une fonction annexe susceptible de générer un bug.

Merci d'avance pour vos idées!
 
Solution
Hello,
est-ce que tes deux classeurs sont ouverts dans la même instance d'Excel ? Si oui tu peux essayer de les ouvrir dans des instances différentes. Pour ouvrir une nouvelle instance : cliquer sur Excel en ayant la touche ALT enfoncé. Et ouvrir ton deuxième classeur dans cette nouvelle instance.
Dans le gestionnaire de tâches on doit voir deux Microsoft Excel dans les applications comme ceci :
Excel2Instances.png



Ami calmant, J.P
Hello,
est-ce que tes deux classeurs sont ouverts dans la même instance d'Excel ? Si oui tu peux essayer de les ouvrir dans des instances différentes. Pour ouvrir une nouvelle instance : cliquer sur Excel en ayant la touche ALT enfoncé. Et ouvrir ton deuxième classeur dans cette nouvelle instance.
Dans le gestionnaire de tâches on doit voir deux Microsoft Excel dans les applications comme ceci :
Excel2Instances.png



Ami calmant, J.P
 
Bonjour Phil,

Merci pour le fichier, j'ai testé et j'ai regardé le code, mais désolé je ne comprends pas du tout l'application pour le moment.

Dans tous les cas je vais garder ça de côté, ça me servira peut-être plus tard pour autre chose, ou bien quand je comprendrais exactement comment ça marche.

Par contre ça me fait revenir sur une question que je me posais il y a un moment et à laquelle je n'avais pas trouvé de réponse: avec ce genre de macro qui boucle sur un ontime, comment faire un bouton pour la stopper / réinitialiser? J'avais trouvé quelques proposition en cherchant il y a quelques mois, mais rien qui ne semblait vraiment fonctionner (ou dont je comprenais suffisamment le fonctionnement pour le modifier), et j'avais laissé tomber temporairement.

Sinon pour le moment la solution de Jurassic Pork de créer une autre instance Excel semble fonctionner, je vais laisser en test encore quelques jours pour m'assurer que c'est suffisant et je vous tiens au courant!
 
Bonjour
ton soucis vient d'ici a mon avis tout simplement
thisworkbook peut être confondu dans le sens ou le app.ontime execute en addressof et "thisworkbook" n'a plus de valeur distincte
même si théoriquement ça ne devrait pas se confondre

ce qu'il faut comprendre
c'est que application.ontime c'est du niveau application
thisworkbook n'est membre de rien c'est l’équivalent de "this" dans d'autre langage

donc quand tu lance un app.ontime donc en addressof au niveau de application
application.thisworkbook n'existe pas
il va donc travailler sur le classeur actif par défaut(qui n'est peut être pas le bon dans la collections des workbooks ouverts )

essaie plutôt workbooks("nom du classeur") peu être avec un Set histoire de faire une verif avant sur eventuel Nothing
pour blinder l’opération
voila
patrick

ps:
et quand je regarde ceci:
VB:
  Dim NomFich$, Wsh As Worksheet
 
     NomFich = "Chemin data base 2"
et qu'il n'est utilisé nulle part je suis convaincu d'être dans la bonne théorie
alors que ça doit certainement faire référence a un classeur
 
Dernière édition:
@Dégé59

Je te propose ce fichier c'est le fichier du post # 6 adapté au code que tu as fourni .
Au 1er lancement il est possible mais pas certain qu'un mail avec le tableau1 parte vers le destinataire.

Merci de ton retour
Merci Phil, je peux tester au moins pour créer le bouton d'arrêt procédure.

D'ailleurs je suppose que ça ne peut pas fonctionner si on le code de la manière suivante pour exemple avec une message box?

VB:
Sub Messagetest()

 Application.OnTime Now + TimeValue("00:00:10"), "Messagetest"

MsgBox ("TEST 10 secondes")


End Sub


Sub Stopmessage()

On Error Resume Next
Application.OnTime "Messagetest", , False

End Sub

En testant ce genre de chose, je prend une erreur "Argument non facultatif", peu importe ce que ça peut bien vouloir dire. En un sens ça me stoppe bien la procédure puisque ça bloque tout, mais bon... ce n'est pas vraiment la manière dont je cherche à le faire.
 
Bonjour
ton soucis vient d'ici a mon avis tout simplement
thisworkbook peut être confondu dans le sens ou le app.ontime execute en addressof et "thisworkbook" n'a plus de valeur distincte
même si théoriquement ça ne devrait pas se confondre

ce qu'il faut comprendre
c'est que application.ontime c'est du niveau application
thisworkbook n'est membre de rien c'est l’équivalent de "this" dans d'autre langage

donc quand tu lance un app.ontime donc en addressof au niveau de application
application.thisworkbook n'existe pas
il va donc travailler sur le classeur actif par défaut(qui n'est peut être pas le bon dans la collections des workbooks ouverts )

essaie plutôt workbooks("nom du classeur") peu être avec un Set histoire de faire une verif avant sur eventuel Nothing
pour blinder l’opération
voila
patrick

ps:
et quand je regarde ceci:
VB:
  Dim NomFich$, Wsh As Worksheet
 
     NomFich = "Chemin data base 2"
et qu'il n'est utilisé nulle part je suis convaincu d'être dans la bonne théorie
alors que ça doit certainement faire référence a un classeur
Bonjour Patrick,

Je n'ai rien mis dans This Workbook, mais dans un module. Est-ce que ta remarque s'applique aussi dans ce cas?

En ce qui concerne ton PS, en effet ce que j'ai modifié pour publier ici en "chemin data base 1" et "2" sont bien des références à des classeurs, mais cette partie du code fonctionne très bien.

Tu veux dire que cette partie du code, en se référant à un autre classeur, pourrait générer l'interférence? Mais ça n'interfère avec aucun de ces classeurs "database".
 
a moins que la tache soit programmée au même instant ou pendant l'execution d'une autre il ne devrait pas y avoir d'interférence
a condition encore une fois je le redis que les classeur cible soient les bons

cela dit en entrée et sortie d'execution tu peux mettre une variable true/false
et quand une execution est appelée si true alors reporté le app.ontime de x seconde ou ce que tu veux

c'est bien pour ca que je préfère de loin la gestion intégrale de la tache par l'object tascksheduler (en francais :Schedule.Service)
et oui on peut le gérer par vba et là il n'y aura pas de confusion
alors oui c'est un peu plus complexe mais plus large en terme de possibilité
un petit exemple :
VB:
'------------------------------------------------------------------
'patricktoulon
' cet exemple te montre comment programer une tache planifiée avec l'object "Schedule.Service" en late binding
'À partir du moment où la tâche est enregistrée.
dans 10 secondes un message "coucou" va s'afficher
'------------------------------------------------------------------
Sub TEST_SHREDULER_MESSAGE()
    Dim delay&, codeVBS$, texte$, Titre$
    texte = "coucou"
    Titre = "test de message"
    codeVBS = "CreateObject(""Wscript.shell"").Popup" & Chr(34) & texte & Chr(34) & "," & temps & "," & Chr(34) & Titre & Chr(34) & vbCrLf
    codeVBS = codeVBS & "Set fso = wscript.CreateObject(""Scripting.FileSystemObject"")" & vbCrLf
    codeVBS = codeVBS & "fso.deletefile WScript.ScriptFullName"
    chemin = Environ("userprofile") & "\Desktop\message.vbs"
    Open chemin For Output As #1: Print #1, codeVBS: Close #1

    
    
    
delay = 10 'DELAY en seconde!!!!!!!

'constante qui spécifie un déclencheur basé sur le temps.
Const TriggerTypeTime = 1
' constante qui spécifie une action exécutable
Const ActionTypeExec = 0


'********************************************************
'Céation  l'objet TaskService
Set service = CreateObject("Schedule.Service") 'latebinding
Call service.Connect

'********************************************************
'obtention d' un dossier pour créer une définition de tâche dans.
Dim rootFolder
Set rootFolder = service.GetFolder("\")

'La variable taskDefinition est l'objet TaskDefinition.
Dim taskDefinition
'Le paramètre flags est 0 car il n'est pas pris en charge.
Set taskDefinition = service.NewTask(0)

'********************************************************
'Définir des informations sur la tâche.
'Définissez les informations d'inscription pour la tâche par
'Création de l'objet RegistrationInfo.
Dim regInfo
Set regInfo = taskDefinition.RegistrationInfo
regInfo.Description = "demarrer le bloc-notes à un certain moment"
regInfo.Author = Environ("username")

'********************************************************
'Définir le principal de la tâche
Dim principal
Set principal = taskDefinition.principal

'Définissez le type de connexion à la connexion interactive
principal.LogonType = 3


' Définissez l'information de réglage de la tâche pour le planificateur de tâches par
'Création d'un objet TaskSettings.
Dim settings
Set settings = taskDefinition.settings
settings.Enabled = True
settings.StartWhenAvailable = True
settings.Hidden = False

'********************************************************
' Créez un déclencheur basé sur le temps.
Dim triggers
Set triggers = taskDefinition.triggers

Dim trigger
Set trigger = triggers.Create(TriggerTypeTime)

' les variables qui définissent quand le déclencheur est actif.
Dim startTime, endTime
'exemple
Dim time
time = DateAdd("s", delay, Now) 'start time = 30 secondes a partir de maintenant
startTime = XmlTime(time)
'selon les disponibilité du PC la tache demarrera entre ces deux moments
time = DateAdd("s", delay + 1, Now) 'end time = 60 secondes*5 a partir de maintenant
endTime = XmlTime(time)

'MsgBox "startTime :" & startTime
'MsgBox "endTime :" & endTime

trigger.StartBoundary = startTime
trigger.EndBoundary = endTime
trigger.ExecutionTimeLimit = "PT5M"    '5 minutes de delay
trigger.ID = "TimeTriggerId"
trigger.Enabled = True

'***********************************************************
' Création  l'action pour la tâche à exécuter.
' Ajoutez une action à la tâche pour exécuter notepad.exe.
Dim Action
Set Action = taskDefinition.Actions.Create(ActionTypeExec)
Action.Path = Environ("userprofile") & "\Desktop\message.vbs"
'MsgBox "Création de la définition de la tâche. À propos de soumettre la tâche ..."

'***********************************************************
'Enregistrez (créer) la tâche.
Call rootFolder.RegisterTaskDefinition( _
    "Test TimeTrigger", taskDefinition, 6, , , 3)

MsgBox "Tâche soumise."
End Sub


'------------------------------------------------------------------
'la fonction qui suit sert a mettre le format date heure minutes secondes au format pour le shreduler
' Utilisé pour obtenir le temps pour le déclencheur
' startBoundary and endBoundary.la fonction sera utilisé deux fois pour le starttime et endtime
' Renvoie l'heure dans le format correct:
' exemple :YYYY-MM-DDTHH:MM:SS.
'------------------------------------------------------------------
Function XmlTime(t)
    Dim cSecond, cMinute, CHour, cDay, cMonth, cYear, tTime, tDate
        cSecond = "0" & Second(t)
    cMinute = "0" & Minute(t)
    CHour = "0" & Hour(t)
    cDay = "0" & Day(t)
    cMonth = "0" & Month(t)
    cYear = Year(t)
    tTime = Right(CHour, 2) & ":" & Right(cMinute, 2) & ":" & Right(cSecond, 2)
    tDate = cYear & "-" & Right(cMonth, 2) & "-" & Right(cDay, 2)
    XmlTime = tDate & "T" & tTime
End Function
 
Bonjour à tous,

Après 2 semaines de tests sans problème, je confirme que la solution d'ouvrir plusieurs instance d'Excel semble être la bonne.

Phil: merci d'avoir essayé pour le bouton stop, je pense que je vais garder ton fichier de côté et y revenir plus tard, car pour le moment je n'ai pas les bases en VBA ce qui fait que je n'arrive pas à comprendre comment ça fonctionne, et donc je ne sais pas l'adapter à mon besoin.

Patrick: visiblement le problème est réglé, mais dans tous les cas les classeurs cibles sont les bons et les procédures se lancent à plusieurs heures d'intervalle, d'où mon incompréhension.
 
@Dégé59

Phil: merci d'avoir essayé pour le bouton stop, je pense que je vais garder ton fichier de côté et y revenir plus tard, car pour le moment je n'ai pas les bases en VBA ce qui fait que je n'arrive pas à comprendre comment ça fonctionne, et donc je ne sais pas l'adapter à mon besoin.


Pour l'adapter c'est simple tu recopies le code VBA dans un module de ton fichier
Et tu modifies l'heure que tu veux et UNIQUEMENT l'heure à ces 2 endroits

Case 1
HeureDpart = Now + TimeValue("12:00:00")

Et ici

Case 2
HeureDpart = Today + TimeValue("23:00:00")

Je pense que tu peux y arriver 🤣

Merci de ton retour
 
- Navigue sans publicité
- Accède à Cléa, notre assistante IA experte Excel... et pas que...
- Profite de fonctionnalités exclusives
Ton soutien permet à Excel Downloads de rester 100% gratuit et de continuer à rassembler les passionnés d'Excel.
Je deviens Supporter XLD

Discussions similaires

Réponses
6
Affichages
669
Réponses
2
Affichages
422
Réponses
1
Affichages
240
Réponses
3
Affichages
504
Retour