Macro mets 30 min à tourner

Bonjour

J'ai une macro qui consiste à créer 75 fichiers en automatique à partir d'un fichier source qui fait des recherches. Le problème est qu'elle met 35 min à tourner ! alors que je l'ai testé pour un autre fichier (création de 65 fichiers) et ça net mets que 2min..

Y a t il une solution svp ?

Merci d'avance.

Cdt,

Hajar

Bonjour,

Déjà, nous montrer le code !

Bonjour

Ci-dessous la macro

Option Explicit

Sub Archiver()

Dim wk1 As Workbook, CC As Workbook

Dim wk2 As String, chemin As String, extension As String, Pays As String

Dim i As Integer, n As Integer

Dim lks As Variant

Application.DisplayAlerts = False

chemin = ThisWorkbook.Path & "\"

Set wk1 = ThisWorkbook

wk2 = "Pays test macro.xlsx"

extension = ".xlsx"

Application.ScreenUpdating = False

For n = 4 To 77 'adapter à la plage de cellules Nom de pays

Pays = wk1.Sheets("Feuil1").Range("A" & n) 'adapter à la plage de cellules Nom de pays

If Pays <> "" Then

Workbooks(wk2).Sheets("E2258_1").Range("A6") = Pays

Workbooks(wk2).SaveAs Filename:=chemin & "Test_" & Pays & extension, FileFormat:=51

Set CC = Workbooks("Test_" & Pays & extension)

On Error Resume Next

CC.ActiveSheet.DrawingObjects(1).Delete

On Error GoTo 0

lks = CC.LinkSources(1)

If Not IsEmpty(lks) Then

For i = 1 To UBound(lks)

CC.BreakLink Name:=lks(i), Type:=xlExcelLinks

Next i

End If

CC.Close SaveChanges:=True

Workbooks.Open chemin & wk2

End If

Next n

Application.ScreenUpdating = True

Application.DisplayAlerts = False

End Sub

Salut,

Juste pour savoir dans ton fichier source (pour en faire 75) ,tu as des différences avec celui qui en fait 65?

Par exemple il y a des liens entre classeur ? des formules ? c'est un fichier partagé ?

Si c'est la même macro qui tourne sur le même pc, je ne pense pas que le code en lui même soit en cause du coup

ECG

Bonsoir,

Pour gagner du temps, ne serait il pas plus rapide de supprimer les liens sur le fichier source et de les rétablir à la fin et de même pour l'objet ? Ceci éviterai les 70 instructions dans la boucle. Une piste pour mémoriser les liaisons et les rétablir ensuite. La fonction qui retourne un tableau :

Function MemoFormules(Fe As Worksheet) As Variant()

    Dim Tbl()
    Dim Cel As Range
    Dim Chemin As String
    Dim I As Integer

    For Each Cel In Fe.Cells.SpecialCells(xlCellTypeFormulas)

        Chemin = Replace(Cel.Formula, "='", "")
        Chemin = Replace(Chemin, "[", "")

        On Error Resume Next
        Chemin = Left(Chemin, InStr(Chemin, "]") - 1)
        On Error GoTo 0

        If Dir(Chemin) <> "" Then

            I = I + 1
            ReDim Preserve Tbl(1 To 2, 1 To I)
            Tbl(1, I) = Cel.Address
            Tbl(2, I) = Cel.Formula

        End If

    Next Cel

    MemoFormules = Tbl()

End Function

appelée de la façon suivante :

Dim Tbl()
Tbl = MemoFormules(wk1.Sheets("Feuil1"))

et à la fin du code, remise en place des formules dans le fichier source :

For I = 1 To UBound(Tbl, 2): Range(Tbl(1, I)).Formula = Tbl(2, I): Next I

Enfin, c'est une piste !

Bonjour,

Une piste à étudier, à comprendre et adapter. A savoir que quand on copie une ou plusieurs feuilles d'un classeur sans en préciser la destination, un nouveau classeur est créé avec la ou les feuilles copiées. Ceci évite après l'enregistrement sous... de devois à nouveau ouvrir le classeur original donc, probablement un gain de temps. N'ayant pas testé, je ne peux pas savoir le temps d'exécution de la proc. Dans mon code, l'objet (wk1.ActiveSheet.DrawingObjects(1).Delete) est détruit avant la boucle, il suffit de le re-créer en fin de code mais ne sachant pas de quel objet il s'agit, je n'est pas mis le code de création :

