XL 2016 Fonction récursive pour eclater une string en sous string

vgendron

XLDnaute Barbatruc
Bonjour à toutes et tous

Me revoici avec un nouveau jeu à vous soumettre :-D

je souhaite eclater une chaine de caractères en sous chaines de caractères
la structure d'une chaine est toujours la suivante:
NOMVAR = OR(AND(OR(ele1,ele2),ele3)
avec plus ou moins d'opérateurs et donc d'ele.. (les opérateurs possibles sont: AND - OR - NOT)
les parenthèses sont toujours en nombre suffisant

de ce NOMVAR, je souhaite obtenir autant de NOMVAR_xx qu'il y a d'opérateurs moins 1...
ainsi : un NOMVAR_xx est constitué d'une formule élémentaire = UN opérateur et DEUX elements
"moins 1" parce que le NOMVAR devient NOMVAR avec une formule elementaire "ele3 or NOMVAR_xx"
chaque NOMVAR_xx doit etre placé dans un tableau avec sa formule élementaire associée...

je vous laisse regarder le fichier ci joint ainsi que le début de code. ce sera plus parlant

merci à vous
 

Pièces jointes

  • Eclater chaine.xlsm
    18.5 KB · Affichages: 14

sousou

XLDnaute Barbatruc
Bonsoir
Pour le fun, et tiré par les cheveux
Utilisation de instr et instrev ;)

Sub deb()
tour = 1
n = 1
With ActiveCell
phrase = .Value
k = InStr(1, phrase, "=")
valeur = Left(phrase, k - 1)
While n <> 0
n = InStr(1, phrase, ")")
If n = 0 Then Exit Sub
n1 = InStrRev(phrase, "(", n)
t = Mid(phrase, n1 + 1, n - n1 - 1)
n3 = InStrRev(phrase, "(", n1 - 1)
s = "_" & tour
If n3 = 0 Then n3 = InStrRev(phrase, "=", n - 1): s = ""
op = Mid(phrase, n3 + 1, n1 - n3 - 1)
v = valeur & "_" & s & op & "/" & t
Call ecriture(valeur & s, op, t)
'MsgBox v
phrase = Left(phrase, n3) & valeur & "_" & tour & Right(phrase, Len(phrase) - n)
tour = tour + 1
'MsgBox phrase
Wend
End With
End Sub

Sub ecriture(v, o, t)
n = InStr(1, t, ",")
e1 = Left(t, n - 1)
e2 = Right(t, Len(t) - n)
MsgBox v & " " & e1 & " " & o & " " & e2
End Sub
 

vgendron

XLDnaute Barbatruc
merci @sousou
suis pas sur que ce soit PLUS capillotracté que la solution que je viens de pondre et que je m'appretais à poster.. ici

je vais quand meme tester ta solution :-D
==> testé : Nickel merci

VB:
Public Type tyvariable
    nom As String
    formuleelem As String
End Type
Sub eclater()
Dim Chaine_init As String
Dim tablogene() As tyvariable
Dim tablo() As tyvariable

ReDim tablo(0)
ReDim tablogene(0)

With ActiveSheet
    Chaine_init = .Range("A9")
    Oldchaine = ""
    nomvar = Split(Chaine_init, "=")(0)
    formule = Split(Chaine_init, "=")(1)
   
    ReDim Preserve tablogene(UBound(tablogene) + 1)
    tablogene(UBound(tablogene)).nom = nomvar
    tablogene(UBound(tablogene)).formuleelem = formule
    ReDim Preserve tablo(UBound(tablo) + 1)
    i = 1

    .Range("G:J").ClearContents
    Chaine_init = Split(Chaine_init, "=")(1)
    While InStr(1, Chaine_init, "(") <> 0

        chainesousvar = Split(Chaine_init, ")")(0)
        tabope = Split(chainesousvar, "(") 'on split selon "("
        operateur = tabope(UBound(tabope) - 1) 'et on récupère l'opérateur
        chainesousvar = Split(chainesousvar, "(")(UBound(Split(chainesousvar, "("))) 'on ne garde que les deux éléments simpls
        Oldchaine = operateur & "(" & chainesousvar & ")" 'on reconstruit l'ancienne chaine qu'il va falloir substituer
        newform = Split(chainesousvar, ",")(0) & " " & operateur & " " & Split(chainesousvar, ",")(1) 'on créé la formule élémentaire associée à la SousVar
       
        ReDim Preserve tablo(UBound(tablo) + 1)
        tablo(UBound(tablo)).nom = nomvar & "_" & i
        tablo(UBound(tablo)).formuleelem = newform
        Chaine_init = Replace(Chaine_init, Oldchaine, tablo(UBound(tablo)).nom)
        i = i + 1
    Wend
    tablo(UBound(tablo)).nom = nomvar 'on remet le nom de la variable initiale
       
'on place le contenu des tablo pour visualisation
For i = LBound(tablogene) To UBound(tablogene)
    .Range("G" & .Rows.Count).End(xlUp).Offset(1, 0) = tablogene(i).nom
    .Range("H" & .Rows.Count).End(xlUp).Offset(1, 0) = tablogene(i).formuleelem
Next i

For i = LBound(tablo) To UBound(tablo)
    .Range("I" & .Rows.Count).End(xlUp).Offset(1, 0) = tablo(i).nom
    .Range("J" & .Rows.Count).End(xlUp).Offset(1, 0) = tablo(i).formuleelem
Next i

End With
End Sub
 
Dernière édition:

patricktoulon

XLDnaute Barbatruc
bonsoir
tu pourrais peut être commencer par la mettre en ordre non? tu y verrais plus clair
VB:
Sub test()
    var1$ = "OR(AND(OR(ele1,ele2),ele3),ele4)"
    MsgBox maisouetdoncornicar(var1)

    var2$ = "OR(AND(ele4,ele5),ele6)"
    MsgBox maisouetdoncornicar(var2)
End Sub
Function maisouetdoncornicar(var As String)
   Dim x&, matches
   With CreateObject("vbscript.regexp")
        .Global = True: .IgnoreCase = True
        .Pattern = "(OR|AND)"
        Set matches = .Execute(var)
        If matches.Count > 0 Then
            var = Replace(Replace(Replace(Replace(var, "(AND", ""), "(OR", ""), "OR", ""), "AND", "")
            For i = 0 To matches.Count - 1
                x = InStr(var, ",")
                var = Left(var, x - 1) & " " & matches(i) & " " & Mid(var, x + 1)
            Next
            maisouetdoncornicar = var
        End If
    End With
End Function
;)

et après ça couper la chaine obtenue par OR ou AND en partant de la fin
 
Dernière édition:

vgendron

XLDnaute Barbatruc
Salut @patricktoulon
merci pour cette solution d'un niveau plus avancé !!
je ne connais pas l'objet vbscript.regexp ==> je vais aller voir les méthodes associées: le matches/executes me plait bien
toutefois, dans ton exemple, le résultat pour la var2 n'est pas bon: les opérateurs sont inversés...
en cause le "pattern" ?? l'ordre serait important?
 

Membres actuellement en ligne

Aucun membre en ligne actuellement.

Statistiques des forums

Discussions
314 022
Messages
2 104 732
Membres
109 116
dernier inscrit
RALAIZANAKA