XL 2013 [RESOLU] VBA: optimisation code Boucle

sarah33

XLDnaute Junior
Bonjour le fofo,

Je suis en train de faire une petite appli Excel qui consiste à importer des données de plusieurs autres feuilles excel, provenant d'une extraction d'un ERP. Les informations sont compilées sur deux feuilles de ~70 000lignes

Dans un second temps, je traite ces données via une boucle qui traite chaque ligne:
- Calculs entre les lignes (IF Cells)
- Recherche dans d'autres Feuilles (VLookup)
- Qui comprend une autre petite boucle "a" à l'intérieur de la boucle principal (i)

C'est pour cette seconde partie que j'ai besoin de votre expertise. En effet, le code que j'ai réalisé fonctionne..mais il est lent environ 40s de traitement avec une machine de compétition...

Je débute le VBA, je bouffe du tuto mais j'ai pas encore les bonnes pratiques...
Merci d'avance si vous pouvez jeter un coup d'oeil, et me conseiller pour améliorer la qualité de mon code.

a+

Code:
Sub Traitement_Imp_Ventes()
Dim derli As String, nbvent As String
Dim R As Variant, S As Variant
nbvent = Sheets("Références").Range("L1").End(xlDown).Row
derli = Sheets("Ventes").Range("K1").End(xlDown).Row

For i = 2 To derli

'Remplacer les vides par dates par ligne
If Cells(i, 2) = "" And Cells(i, 10) <> "" Then
Cells(i, 2) = Cells(i - 1, 2)
End If
'Remplacer les vides par N°commande par ligne
If Cells(i, 3) = "" And Cells(i, 10) <> "" Then
Cells(i, 3) = Cells(i - 1, 3)
End If

'Remplacer les Vides par zéro  Prix Achats
If IsEmpty(Cells(i, 4)) Then
Cells(i, 4).Value = 0
End If


'Remplacer les Vides par zéro Prix Public
If IsEmpty(Cells(i, 5)) Then
Cells(i, 5).Value = 0
End If

'Remplacer les Vides par zéro Prix Vente
If IsEmpty(Cells(i, 6)) Then
Cells(i, 6).Value = 0
End If


'Remplacer les vides par Clients par ligne
If Cells(i, 8) = "" And Cells(i, 10) <> "" Then
Cells(i, 8) = Cells(i - 1, 8)
End If

'Remplacer les vides par Statut par ligne
If Cells(i, 9) = "" And Cells(i, 10) <> "" Then
Cells(i, 9) = Cells(i - 1, 9)
End If
'Calcul Total vendu
Cells(i, 12) = Cells(i, 7) * Cells(i, 6)
'Ref Interne démentellée
Cells(i, 13).Value = Replace(Replace(Left(Cells(i, 10), InStr(Cells(i, 10), "]")), "[", ""), "]", "")
'N°semaine
Cells(i, 14) = NoSemaineISO(Cells(i, 2))

'Déterminer les type de vente à classer comme Interne

For a = 2 To nbvent
If Sheets("Ventes").Cells(i, 8) = Sheets("Références").Cells(a, 12) Then
Sheets("Ventes").Cells(i, 15) = "Interne"
End If
Next a
'Détermine les types de ventes à classer en externe
If IsEmpty(Cells(i, 15)) Then
Cells(i, 15) = "Externe"
End If

'Calcul Taux Réduction
If Cells(i, 6) > 0 And Cells(i, 5) Then
Cells(i, 16) = 1 - (Cells(i, 6) / Cells(i, 5))
'Calcul Réduction
Cells(i, 17) = (Cells(i, 5) - Cells(i, 6)) * Cells(i, 7)
Else
Cells(i, 16) = 0
Cells(i, 17) = 0
End If

'Calcul Marge
Cells(i, 18) = Cells(i, 12) - (Cells(i, 4) * Cells(i, 7))
'Calcul Taux MArge
If Cells(i, 18) > 0 Then
Cells(i, 19) = Cells(i, 18) / Cells(i, 12)
End If


'Recherche dans une autre feuille les Marques
R = Application.VLookup(Cells(i, 13), Sheets("Article Table").Range("D:E"), 2, False)
If IsError(R) Then
Cells(i, 20) = ""
Else
Cells(i, 20) = R
End If


