Optimisation vitesse de calcul
Bonjour à tous, j'ai réalisé la macro ci dessous:
Elle fonctionne parfaitement par contre son temps d’exécution est d'environ 2 minutes, c'est la boucle " For i " qui prends enormement de temps.
Est ce qu'il y aurait une écriture différente afin d'optimiser la vitesse de calcul?
Private Sub RemplissageTableau()
Dim tabBDD()
Dim wsBDD As Object
Dim wsResult As Object
Dim som(9)
Dim crit(6)
Dim cptBDD
Dim i, j As Long
Set wsBDD = Worksheets("BDD")
Set wsResult = Worksheets("Familly & Country")
With wsBDD
tabBDD = Range(.Cells(2, 1), .Cells(.Cells(Rows.Count, 1).End(xlUp).Row, 30)) ' Définition du tableau de travail
End With
With wsResult
derlig = Cells(Rows.Count, 2).End(xlUp).Offset(0, 0).Row
dercol = Cells(1, Cells.Columns.Count).End(xlToLeft).Offset(0, 0).Column
For i = 2 To derlig Step 4
For j = 4 To dercol
som1 = 0
som2 = 0
som3 = 0
som4 = 0
som5 = 0
som6 = 0
som7 = 0
som8 = 0
som9 = 0
crit2 = Sheets("Données").Cells(4, 2) 'Réel
crit3 = Sheets("Familly & Country").Cells(i, 1) ' Country
crit4 = Sheets("Familly & Country").Cells(1, j) 'Familly
crit5 = Sheets("Données").Cells(5, 2) 'YTD n
crit6 = Sheets("Données").Cells(6, 2) 'YTD n-1
For cptBDD = 1 To UBound(tabBDD, 1)
If (tabBDD(cptBDD, 1) = crit2) And (tabBDD(cptBDD, 30) = crit3) And (tabBDD(cptBDD, 24) = crit4) Then
som1 = som1 + tabBDD(cptBDD, 11) 'total1
som2 = som2 + tabBDD(cptBDD, 12) 'total2
som3 = som3 + tabBDD(cptBDD, 14) + tabBDD(cptBDD, 15) + tabBDD(cptBDD, 16) + tabBDD(cptBDD, 18) + tabBDD(cptBDD, 20) 'total3
End If
If (tabBDD(cptBDD, 1) = crit5) And (tabBDD(cptBDD, 30) = crit3) And (tabBDD(cptBDD, 24) = crit4) Then
som4 = som4 + tabBDD(cptBDD, 11) 'total1
som5 = som5 + tabBDD(cptBDD, 12) 'total2
som6 = som6 + tabBDD(cptBDD, 14) + tabBDD(cptBDD, 15) + tabBDD(cptBDD, 16) + tabBDD(cptBDD, 18) + tabBDD(cptBDD, 20) 'total3
End If
If (tabBDD(cptBDD, 1) = crit6) And (tabBDD(cptBDD, 30) = crit3) And (tabBDD(cptBDD, 24) = crit4) Then
som7 = som7 + tabBDD(cptBDD, 11) 'total1
som8 = som8 + tabBDD(cptBDD, 12) 'total2
som9 = som9 + tabBDD(cptBDD, 14) + tabBDD(cptBDD, 15) + tabBDD(cptBDD, 16) + tabBDD(cptBDD, 18) + tabBDD(cptBDD, 20) 'total3
End If
Next
.Cells(i, j) = som1 + som4 - som7 'Total 1
.Cells(i + 1, j) = (som2 + som5 - som8) Total 2
.Cells(i + 2, j) = ((som3 + som6 - som9) * -1) 'Total 3
If (som2 + som5 - som8) <= 0 Then
.Cells(i + 3, j) = 0
Else
.Cells(i + 3, j) = ((som3 + som6 - som9) * -1) / (som2 + som5 - som8) ' %Total
End If
Next
Next
End With
Cells.EntireColumn.AutoFit
End Sub
Derlign vaut "221" et dercol "52".
Merci à vous
Bonjour,
as-tu des formules et des mises en forme conditionnelles dans ton fichier ? merci de nous mettre une version du fichier dans lequel on peut voir ton problème de performance.
Bonjour,
un essai :
Private Sub RemplissageTableau()
Application.ScreenUpdating = False
Application.EnableEvents = False
Application.Calculation = xlCalculationManual
Dim tabBDD()
Dim wsBDD As Object
Dim wsResult As Object
Dim som(9)
Dim crit(6)
Dim cptBDD
Dim i, j As Long
Set wsBDD = Worksheets("BDD")
Set wsResult = Worksheets("Familly & Country")
With wsBDD
tabBDD = Range(.Cells(2, 1), .Cells(.Cells(Rows.Count, 1).End(xlUp).Row, 30)) ' Définition du tableau de travail
End With
With wsResult
derlig = Cells(Rows.Count, 2).End(xlUp).Offset(0, 0).Row
dercol = Cells(1, Cells.Columns.Count).End(xlToLeft).Offset(0, 0).Column
For i = 2 To derlig Step 4
For j = 4 To dercol
som1 = 0
som2 = 0
som3 = 0
som4 = 0
som5 = 0
som6 = 0
som7 = 0
som8 = 0
som9 = 0
crit2 = Sheets("Données").Cells(4, 2) 'Réel
crit3 = Sheets("Familly & Country").Cells(i, 1) ' Country
crit4 = Sheets("Familly & Country").Cells(1, j) 'Familly
crit5 = Sheets("Données").Cells(5, 2) 'YTD n
crit6 = Sheets("Données").Cells(6, 2) 'YTD n-1
For cptBDD = 1 To UBound(tabBDD, 1)
If (tabBDD(cptBDD, 1) = crit2) And (tabBDD(cptBDD, 30) = crit3) And (tabBDD(cptBDD, 24) = crit4) Then
som1 = som1 + tabBDD(cptBDD, 11) 'total1
som2 = som2 + tabBDD(cptBDD, 12) 'total2
som3 = som3 + tabBDD(cptBDD, 14) + tabBDD(cptBDD, 15) + tabBDD(cptBDD, 16) + tabBDD(cptBDD, 18) + tabBDD(cptBDD, 20) 'total3
ElseIf (tabBDD(cptBDD, 1) = crit5) And (tabBDD(cptBDD, 30) = crit3) And (tabBDD(cptBDD, 24) = crit4) Then
som4 = som4 + tabBDD(cptBDD, 11) 'total1
som5 = som5 + tabBDD(cptBDD, 12) 'total2
som6 = som6 + tabBDD(cptBDD, 14) + tabBDD(cptBDD, 15) + tabBDD(cptBDD, 16) + tabBDD(cptBDD, 18) + tabBDD(cptBDD, 20) 'total3
ElseIf (tabBDD(cptBDD, 1) = crit6) And (tabBDD(cptBDD, 30) = crit3) And (tabBDD(cptBDD, 24) = crit4) Then
som7 = som7 + tabBDD(cptBDD, 11) 'total1
som8 = som8 + tabBDD(cptBDD, 12) 'total2
som9 = som9 + tabBDD(cptBDD, 14) + tabBDD(cptBDD, 15) + tabBDD(cptBDD, 16) + tabBDD(cptBDD, 18) + tabBDD(cptBDD, 20) 'total3
End If
Next
.Cells(i, j) = som1 + som4 - som7 'Total 1
.Cells(i + 1, j) = (som2 + som5 - som8) 'Total 2
.Cells(i + 2, j) = ((som3 + som6 - som9) * -1) 'Total 3
If (som2 + som5 - som8) <= 0 Then
.Cells(i + 3, j) = 0
Else
.Cells(i + 3, j) = ((som3 + som6 - som9) * -1) / (som2 + som5 - som8) ' %Total
End If
Next
Next
End With
Cells.EntireColumn.AutoFit
Application.Calculation = xlCalculationAutomatic
Application.EnableEvents = True
Application.ScreenUpdating = True
End Sub
Ajout de trois instructions qui fiche l'écran, arrête les calculs et inhibe la surveillances des événements.
Ensuite on réactive ces trois choses.
Raccourcis de IF en mettant des ElseIf car si dans la boucle on a (tabBDD(cptBDD, 1) = crit2) alors il ne peut être égal à crit5 ou crit6 sur la même boucle, cela supprime deux tests....
Sans fichier je n'ai pas pu essayer...
@ bientôt
LouReeD
Merci LouReeD,
J'ai testé ta solution, et le temps est encore 2minutes et 6s contre 2minutes et 10s pour l'autre code, un gain de 4s.
Je précise tabBDD est sur 55000 lignes et 31 colonnes, sa fait pas mal de cellules à traiter
quand j'ai vu ton code je me suis dis que le gain allait être énorme mais en fait pas temps que ça.
Est ce que tu penses que du fait que TabBDD est grand je ne pourrais pas gagner beaucoup plus, ou est ce qu'il y aurait une autre méthode, par exemple changer la boucle For par une autre boucle qui serait plus rapide ?
Merci
h2so4 a écrit :Bonjour,
as-tu des formules et des mises en forme conditionnelles dans ton fichier ? merci de nous mettre une version du fichier dans lequel on peut voir ton problème de performance.
Bonjour h2so4, dans la feuille BDD je n'ai que des valeurs bruts, aucune formules ni MFC, c'est la macro qui additionne les valeurs de TabBDD en fonction des critères pour par la suite les afficher sur la feuille "Family & Country"
Bonjour,
mets-nous un fichier pour voir ce qu'on peut faire ...
Il y a aussi l'idée de travailler en "tout VBA" tableau source comme tableau résultat.
Au lieu que chaque calcul s'inscrive sur la feuille wsResult, ils s'inscrivent dans un tableau VBA de "même dimension".Une fois la boucle terminée il suffit d'attribuer le tableau VBA Résult à la zone voulue sur la feuille wsResult.
@ bientôt
LouReeD
Je suis actuellement essayé de faire un code en "tout VBA", je vais le poster une fois que celui ci sera fini afin d'avoir vos impressions.
LouReeD a écrit :Il y a aussi l'idée de travailler en "tout VBA" tableau source comme tableau résultat.
Au lieu que chaque calcul s'inscrive sur la feuille wsResult, ils s'inscrivent dans un tableau VBA de "même dimension".Une fois la boucle terminée il suffit d'attribuer le tableau VBA Résult à la zone voulue sur la feuille wsResult.
@ bientôt
LouReeD
J'ai essayé un code qui m'a pris pas mal de temps et qui ne fonctionne pas du tout
Option Base 1
Sub test()
Dim wsBDD As Object
Dim wsResult As Object
Dim tabBDD
Dim som(19)
Dim Ncol As Integer, Nlgn As Long, cptBDD As Long, dercol As Integer
Dim crit(5)
'
Set wsBDD = Worksheets("BDD")
Set wsResult = Worksheets("Familly & Country")
'
Application.ScreenUpdating = False
'
With wsBDD
tabBDD = .Range("A3:AE" & .Range("A" & Rows.Count).End(xlUp).Row)
End With
'
With wsResult
derlgn = Range("B" & Rows.Count).End(xlUp).Row
dercol = Cells(2, Columns.Count).End(xlToLeft).Column
For Ncol = 4 To dercol
For Nlgn = 2 To derlgn Step 4
Erase som
crit1 = Sheets("Données").Cells(4, 2) ' Réél ( n )
crit2 = .Cells(1, Nlgn) ' Country
crit3 = .Cells(8, Ncol) ' Familly
crit4 = Sheets("Données").Cells(5, 2) ' YTD ACT ( n )
crit5 = Sheets("Données").Cells(6, 2) ' YTD ACT ( n - 1 )
For cptBDD = 1 To UBound(tabBDD, 1)
If (tabBDD(cptBDD, 1) = crit1) And (tabBDD(cptBDD, 30) = crit2) And (tabBDD(cptBDD, 24) = crit3) Then iIdx = 0
If (tabBDD(cptBDD, 1) = crit4) And (tabBDD(cptBDD, 30) = crit2) And (tabBDD(cptBDD, 24) = crit3) Then iIdx = 1
If (tabBDD(cptBDD, 1) = crit5) And (tabBDD(cptBDD, 30) = crit2) And (tabBDD(cptBDD, 24) = crit3) Then iIdx = 2
som(1 + (iIdx * 4)) = som(1 + (iIdx * 4)) + tabBDD(cptBDD, 11)
som(2 + (iIdx * 4)) = som(2 + (iIdx * 4)) + tabBDD(cptBDD, 12)
som(3 + (iIdx * 4)) = som(3 + (iIdx * 4)) + tabBDD(cptBDD, 14) + tabBDD(cptBDD, 15) + tabBDD(cptBDD, 16) + tabBDD(cptBDD, 18) + tabBDD(cptBDD, 20)
som(4 + (iIdx * 4)) = som(3 + (iIdx * 4)) / som(2 + (iIdx * 4))
For x = 1 To 4
For i = 1 To derlgn
.Cells((x + 1 + i), Ncol) = som(x + (iIdx * 4))
Next
Next
Next
Next
Next
End With
'
Set wsBDD = Nothing
Set wsResult = Nothing
'
Application.ScreenUpdating = True
End Sub
Est ce que tu pourrais me guider afin de faire un code en "Tableau VBA" stp ?