Optimisation temps d'exécution macro - remplir tableau via userform
Bonjour,
Je souhaiterai avoir vos conseils pour améliorer la macro suivante. Son temps d'exécution est d'environ 15 secondes. Merci pour votre aide
Private Sub CommandButton1_Click()
Application.EnableEvents = False
Dim sh As Worksheet
Dim tsh As Worksheet
Set sh = ThisWorkbook.Sheets("Data_source")
Set tsh = ThisWorkbook.Sheets("Tasks_ref")
'défini la ligne où seront insérées les nouvelles données
Dim lr As Long
Dim lrt As Long
If Me.BoInsert.Value = "" Then
lr = sh.Cells(sh.Rows.Count, "A").End(xlUp).Row
sh.ListObjects("Data_tab").ListRows.Add
End If
'Copier coller la ligne précédente pour récupérer les formules des cellules calculées
sh.Range("A" & lr - 1).EntireRow.Copy
sh.Range("A" & lr).PasteSpecial xlPasteAll
'insérer les valeurs mises dans les boxes du formulaire dans le tableau data_tab
sh.Range("B" & lr).Value = 7
sh.Range("D" & lr).Value = "legumes"
sh.Range("E" & lr).Value = Me.cboLots.Value
sh.Range("F" & lr).Value = Me.cboZone.Value
sh.Range("H" & lr).Value = Me.cboQui.Value
sh.Range("I" & lr).Value = Me.cboType.Value
sh.Range("K" & lr).Value = Me.tboDescription.Value
sh.Range("L" & lr).Value = Me.cboJalons.Value
sh.Range("AN" & lr).Value = Me.tboStart.Value
sh.Range("AO" & lr).Value = Me.tboEnd.Value
sh.Range("AP" & lr).FormulaLocal = "=NB.JOURS.OUVRES([@[Actual Start]];[@[Actual End]];Tableau22)"
sh.Range("AS" & lr).Value = Me.tboStart.Value
sh.Range("AT" & lr).Value = Me.tboEnd.Value
sh.Range("AU" & lr).FormulaLocal = "=NB.JOURS.OUVRES([@[Actual Start]];[@[Actual End]];Tableau22)"
sh.Range("AQ" & lr).Value = Me.tboProgress.Value
sh.Range("AV" & lr).Value = Me.tboProgress.Value
'ajout de la nouvelle ligne dans feuille Tasks_ref: tableau tasks_tab
lrt = tsh.Cells(tsh.Rows.Count, "A").End(xlUp).Row
sh.ListObjects("Data_tab").ListRows.Add
sh.Range("A" & lr).EntireRow.Copy
tsh.Range("A" & lrt).PasteSpecial xlPasteAll
MsgBox "Done", vbInformation
Unload Me
Application.EnableEvents = True
End SubBonjour,
Peux-tu poster le fichier (anonymisé) ? cela permettrait de déterminer les parties chronophages
Pour moi, l'hypothèse la plus probable, ce sont les 2 lignes
sh.Range("AP" & lr).FormulaLocal = "=NB.JOURS.OUVRES([@[Actual Start]];[@[Actual End]];Tableau22)"
sh.Range("AU" & lr).FormulaLocal = "=NB.JOURS.OUVRES([@[Actual Start]];[@[Actual End]];Tableau22)"Il n'est pas nécessaire de reproduire ces formules à chaque ligne, un tableau le fait automatiquement : une nouvelle ligne hérite d'un certain nombre de propriétés des lignes précédentes. Et il est fort probable que puisque tu les répètes, excel les recalcule pour toutes les lignes du tableau.
Bonjour,
Je te remercie pour ta réponse. Le fichier anonymisé est joint.
Je vais essayer en supprimant les [@xxx] de mes tableaux par les noms de cellules pour l'empêcher de recalculer tout à chaque fois.
Bonjour,
Je vais essayer en supprimant les [@xxx] de mes tableaux par les noms de cellules pour l'empêcher de recalculer tout à chaque fois.
Non, fais le sur la toute première ligne, la toute première fois, à la main si besoin. Ensuite elle sera reproduite. Ne le fais pas en remplaçant par les noms des cellules cela ne changerait rien !
Il a plein d'erreurs #REF! dans le fichier.
Essaie simplement comme ceci sans rien changer d'autre
Private Sub CommandButton1_Click()
Application.EnableEvents = False
If Me.tboDescription.Value = "" Then
MsgBox "Please enter", vbCritical, "add new action"
Exit Sub
End If
If Me.cboQui.Value = "" Then
MsgBox "Please enter ", vbCritical, "add new action"
Exit Sub
End If
If Me.cboJalons.Value = "" Then
MsgBox "Please enter", vbCritical, "add new action"
Exit Sub
End If
Dim sh As Worksheet
Dim tsh As Worksheet
Set sh = ThisWorkbook.Sheets("Data_source")
Set tsh = ThisWorkbook.Sheets("Tasks_ref")
'défini la ligne où seront insérées les nouvelles données
Dim lr As Long
Dim lrt As Long
lr = sh.Cells(sh.Rows.Count, "A").End(xlUp).Row
'Application.CountA(sh.Range("K:K")) + 1
sh.ListObjects("Data_tab").ListRows.Add
'Copier coller la ligne précédente pour récupérer les formules des cellules calculées
sh.Range("A" & lr - 1).EntireRow.Copy
sh.Range("A" & lr).PasteSpecial xlPasteAll
'insérer les valeurs mises dans les boxes du formulaire dans le tableau data_tab
sh.Range("B" & lr).Value = 7
sh.Range("D" & lr).Value = "legumes"
sh.Range("E" & lr).Value = Me.cboLots.Value
sh.Range("F" & lr).Value = Me.cboZone.Value
sh.Range("H" & lr).Value = Me.cboQui.Value
sh.Range("I" & lr).Value = Me.cboType.Value
sh.Range("K" & lr).Value = Me.tboDescription.Value
sh.Range("L" & lr).Value = Me.cboJalons.Value
sh.Range("AN" & lr).Value = Me.tboStart.Value
sh.Range("AO" & lr).Value = Me.tboEnd.Value
'sh.Range("AP" & lr).FormulaLocal = "=NB.JOURS.OUVRES([@[S]];[@[T]];tableau22)"
sh.Range("AS" & lr).Value = Me.tboStart.Value
sh.Range("AT" & lr).Value = Me.tboEnd.Value
'sh.Range("AU" & lr).FormulaLocal = "=NB.JOURS.OUVRES([@[S]];[@[T]];Tableau22)"
sh.Range("AQ" & lr).Value = Me.tboProgress.Value
sh.Range("AV" & lr).Value = Me.tboProgress.Value
'ajout de la nouvelle ligne dans feuille Tasks_ref: tableau tasks_tab
lrt = tsh.Cells(tsh.Rows.Count, "A").End(xlUp).Row
'Application.CountA(tsh.Range("K:K")) + 1
sh.ListObjects("Data_tab").ListRows.Add
sh.Range("A" & lr).EntireRow.Copy
tsh.Range("A" & lrt).PasteSpecial xlPasteAll
ThisWorkbook.Sheets("Tasks_ref").Select
MsgBox "Task added successfully", vbInformation
Unload Me
Application.EnableEvents = True
End Sub
Private Sub CommandButton2_Click()
Unload Me
End SubJ'aurais quand même bien aimé avoir un fichier "opérationnel" pour en faire l'analyse.
Bonjour,
Merci pour tes réponses. Je vais faire le ménage dans le fichier pour qu’il soit propre demain.
J’avais entre-temps supprimer tous les @xxx et ça a déjà divisé par deux le temps. J’ai fait un test en supprimant les deux lignes qui te semblaient poser pb mais le temps est resté sensiblement pareil.
Merci pour ton aide et je fais un fichier plus propre.
Bonjour,
J'ai remis le fichier au propre.
Le fichier comporte Trois Feuil :
- Data_Source qui regroupent l'ensemble des données,
- SupData qui regroupent les listes pour faire des validations dans les cellules de la Data_Source
- Tasks ref qui affiche que certains éléments de la Data_Source. Deux Icones en haut de cette feuille lancent deux macros. Une qui actualise les données et une qui ajoute une activité à travers d'un userform. C'est cette macro qui est lente dans l'exécution. Elle permet d'enregistrer la nouvelle ligne ligne à la fois dans la Feuil data_Source et la Feuil Tasks_ref.
En ajoutant,
Debug.Print "#x: " & Format(Now - topdebut, "hh:mm:ss")avec x plusieurs valeurs, on a :
#1 : 00:00:03
#2 : 00:00:22
#3 : 00:00:22
#4 : 00:00:23on s'aperçoit que 95% du temps est pris par ceci :
'insérer les valeurs mises dans les boxes du formulaire dans le tableau data_tab
sh.Range("B" & lr + 1).Value = 7
sh.Range("D" & lr + 1).Value = "legumes"
sh.Range("E" & lr + 1).Value = Me.cboLots.Value
sh.Range("F" & lr + 1).Value = Me.cboZone.Value
sh.Range("H" & lr + 1).Value = Me.cboQui.Value
sh.Range("I" & lr + 1).Value = Me.cboType.Value
sh.Range("K" & lr + 1).Value = Me.tboDescription.Value
sh.Range("L" & lr + 1).Value = Me.cboJalons.Value
sh.Range("AN" & lr + 1).Value = Me.tboStart.Value
sh.Range("AO" & lr + 1).Value = Me.tboEnd.Value
'sh.Range("AP" & lr).FormulaLocal = "=NB.JOURS.OUVRES([@[S]];[@[T]];tableau22)"
sh.Range("AS" & lr + 1).Value = Me.tboStart.Value
sh.Range("AT" & lr + 1).Value = Me.tboEnd.Value
'sh.Range("AU" & lr).FormulaLocal = "=NB.JOURS.OUVRES([@[S]];[@[T]];Tableau22)"
sh.Range("AQ" & lr + 1).Value = Me.tboProgress.Value
sh.Range("AV" & lr + 1).Value = Me.tboProgress.ValueCe qui signifie que ce qui est chronophage, ce sont les formules de calcul dans la feuille ... à investiguer (je continuerai plus tard)
Les MFC qui se rajoutent au fur et a mesure des recopies peuvent gêner le déroulement ... c'est déjà une hypothèse que j'ai écartée ici.
J'ai enlevé tous les calculs ... le temps tombe à moins de 1 secondes !
Je n'ai pas encore pu déterminer quel calcul était en cause (d'autant que certaines formules ne sont pas disponibles chez moi), en tous cas ce n'est pas la macro !
In fine la solution la plus simple est quand même dans la macro. 2 lignes ajoutées ici :
Application.Calculation = xlCalculationManual
topdebut = Now
Dim sh As Worksheet
Dim tsh As Worksheet
Set sh = ThisWorkbook.Sheets("Data_source")
Set tsh = ThisWorkbook.Sheets("Tasks_ref")et en final, une ligne ajoutée et une modifiée
tsh.ListObjects("Tasks_tab").ListRows.Add
sh.Range("A" & lr + 1).EntireRow.Copy
tsh.Range("A" & lrt + 1).PasteSpecial xlPasteAll
Application.Calculation = xlCalculationAutomatic
MsgBox "Task added successfully in " & Format(Now - topdebut, "hh:mm:ss"), vbInformationBonjour,
Merci pour ton aide précieuse.
Avec ce que tu m'as dit, j'ai donc contourné le problème en créant une ligne en dehors du tableau puis j'ai recopié la ligne entière dans data_tab et tasks_tab. La macro tourne en deux secondes. Le problème est non identifié mais au moins le temps est divisé par dix :)
Private Sub CommandButton1_Click()
Application.EnableEvents = False
If Me.tboDescription.Value = "" Then
MsgBox "Please enter", vbCritical, "add new action"
Exit Sub
End If
If Me.cboQui.Value = "" Then
MsgBox "Please enter ", vbCritical, "add new action"
Exit Sub
End If
If Me.cboJalons.Value = "" Then
MsgBox "Please enter", vbCritical, "add new action"
Exit Sub
End If
Application.Calculation = xlCalculationManual
topdebut = Now
Dim sh As Worksheet
Dim tsh As Worksheet
Set sh = ThisWorkbook.Sheets("Data_source")
Set tsh = ThisWorkbook.Sheets("Tasks_ref")
'défini la ligne où seront insérées les nouvelles données
Dim lr As Long
Dim lrt As Long
lr = sh.Cells(sh.Rows.Count, "A").End(xlUp).Row
sh.ListObjects("Data_tab").ListRows.Add
Debug.Print "1 :" & Format(Now - topdebut, "hh:mm:ss")
'Copier coller la ligne précédente pour récupérer les formules des cellules calculées
sh.Range("A" & lr).EntireRow.Copy
sh.Range("A" & lr + 6).PasteSpecial xlPasteAll
'insérer les valeurs mises dans les boxes du formulaire dans le tableau data_tab
sh.Range("B" & lr + 6).Value = 7
sh.Range("D" & lr + 6).Value = "legumes"
sh.Range("E" & lr + 6).Value = Me.cboLots.Value
sh.Range("F" & lr + 6).Value = Me.cboZone.Value
sh.Range("H" & lr + 6).Value = Me.cboQui.Value
sh.Range("I" & lr + 6).Value = Me.cboType.Value
sh.Range("K" & lr + 6).Value = Me.tboDescription.Value
sh.Range("L" & lr + 6).Value = Me.cboJalons.Value
sh.Range("AN" & lr + 6).Value = Me.tboStart.Value
sh.Range("AO" & lr + 6).Value = Me.tboEnd.Value
'sh.Range("AP" & lr).FormulaLocal = "=NB.JOURS.OUVRES([@[S]];[@[T]];tableau22)"
sh.Range("AS" & lr + 6).Value = Me.tboStart.Value
sh.Range("AT" & lr + 6).Value = Me.tboEnd.Value
'sh.Range("AU" & lr).FormulaLocal = "=NB.JOURS.OUVRES([@[S]];[@[T]];Tableau22)"
sh.Range("AQ" & lr + 6).Value = Me.tboProgress.Value
sh.Range("AV" & lr + 6).Value = Me.tboProgress.Value
'ajout de la nouvelle ligne dans feuille Tasks_ref: tableau tasks_tab
lrt = tsh.Cells(tsh.Rows.Count, "A").End(xlUp).Row
sh.Range("A" & lr + 6).EntireRow.Copy
sh.Range("A" & lr + 1).PasteSpecial xlPasteAll
sh.Range("A" & lr + 6).EntireRow.Delete
tsh.ListObjects("Tasks_tab").ListRows.Add
sh.Range("A" & lr + 1).EntireRow.Copy
tsh.Range("A" & lrt + 1).PasteSpecial xlPasteAll
Application.Calculation = xlCalculationAutomatic
MsgBox "Task added successfully in " & Format(Now - topdebut, "hh:mm:ss"), vbInformation
MsgBox "Task added successfully", vbInformation
Unload Me
Application.EnableEvents = True
End SubRe-bonjour,
J'ai converti mon tableau data_tab en plage de données classique. La macro se déroule en moins d'une seconde.
Je vais modifier mon autre macro pour conserver des data en simple plage de données.
Merci encore pour ton appui. Je mets le sujet en résolu :)
