Toutes les séquences possibles à partir d'une liste d'enchaînements

chicoelmatador

XLDnaute Nouveau
Bonjour,

A partir d'une liste d'enchaînements (A => B, B => C, A => C, B => F, etc), j'essaie de reconstituer toutes les séquences possibles (ici : ABC, ABF et AC).
L'exemple ci-joint sera peut-être plus clair.

Est-ce réalisable par macro ???

D'avance merci,
Florent
 

Pièces jointes

  • Processus amont-aval.xlsm
    11.1 KB · Affichages: 59
Dernière édition:

chicoelmatador

XLDnaute Nouveau
Re : Toutes les séquences possibles à partir d'une liste d'enchaînements

Bonsoir,

J'ai pris mon courage à deux mains, ainsi que les forums excel downloads et la touche F1, et j'ai écrit une macro qui marche... mais elle tourne lentement !

Elle est forcément améliorable, mais le document allégé au maximum fait 100 Ko et ne passe pas sur le forum... y'a-t-il un moyen de le partager ?
 

KenDev

XLDnaute Impliqué
Re : Toutes les séquences possibles à partir d'une liste d'enchaînements

Bonjour chicoelmatador, CISCO,

Une solution possible, dans la configuration du classeur posté. Fichier joint.

Cordialement

KD

VB:
Option Explicit

Sub SeqAA()
Dim Rw As Long, Cpt(1 To 3) As Long, i As Long, b As Boolean, j As Long, Tda() As String, Tdb() As String
        'tableau Départ
    Rw = Cells(5, 2).End(xlDown).Row
    If Rw = Rows.Count Then Exit Sub
        'couples
    Cpt(1) = 1: ReDim Tda(1 To 2, 1 To Cpt(1)): Tda(1, 1) = Cells(6, 2): Tda(2, 1) = Cells(6, 3)
    For i = 7 To Rw
        Cpt(1) = Cpt(1) + 1: ReDim Preserve Tda(1 To 2, 1 To Cpt(1)): Tda(1, Cpt(1)) = Cells(i, 2): Tda(2, Cpt(1)) = Cells(i, 3)
    Next i
        'départs
    Cpt(2) = 0: ReDim Tdb(0 To 0)
    For i = 1 To Cpt(1)
        b = True
        For j = 1 To Cpt(1)
            If Tda(1, i) = Tda(2, j) Then b = False
        Next j
        If b = True Then
            For j = 1 To Cpt(2)
                If Tda(1, i) = Tdb(j) Then b = False
            Next j
            If b = True Then
                Cpt(2) = Cpt(2) + 1
                If Cpt(2) = 1 Then
                    ReDim Tdb(1 To 1)
                Else
                    ReDim Preserve Tdb(1 To Cpt(2))
                End If
                Tdb(Cpt(2)) = Tda(1, i)
            End If
        End If
    Next i
    If Cpt(2) = 0 Then Exit Sub
        'séquences
    For i = 1 To Cpt(1)
        Cpt(3) = Cpt(2)
        For j = 1 To Cpt(3)
            If Right(Tdb(j), 1) = Tda(1, i) Then
                Cpt(2) = Cpt(2) + 1: ReDim Preserve Tdb(1 To Cpt(2)): Tdb(Cpt(2)) = Tdb(j) & Tda(2, i)
            End If
        Next j
    Next i
        'écritures
    For i = 1 To Cpt(2)
        Cells(i + 5, 4) = Tdb(i)
    Next i
    
End Sub
 

Pièces jointes

  • SeqAA.xls
    36.5 KB · Affichages: 49

KenDev

XLDnaute Impliqué
Re : Toutes les séquences possibles à partir d'une liste d'enchaînements

Bonjour,

Une petite amélioration,

La version précédente liste tous les chemins (ex: AB, ABF, H, HK, HKB, HKBF), celle ci ne liste que les chemins complets (ABF, HKBF). Dans le code précédent remplacer
VB:
'écritures
   For i = 1 To Cpt(2)
        Cells(i + 5, 4) = Tdb(i)
    Next i
