Je me suis affranchi dans cette nouvelle version de la dénomination des Cellules M et A
juste pour compliquer encore le bazar !
Sub creerTableaux()
Dim cel1 As Range, cel2 As Range, cel3 As Range, plage As Range, cel4 As Range
Dim dico As Object
Dim dicoTrie As Object
Set dico = CreateObject("Scripting.Dictionary")
Set dicoTrie = CreateObject("Scripting.Dictionary")
Set plage = Range("A1:A" & [A2].End(xlDown).Row)
' effacement des données de M - recherche de la fin de liste
Set cel1 = Rows(1).Find(What:="M", After:=Range("A1"), SearchDirection:=xlNext)
Set cel4 = Columns(cel1.Column).Find(What:="Fin de liste", After:=cel1, SearchDirection:=xlNext)
If Not cel4 Is Nothing Then Range(cel1.Offset(1, 0), cel4.Offset(0, cel1.End(xlToRight).Column - cel1.Column)).ClearContents
' effacement des données de A - recherche de la fin de liste
Set cel1 = Rows(1).Find(What:="A", After:=Range("A1"), SearchDirection:=xlNext)
Set cel4 = Columns(cel1.Column).Find(What:="Fin de liste", After:=cel1, SearchDirection:=xlNext)
If Not cel4 Is Nothing Then Range(cel1.Offset(1, 0), cel4.Offset(0, cel1.End(xlToRight).Column - cel1.Column)).ClearContents
For i = 3 To [A2].End(xlDown).Row
For j = 2 To [B1].End(xlToRight).Column
If Not dico.Exists(Cle) Then dico.Add Cells(i, j), 1
Next
Next
Tbl = dico.keys
QuickSort Tbl
For i = LBound(Tbl) To UBound(Tbl)
For j = 2 To [B1].End(xlToRight).Column
dicoTrie(Tbl(i)) = WorksheetFunction.Max(WorksheetFunction.CountIf(plage.Offset(0, j - 1), Tbl(i)), dicoTrie(Tbl(i)))
Next
Next i
For Each Cle In dicoTrie.keys
'Debug.Print Cle & " - " & dicoTrie(Cle)
Next
ici = 1
Set cel1 = Rows(1).Find(What:="M", After:=Range("A1"), SearchDirection:=xlNext)
For Each Cle In dicoTrie.keys
If UCase(Mid(Cle, 1, 1)) = "M" Then
cel1.Offset(ici, 0).Value = Mid(Cle, 2, Len(Cle) - 1)
ici = ici + dicoTrie(Cle) + 1
End If
Next
cel1.Offset(ici, 0).Value = "Fin de liste"
ici = 1
Set cel1 = Rows(1).Find(What:="A", After:=Range("A1"), SearchDirection:=xlNext)
For Each Cle In dicoTrie.keys
If UCase(Mid(Cle, 1, 1)) = "A" Then
cel1.Offset(ici, 0).Value = Mid(Cle, 2, Len(Cle) - 1)
ici = ici + dicoTrie(Cle) + 1
End If
Next
cel1.Offset(ici, 0).Value = "Fin de liste"
For i = 2 To [A2].End(xlDown).Row
For j = 2 To [B1].End(xlToRight).Column
Set cel1 = Rows(1).Find(What:=Mid(Cells(i, j), 1, 1), After:=Range("A1"), SearchDirection:=xlNext)
Set cel2 = Rows(1).Find(What:=Cells(1, j), After:=cel1, SearchDirection:=xlNext)
Set cel3 = Columns(cel1.Column).Find(What:=Mid(Cells(i, j), 2, Len(Cells(i, j)) - 1), After:=cel1, SearchDirection:=xlNext)
plus = 0
Do Until Cells(cel3.Row + plus, cel2.Column) = ""
plus = plus + 1
Loop
Cells(cel3.Row + plus, cel2.Column) = Cells(i, 1)
Next
Next
End Sub
Public Sub QuickSort(vArray As Variant, _
Optional ByVal inLow As Long = -1, _
Optional ByVal inHi As Long = -1)
Dim pivot As Variant
Dim tmpSwap As Variant
Dim tmpLow As Long
Dim tmpHi As Long
inLow = IIf(inLow = -1, LBound(vArray), inLow)
inHi = IIf(inHi = -1, UBound(vArray), inHi)
tmpLow = inLow
tmpHi = inHi
pivot = vArray((inLow + inHi) \ 2)
While (tmpLow <= tmpHi)
While (vArray(tmpLow) < pivot And tmpLow < inHi)
tmpLow = tmpLow + 1
Wend
While (pivot < vArray(tmpHi) And tmpHi > inLow)
tmpHi = tmpHi - 1
Wend
If (tmpLow <= tmpHi) Then
tmpSwap = vArray(tmpLow)
vArray(tmpLow) = vArray(tmpHi)
vArray(tmpHi) = tmpSwap
tmpLow = tmpLow + 1
tmpHi = tmpHi - 1
End If
Wend
If (inLow < tmpHi) Then QuickSort vArray, inLow, tmpHi
If (tmpLow < inHi) Then QuickSort vArray, tmpLow, inHi
End Sub
C'est avec une telle usina à gaz qu'on voit l'intérêt de PowerQuery proposé par Jean-Eric