Fusion de ligne si doublon par macro

citizenbaban

XLDnaute Junior
Bonjour à tous,

J'ai un petit problème avec une macro. Voici l'idée :
Je voudrais fusionner des lignes de B à H, si et seulement si, des dates en colonne A sont identiques sur plusieurs lignes.
Par exemple :

12/03/13 50 60 "vide" 10
12/03/13 50 60 "vide" 10
12/03/13 "vide" "vide" 100 "vide"

Donnerait :
12/03/13 50 60 100 10


En me balladant ici et ailleurs, j'ai trouvé un code qui fonctionne bien pour ce que la personne recherchait, mais pour être honnête, je ne le comprend pas ^^ Du coup ça serait surtout pour avoir quelques explications sur ce code, à quel chiffre correspond les colonnes, les lignes, etc. Car même en tatonnant, je n'obtiens que des résultats bizarres ^^

Voici le code :
Code:
Sub Groupage()
Dim Col As Integer, Lg As Long, nLg As Byte, Nom As String
Application.ScreenUpdating = False
Nom = Cells(2, 2): Lg = 2
While Nom <> ""
  While Cells(Lg, 2).Offset(nLg, 0) = Nom
    nLg = nLg + 1
    For Col = 3 To 7
      If Cells(Lg, Col) = "" Then
        Cells(Lg, Col) = Cells(Lg, Col).Offset(nLg, 0)
      End If
    Next
  Wend
  Lg = Lg + nLg
  Nom = Cells(Lg, 2)
  nLg = 0
Wend
For Lg = Range("B" & Rows.Count).End(xlUp).Row To 2 Step -1
  If Application.WorksheetFunction.CountIf(Feuil1.Range("B:B"), Cells(Lg, 2).Value) > 1 Then
    Rows(Lg).EntireRow.Delete
  End If
Next
Application.ScreenUpdating = True
End Sub

Je ne sais plus ou je l'ai récupéré, donc si quelqu'un reconnait son code, désolé pour l'absence de référence :)

Merci beaucoup.
Citizen
 

job75

XLDnaute Barbatruc
Re : Fusion de ligne si doublon par macro

Bonjour citizenbaban, le fil,

Ma macro (1) du post #10 ne sera pas du tout rapide sur un grand tableau, en effet :

- Application.CountIf prend beaucoup de temps

- il faut traiter des tableaux VBA et non pas des plages.

Voici donc la macro qui va bien, elle utilise au mieux l'objet "Dictionary" :

Code:
Sub Regrouper()
Dim plage As Range, tablo, ncol%, d As Object, i&, t$(), j%
Set plage = Sheets("Données").UsedRange
If plage.Count = 1 Then Exit Sub 'sécurité
plage.Sort plage(1), xlAscending, Header:=xlYes 'tri avec en-têtes
tablo = plage.Resize(Application.Count(plage.Columns(1)) + 2).Value2
ncol = UBound(tablo, 2)
Set d = CreateObject("Scripting.Dictionary")
For i = 1 To UBound(tablo) - 1
  If Not d.exists(tablo(i, 1)) Then
    d(tablo(i, 1)) = ""
    ReDim t(1 To ncol) 'RAZ
  End If
  For j = 1 To ncol
    If tablo(i, j) <> "" Then t(j) = tablo(i, j)
  Next
  If Not d.exists(tablo(i + 1, 1)) Then d(tablo(i, 1)) = Join(t, Chr(1))
Next
'---restitution---
With Sheets("Résultats")
  .Cells.ClearContents
  .[A1].Resize(d.Count) = Application.Transpose(d.items)
  Application.DisplayAlerts = False
  .[A:A].TextToColumns .[A1], xlDelimited, Other:=True, OtherChar:=Chr(1)
  .Activate
End With
End Sub
Fichier (2).

A+
 

Pièces jointes

  • Regrouper(2).xls
    57.5 KB · Affichages: 62
  • Regrouper(2).xls
    57.5 KB · Affichages: 58
  • Regrouper(2).xls
    57.5 KB · Affichages: 54

citizenbaban

XLDnaute Junior
Re : Fusion de ligne si doublon par macro

Bonjour Job75, le fil