'Recherche dans une autre feuille les groupes ref
S = Application.VLookup(Cells(i, 13), Sheets("Article Table").Range("D:AN"), 36, False)
If IsError(S) Then
Cells(i, 21) = ""
Else
Cells(i, 21) = S
End If
'Détermine Type de vente
If Left(Cells(i, 13), 2) = "PS" Then
Cells(i, 22) = "Main d'oeuvre"
ElseIf Cells(i, 13) = "AVPURA" Then
Cells(i, 22) = "Taxe"
Else
Cells(i, 22) = "Pièce"
End If

Next i


'Renommer entêtes
Cells(1, 2) = "Date"
Cells(1, 3) = "N°Commande"
Cells(1, 4) = "PU Achat"
Cells(1, 5) = "PU Public"
Cells(1, 6) = "PU Vente"
Cells(1, 7) = "Qtité"
Cells(1, 8) = "Client"
Cells(1, 9) = "Etat"
Cells(1, 10) = "Designation"
Cells(1, 12) = "Total vendu"
Cells(1, 13) = "Ref interne"
Cells(1, 14) = "Semaine"
Cells(1, 15) = "Vente"
Cells(1, 16) = "Taux Réduction"
Cells(1, 17) = "Réduction"
Cells(1, 18) = "Marge"
Cells(1, 19) = "Taux Marge"
Cells(1, 20) = "Marque"
Cells(1, 21) = "Ref Groupe"
Cells(1, 22) = "Type de vente"
Cells(1, 23) = "Catégorie"
End Sub
 
Dernière édition:

sarah33

XLDnaute Junior
Re : VBA: optimisation code Boucle beaucoup de ligne

re!

Bon, je n'arrive décidément pas à mettre en ligne un fichier avec suffisamment de ligne, je dépasse tout dessuite la limite du site, meme zippé..

Je viens de test sur mon fichier original, incroyable, 20s, par contre le résultat n'est pas bon xD j'ai beaucoup moins de valeurs retrouvée qu'à l'origine.
 

sarah33

XLDnaute Junior
Re : VBA: optimisation code Boucle beaucoup de ligne

Ok, donc 57s de chargement total contre 1min40 avec les Vlookup ! soit 37s pour la partie recherche contre 80s avec Vlookup !
Impressionnant !
Pour info, il y a 69000 lignes dans le array, et 12000 dans Article Table (table de recherche)


une idée de pourquoi ça passe pas ?
Code:
numLigne = Application.Match(tablo(i, 13), Sheets("Article Table").Range(Cells(1, 4), Cells(derli2, 4)), 0)
j'ai fait mon test 57s avec :
Code:
numLigne = Application.Match(tablo(i, 13), Sheets("Article Table").Range("D1:D12092"), 0)
merci
 
Dernière édition:

Modeste

XLDnaute Barbatruc
Re : VBA: optimisation code Boucle beaucoup de ligne

une idée de pourquoi ça passe pas ?

Euh ... c'est quoi qui "ne passe pas"? Les résultats sont erronés? Il en manque encore?


J'ai testé l'utilisation du Dictionary, mais j'ai un autre souci: dans la feuille "Article Table", en colonne D, j'ai plusieurs fois la référence "69259", mais avec des Marques et des groupes ref différents ... c'est normal??
 

sarah33

XLDnaute Junior
Re : VBA: optimisation code Boucle beaucoup de ligne

Re,

C'est ma faute pour les 69259, erreur dans la création du fichier Exemple.
Cette colonne est une clée primaire, pas de doublon possible sur Référence (normalement).

le ça ne passe pas correspond enfaite à une Erreur d'exécution 1004:
Erreur définie par l'application ou par l'objet

et ça me surligne cette fameuse ligne:
Code:
numLigne = Application.Match(tablo(i, 13), Sheets("Article Table").Range(Cells(1, 4), Cells(derli2, 4)), 0)
 

Modeste

XLDnaute Barbatruc
Re : VBA: optimisation code Boucle beaucoup de ligne

Cette colonne est une clé primaire, pas de doublon possible sur Référence (normalement)
Pourquoi est-ce que je n'aime pas ce "normalement" ajouté en fin de ligne ? ;)

Pour l'erreur, difficile à dire ... tu travailles toujours sur l'extrait que tu avais déposé ou un autre fichier? À quoi correspond derli2 ?

Le reste, ce sera peut-être pour demain: à cette heure je bats tous mes records d'âneries proférées par minute

