Lenteur exécution programme

Résolu
Bjr, j'ai créé deux fichiers xlsm (codes vba) que j'appellerai À et B, quand les deux sont ouvert le B exécuté une boucle for i to.... D'une lenteur extrême alors que si À est fermé la boucle de B est très rapide. Avez vous une suggestion à ce sujet merci.

8 réponses

Résumé de la discussion

Lorsqu'on ouvre simultanément deux fichiers xlsm nommés A et B, la boucle For de B s'exécute lentement, tandis que sa vitesse remonte lorsque A est fermé. Plusieurs réponses proposent d'optimiser le code VBA en désactivant ScreenUpdating et le recalcul, en évitant les sélections, et en utilisant des filtres et suppressions ciblés plutôt que des opérations lourdes. D'autres interventions évoquent l'usage de dictionnaires pour suivre les UT enregistrés et les nouveaux, ou encore d'isoler A et B avec EnableEvents à false pour éviter des déclencheurs indésirables. En cas d'incertitude sur le comportement exact des deux macros, les échanges recommandent d'analyser le code des fichiers et de tester pas à pas, car sans fichier précis les causes restent ambiguës.

Bobot (l’IA à votre service)
  1. Re,

    Si tu cherches la rapidité, il n'y a pas besoin de la feuille extraction :
    Option Explicit
    Public Sub ExtraireUT()
    Dim dUT As Object
    Dim dNw As Object
    Dim wshRes As Worksheet
    Dim tUT As Variant
    Dim tdB As Variant
    Dim tdH As Variant
    Dim rng As Range
    Dim i As Long
    
      Set wshRes = ThisWorkbook.Worksheets("resultat")
      ' Effacer les données précédentes
      With wshRes.UsedRange.Offset(1).EntireRow.Columns("D")
        .ClearContents
        With .Interior
          .Pattern = xlPatternNone
          .TintAndShade = 0
          .PatternTintAndShade = 0
        End With
      End With
      ' Liste des UT enregistrés
      Set dUT = CreateObject("Scripting.Dictionary")
      With wshRes
        tUT = Application.Transpose(.Range("B2", .Cells(.Rows.Count, "B").End(xlUp)).Value)
        For i = LBound(tUT) To UBound(tUT)
          dUT(tUT(i)) = ""
        Next i
        Erase tUT
      End With
      ' Liste des nouveaux UT
      Set dNw = CreateObject("Scripting.Dictionary")
      Set rng = Workbooks("Données M.csv").Worksheets(1).UsedRange
      tdB = Application.Transpose(rng.Columns("B").Value)
      tdH = Application.Transpose(rng.Columns("H").Value)
      For i = LBound(tdB) + 1 To UBound(tdB)
        If tdB(i) = 404 And Left(CStr(tdH(i)), 1) <> "0" Then
          If Not dUT.Exists(tdH(i)) Then dNw(tdH(i)) = ""
        End If
      Next i
      Erase tdB
      Erase tdH
      ' Résultat
      If dNw.Count = 0 Then
        MsgBox ("Vous n'avez aucun nouvel UT")
      Else
        With wshRes
          With .Cells(2, "D").Resize(dNw.Count)
            .Value = Application.Transpose(dNw.Keys)
            .Interior.ColorIndex = 4
          End With
          With .Cells(.Rows.Count, "B").End(xlUp).Offset(1).Resize(dNw.Count)
            .Value = Application.Transpose(dNw.Keys)
            .NumberFormat = .Cells(1, 1).Offset(-1).NumberFormat
          End With
        End With
        MsgBox ("Vous avez " & dNw.Count & " nouveau(x) UT " & "Notez les N°")
      End If
    End Sub
    1
    1. il est vrai que le résultat est la, mais dans la feuille extraction je visualise des infos .
      0
  2. Patrice et f894009, en combinant vos deux codes et suggestions je suis arrivé à un super résultat, rendez vous compte moins d'une seconde pour afficher le calcul.
    Vraiment merci à vous deux , champions.

    A bientôt, j'aime bien bidouiller le VBA et j'aurais surement besoin encore de vous.
    0
    1. Bonjour,

      Essaies ce code:
      Option Explicit
      Public Sub extraire()
      Dim wshRes As Worksheet
      Dim wshExt As Worksheet
      Dim rng As Range
      Dim cel As Range
      Dim n°L As Long
      Dim nUT As Long
      
        Set wshRes = ThisWorkbook.Worksheets("resultat")
        Set wshExt = ThisWorkbook.Worksheets("extraction")
        Application.ScreenUpdating = False
        Application.Calculation = xlCalculationManual
        ' Effacer les données précédentes
        wshExt.Cells.Clear
        With wshRes.UsedRange.Offset(1).EntireRow.Columns("D")
          .ClearContents
          With .Interior
            .Pattern = xlPatternNone
            .TintAndShade = 0
            .PatternTintAndShade = 0
          End With
        End With
        ' Copier les données
        Workbooks("Données M.csv").Worksheets(1).UsedRange.Copy wshExt.Range("A1")
        ' Traiter les données
        With wshExt
          ' Filtrer et supprimer <> 404
          With .Range("A1").CurrentRegion
            .AutoFilter
            .AutoFilter Field:=2, Criteria1:="<>404"
            .Offset(1).EntireRow.Delete
            .AutoFilter
          End With
          ' Supprimer colonnes
          .Range("A:A,B:B,I:J,M:M,Q:Q").Delete
          ' Filtrer et supprimer UT commence par 0 et =0
          With .Range("A1").CurrentRegion
            .AutoFilter
            .AutoFilter Field:=6, Criteria1:="=0*"
            .Offset(1).EntireRow.Delete
            .AutoFilter Field:=6, Criteria1:="=0"
            .Offset(1).EntireRow.Delete
            .AutoFilter
            .Offset(1).Columns("F").Copy wshRes.Range("D2")
          End With
        End With
        ' Ajouter les UT non enregistrés
        With wshRes
          Set rng = .Range("B2", .Cells(.Rows.Count, "B").End(xlUp))
          rng.Interior.ColorIndex = xlNone
          n°L = .Cells(.Rows.Count, "D").End(xlUp).Row
          Do While n°L > 1
            Set cel = rng.Find(.Cells(n°L, "D").Value, , xlFormulas, xlWhole)
            If cel Is Nothing Then
              With rng.Offset(rng.Rows.Count).Cells(1, 1)
                .Value = wshRes.Cells(n°L, "D").Value
                .NumberFormat = .Offset(-1).NumberFormat
                .Interior.ColorIndex = 4
              End With
              .Cells(n°L, "D").Interior.ColorIndex = 4
              Set rng = rng.Resize(rng.Rows.Count + 1)
              nUT = nUT + 1
            End If
            n°L = n°L - 1
          Loop
        End With
        Application.ScreenUpdating = True
        Application.Calculation = xlCalculationAutomatic
        If nUT = 0 Then
          MsgBox ("Vous n'avez aucun nouvel UT")
        Else
          MsgBox ("Vous avez " & nUT & " nouveau(x) UT " & "Notez les N°")
        End If
      End Sub


      1
      1. Salut,
        impressionnant de rapidité, plusieurs remarques que je n'arrive pas à corriger, onglet résultat colonne D je voudrais voir apparaître uniquement les valeurs nouvelles, inconnues de la colonne B ,sans doublon et en fond vert , une incrémentation de ces valeurs en colonne B mais sans fond vert, c'est ce que j'ai créé avec mon code, malheureusement désespéramment long. Vois tu ce que je veux dire ?(exigent le gars)

        En tout cas bravo et merci.
        0
    2. Bonjour a tous,

      un exemple de suppression lignes avec filtre et suppression colonnes sans select. D'ailleur trop de select

      Sub Test()
          ' remplacer la ligne de fin par la derniere ligne cellule colonne B non vide
          With Sheets("extraction")
              .Range("A1:C114").AutoFilter
              .Range("$A$1:$C$114").AutoFilter Field:=2, Criteria1:="<>404"
              .Range("A2:C114").EntireRow.Delete
              .Range("$A$1:$C$114").AutoFilter Field:=2
              'suppression colonnes
              .Range("A:A,B:B,I:J,M:M,Q:Q").Delete
          End With
      End Sub
      1
      1. je vais essaye votre code merci
        0
      2. Re,

        Attention, le delete supprime tout, je regarde pour faire sup des lignes filterees

        Rectification, ca marche bien, c'est la suppression colonnes qui supprime tout, donc gaffe....
        0
      3. j'ai donc supprimé la boucle for et remplacé par votre code ça fonctionne beaucoup mieux, merci .
        La deuxieme boucle par contre brille aussi par sa lenteur.

        DernLigne3 = Sheets("resultat").Range("b" & Rows.Count).End(xlUp).Row

        DernLigne5 = Sheets("resultat").Range("d" & Rows.Count).End(xlUp).Row
        For m = 2 To DernLigne5
        For n = 2 To DernLigne3
        If Range("d" & m).Value = Range("b" & n).Value Then
        Range("d" & m).Select
        Selection.Delete Shift:=xlUp
        m = m - 1
        End If
        Next n
        Next m

        qu'en pensez vous ?
        0
      4. Re,

        Je regarde la chose, mais cake chose m'intrigue:
        If Range("d" & m).Value = Range("b" & n).Value Then
        Range("d" & m).Select
        Selection.Delete Shift:=xlUp 


        Vous pouvez mettre un fichier avec des donnees en B et D qui soient representatives pour que je puisse vraiment tester?
        0
      5. B D
        UT Enregistrés UT à Enregistrés
        1039380 1037178
        1039295 1037754
        1038641 1038017
        1038805 1037178
        1038804 1037178
        1037830 1037178
        1037791 1037178
        1037961 1037178
        1037178 1037178
        1037754 1037178
        1038017 1037178
        1037611 1037178
        1037586 1037178
        1037427 1037611
        1037429 1037586
        1037250 1037611
        1038549 1037427
        1038345 1037429
        1037787 1037250
        1037829 1037250
        1038031 1038345

        en fait je teste si une valeur colonne d est = a une valeur colonne B si oui je l'efface si non je la garde
        0
    3. Contributeur
      Bonjour,

      et que fait la macro de A ? Si elle prend un max de ressources, B prend ce qu'il reste.
      Comme dit patrice, sans fichier ni les macros il faudrait une boule de cristal.
      eric
      1
      1. bjr Eric ,
        la macro A normalement n'est pas sollicité quand j'utilise B et vice et versa
        0
    4. Bonjour,

      Tu peux aussi regarder du coté de
      Application.ScreenUpdating
      et
      Application.Calculation
      1
      1. j'ai regardé et essayé mais ça ne change rien, merci à toi aussi d'avoir tenté une solution
        0
      2. Sinon effectivement c'est compliqué de savoir ce qu'il se passe sans avoir le code... [Sic]
        0
      3. bonjour,
        voici le code de B
        Sub extraire()
        '
        ' extraire Macro
        '
        If Sheets("resultat").Range("d2") <> " " Then
        Dim DernLigne3 As Long
        DernLigne3 = Range("b" & Rows.Count).End(xlUp).Row
        Range("d2:d" & DernLigne3).Select
        Selection.ClearContents
        With Selection.Interior
        .Pattern = xlNone
        .TintAndShade = 0
        .PatternTintAndShade = 0
        End With
        Range("D2").Select
        End If

        Windows("Données M.csv").Activate
        Cells.Select
        Selection.Copy
        Windows("tri liste expe.xlsm").Activate
        Sheets("extraction").Select

        Range("A1").Select
        ActiveSheet.Paste

        'tri_404 Macro c'est lent sur cette boucle

        Range("B1").Select
        Dim DernL1 As Long
        DernL1 = Sheets("extraction").Range("e" & Rows.Count).End(xlUp).Row

        For i = 2 To DernL1

        If Range("b" & i).Value <> 404 Then
        Rows(i & ":" & i).Select

        Selection.Delete Shift:=xlUp
        i = i - 1
        j = j + 1
        If j = DernL1 Then
        i = DernL1
        End If
        End If

        Next i
        'sélection des colonne
        Columns("A:A").Select
        Selection.Delete Shift:=xlToLeft
        Columns("B:J").Select
        Selection.Delete Shift:=xlToLeft
        Columns("C:D").Select
        Selection.Delete Shift:=xlToLeft
        Columns("F:G").Select
        Selection.Delete Shift:=xlToLeft
        Columns("K:K").Select
        Selection.Delete Shift:=xlToLeft
        Columns("K:L").Select
        Selection.Delete Shift:=xlToLeft
        Columns("M:M").Select
        Selection.Delete Shift:=xlToLeft
        Range("a1").Select
        'tri UT
        '
        Dim DernLigne2 As Long
        DernLigne2 = Sheets("extraction").Range("e" & Rows.Count).End(xlUp).Row

        For l = 2 To DernLigne2
        If Left(Range("f" & l), 1) = 0 Then
        Rows(l & ":" & l).Select
        Selection.Delete Shift:=xlUp
        l = l - 1
        End If
        Next l
        'copie ds UT
        Range("F2:F" & DernLigne2).Select
        Selection.Copy
        Sheets("resultat").Select

        If Range("b2") = "" Then

        Range("d2").Select
        ActiveSheet.Paste

        GoTo fin
        End If
        Range("d2").Select
        ActiveSheet.Paste

        'tri ut non enregistrés
        Sheets("resultat").Select
        Dim DernLigne5 As Long

        DernLigne3 = Sheets("resultat").Range("b" & Rows.Count).End(xlUp).Row

        DernLigne5 = Sheets("resultat").Range("d" & Rows.Count).End(xlUp).Row
        For m = 2 To DernLigne5
        For n = 2 To DernLigne3
        If Range("d" & m).Value = Range("b" & n).Value Then
        Range("d" & m).Select
        Selection.Delete Shift:=xlUp
        m = m - 1
        End If
        Next n
        Next m

        'ajout liste
        fin:
        Range("b1").Value = "UT Enregistrés"
        Range("d1").Value = "UT à Enregistrés"
        Dim DernLigne4 As Long
        DernLigne4 = Sheets("resultat").Range("d" & Rows.Count).End(xlUp).Row
        If DernLigne4 = 1 Then
        MsgBox ("Vous n'avez aucun nouvel UT")
        Exit Sub
        End If
        Range("D2:D" & DernLigne4).Select
        Selection.Copy
        Range("b2").Select
        Selection.Insert Shift:=xlDown
        Application.CutCopyMode = False
        DernLigne5 = Sheets("resultat").Range("b" & Rows.Count).End(xlUp).Row
        ActiveSheet.Range("B1:B" & DernLigne5).RemoveDuplicates Columns:=1, Header:=xlYes
        ActiveSheet.Range("d1:d" & DernLigne4).RemoveDuplicates Columns:=1, Header:=xlYes
        DernLigne4 = Sheets("resultat").Range("d" & Rows.Count).End(xlUp).Row
        MsgBox ("Vous avez " & (DernLigne4 - 1) & " nouveau(x) UT " & "Notez les N°")
        Range("D2:D" & DernLigne4).Interior.ColorIndex = 4

        End Sub

        pour A c'est plus compliqué j'ai plusieurs module assez long.
        0
      4. Bonjour,

        La lenteur vient de cette ligne : Selection.Delete Shift:=xlUp
        La suppression de lignes via macro prend énormément de ressources.

        Vous pouvez modifier cela non par par un delete mais par un cut/paste des données (les faire remonter progressivement)
        0
    5. Hello,

      Si tu utilises la fonction "Private Sub Worksheet_Change(ByVal Target As Range)" dans le classeur A, elle se lancera à chaque édition dans ta macro.
      Tu peux tenter, dans ta macro B, d'ajouter application.EnableEvents=false au début et le mettre à true à la fin de ta boucle for.
      Sinon effectivement c'est compliqué de savoir ce qu'il se passe sans avoir le code...
      Bonne journée.
      1
      1. Merci de ta réponse je vais essayé
        0
      2. j'ai essayé d'ajouter application.EnableEvents=false au début et le mettre à true à la fin de ta boucle for. c'est pareil , merci d'avoir tenté une solution.
        0
      3. j'ai remarqué que lorsque j'appuis une fois sur Esc lors du déroulement de la macro ça accélère légèrement ???
        0
    6. Bonjour,

      Que fait B par rapport a A?????
      1
      1. Rien aucune liaison
        0