Message-ID: <386BC3A8.F0774C5D@free.fr> Date: Thu, 30 Dec 1999 21:42:16 +0100 From: Laurent longre X-Mailer: Mozilla 4.7 [fr] (Win95; I) X-Accept-Language: fr MIME-Version: 1.0 Subject: Re: Suppression de doublons References: <84g1ek$2di2$1@buggy.easynet.fr> <386B99E1.8B46447D@free.fr> <84gb79$2inj$1@buggy.easynet.fr> Content-type: text/plain; charset=iso-8859-1 Content-Transfer-Encoding: 8bit Newsgroups: microsoft.public.fr.excel NNTP-Posting-Host: lyon2-55-225.dial.proxad.net 212.27.55.225 Path: cppssbbsa01.microsoft.com!cppssbbsa04 Lines: 128 Xref: cppssbbsa01.microsoft.com microsoft.public.fr.excel:20392 tiger a écrit : > > Je m'attendais à un code simple du genre While...Wend ou for each next. > Après sélection de la dernière cellule pleine de la colonne tant que la > cellule active est différente de la cellule situé une ligne plus haut, > sélectionne la cellule situé plus haut sinon efface la valeur de la cellule > active et sélectionne la cellule situé plus haut. Je n'ai pas su l'écrire. Plus simple (quoique pas plus court), mais *beaucoup moins* rapide, et aussi AMHA moins intéressant. > A quoi sert le (0).Row? Je veux dire qu'apporte de plus le (0)? range("...")(X) est un raccourci syntaxique de la popriété Item, équivalent de range("...").Item(X). Avec 0, ça renvoie la cellule qui se trouve une ligne plus haut. Avec 2, la référence de la cellule deux lignes plus bas. > Pourquoi I = > J + 1? Pouvait-on se passer de cells? Il s'agit d'identifier la dernière ligne d'un bloc de cellules comportant des valeurs identiques, afin de les effacer, sauf la première. Au lieu de tester chaque cellule une à une (méthode très lente, lourdingue et pas intéressante), j'utilise la propriété ColumnDifferences. Le I sert juste à stocker le numéro de la première ligne du bloc. Au début, c'est donc 1. Ensuite: range(cells(I, 1), Fin).ColumnDifferences(cells(I, 1)) renvoie la référence du premier bloc de cellules non égal à cells(I,1) dans la plage allant de cells(I,1) jusqu'à la cellule "Fin" (Fin = dernière cellule remplie de la colonne). Je ne commente pas plus, c'est précisément là le but et la fonction de la propriété ColumnDifferences. Pour avoir la *dernière* ligne du bloc précédent (celui de cells(I,1)), il faut remonter d'une ligne par rapport au bloc de cellules renvoyés. D'où le (0), équivalent de Item(0). donc, la variable J assigné par : J = range(cells(I, 1), Fin).ColumnDifferences(cells(I, 1))(0).Row ... reçoit le numéro de ligne de la dernière cellule consécutive à cells(I, 1) dont le contenu est égal à cells(I, 1), dans la plage de recherche range(cells(I, 1), Fin). Ensuite : if J > I then ... Veut dire : *si J > I* (cad, si *effectivement il y a des doublons après la cellule cells(I, 1)*, ce qui implique que le numéro de ligne J est en-dessous du numéro de ligne J), *alors* il faut effacer le contenu de ces doublons, ce qui est effectué par: ... range(cells(I + 1, 1), cells(J, 1)).ClearContents I + 1, car il faut effacer à partir de la ligne suivant le début du bloc de doublons, pour garder la première cellule. Enfin : loop Until Err C'est la fin de la boucle. Si on est arrivés à la fin de la plage et que ColumnDifferences ne trouve plus de nouveau bloc, cette propriété échoue et génère une erreur, la valeur de l'objet Err devient donc différente de 0. C'est la condition de terminaison de la boucle: jusqu'à ce que Err soit différent de 0 (loop Until Err). Pour la boucle suivante, il faut que ColumnDifferences prenne comme plage de recherche ce qui reste dans la colonne, en-dessous du dernier bloc de doublons identifiés. Comme la variable J stocke maintenant la dernière ligne du bloc précédent, j'affecte J+1 à J, de manière à repartir sur la ligne suivante. De cette manière, dans le passage suivant de la boucle, la nouvelle plage de recherche, range(cells(I, 1), Fin), contiendra uniquement le reste de la colonne, après le dernier bloc de doublons trouvé et "nettoyé". Je m'avise d'ailleurs que ma variable "Col" ne sert pas à grand-chose dans la macro que je t'ai indiqué. Voici une meilleure version: Const Cell_Départ As String = "A1" dim Fin As range, I As long, J As long, Col As Integer dim ModeCalcul As long with application ModeCalcul = .Calculation .Calculation = xlCalculationManual .screenupdating = false end with Col = range(Cell_Départ).Column set Fin = range(Cell_Départ).end(xldown)(2) On Error Resume next do I = J + 1 J = range(cells(I, Col), Fin).ColumnDifferences(cells(I, Col))(0).Row if J > I then range(cells(I + 1, Col), cells(J, 1)).ClearContents loop Until Err application.Calculation = ModeCalcul Bien sûr que tout ça est un peu plus compliqué qu'une bête boucle parcourant des cellules une à une. Mais c'est beaucoup plus efficace. VBA dispose avec la propriété ColumnDifferences d'un moyen adapté et très rapide permettant d'identifier des blocs de cellules identiques. Il faut en profiter. Si tu fais un test avec une colonne de 10000 cellules comportant 8000 doublons, tu vas te rendre compte très vite de la différence entre les deux méthodes. > Je vois que tu as quitté Wanadoo. Free est-il mieux? Pour moi, oui, parce que c'est entièrement gratuit et que leur serveur de pages perso est nettement meilleur. Pour d'autres c'est moins bien à cause de l'instabilité des connexions, qui dépend apparemment du point d'accès. A priori, il vaut mieux être à proximité directe ou à l'intérieur d'une grande ville. Et voilà. Maintenant je file regarder "Microcosmos", dont j'ai déjà raté une grande partie. A + Laurent