par
VB:
'séquences complètes
    ReDim Tda(1 To Cpt(2), 1 To 2)
    For i = 1 To Cpt(2)
        Tda(i, 1) = Tdb(i): Tda(i, 2) = Len(Tda(i, 1))
    Next i
    i = 1: Cpt(1) = 1
    Do While Cpt(1) < Cpt(2)
        For j = 1 To Cpt(2)
            If Tda(j, 2) = i Then
                Tdb(Cpt(1)) = Tda(j, 1): Cpt(1) = Cpt(1) + 1
            End If
        Next j
        i = i + 1
    Loop
    For i = 1 To Cpt(2)
        For j = i + 1 To Cpt(2)
            If Left(Tda(j, 1), Tda(i, 2)) = Tda(i, 1) Then Tda(i, 1) = ""
        Next j
    Next i
        'écritures
    Cpt(1) = 5
    For i = 1 To Cpt(2)
        If Tda(i, 1) <> "" Then
            Cpt(1) = Cpt(1) + 1:Cells(Cpt(1), 4) = Tda(i, 1)
        End If
    Next i
 

Pièces jointes

  • SeqAA2.zip
    11.8 KB · Affichages: 26

chicoelmatador

XLDnaute Nouveau
Re : Toutes les séquences possibles à partir d'une liste d'enchaînements

Merci beaucoup KenDev,

cependant je n'arrive pas à faire tourner votre macro avec mon tableau de données. Le problème est peut-être triple :
1- d'une part, les relations ne sont pas "classées", ce qui semble être pré-requis dans votre macro ;
2- les intitulés de mes items contiennent plusieurs mots en réalité (disons "Livrable alpha") ;
3- d'autre part, il existe des "boucles" A -> B -> A que je dois prendre en compte.

J'ai mis ma macro cro-magnon, qui fonctionne bien mais qui est très lente, sur ci-joint.fr : Cijoint.fr - Service gratuit de dépôt de fichiers

Une première macro génère les items de niveau 1 (ceux qui n'ont aucun antécédent), puis une 2e macro génère la liste des séquences.

C'est laaaaaargement améliorable, pouvez-vous y jeter un oeil ?

D'avance merci !
 

KenDev

XLDnaute Impliqué
Re : Toutes les séquences possibles à partir d'une liste d'enchaînements

Bonjour Chicoelmatador,

1 - Non ce n'était un prérequis. Cependant vos données ne semblaient pas particulièrement classées et j'ai obtenu toutes les séquences avec ma macro. En fait vos données exemples étaient piégées ! ;-) C'est quelque chose que j'aurai pu/du cependant prévoir. Avec les données du nouveau classseur fourni (après transformation sur 1 caractère), en effet, il y a une séquence à laquelle il manque une dernière étape.

2 - Cela aurait été gentil de le mentionner au 'cahier des charges', le nombre de mots importait peu en soit mais le fait tout simplement qu'il y ai plus d'1 caractère ET que les items n'avaient pas tous le même nombre de caractères m'aurait fait aborder le problème d'une autre façon.

3 - Encore une fois il eut été souhaitable que cela figure dans l'exemple initial. Toutefois un test sans rien toucher marchait dans ce cas.

Je n'ai pas regardé votre macro, désolé.

Par contre je vous propose une troisième version.
La limitation : elle impose que vos items aient un caractère interdit dont je me sers pour égaliser toutes les données au même nombre de caractères (il y a un certain nombre de left et right dans le code). J'ai pris le "!". Ce paramètre est modifiable puisque la macro est appellée avec trois paramètres, celui ci et la position de la case "Amont" par référence au 1er classeur.

Un détail, si on prends à la lettre 'toutes les séquences possibles' et qu'il y a des allers retours, c'est s'attendre à récupérer des séquences du type ABCDEDEDEDEDEDE etc.. Pour palier à ça, j'ai considérer que 3 caractères étaient significatifs, l'exemple précédent devra apparaitre comme ABCDED. En espérant que vous trouviez toutes vos séquences cette fois. Fichier Joint.

Cordialement

KD

VB:
Option Explicit
Sub AALaunch()
    Call SeqAA(1, 1, "!")
End Sub
Sub SeqAA(x&, y&, z$)
'entrées : coordonnées case 'Amont', caractère interdit données
Dim Tda$(), Tdb$(), Rw&, Cpt&(1 To 3), i&, j&, NbC%, k%, b As Boolean
    'plage
Rw = Cells(y, x).End(xlDown).Row: If Rw = Rows.Count Then Exit Sub
    'tableau couples
