Sub Macro1()
Dim D As Worksheet 'déclare la variable D (Onglet Détails)
Dim U As Worksheet 'déclare la variable U (Onglet User)
Dim N As Worksheet 'déclare la variable N (Onglet Norme)
Dim DL As Integer 'déclare la variable DL (Dernière Ligne)
Dim TV As Variant 'déclare la variable TV (Tableau des Valeurs)
Dim I As Integer 'déclare la variable I (Incrément)
Dim J As Integer 'déclare la variable J (incrément)
Dim R As Range 'déclare la variable R (Recherche)
Dim PL As Range 'déclare la variable PL (PLage)
Dim TL As Variant 'déclare la variable TL (Tableau de la Liste)
Dim CEL As Range 'déclare la variable CEL (CELlule)
Dim L As String 'déclare la variable L (Liste)
Application.ScreenUpdating = False 'masque les rafraîchissements d'écran
Set D = Worksheets("Détails") 'définit l'onglet D
DL = D.Cells(Application.Rows.Count, "A").End(xlUp).Row 'définit la dernière ligne éditée DL de la colonne A de l'onglet D
For I = DL To 2 Step -1 'boucle inversée sur toutes les lignes I de DL à 2
If D.Cells(I, "A").Value <> "" Then Rows(I).Insert Shift:=xlDown 'si la cellule en colonne A est vide ajoute une ligne au-dessous
Next I 'prochaine ligne de la boucle
Set U = Worksheets("User") 'définit l'onglet U
Set N = Worksheets("Norme") 'définit l'onglet N
TV = U.Range("A1").CurrentRegion 'définit le tableau des valeurs TV
For I = 2 To UBound(TV, 1) 'boucle 1 : sur toutes les lignes du tableau des valeurs TV (en partant de la seconde)
Set R = N.Rows(1).Find(TV(I, 2)) 'définit la recherche R (recherche le profil de la boucle dans la première ligne de l'onglet N)
'si il existe au moins une occurrence trouvée, définit le tableau de la liste TL (= la liste de la norme trouvée)
If Not R Is Nothing Then TL = Application.Transpose(Range(R.Offset(1, 0), N.Cells(Application.Rows.Count, R.Column).End(xlUp)))
Set R = Nothing 'vide la variable R
Set R = D.Columns(1).Find(TV(I, 1)) 'définit la recherche R (recherche le nom de la boucle danws la colonne 1 (=A) de l'onglet D
If Not R Is Nothing Then Set PL = R.CurrentRegion 'définit la plage PL
Set PL = PL.Offset(0, 1).Resize(, 1) 'redéfinit la plage PL (uniquement la colonne B)
For J = 1 To UBound(TL) 'boucle 2 : sur toutes les données du tableau de la liste TL
For Each CEL In PL 'boucle 3 : sur toutes les cellules CEL de la plage PL
If TL(J) = CEL.Value Then GoTo suite: 'si la donnée correspond à la valeur de la cellule CEL, va à l'étiquette "suite"
Next CEL 'procheiane cellule de la boucle 3
L = IIf(L = "", TL(J), L & ", " & TL(J)) 'définit la liste L
suite: 'étiquette
Next J 'prochaine donnée de la boucle 2
U.Cells(I, "C").Value = IIf(L <> "", L, "Complet") 'renvoie la liste L dans la cellule ligne I colonne C
Set R = Nothing: Erase TL: L = "" 'vide la variable R, efface le tableau TL, vide la liste L
Next I 'prochaijne ligne de la boucle 1
DL = D.Cells(Application.Rows.Count, "A").End(xlUp).Row 'définit la dernière ligne éditée DL de la colonne A de l'onglet D
For I = DL To 2 Step -1 'boucle inversée sur toutes les lignes I de DL à 2
If D.Cells(I, "B").Value = "" Then Rows(I).Delete 'si la cellule en colonne B est vide, supprime la ligne
Next I 'prochaine ligne de la boucle
Application.ScreenUpdating = True 'affiche les rafraîchissements d'écran
End Sub