Sub Archiver()

    Dim wk1 As Workbook
    Dim wk2 As Workbook
    Dim Chemin As String, extension As String, Pays As String
    Dim I As Integer, n As Integer
    Dim lks As Variant
    Dim Tbl()

    Application.DisplayAlerts = False
    Application.ScreenUpdating = False

    Set wk1 = ThisWorkbook
    Set wk2 = Workbooks("Pays test macro.xlsx") '<--- il doit être ouvert !

    Chemin = ThisWorkbook.Path & "\"
    extension = ".xlsx"

    'adapter le nom de la feuille, créer autant de tableaux que de feuilles
    'et appeler plusieurs fois la fonction si nécessaire
    Tbl = MemoFormules(wk1.Worksheets("Feuil1"))

    'si liaisons...
    If Tbl(1, 1) <> "Aucune valeur" Then

        lks = wk1.LinkSources(1)

        If Not IsEmpty(lks) Then
            For I = 1 To UBound(lks): wk1.BreakLink lks(I), 1: Next I
        End If

    End If

    'suppression de l'objet qui sera à re-créé
    'peut être en mémoriser le type afin de le re-créé plus facilement, à voir...
    On Error Resume Next
    wk1.ActiveSheet.DrawingObjects(1).Delete
    On Error GoTo 0

    For n = 4 To 77 'adapter à la plage de cellules Nom de pays

        Pays = wk1.Sheets("Feuil1").Range("A" & n) 'adapter à la plage de cellules Nom de pays

        If Pays <> "" Then

            wk2.Sheets("E2258_1").Range("A6") = Pays

            'si la destination de la copie n'est pas précisée, un classeur est créé avec la ou les feuilles copiées
            'adapter le nom de la ou des feuilles copiées dans le nouveau classeur
            wk1.Worksheets(Array("Feuil1", "Feuil3")).Copy '<--- si une seule feuille, supprimer l'Array()

            'le classeur nouvellement créé devient le classeur actif
            ActiveWorkbook.SaveAs Chemin & "Test_" & Pays & extension, 51
            ActiveWorkbook.Close True

            'le classeur n'étant pas fermé lors de l'enregistrment sous... plus la peine de l'ouvrir à nouveau donc, gain de temps
            '''Workbooks.Open chemin & wk2

        End If

    Next n

    'remise en place des liaisons, adapter le nom de la feuille
    For I = 1 To UBound(Tbl, 2): wk1.Worksheets("Feuil1").Range(Tbl(1, I)).Formula = Tbl(2, I): Next I

    'ici, création de l'objet supprimé plus haut...

    Application.ScreenUpdating = True
    Application.DisplayAlerts = False

End Sub

Function MemoFormules(Fe As Worksheet) As Variant()

    Dim Tbl()
    Dim Cel As Range
    Dim Chemin As String
    Dim I As Integer

    On Error GoTo Fin
    For Each Cel In Fe.Cells.SpecialCells(xlCellTypeFormulas)

        Chemin = Replace(Cel.Formula, "='", "")
        Chemin = Replace(Chemin, "[", "")

        On Error Resume Next
        Chemin = Left(Chemin, InStr(Chemin, "]") - 1)
        On Error GoTo 0

        If Dir(Chemin) <> "" Then

            I = I + 1
            ReDim Preserve Tbl(1 To 2, 1 To I)
            Tbl(1, I) = Cel.Address
            Tbl(2, I) = Cel.Formula

        End If

    Next Cel

    MemoFormules = Tbl()

    Exit Function

Fin:

    ReDim Tbl(1 To 1, 1 To 1)
    Tbl(1, 1) = "Aucune valeur"
    MemoFormules = Tbl()

End Function

Bonjour

Merci pour votre retour. les liens sont indispensables car chaque variable entrée, les liens doivent se réactualiser pour afficher les bonnes valeurs donc je ne peux pas les supprimer en premier

Merci

Hajar

bonjour,

j'ai essayé la macro mais en fait elle ne fait que reproduire le fichier source en plusieurs fichiers, ce qui n'est pas le but de ma macro initiale..

effectivement dans ce cas elle met moins de temps à tourner !

Bonjour,

...chaque variable entrée...

Le nom du pays je suppose ?

Bonjour

Oui tout à fait

Re,

Il faudrait poster les deux classeurs liés afin de voir les formules et, selon le cas, voir si il est possible de réduire le temps d'exécution de la macro ?

Il faudrait poster les classeurs sans données confidentielles !

Bonjour

Ci-joint la macro sur laquelle j'ai pu économiser 30 min de tournage (elle passe de 40 min à 10 min mnt), le fichier principal qui sert à alimenter les fichiers, et le fichier modèle de création des sous fichiers;

Idéalement je voudrais que la macro me supprime les colonnes A et B quand elle finit de créer chaque fichier car ce sont des colonnes qui me servent uniquement de recherchev mais ça je n'ai pas encore trouvé..

merci d'avance pour votre aide précieuse !

cdt

Hajar

8macro.xlsm (39.72 Ko)
7final.xlsx (68.73 Ko)

Bonjour,

Désolé du retard !

Avec le code ci-dessous, et par rapport aux classeurs postés, il mets chez moi 28 secondes à créer tous les classeurs (74 par rapport aux classeurs postés). Il faut savoir que les formules sont supprimées donc les liaisons et seules les valeurs correspondantes sont récupérées par l'intermédiaire de la fonction Find(). Voir commentaires dans le code :

Sub Archiver()

    Dim wk1 As Workbook
    Dim wk2 As Workbook
    Dim CC As Workbook
    Dim Plage As Range
    Dim PlgVal As Range
    Dim Cel As Range
    Dim Chemin As String, extension As String, Pays As String
    Dim n As Integer
    Dim Debut As Date

    Debut = Time 'pour la mesure du temps d'exécution

    Application.ScreenUpdating = False

    Set wk1 = ThisWorkbook
    Set wk2 = Workbooks("Pays test macro.xlsx") '<--- il doit être ouvert !

    Chemin = ThisWorkbook.Path & "\"
    extension = ".xlsx"

    With Workbooks("Final.xlsx").Worksheets("Feuille 1"): Set Plage = .Range(.Cells(6, 1), .Cells(.Rows.Count, 1).End(xlUp)): End With

    'supprime les valeurs et formules de la ligne 6 du classeur "Pays test macro.xlsx"
    wk2.Worksheets("Feuille 1").Rows(6).ClearContents

    For n = 4 To 77

        Pays = wk1.Sheets("Feuil1").Range("A" & n)

        If Pays <> "" Then

            'la recherche est effectuée sur la colonne A où se trouvent les pays...
            Set Cel = Plage.Find(Pays, , xlValues, xlWhole)

            'si trouvé...
            If Not Cel Is Nothing Then

                'copie la feuille dans un nouveau classeur pour avoir la mise en forme et les valeurs non supprimées
                wk2.Worksheets("Feuille 1").Copy
                Set CC = ActiveWorkbook

                'défini la plage sur la ligne de la valeur cherchée...
                With Workbooks("Final.xlsx").Worksheets("Feuille 1"): Set PlgVal = .Range(.Cells(Cel.Row, 1), .Cells(Cel.Row, .Columns.Count).End(xlToLeft)): End With

                'et colle ces valeurs en ligne 6
                With CC.Worksheets("Feuille 1"): .Range(.Cells(6, 1), .Cells(6, PlgVal.Columns.Count)).Value = PlgVal.Value: End With

                'enregistre et ferme
                CC.SaveAs Chemin & "Test_" & Pays & extension, 51
                ActiveWorkbook.Close True

            End If

        End If

    Next n

    Application.ScreenUpdating = True

    'affiche le temps d'exécution
    MsgBox Format(Time - Debut, "hh:mm:ss")

End Sub

Bonjour

Merci pour la macro ça marche impec ùais ça ne me copie que le premier onglet..j'ai besoin qu'elle fasse la copie sur les trois onglets où j'ai des formules de recherche..sinon rapidité top !

merci d'avance

Cdt

Hajar

Bonjour,

Ok, je regarde ça quand j'ai un peu de temps et te re poste un code !

Bonjour,

Voici le nouveau code à tester :

Sub Archiver()

    Dim wk1 As Workbook
    Dim wk2 As Workbook
    Dim CC As Workbook
    Dim Plage As Range
    Dim PlgVal As Range
    Dim Cel As Range
    Dim Chemin As String, extension As String, Pays As String
    Dim n As Integer
    Dim Debut As Date
    Dim Adr As String
    Dim Lgn As Long
    Dim I As Integer

    Debut = Time 'pour la mesure du temps d'exécution

    Application.ScreenUpdating = False

    Set wk1 = ThisWorkbook
    Set wk2 = Workbooks("Pays test macro.xlsx") '<--- il doit être ouvert !

    Chemin = ThisWorkbook.Path & "\"
    extension = ".xlsx"

    For n = 4 To 77

        Pays = wk1.Sheets("Feuil1").Range("A" & n)

        'supprime les valeurs et formules de la ligne 6 du classeur "Pays test macro.xlsx"
        wk2.Worksheets("Feuille 1").Rows(6).ClearContents
        wk2.Worksheets("Feuille 2").Rows("6:25").ClearContents
        wk2.Worksheets("Feuille 3").Rows("6:25").ClearContents

        If Pays <> "" Then

    '----feuille "Feuille 1"-----
            With Workbooks("Final.xlsx").Worksheets("Feuille 1"): Set Plage = .Range(.Cells(6, 1), .Cells(.Rows.Count, 1).End(xlUp)): End With

            'la recherche exacte sur la colonne A
            Set Cel = Plage.Find(Pays, , xlValues, xlWhole)

            'si trouvé...
            If Not Cel Is Nothing Then

                With Workbooks("Final.xlsx").Worksheets("Feuille 1"): Set PlgVal = .Range(.Cells(Cel.Row, 1), .Cells(Cel.Row, .Columns.Count).End(xlToLeft)): End With
                With wk2.Worksheets("Feuille 1"): .Range(.Cells(6, 1), .Cells(6, PlgVal.Columns.Count)).Value = PlgVal.Value: End With

            End If

            For I = 2 To 3

    '----feuilles "Feuille 2" et "Feuille 3"-----
                With Workbooks("Final.xlsx").Worksheets("Feuille " & I): Set Plage = .Range(.Cells(6, 1), .Cells(.Rows.Count, 1).End(xlUp)): End With

                'recherche partielle sur la colonne A
                Set Cel = Plage.Find(Pays, , xlValues, xlPart)

                'si trouvé...
                If Not Cel Is Nothing Then

                    Adr = Cel.Address

                    Do

                        With Workbooks("Final.xlsx").Worksheets("Feuille " & I): Set PlgVal = .Range(.Cells(Cel.Row, 1), .Cells(Cel.Row, .Columns.Count).End(xlToLeft)): End With

                        With wk2.Worksheets("Feuille " & I)

                            Lgn = .Cells(.Rows.Count, 1).End(xlUp).Row + 1
                            If Lgn < 6 Then Lgn = 6
                            .Range(.Cells(Lgn, 1), .Cells(Lgn, PlgVal.Columns.Count)).Value = PlgVal.Value

                        End With

                        Set Cel = Plage.FindNext(Cel)

                    Loop While Cel.Address <> Adr

                End If

            Next I

            'copie la feuille dans un nouveau classeur pour avoir la mise en forme et les valeurs non supprimées
            wk2.Worksheets(Array("Feuille 1", "Feuille 2", "Feuille 3")).Copy

            ActiveWorkbook.SaveAs Chemin & "Test_" & Pays & extension, 51
            ActiveWorkbook.Close True

        End If

    Next n

    Application.ScreenUpdating = True

    'affiche le temps d'exécution
   MsgBox Format(Time - Debut, "hh:mm:ss")

End Sub

Bonjour

Merci pour la macro

je n'ai pas pu la tester car au niveau du code suivant je ne peux pas laisser Feuille vu qu'en fait mes onglets sont renommés différemment. Que proposez vous comme solution svp ?

'----feuilles "Feuille 2" et "Feuille 3"-----

With Workbooks("Final.xlsx").Worksheets("Feuille " & I): Set Plage = .Range(.Cells(6, 1), .Cells(.Rows.Count, 1).End(xlUp)): End With

Cdt

Hajar

Re,

En utilisant un tableau (Array) où seront indiqués en début de code les noms des feuilles :

Sub Archiver()

    Dim wk1 As Workbook
    Dim wk2 As Workbook
    Dim CC As Workbook
    Dim Plage As Range
    Dim PlgVal As Range
    Dim Cel As Range
    Dim TblFe
    Dim Chemin As String, extension As String, Pays As String
    Dim n As Integer
    Dim Debut As Date
    Dim Adr As String
    Dim Lgn As Long
    Dim I As Integer

    Debut = Time 'pour la mesure du temps d'exécution

    Application.ScreenUpdating = False

    Set wk1 = ThisWorkbook
    Set wk2 = Workbooks("Pays test macro.xlsx") '<--- il doit être ouvert !

    Chemin = ThisWorkbook.Path & "\"
    extension = ".xlsx"

    'ici, adapter les noms des feuilles !
    TblFe = Array("Feuille 2", "Feuille 3") '<------ !!!

    For n = 4 To 77

        Pays = wk1.Sheets("Feuil1").Range("A" & n)

        'supprime les valeurs et formules des feuilles du classeur "Pays test macro.xlsx"
        wk2.Worksheets("Feuille 1").Rows(6).ClearContents
        wk2.Worksheets("Feuille 2").Rows("6:25").ClearContents
        wk2.Worksheets("Feuille 3").Rows("6:25").ClearContents

        If Pays <> "" Then

    '----feuille "Feuille 1"-----
           With Workbooks("Final.xlsx").Worksheets("Feuille 1"): Set Plage = .Range(.Cells(6, 1), .Cells(.Rows.Count, 1).End(xlUp)): End With

            'recherche exacte sur la colonne A
            Set Cel = Plage.Find(Pays, , xlValues, xlWhole)

            'si trouvé...
            If Not Cel Is Nothing Then

                With Workbooks("Final.xlsx").Worksheets("Feuille 1"): Set PlgVal = .Range(.Cells(Cel.Row, 1), .Cells(Cel.Row, .Columns.Count).End(xlToLeft)): End With
                With wk2.Worksheets("Feuille 1"): .Range(.Cells(6, 1), .Cells(6, PlgVal.Columns.Count)).Value = PlgVal.Value: End With

            End If

            For I = 0 To UBound(TblFe)

    '----autres feuilles dont les noms sont dans le tableau "TblFe"-----
               With Workbooks("Final.xlsx").Worksheets(TblFe(I)): Set Plage = .Range(.Cells(6, 1), .Cells(.Rows.Count, 1).End(xlUp)): End With

                'recherche partielle sur la colonne A
                Set Cel = Plage.Find(Pays, , xlValues, xlPart)

                'si trouvé...
                If Not Cel Is Nothing Then

                    Adr = Cel.Address

                    Do

                        With Workbooks("Final.xlsx").Worksheets(TblFe(I)): Set PlgVal = .Range(.Cells(Cel.Row, 1), .Cells(Cel.Row, .Columns.Count).End(xlToLeft)): End With

                        With wk2.Worksheets(TblFe(I))

                            Lgn = .Cells(.Rows.Count, 1).End(xlUp).Row + 1
                            If Lgn < 6 Then Lgn = 6
                            .Range(.Cells(Lgn, 1), .Cells(Lgn, PlgVal.Columns.Count)).Value = PlgVal.Value

                        End With

                        Set Cel = Plage.FindNext(Cel)

                    Loop While Cel.Address <> Adr

                End If

            Next I

            'adapter les noms des feuilles ici aussi !!!
            wk2.Worksheets(Array("Feuille 1", "Feuille 2", "Feuille 3")).Copy

            ActiveWorkbook.SaveAs Chemin & "Test_" & Pays & extension, 51
            ActiveWorkbook.Close True

        End If

    Next n

    Application.ScreenUpdating = True

    'affiche le temps d'exécution
    MsgBox Format(Time - Debut, "hh:mm:ss")

End Sub

Bonjour

Merci pour la maco impec niveau rapidité

par contre les deux derniers onglets ne contiennent plus de valeurs alors que dans le fichier source ils sont censés chercher des valeurs dans le premier onglet selon le pays..

merci pour votre aide

Cdt

Hajar

Attention, le code que je t'ai donné a été fait en fonction des classeurs postés ! Tu as dû remarquer que la feuille "Feuille 2" du classeur "Final.xlsx" ne contient pas de valeur de la ligne 6 à 24 ? Par contre, par exemple, le classeur Test_CL.xlsx contient en feuille "Feuille 1" des valeurs en ligne 6 de A à R, en feuille "Feuille 2" des valeurs de A6 à U10 concernant CL1 à CL6 et en feuille "Feuille 3" des valeurs de A6 à AA10 concernant CL1 à CL6 où en AA10 il y a un X.

Je te poste ce classeur afin que tu vois les résultats car pour moi, ça marche à priori très bien, mais par rapport aux classeurs que tu as posté. Si les classeurs réels sont différents, forcément les résultats le seront aussi !

PS : Sur mon petit PC portable, les classeurs sont créés en 29 secondes, sur mon PC de bureau ils sont créés en 14 secondes !

3test-cl.xlsx (16.29 Ko)
Rechercher des sujets similaires à "macro mets min tourner"