Regroupement de doublons dans un tableau
Bonjour,
J'ai un fichier regroupant des organes (rouleau, moteur, tambour etc...) ainsi que leur caractéristiques et leur quantité en fonction de l'équipement auxquels ils appartiennent. Il arrive que certains organes soit communs à plusieurs équipement et je souhaiterai pouvoir regrouper tous les organes ayant les même caractéristiques pour connaître le nombre total. Il faudrait donc que la colonne quantité soit additionné avant le regroupement en une seule ligne.
Seuls les colonnes de caractéristiques seraient à prendre en compte pour savoir si les organes sont identiques et donc à grouper.
Le fichier réel comporte plus de caractéristiques que celles présentes pour l'exemple.
Je tire déjà cette liste à travers un code vba qui copie tout dans ce format de tableau-ci, et j'aimerai ajouter à ce code le regroupement des doublons.
J'espère que vous pourrez m'aider.
Bonne journée
Il y a deux tableaux ou un seul?
Bonjour,
Une proposition Power Query, (Recherchercher et transformer des données), intégré à ta version Excel.
Cdlt.
Bonjour,
Merci de votre rapidité
Non il n'y a qu'un seul tableau, celui de gauche.
Celui de droite est un modèle de ce que je souhaiterai avoir, les couleurs ne servent seulement à montrer les regroupements pour une meilleure compréhension.
Je ne connaissais pas le système power query, il semble répondre à mes attentes, mais je souhaiterai avoir un code vba, car le fichier étant destiné à être utiliser par de nombreuses personnes n'ayant pas forcément de grandes connaissances sur excel. Je souhaiterai donc combiner cette fonction avec celle qui me permet d'extraire ma liste d'organe. Et n'avoir qu'un seul bouton pour les deux fonctions.
J'ai trouvé une solution qui utilise la fonction des dictionnaires.
Pour ceux que ça intéresse je mets le code final :
Dim mondico(6)
Dim i As Integer
Dim j As Integer
Application.ScreenUpdating = True
Set f1 = Sheets("Feuil10")
a = f1.Range("A1").CurrentRegion.Value
f1.Range("P1").CurrentRegion.Clear
For i = 1 To 6
Set mondico(i) = CreateObject("Scripting.Dictionary")
Next
For i = 1 To 6
mondico(i).RemoveAll
Next
For i = 2 To UBound(a)
temp = a(i, 4) & " / " & a(i, 5) & " / " & a(i, 6) & " / " & a(i, 7) & " / " & a(i, 3)
mondico(1)(temp) = mondico(1)(temp) + a(i, UBound(a, 2))
For j = 2 To 6
mondico(j)(temp) = a(i, j + 1)
Next
Next
For x = 2 To 6
f1.Cells(1, x + 14).Resize(mondico(1).Count) = Application.Transpose(mondico(x).items)
Next
f1.[U1].Resize(mondico(1).Count) = Application.Transpose(mondico(1).items)Bonjour à tous,
Bonjour Mending
Comme les dictionnaires ont l'air de vous intéresser, essayez ceci :
Option Explicit
Sub test()
Dim a, w(), i As Long, txt As String, e, n As Long, dico As Object
Application.ScreenUpdating = False
Set dico = CreateObject("Scripting.Dictionary")
dico.CompareMode = 1
a = Sheets("Exemple").Cells(1).CurrentRegion.Value
For i = 2 To UBound(a, 1)
If Not dico.exists(a(i, 3)) Then
Set dico(a(i, 3)) = CreateObject("Scripting.Dictionary")
dico(a(i, 3)).CompareMode = 1
End If
txt = Join$(Array(a(i, 4), a(i, 5), a(i, 6), a(i, 7)), "|")
If Not dico(a(i, 3)).exists(txt) Then
dico(a(i, 3))(txt) = VBA.Array(a(i, 1), a(i, 2), a(i, 3), a(i, 4), a(i, 5), a(i, 6), a(i, 7), a(i, 8))
Else
w = dico(a(i, 3))(txt)
If InStr(w(0), a(i, 1)) = 0 Then w(0) = w(0) & "|" & a(i, 1)
If InStr(w(1), a(i, 2)) = 0 Then w(1) = w(1) & "|" & a(i, 2)
w(7) = w(7) + a(i, 8)
dico(a(i, 3))(txt) = w
End If
Next
With Sheets.Add
With .Cells(1).Resize(, 8)
.Value = Array(a(1, 1), a(1, 2), a(1, 3), a(1, 4), "", "", "", a(1, 8))
.HorizontalAlignment = xlCenter
.BorderAround Weight:=xlThin
.Interior.Color = 4697456
With .Cells(4).Resize(, 4)
.HorizontalAlignment = xlCenterAcrossSelection
.Interior.Color = 9359529
End With
End With
n = 2
For Each e In dico.keys
With .Cells(n, 1).Resize(dico(e).Count, UBound(Application.Index(dico(e).Items, 0, 0), 2))
.Value = Application.Index(dico(e).Items, 0, 0)
.BorderAround Weight:=xlThin
End With
n = n + dico.Item(e).Count
Next
With .Cells(1).CurrentRegion
.Borders(xlInsideVertical).Weight = xlThin
.VerticalAlignment = xlCenter
.Columns.AutoFit
End With
End With
Set dico = Nothing
Application.ScreenUpdating = True
End Subklin89
Re Mending,
Essayez plutôt ceci :
Option Explicit
Sub test()
Dim a, w(), i As Long, txt As String, e, s, n As Long, dico As Object
Application.ScreenUpdating = False
Set dico = CreateObject("Scripting.Dictionary")
dico.CompareMode = 1
a = Sheets("Exemple").Cells(1).CurrentRegion.Value
For i = 2 To UBound(a, 1)
If Not dico.exists(a(i, 3)) Then
Set dico(a(i, 3)) = CreateObject("Scripting.Dictionary")
dico(a(i, 3)).CompareMode = 1
End If
txt = Join$(Array(a(i, 4), a(i, 5), a(i, 6), a(i, 7)), "|")
If Not dico(a(i, 3)).exists(txt) Then
ReDim w(1 To 3)
Set w(1) = CreateObject("Scripting.Dictionary")
w(1).CompareMode = 1
Set w(2) = CreateObject("Scripting.Dictionary")
w(2).CompareMode = 1
w(3) = VBA.Array(Empty, Empty, a(i, 3), a(i, 4), a(i, 5), a(i, 6), a(i, 7), 0)
dico(a(i, 3))(txt) = w
End If
w = dico(a(i, 3))(txt)
If Not w(1).exists(a(i, 1)) Then
w(1)(a(i, 1)) = Empty
w(3)(0) = w(3)(0) & IIf(w(3)(0) <> "", "|", "") & a(i, 1)
End If
If Not w(2).exists(a(i, 2)) Then
w(2)(a(i, 2)) = Empty
w(3)(1) = w(3)(1) & IIf(w(3)(1) <> "", "|", "") & a(i, 2)
End If
w(3)(7) = w(3)(7) + a(i, 8)
dico(a(i, 3))(txt) = w
Next
With Sheets.Add
With .Cells(1).Resize(, 8)
.Value = Application.Index(a, 1, 0)
End With
n = 2
For Each e In dico.keys
For Each s In dico(e).keys
With .Cells(n, 1).Resize(1, UBound(dico(e)(s)(3), 1) + 1)
.Value = dico(e)(s)(3)
End With
n = n + 1
Next
With .Cells(n, 1).Resize(1, UBound(a, 2))
.Borders(xlEdgeTop).Weight = xlThin
End With
Next
With .Cells(1).CurrentRegion
.BorderAround Weight:=xlThin
.Borders(xlInsideVertical).Weight = xlThin
.VerticalAlignment = xlCenter
With .Rows(1)
.HorizontalAlignment = xlCenter
.BorderAround Weight:=xlThin
.Interior.Color = 44522
With .Cells(4).Resize(, 4)
.HorizontalAlignment = xlCenterAcrossSelection
.Interior.Color = 6740479
End With
End With
.Columns.AutoFit
End With
End With
Set dico = Nothing
Application.ScreenUpdating = True
End Subklin89
Bonjour et merci pour ton aide,
Ton code fonctionne parfaitement, mieux que le mien vu qu'il répond à tous mes problèmes. J'ai pas encore tout compris de son fonctionnement.
J'ai quelques petites questions par rapport aux boucles:
1) Suivant l'organe que je choisi, il y a plus ou moins de colonnes, cela va de 3-4 au mini à 8-9 pour les plus grandes. Serait-il possible de boucler suivant le nombre de colonne ? Ou faut-il copié collé le code pour l'adapter à chaque cas?
2) Lors de la création de la feuille je souhaiterai la nommer d'une certaine façon et ne pas la créer si elle existe.
Set f1 = Sheets("Feuille transition inventaire")
critère = f1.Range("aa1")
Feuille_Existe = False
For Each Feuille In Worksheets
If Feuille.Name = critère & " INV" Then
Feuille_Existe = True
End If
Next Feuille
If Feuille_Existe = False Then
Sheets.Add(After:=f1).Name = critère & " INV" 'cette méthode fonctionne
End IfCeci est un code que j'avais testé pour ce problème, il fonctionne mais je ne sais pas si je pourrais le rajouter à ton code juste avant la création de la feuille. Cela me permettrait de ne pas créer une nouvelle feuille à chaque fois.
3) Est ce que tu pourrais rajouter des commentaires sur à quoi servent les boucles ( pas forcément pour chaque ligne mais l'idée générale plutôt) si ce n'est pas trop te demander?
En tout cas merci beaucoup pour ton aide
Bonne semaine
Re Mending,
Le code réajusté :
Option Explicit
Sub test()
Dim a, w(), x(), i As Long, j As Byte, n As Long, txt As String, e, s, dico As Object
Application.ScreenUpdating = False
Set dico = CreateObject("Scripting.Dictionary")
dico.CompareMode = 1
a = Sheets("Exemple").Cells(1).CurrentRegion.Value
For i = 2 To UBound(a, 1)
If Not dico.exists(a(i, 3)) Then
Set dico(a(i, 3)) = CreateObject("Scripting.Dictionary")
dico(a(i, 3)).CompareMode = 1
End If
txt = ""
For j = 4 To UBound(a, 2) - 1
txt = txt & a(i, j) & "|"
Next
txt = Left(txt, Len(txt) - 1)
If Not dico(a(i, 3)).exists(txt) Then
ReDim w(1 To 3): ReDim x(1 To UBound(a, 2) + 1)
Set w(1) = CreateObject("Scripting.Dictionary")
w(1).CompareMode = 1
Set w(2) = CreateObject("Scripting.Dictionary")
w(2).CompareMode = 1
For j = 3 To UBound(a, 2) - 1
x(j) = a(i, j)
Next
w(3) = x
dico(a(i, 3))(txt) = w
End If
w = dico(a(i, 3))(txt)
If Not w(1).exists(a(i, 1)) Then
w(1)(a(i, 1)) = Empty
w(3)(1) = w(3)(1) & IIf(w(3)(1) <> "", "|", "") & a(i, 1)
End If
If Not w(2).exists(a(i, 2)) Then
w(2)(a(i, 2)) = Empty
w(3)(2) = w(3)(2) & IIf(w(3)(2) <> "", "|", "") & a(i, 2)
End If
w(3)(UBound(w(3)) - 1) = w(3)(UBound(w(3)) - 1) + a(i, UBound(a, 2))
w(3)(UBound(w(3))) = w(3)(UBound(w(3))) & IIf(w(3)(UBound(w(3))) <> "", "|", "") & i
dico(a(i, 3))(txt) = w
Next
On Error Resume Next
Application.DisplayAlerts = False
Sheets("restitution").Delete
Sheets.Add().Name = "restitution"
On Error GoTo 0
With Sheets("restitution")
With .Cells(1).Resize(, UBound(a, 2) + 1)
.Value = Application.Index(a, 1, 0)
.Cells(.Cells.Count).Value = "Fusion"
End With
n = 2
For Each e In dico.keys
For Each s In dico(e).keys
With .Cells(n, 1).Resize(1, UBound(dico(e)(s)(3), 1))
.Value = dico(e)(s)(3)
End With
n = n + 1
Next
With .Cells(n, 1).Resize(1, UBound(a, 2) + 1)
.Borders(xlEdgeTop).Weight = xlThin
End With
Next
With .Cells(1).CurrentRegion
.BorderAround Weight:=xlThin
.Borders(xlInsideVertical).Weight = xlThin
.VerticalAlignment = xlCenter
With .Rows(1)
.HorizontalAlignment = xlCenter
.BorderAround Weight:=xlThin
.Interior.Color = 44522
With .Cells(4).Resize(, UBound(a, 2) - 4)
.HorizontalAlignment = xlCenterAcrossSelection
.Interior.Color = 6740479
End With
End With
With .Columns(.Columns.Count)
.NumberFormat = "@"
.HorizontalAlignment = xlCenter
End With
.Columns.AutoFit
End With
End With
Set dico = Nothing
Application.ScreenUpdating = True
End Subklin89