Optimisation de Macro
Bonjour à tous
Grace à une aide bien précieuse, j'ai pu obtenir ce code. Mais le problème c'est que sur mon fichier de plus de 30 000 Lignes il rame à fond.
Des idées pour m'aider à l'optimiser
Option Base 1
Sub test()
Dim cellule As Range, ind%, ws As Worksheet, Der_Ligne%, D As Object
Set ws = Worksheets("feuil1")
Der_Ligne = ws.Range("A" & Rows.Count).End(xlUp).Row
Dim Tablo
Tablo = ws.Range("A1").CurrentRegion
Set D = CreateObject("Scripting.dictionary")
For i = 3 To UBound(Tablo)
ind = CLng(Evaluate("=INDEX(Tableau1[Dates sorties],LARGE(IF(((Tableau1[Clé]=""" & Tablo(i, 1) & """)*(Tableau1[Dates sorties]<>"""")),ROW(Tableau1[Clé])-2),1))"))
If Not D.exists(Tablo(i, 1)) Then D.Add Tablo(i, 1), ind
Next i
Set i = Nothing
Dim tablo2()
ReDim tablo2(D.Count, 1 To 2)
tablo2 = Application.Transpose(Array(D.keys, D.Items))
For Each cellule In ws.Range("C3:C" & Der_Ligne)
For t = 1 To UBound(tablo2)
If CLng(cellule.Offset(0, 2)) = tablo2(t, 2) Then cellule.Offset(0, 12) = cellule.Offset(0, 11).Value2
If CLng(cellule) >= tablo2(t, 2) And cellule.Offset(0, -2) = tablo2(t, 1) Then
cellule.Offset(0, 12) = cellule.Offset(0, 11).Value2
End If
Next t
Next cellule
End SubEn vous remerciant par avance
Bonjour,
Sans le classeur on ne va pas pouvoir faire grand chose...
Il faut travailler le dernier For each dans un Array : Tu nous fais tout un show avec des Array et un Dico et tu massacres le final avec des tripatouillages de cellules et d'offset...
A+
Sans le classeur on ne va pas pouvoir faire grand chose...
Bonjour
Ci-joint le classeur.
Merci
Le moins que tu puisses faire c'est de me fournir un classeur ou la macro fonctionne.
Sinon je ne peux rien pour toi.
A+
Vraiment désolé. Le bug était du à la ligne vide (Ligne 8) dès quon la supprime la macro marche. Je vous joins à nouveau le fichier corrigé
Bonjour,
Je précise que je n'ai pas vu votre fichier mais de ce que je comprends du code, vous avez un tableau structuré donc il faut l'intégrer dans le code.
Voici un essai d'adaptation du code (avec le peu que j'ai cru comprendre) en attendant des explications détaillées sur la manipulation (j'ai besoin de comprendre les tests effectués et de connaitre les index des colonnes dans Tableau1 qui importent, notamment celles qui correspondent à des dates) :
Sub test()
with range("Tableau1")
t = .value2
For i = lbound(t) To UBound(t)
ind = CLng(Evaluate("=INDEX(Tableau1[Dates sorties],LARGE(IF(((Tableau1[Clé]=""" & t(i, 1) & """)*(Tableau1[Dates sorties<>"""")),ROW(Tableau1[Clé])-2),1))"))
If t(i, 5) = ind or t(i, 3) >= ind Then t(i, 15) = t(i, 14)
Next i
.columns(15).value2 = application.index(t, , 15)
end with
End SubPar ailleurs, il faudrait peut-être renommer la colonne clé car clé sous-entend unicité, ce qui n'est visiblement pas le cas.
Cdlt,
J'ai toujours la même erreur.
Dans un premier temps moi ce qui me pose problème c'est la colonne L une formule qui se réfère à une ligne vide, c'est plus un tableau Excel : Dans un langage un peu pudique on appelle généralement ça "une usine à gaz"."
De la même manière ta ligne 1 relève du même principe...
Je n'ai pas pris le temps de relire tes précédents messages, mais à priori tu cèdes au travers habituel des débutants : Tu mélanges les données brutes et le résultat à obtenir. Tu confonds le départ et l'arrivée.
Le point de départ c'est les données brutes : Un tableau avec des lignes et des colonnes. Si paramètres il y a, ils ont vocation à résider dans une autre feuille (ou peut-être dans les Noms du Gestionnaire de Noms.)
L'arrivée ou le résultat souhaité c'est rarement dans la même feuille. Pourquoi ? Parce que ce résultat suppose souvent des tas de bricolages, calculs intermédiaires, mises en forme destinées à en faciliter la lecture... Alors oui ton tableau principal peut supporter dans les dernières colonnes quelques formules calculées. Mais pas des formules qui font références à des lignes vides...
Par rapport au code, même les développeurs les plus avertis se soumettent à l'exigence des déclarations.
Option Explicit en tête de module est une saine habitude à prendre : Pour cela cochez définitivement dans VBA : Options > Editeur > Déclaration de variables obligatoires ou alors abstenez vous de macroter...
A+
EDIT : 3GB Oui dans ta boule de cristal tu as bien vu le truc c'est un tableau de frimeur : Ça en a tout juste vaguement l'aspect !
Voici un essai d'adaptation du code (avec le peu que j'ai cru comprendre) en attendant des explications détaillées sur la manipulation
Bonjour 3GB
Je m'excuse pour le délai de réponse.
Avec ce code, c'est sûr j'ai gagné un temps mon monstre sur mon fichier.
Mais il reste un petit réglage que je ne suis pas arrivé à faire.
J'ai joins le fichier (Un qui marche avec votre code) et à coté j'y ais mis le résultat attendu.
Merci d'avance de vous pencher sur mon cas
Ps: Votre approche est la seule qui ait pris moins de 5 min sur mes 37000 lignes de fichier
Bonjour à tous,
Désolé, je n'ouvre pas les fichiers...
Moins de 5 minutes ou quelques secondes ? Déjà, peut-être qu'en mettant temporairement le calcul sur manuel, ça pourrait réduire le temps d'exécution car il est possible que le calcul matriciel entraine un recalcul des fonctions volatiles du fichier. C'est à vérifier, je n'en suis pas sur.
Sub test()
application.calculation = xlcalculationmanual
with range("Tableau1")
t = .value2
For i = lbound(t) To UBound(t)
ind = CLng(Evaluate("=INDEX(Tableau1[Dates sorties],LARGE(IF(((Tableau1[Clé]=""" & t(i, 1) & """)*(Tableau1[Dates sorties<>"""")),ROW(Tableau1[Clé])-2),1))"))
If t(i, 5) = ind or t(i, 3) >= ind Then t(i, 15) = t(i, 14)
Next i
.columns(15).value2 = application.index(t, , 15)
end with
application.calculation = xlcalculationautomatic
End SubCes 2 lignes ne coûtent rien...
Cdlt,
Désolé, je n'ouvre pas les fichiers...
Bonjour 3GB
Ah je comprends mieux alors; Je vous détaille ici alors mon soucis.
CLng(Evaluate("=INDEX(Tableau1[Dates sorties],LARGE(IF(((Tableau1[Clé]=""" & t(i, 1) & """)*(Tableau1[Dates sorties<>"""")),ROW(Tableau1[Clé])-2),1))"))Cette formule dans le code, je me suis rendu compte qu'elle ne marche pas. J'ai donc obtenu une formule Excel matricielle qui marche très bien mais le problème c'est que quand je la lance, au bout d'une nuit la formule ne s'exécute pas sur les 37 000 lignes; du coup je me demandais si on ne pouvait pas l'adapter sur la macro optimisée qui je précise prend moins de 5 secondes pour s'exécuter.
Voici la formule :
=SI{NB.SI($A$3:$A7;$A7)>=EQUIV(MAX(FILTER($E:$E;$A:$A=$A7));FILTER($E:$E;$A:$A=$A7);0);$N7;""}Merci d'avance pour l'aide
Bonjour relmo,
Mais cette formule a bien marché auparavant ?
Je me rends compte qu'en copiant ton code, j'ai malencontreusement supprimé un crochet fermant. Peux-tu essayer ainsi :
CLng(Evaluate("=INDEX(Tableau1[Dates sorties],LARGE(IF(((Tableau1[Clé]=""" & t(i, 1) & """)*(Tableau1[Dates sorties]<>"""")),ROW(Tableau1[Clé])-ROW(Tableau1[#All])),1))"))Pour l'autre formule, d'une part elle ne m'est pas familière, n'ayant pas 365. D'autre part, elle serait probablement plus lourde vu qu'elle traite des colonnes entières. En général, il vaut mieux, quand c'est possible, privilégier les formules sur des références dynamiques, comme c'est le cas avec le tableau structuré Tableau1.