Cpt(1) = 1: ReDim Tda(1 To 2, 1 To Cpt(1)): Tda(1, 1) = Cells(y + 1, x): Tda(2, 1) = Cells(y + 1, x + 1)
For i = y + 2 To Rw
    Cpt(1) = Cpt(1) + 1: ReDim Preserve Tda(1 To 2, 1 To Cpt(1)): Tda(1, Cpt(1)) = Cells(i, x): Tda(2, Cpt(1)) = Cells(i, x + 1)
Next i
    'égalisation Len
NbC = 0
For k = 1 To 2
    For i = 1 To Cpt(1)
        If Len(Tda(k, i)) > NbC Then NbC = Len(Tda(k, i))
    Next i
Next k
For i = 1 To Cpt(1)
    For k = 1 To 2
        If Len(Tda(k, i)) < NbC Then
            For j = 1 To NbC - Len(Tda(k, i))
                Tda(k, i) = Tda(k, i) & z
            Next j
        End If
    Next k
Next i
    'départs
Cpt(2) = 0: ReDim Tdb(0 To 0)
For i = 1 To Cpt(1)
    b = True
    For j = 1 To Cpt(1)
        If Tda(1, i) = Tda(2, j) Then b = False
    Next j
    If b = True Then
        For j = 1 To Cpt(2)
            If Tda(1, i) = Tdb(j) Then b = False
        Next j
        If b = True Then
            Cpt(2) = Cpt(2) + 1
            If Cpt(2) = 1 Then
                ReDim Tdb(1 To 1)
            Else
                ReDim Preserve Tdb(1 To Cpt(2))
            End If
            Tdb(Cpt(2)) = Tda(1, i)
        End If
    End If
Next i
If Cpt(2) = 0 Then Exit Sub
    'toutes séquences
Do
For i = 1 To Cpt(1)
    Cpt(3) = Cpt(2)
    For j = 1 To Cpt(2)
        If Right(Tdb(j), NbC) = Tda(1, i) Then
            Cpt(2) = Cpt(2) + 1: ReDim Preserve Tdb(1 To Cpt(2))
            Tdb(Cpt(2)) = Tdb(j) & Tda(2, i)
            For k = 1 To Cpt(2) - 1
                If Tdb(Cpt(2)) = Tdb(k) Then
                    ReDim Preserve Tdb(1 To Cpt(2) - 1): Cpt(2) = Cpt(2) - 1: Exit For
                End If
            Next k
        End If
    Next j
Next i
Loop Until Cpt(2) = Cpt(3)
    'séquences abouties
ReDim Tda(1 To Cpt(2), 1 To 2)
For i = 1 To Cpt(2)
    Tda(i, 1) = Tdb(i): Tda(i, 2) = Len(Tda(i, 1))
Next i
i = 1: Cpt(1) = 1
Do While Cpt(1) < Cpt(2)
    For j = 1 To Cpt(2)
        If Tda(j, 2) = i Then
            Tdb(Cpt(1)) = Tda(j, 1): Cpt(1) = Cpt(1) + 1
        End If
    Next j
    i = i + 1
Loop
For i = 1 To Cpt(2)
    For j = i + 1 To Cpt(2)
        If Left(Tda(j, 1), Tda(i, 2)) = Tda(i, 1) Then Tda(i, 1) = ""
    Next j
Next i
    'réduction A/R significatifs
For i = 1 To Cpt(2)
    Cpt(3) = Len(Tda(i, 1)) / NbC
    If Cpt(3) <> 0 Then
        ReDim Tdb(1 To Cpt(3))
        For j = 1 To Cpt(3)
           Tdb(j) = Right(Left(Tda(i, 1), j * NbC), NbC)
        Next j
        For j = 4 To Cpt(3)
            If Tdb(j) = Tdb(j - 2) And Tdb(j - 1) = Tdb(j - 3) Then
                Tda(i, 1) = Left(Tda(i, 1), (j - 1) * NbC): Exit For
            End If
        Next j
    End If
Next i
    'nettoyage caractère interdit
For i = 1 To Cpt(2)
    For j = 3 To Len(Tda(i, 1))
        If Right(Left(Tda(i, 1), j), 1) = z Then
            Tda(i, 1) = Left(Tda(i, 1), j - 1) & Right(Tda(i, 1), Len(Tda(i, 1)) - j): j = j - 1
        End If
        If j > Len(Tda(i, 1)) - 1 Then Exit For
    Next j
Next i
 'écritures
Cpt(1) = y
For i = 1 To Cpt(2)
    If Tda(i, 1) <> "" Then Cpt(1) = Cpt(1) + 1: Cells(Cpt(1), x + 2) = Tda(i, 1)