Comment dire...c'est beau :)
Ca marche tip-top et je pense avoir compris le code dans ses grands axes. (Le code de Thierry m'a aidé à bien comprendre 2-3 points un peu flous pour moi).
Je vais me plonger dedans pour le comprendre en détail maintenant, ça restera le meilleur moyen pour restituer, un jour, un peu de ce qui m'a été donné ici.

Merci à tous. Problème résolu (comme toujours ici :) )
Bonne journée à tous

Citizen
 

job75

XLDnaute Barbatruc
Re : Fusion de ligne si doublon par macro

Re citizenbaban,

Je suis content que ma macro vous convienne.

Pour info je l'ai testée avec le tableau recopié sur 60000 lignes (nouvelles dates sans doublon).

Sur Win XP - Excel 2003 elle s'exécute en 5,3 secondes.

A+
 

BOISGONTIER

XLDnaute Barbatruc
Repose en paix
Re : Fusion de ligne si doublon par macro

Bonjour,

La table Tbl() est indexée par le dictionnaire pour accéder plus rapidement aux lignes du tableau.

RegroupeIndex.gif

Code:
Sub Stat2DCumul()
  Set d1 = CreateObject("Scripting.Dictionary")
  Set f1 = Sheets("données")
  ncol = f1.[a1].CurrentRegion.Columns.Count
  Dim Tbl()
  ReDim Tbl(1 To 1000, 1 To ncol)
  ligT = 1
  MaxligT = ligT
  a = f1.[a1].CurrentRegion
  For ligne = 2 To UBound(a)
    crit = a(ligne, 1)
    If d1.exists(crit) Then ligT = d1(crit) Else d1(crit) = MaxligT: ligT = MaxligT: MaxligT = MaxligT + 1
    For col = 2 To ncol
      If a(ligne, col) <> "" Then Tbl(ligT, col - 1) = Tbl(ligT, col - 1) + Val(a(ligne, col))
    Next col
  Next ligne
  Set f2 = Sheets("résultats")
  f1.[a1].Resize(, ncol).Copy f2.[a1]
  f2.[a2].Resize(d1.Count, 1) = Application.Transpose(d1.keys)
  f2.[B2].Resize(d1.Count, ncol - 1) = Tbl
End Sub

JB
 

Pièces jointes

  • Copie de Regrouper(1).xls
    60.5 KB · Affichages: 67
  • RegroupeIndex.gif
    RegroupeIndex.gif
    8.4 KB · Affichages: 66
  • RegroupeIndex.gif
    RegroupeIndex.gif
    8.4 KB · Affichages: 62
  • RegroupeIndex.gif
    RegroupeIndex.gif
    8.4 KB · Affichages: 63
  • RegroupeIndex.gif
    RegroupeIndex.gif
    7.1 KB · Affichages: 80
  • RegroupeIndex.gif
    RegroupeIndex.gif
    7.1 KB · Affichages: 87
Dernière édition:

job75

XLDnaute Barbatruc
Re : Fusion de ligne si doublon par macro

Bonjour citizenbaban, JB, le fil,

J'ai voulu voir ce que ça donnait sans "Dictionary" :

Code:
Sub Regrouper()
Dim plage As Range, tablo, ncol%, t(), lig&, i&, dat, j%
Set plage = Sheets("Données").UsedRange
If plage.Count = 1 Then Exit Sub 'sécurité
plage.Sort plage(1), xlAscending, Header:=xlYes 'tri avec en-têtes
tablo = plage.Resize(Application.Count(plage.Columns(1)) + 2).Value2
ncol = UBound(tablo, 2)
ReDim t(1 To UBound(tablo), 1 To ncol)
lig = 1
For i = 1 To UBound(tablo) - 1
  dat = tablo(i, 1): t(lig, 1) = dat
  While tablo(i, 1) = dat
    For j = 2 To ncol
      If tablo(i, j) <> "" Then t(lig, j) = tablo(i, j)
    Next
    i = i + 1
  Wend
  lig = lig + 1
  i = i - 1
Next
'---restitution---
With Sheets("Résultats")
  .Cells.ClearContents
  .[A1].Resize(lig - 1, ncol) = t
  .Activate
End With
End Sub
Noter que Application.Transpose n'est plus utilisée.

Fichier (3).