@+
 

sarah33

XLDnaute Junior
Re : VBA: optimisation code Boucle beaucoup de ligne

Code:
derli = Sheets("Ventes").Range("K1").End(xlDown).Row
derl2 = Sheets("Article Table").Range("D1").End(xlDown).Row

pour l'erreur, non sur un autre fichier..

Bonne fin de soirée ! et merci pour le temps consacré à mon projet.
 

sarah33

XLDnaute Junior
Re : VBA: optimisation code Boucle beaucoup de ligne

Hello,

Enfaite, j'ai encore le problème sur cette ligne...malgré le bon renommage.
Après test, ce n'est pas la variante "derli2" qui dérange, mais le fait d'utiliser des cells() dans le range..

Si vous avez une idée, vous trouverez la doc en pièce jointe.

mercii
 

Pièces jointes

  • Exemple ouf.xlsm
    40.7 KB · Affichages: 45
  • Exemple ouf.xlsm
    40.7 KB · Affichages: 50

Modeste

XLDnaute Barbatruc
Re : VBA: optimisation code Boucle beaucoup de ligne

Salut :)

On célèbre l'Armistice aujourd'hui ... n'entre pas en guerre avec un bout de code! :D
Teste ce qui suit:
VB:
'Recherche dans une autre feuille
With Sheets("Article Table")
numLigne = Application.Match(tablo(i, 13), .Range(.Cells(1, 4), .Cells(derli2, 4)), 0)
If IsNumeric(numLigne) Then
    tablo(i, 20) = .Cells(numLigne, 5) 'Recherche les Marques
    tablo(i, 21) = .Cells(numLigne, 39) 'Recherche les groupes ref
End If
End With

Si tu veux tester un Dictionary, il faudra que tu répondes à la question des doublons en feuille "Article Table": s'il peut y en avoir (même un risque infime!), que fait-on?
Application.Match trouve la première occurrence de la référence en colonne D; le dico peut s'arrêter à la première ou ... aller jusqu'à la dernière occurrence. Si pour une réf, il ne peut y avoir 2 marques différentes ou 2 "ref groupe" différentes, la question est de moindre importance. Si tu me dis que ce cas de figure est définitivement impossible (et pas "normalement" :rolleyes:), je peux essayer le dico.
 

sarah33

XLDnaute Junior
Re : VBA: optimisation code Boucle beaucoup de ligne

Salut Modeste !

Je vais faire la paix avec mon code !!
Merci pour la correction !

Concernant dictionnary et la table Article.
Une Ref, ne peut avoir que UNE Marque et que UNE Groupe Ref. En théorie il n'y a pas et n'aura "jamais" (oups) de doublons en cette colonne.
Donc, si le dico s'arrête à la première occurrence trouvée, ça me va très bien !

mici
 
Dernière édition:

Modeste

XLDnaute Barbatruc
Re : VBA: optimisation code Boucle beaucoup de ligne

Re,

Un essai avec un dico (qui s'arrête donc à la première occurrence ... sauf erreur :eek:)
J'ai recopié le code dans ton dernier fichier ... vérifie si je n'ai rien oublié (et si les résultats sont corrects)!

Ne te restera plus ensuite qu'à comparer la vitesse d'exécution (tu nous diras, hein!?)
 

Pièces jointes

  • exemple ouf dico (sarah33).xlsm
    40.7 KB · Affichages: 63

sarah33

XLDnaute Junior
Re : VBA: optimisation code Boucle beaucoup de ligne

Ok, roulement de tambour........


Cette dernière version du code me fait passer à un chargement total de 10s !!!!!!!
euhhhh c'est juste incroyable, j'étais à 2min40 en postant hier !

Milles fois merci à toi Modeste et Laeti qui nous a mis sur la voix des Dico !!!! je vais maintenant fignoler tout ça, et créer une dernière grosse formule de recherche, faire mes tests pour être sur que les résultats sont bon !!

En tout cas le moins qu'on puisse dire, c'est que tu me l'as optimisé mon code !!!!
Mon "probleme" est donc bien résolu grâce à toi, et à vous le fofo !!

merciiiiiii
 
Dernière édition:

Discussions similaires

Statistiques des forums

Discussions
312 105
Messages
2 085 350
Membres
102 870
dernier inscrit
Armisa