Next i
End Sub
 

Pièces jointes

  • SeqAA3.xls
    41.5 KB · Affichages: 51

chicoelmatador

XLDnaute Nouveau
Re : Toutes les séquences possibles à partir d'une liste d'enchaînements

Merci beaucoup KenDev,

et 1000 excuses de n'avoir pas été plus clair au démarrage. N'étant pas grand connaisseur des macros, je n'ai pas pensé que c'étaient des contraintes structurantes.

J'essaie de faire tourner votre macro sur un cas "réel", elle fonctionne bien sauf dans certains cas que je n'ai pas encore réussi à identifier. Il est encore un peu lourd, je l'ai déposé ici :
Cijoint.fr - Service gratuit de dépôt de fichiers

salutations
 

KenDev

XLDnaute Impliqué
Re : Toutes les séquences possibles à partir d'une liste d'enchaînements

Bonjour chicoelmatador,

Un nouvel essai, je n'ai pas vérifier toutes les combinaisons avec les séquences exemples (puisque excel avait dépassé les 8000 séquences et en était toujours sur le premier départ...). S il en manque encore, lors du prochain jeu de données, précisez les séquences manquantes ou au moins quelques unes.

Les séquences circulaires sont maintenant en rouge et sont pris en compte les cycles genres (A-B, B-AC, AC-F, F-G, G-A). Clear All a donc été modifié en conséquences.

Il n'y a plus de caractères interdit (plus de left etc.). Je ne me suis pas occupé des séquences avec élément vide, à vous de contrôler vos données un minimum avant la macro ou de prévoir une moulinette, déjà le coup du B-B c'était pas mal. Je n'ai pas prévu non plus le cas ou l'ordinateur serait débranché pendant l'éxécution. Fichier joint.

Cordialement

KD

VB:
Option Explicit
Sub AALaunchd()
    Call SeqAAd(1, 3, 4, 2)
End Sub
Sub SeqAAd(x&, y&, r&, c&)
'entrées : coordonnées 1 ere cellule upstream, coordonnées 1ere cellule écriture séquences
Dim Tda(), Tdb(), Tdc(), Tdd(), RwT&, Cpt&(1 To 5), i&, j&, m&, n&, k%, Fl&, Dl&, ps&, a%, Rd%, Cc%, b As Boolean, oT As Worksheet, oS As Worksheet
Set oT = Worksheets("Tables"): Set oS = Worksheets("Sequences")
RwT = oT.Cells(y, x).End(xlDown).Row: If RwT = Rows.Count Then Exit Sub
    'individus
For i = y To RwT
    For j = 1 To 2
        If i * j = y Then
            Cpt(1) = 1: ReDim Tda(1 To 1): Tda(1) = oT.Cells(i, j)
        Else
            Cpt(1) = Cpt(1) + 1: ReDim Preserve Tda(1 To Cpt(1)): Tda(Cpt(1)) = oT.Cells(i, j)
        End If
        For k = 1 To Cpt(1) - 1
            If Tda(Cpt(1)) = Tda(k) Then
                Cpt(1) = Cpt(1) - 1: ReDim Preserve Tda(1 To Cpt(1)): Exit For
            End If
        Next k
    Next j
Next i
    'départs
For i = 1 To Cpt(1)
    If WorksheetFunction.CountIf(oT.Range(oT.Cells(y, 2), oT.Cells(RwT, 2)), Tda(i)) = 0 Then
        Cpt(2) = Cpt(2) + 1
        If Cpt(2) = 1 Then
            ReDim Tdb(1 To 1)
        Else
            ReDim Preserve Tdb(1 To Cpt(2))
        End If
        Tdb(Cpt(2)) = Tda(i)
    End If
Next i
If Cpt(2) = 0 Then Exit Sub
    'couples