Eh bien sur le tableau de 60000 lignes la durée d'exécution se réduit à 2,1 secondes.

Et la macro de JB s'exécute en 3,7 secondes.

Comme quoi "Dictionary" n'est pas forcément la panacé.

A+
 

Pièces jointes

  • Regrouper(3).xls
    56.5 KB · Affichages: 63

BOISGONTIER

XLDnaute Barbatruc
Repose en paix
Re : Fusion de ligne si doublon par macro

Bonjour,

Je faisais l'hypothèse que l'on ne touchait pas au tableau d'origine qui n'est pas nécessairement trié.
Le dictionnaire d1 indexe le tableau Tbl(,) permettant ainsi de retrouver rapidement la bonne ligne du tableau Tbl(,) pour effectuer le cumul.
Ce n'est pas Dictionary qui est en cause, mais la méthode utilisée.
Une recherche d'une clé dans un dictionnaire est 100 fois plus rapide qu'une recherche dans un tableau de taille importante.

JB
 
Dernière édition:

job75

XLDnaute Barbatruc
Re : Fusion de ligne si doublon par macro

Re JB,

Avec ma dernière macro rien n'empêche de copier le tableau d'origine dans la 2ème feuille et d'y faire le tri :

Code:
Sub Regrouper()
Dim plage As Range, tablo, ncol%, t(), lig&, i&, dat, j%
Set plage = Sheets("Données").UsedRange
If plage.Count = 1 Then Exit Sub 'sécurité
With Sheets("Résultats")
  .Cells.ClearContents
  plage.Copy .[A1]
  Set plage = .UsedRange
  plage.Sort plage(1), xlAscending, Header:=xlYes 'tri avec en-têtes
  tablo = plage.Resize(Application.Count(plage.Columns(1)) + 2).Value2
  ncol = UBound(tablo, 2)
  ReDim t(1 To UBound(tablo), 1 To ncol)
  lig = 1
  For i = 1 To UBound(tablo) - 1
    dat = tablo(i, 1): t(lig, 1) = dat
    While tablo(i, 1) = dat
      For j = 2 To ncol
        If tablo(i, j) <> "" Then t(lig, j) = tablo(i, j)
      Next
      i = i + 1
    Wend
    lig = lig + 1
    i = i - 1
  Next
  '---restitution---
  .Cells.ClearContents
  .[A1].Resize(lig - 1, ncol) = t
  .Activate
End With
End Sub
Sur 60000 lignes la durée d'exécution passe à 2,3 secondes.

A+
 
Dernière édition:

citizenbaban

XLDnaute Junior
Re : Fusion de ligne si doublon par macro

Bonjour à tous,

Désolé pour cette longue absence mais j'ai eu droit à un déplacement professionnel au dernier moment et j'ai été pas mal pris. J'ai bien intégré ta modif Job, c'est royal :)
J'ai un autre petit souci de mise en forme sur fichier mais pour un tout autre problème, je vais ouvrir un nouveau topic car je pense que ça pourra aider certaines personnes sur les problèmes de barres de seuil sur des graphiques :)

Bonne journée à tous et peut être a très vite sur le nouveau topic.

Citizen
 

nicogif

XLDnaute Nouveau
Re : Fusion de ligne si doublon par macro

Salut à tous,

J'ai lu avec attention tout ça car concerné par le meme soucis, toutes les réponses m'ont évidemment fortement intéressé mais mes limitations en VBA ont eu definitivement raison de moi.

Alors j'ai investigué le truc seul en me disant que les TCD pourraient m'aider...

Et j'ai trouver la solution ! Je suis en Excel 2010 PC Je partage avec ceux que ca intéresse mon fichier exemple ! La source est sur la feuille 1 le TCD sur la feuille 2

Après la solution devellopeur... Voici la solution Utilisateur, peut etre un poil plus accessible...
 

Pièces jointes

  • Classeur2.xlsx
    154 KB · Affichages: 41
  • Classeur2.xlsx
    154 KB · Affichages: 46
  • Classeur2.xlsx
    154 KB · Affichages: 39
Dernière édition:

Statistiques des forums

Discussions
312 493
Messages
2 088 956
Membres
103 990
dernier inscrit
lamiadebz