For i = y To RwT
    Cpt(3) = Cpt(3) + 1
    If Cpt(3) = 1 Then
        ReDim Tdc(1 To 3, 1 To 1)
    Else
        ReDim Preserve Tdc(1 To 3, 1 To Cpt(3))
    End If
    Tdc(1, Cpt(3)) = oT.Cells(i, 1): Tdc(2, Cpt(3)) = oT.Cells(i, 2)
    For j = 1 To Cpt(3) - 1
        If Tdc(1, Cpt(3)) = Tdc(1, j) And Tdc(2, Cpt(3)) = Tdc(2, j) Then
            Cpt(3) = Cpt(3) - 1: ReDim Preserve Tdc(1 To 3, 1 To Cpt(3)): Exit For
        End If
        If Tdc(1, Cpt(3)) = Tdc(2, j) And Tdc(2, Cpt(3)) = Tdc(1, j) Then
            Cpt(3) = Cpt(3) - 1: ReDim Preserve Tdc(1 To 3, 1 To Cpt(3)): Tdc(3, j) = 1: Exit For
        End If
    Next j
Next i
For i = 1 To Cpt(3)
    If Tdc(3, i) = 1 Then
        Cpt(3) = Cpt(3) + 1: ReDim Preserve Tdc(1 To 3, 1 To Cpt(3))
        Tdc(1, Cpt(3)) = Tdc(2, i): Tdc(2, Cpt(3)) = Tdc(1, i): Tdc(3, Cpt(3)) = 1
    End If
Next i
    'séquences
Dl = r - 1: Fl = Dl + 1: oS.Cells(Fl, c) = Tdb(1)
For i = 1 To Cpt(2)
    If i > 1 Then Fl = Dl + 1
    oS.Cells(Fl, c) = Tdb(i)
    Do
        Dl = oS.Cells(Rows.Count, c).End(xlUp).Row: ReDim Tdd(1 To 4, Fl To Dl)
    For j = Fl To Dl
        k = c
        Do
            If oS.Cells(j, k) = "" Then Exit Do
            k = k + 1
        Loop
        Tdd(1, j) = oS.Cells(j, k - 1): Tdd(2, j) = k - 1
        If k - c >= 2 Then
            m = 1
            Do While m <= k - 1 - c
                Cc = 0
                For n = 1 To m
                    If k - n - m >= c Then
                        If oS.Cells(j, k - n) = oS.Cells(j, k - n - m) Then Cc = Cc + 1
                    Else
                        Exit For
                    End If
                Next n
                If Cc = m Then
                    Tdd(3, j) = True: oS.Range(oS.Cells(j, k - 2 * m), oS.Cells(j, k - 1)).Font.Color = 255: Exit Do
                End If
                m = m + 1
            Loop
        End If
        Tdd(4, j) = False
    Next j
    Cpt(4) = 0: Cpt(5) = 0
    For j = Fl To Dl
        For k = 1 To Cpt(3)
            If Tdd(3, j) = True Then Exit For
            If Tdc(1, k) = Tdd(1, j) Then
                If Tdd(4, j) = True Then
                    Cpt(4) = Cpt(4) + 1
                    For m = c To Tdd(2, j)
                        oS.Cells(Dl + Cpt(4), m) = oS.Cells(j, m)
                    Next m
                    oS.Cells(Dl + Cpt(4), m) = Tdc(2, k)
                Else
                    Cpt(5) = Cpt(5) + 1: oS.Cells(j, Tdd(2, j) + 1) = Tdc(2, k): Tdd(3, j) = False: Tdd(4, j) = True
                End If
            End If
        Next k
    Next j
    Loop Until Cpt(4) + Cpt(5) = 0
Next i
For i = r To oS.Cells(r, c).End(xlDown).Row
    Rd = 0: a = c
    Do
        If oS.Cells(i, a) = "" Then Exit Do
        If oS.Cells(i, a).Font.Color = 255 Then Rd = Rd + 1
        a = a + 1
    Loop
    If Rd > 0 Then
        oS.Range(oS.Cells(i, a - Rd / 2), oS.Cells(i, a - 1)).ClearContents
    End If
Next i
End Sub
 

Pièces jointes

  • SEQAA3D.xlsm
    39 KB · Affichages: 63

chicoelmatador

XLDnaute Nouveau
Re : Toutes les séquences possibles à partir d'une liste d'enchaînements

Merci beaucoup KenDev !

Après avoir testé et malmené le fichier, il fonctionne très bien. Il faut effectivement un contrôle manuel des données au préalable, mais c'est un passage utile entre la réalité parfois confuse et l'outil bien ficelé.

Je pense que cette macro pourrait aussi être utile à tous ceux qui font des plannings et de l'ordonnancement de tâches.

Encore merci,
Florent
 

Discussions similaires

Statistiques des forums

Discussions
314 626
Messages
2 111 294
Membres
111 093
dernier inscrit
Yvounet