Microsoft 365 Isoler, convertir et calculer une chaîne de caractères entre parenthèses

manu_tella

XLDnaute Junior
Bonjour à tous,

Suite à un coup de main non négligeable des membres je reviens vers vous pour compléter mon code car je fais face a un use-case que je n'arrive pas à gérer.
Je cherche à traiter une chaîne de caractères bien spécifiquement avec le traitement des opérations entre parenthèses en priorité.
Je ne peux malheureusement pas partager le fichier car les données sont confidentielles mais je vais tenter d’être le plus clair possible dans la demande.

Au départ j'ai variable string type :

APS = (Banane OR fraise) AND NOT (pomme OR Groseille)

avec une matrice qui fonctionne j'arrive a convertir mes fruits et mes légumes en un expression de type:

APS = (1 OR 0) AND NOT (0 OR 1)

et là ou je remplaçais les OR et les AND par des opérations mathématiques je me rends compte que le le cas du AND NOT pose problème, il me faudrait d'abord calculer ce qui est présent dans la parenthèse.
j'imaginais d'abord remplacer les OR et les AND par des + et des * sans tenir compte des AND NOT ou OR NOT
pour arriver à cette étape intermédiaire:
APS = (1 + 0) AND NOT (0 + 1)
APS = (1) AND NOT (1)

comment est-il possible de créer un calcul intermédiaire dans mon code pour arriver à cette étape ? je pensais passer par un split et en faisant une évaluation de chaque calcul entre parenthèse et ainsi à la fin, remplacer les chaines AND NOT (1) ou AND NOT (0) par * 0 et * 1?

d'avance merci pour votre aide

manu
 
Solution
mais la contrainte du "NOT" suivi d'une parenthèse n'est pas vraie dans tous les cas
Alors dans ce fichier (3) la macro ajoute les parenthèses après "NOT" quand il n'y en a pas :
VB:
Sub Calcul()
Dim P As Range, tablo, i&, txt$, s, j%, v As Variant
Set P = [A15].CurrentRegion.Resize(, 2)
With [A1].CurrentRegion.Resize(, 4)
    tablo = .Value 'matrice, plus rapide
    For i = 2 To UBound(tablo)
        txt = tablo(i, 2)
        s = Split(Replace(Replace(Replace(Replace(Replace(txt, "AND", ""), "OR", ""), "NOT", ""), "(", ""), ")", ""))
        For j = 0 To UBound(s)
            v = Application.VLookup(s(j), P, 2, 0)
            If Not IsError(v) Then txt = Replace(txt, s(j), IIf(LCase(v) = "x", 1, 0))
        Next j
        txt =...

sylvanu

XLDnaute Barbatruc
Supporter XLD
Bonjour manu_tella,
Difficile sans fichier test. Alors j'essaie :
Si la chaine PAS est constante de type texte : APS = (A + B) AND NOT (C + D)
Alors on peut extraire ABCD et le mettre sous forme décimale de type :
VB:
R = 8 * Val(Mid(APS, 2, 1)) + 4 * Val(Mid(APS, 7, 1)) + 2 * Val(Mid(APS, 19, 1)) + 1 * Val(Mid(APS, 24, 1))
Ensuite par un tableau de Karnaugh on voit que APS vaut 1 si l'expression en décimal vaut 4, 8 ou 12. On peut donc trouver le résultat APS par :
Code:
R Mod 4 = 0
D'où :
Code:
Sub essai()
    APS = "(1 Or 0) And Not (0 Or 1)"
    R = 8 * Val(Mid(APS, 2, 1)) + 4 * Val(Mid(APS, 7, 1)) + 2 * Val(Mid(APS, 19, 1)) + 1 * Val(Mid(APS, 24, 1))
    If R Mod 4 = 0 Then Result = 1 Else Result = 0
End Sub
Capillotracté, je le reconnais et l'assume. Il doit y avoir plus simple si on avait la structure initiale. :)
 

manu_tella

XLDnaute Junior
Bonjour à tous les 2,

merci pour vos réponses.
En effet c'est pas super simple a comprendre pourtant je suis sur que ce n'est que de la logique que je n'arrive pas à mettre en place.
Je mets en pièce jointe un petit fichier test qui montre les différentes étapes...

en colonne A ce sont des références à prendre en compte ou pas en fonction de la définition de la colonne B et de la matrice
en colonne C et D ce que j'arrive à faire avec un petit bout de code basé sur la fonction replace
et en F le produit de sorti auquel je dois aboutir (là je l'ai rempli à la main avec une petite justif en G) mais l'idée c'est bien que le OUI/NON soit automatiquement déduis de la chaîne de caractères de la colonne B

Voila j’espère que c'est plus clair..

manu
 

Pièces jointes

  • fichier_test.xlsx
    12.4 KB · Affichages: 5

manu_tella

XLDnaute Junior
Re,

Apres je vous oriente peut être sur une mauvaise piste, si il existe plus simple pour donner le résultat d'une chaîne de booléens composés de OR, AND, NOT, AND NOT ... c'est aussi bien, voir mieux.
Apres tout c'est peut être beaucoup plus facile que je ne l'imagine, c'est surement ce besoin que j’aurais du exprimer dès le début ;). C'est peut etre quelque chose de natif sous excel ... on peut rêver, on sait jamais.

d'avance merci pour votre aide

manu
 

manu_tella

XLDnaute Junior
Hello,

Je me répond et je simplifie le cas..
En fait parti dans le mouvement, je n'ai pas vu la simplicité dans mon problème.

Excel fait très bien des opérations du type:
VB:
dim result as string
Result = (0 Or 1) And Not (0 Or 1)

le problème c'est que moi après la transformation des chaines de caractères en 0 et en 1 j'ai une variable String Variant du type:
APS : "(0 OR 1) AND NOT (0 OR 1)" : Variant/String : Module06.project_filtering
quand je fais evaluate APS il me donne dans la fenêtre espion l'erreur 2015.

donc la solution à mon problème serait "juste" de pouvoir calculer la variable APS....
=> les étapes que je propose pour remplacer les AND, OR et NOT... est complètement inutile.

comment dois-je déclarer la variable APS pour qu'elle puisse etre calculée?

d'avance merci

manu
 

job75

XLDnaute Barbatruc
Bonjour manu_tella, Wayki, sylvanu, le forum,

Voyez le fichier joint et la macro du bouton :
VB:
Sub Calcul()
Dim P As Range, tablo, i&, txt$, s, j%, v As Variant
Set P = [A15].CurrentRegion.Resize(, 2)
With [A1].CurrentRegion.Resize(, 4)
    tablo = .Value 'matrice, plus rapide
    For i = 2 To UBound(tablo)
        txt = tablo(i, 2)
        s = Split(Replace(Replace(Replace(Replace(Replace(txt, "AND", ""), "OR", ""), "NOT", ""), "(", ""), ")", ""))
        For j = 0 To UBound(s)
            v = Application.VLookup(s(j), P, 2, 0)
            If Not IsError(v) Then txt = Replace(txt, s(j), IIf(LCase(v) = "x", 1, 0))
        Next j
        txt = Replace(Replace(Replace(txt, "AND", "*"), "OR", "+"), "NOT", "1 -")
        If txt Like "1 -*" Then txt = "(" & txt & ")" 'évite la conversion en date
        tablo(i, 3) = txt
        tablo(i, 4) = Evaluate(txt)
    Next i
    .Value = tablo
End With
End Sub
A+
 

Pièces jointes

  • fichier_test(1).xlsm
    20.7 KB · Affichages: 4

job75

XLDnaute Barbatruc
Je pense que le remplacement de "NOT" par "1 -" ne va pas bien.

Dans ce fichier (2) on ne touche pas à "NOT" mais il doit être suivi par un texte entre parenthèses :
VB:
Sub Calcul()
Dim P As Range, tablo, i&, txt$, s, j%, v As Variant
Set P = [A15].CurrentRegion.Resize(, 2)
With [A1].CurrentRegion.Resize(, 4)
    tablo = .Value 'matrice, plus rapide
    For i = 2 To UBound(tablo)
        txt = tablo(i, 2)
        s = Split(Replace(Replace(Replace(Replace(Replace(txt, "AND", ""), "OR", ""), "NOT", ""), "(", ""), ")", ""))
        For j = 0 To UBound(s)
            v = Application.VLookup(s(j), P, 2, 0)
            If Not IsError(v) Then txt = Replace(txt, s(j), IIf(LCase(v) = "x", 1, 0))
        Next j
        txt = Replace(Replace(Replace(txt, "AND", "*"), "OR", "+"), " ", "")
        tablo(i, 3) = txt
        tablo(i, 4) = Evaluate(txt)
    Next i
    .Value = tablo
End With
End Sub
 

Pièces jointes

  • fichier_test(2).xlsm
    20.6 KB · Affichages: 2

manu_tella

XLDnaute Junior
Hello @tous,

merci job75 pour ce morceau de code. Ça fonctionne plutôt bien mais la contrainte du "NOT" suivi d'une parenthèse n'est pas vraie dans tous les cas donc malheureusement ce n'est pas assez robuste.

J'ai de mon coté regardé plus précisément l’idée de faire calculer à excel directement l'expression après remplacement des critères par des 0 et des 1.

Pourquoi quand je lui fait calculer une variable avec une formule rentrée à la main dans le code ça fonctionne bien et pourquoi quand cette formule est issue d'une variable ça ne fonctionne plus?

Code:
'methode 1

                result_m1 = (0 Or 1) 'je rentre la formule directement dans VBA
                
'methode 2

                conversion_binaire_de_la_def= "0 OR 1" 'c'est la chaîne de caractères qui sort de ma première conversion (remplacer les équipements par des 0 et des 1

                result_m2= Evaluate(conversion_binaire_de_la_def)
                
'methode 3

               conversion_binaire_de_la_def= "0 OR 1" 'c'est la chaîne de caractères qui sort de ma première conversion (remplacer les équipements par des 0 et des 1

                result_m3 = val(conversion_binaire_de_la_def)

la méthode 1 donne: result_m1 = 1
la méthode 2 donne: result_m2 erreur 2015
la méthode 3 donne: result_m3 = 0 puisque le OR est vu comme du texte et la fonction Val n'est pas compatible avec autre chose que des chiffres à priori.

Je pense que je déclare mal quelque chose ou qu'il faut que je passe par une conversion quelconque mais je n'arrive pas à trouver la solution.

Encore merci pour votre aide.

manu
 

job75

XLDnaute Barbatruc
mais la contrainte du "NOT" suivi d'une parenthèse n'est pas vraie dans tous les cas
Alors dans ce fichier (3) la macro ajoute les parenthèses après "NOT" quand il n'y en a pas :
VB:
Sub Calcul()
Dim P As Range, tablo, i&, txt$, s, j%, v As Variant
Set P = [A15].CurrentRegion.Resize(, 2)
With [A1].CurrentRegion.Resize(, 4)
    tablo = .Value 'matrice, plus rapide
    For i = 2 To UBound(tablo)
        txt = tablo(i, 2)
        s = Split(Replace(Replace(Replace(Replace(Replace(txt, "AND", ""), "OR", ""), "NOT", ""), "(", ""), ")", ""))
        For j = 0 To UBound(s)
            v = Application.VLookup(s(j), P, 2, 0)
            If Not IsError(v) Then txt = Replace(txt, s(j), IIf(LCase(v) = "x", 1, 0))
        Next j
        txt = Replace(Replace(Replace(txt, "AND", "*"), "OR", "+"), " ", "")
        txt = Replace(Replace(txt, "NOT1", "NOT(1)"), "NOT0", "NOT(0)") 'ajoute les parenthèses s'il n'y en a pas
        tablo(i, 3) = txt
        tablo(i, 4) = Evaluate(txt)
    Next i
    .Value = tablo
End With
End Sub
 

Pièces jointes

  • fichier_test(3).xlsm
    20.7 KB · Affichages: 5

manu_tella

XLDnaute Junior
Hello,

Ca marche impec, merci.
rapide et efficace et plus le code est clair et je l'ai compris.

Par contre, pour ma culture perso quelqu'un peut-il me dire comment "évaluer" une chaîne de caractères quand elle est sous forme d'une variable: (0 OR 1) AND NOT (1 OR 0) AND 1

Excel doit bien savoir calculer ça puisque quand on rentre la formule à la main dans le code ça fonctionne.

manu
 

manu_tella

XLDnaute Junior
Bonjour,

j'ai fais ce petit test dans un fichier isolé:

j'ai mis dans la cellule A1 de la feuil 1 la formule suivante
(0 OR 1)
puis dans un module le bout de code suivant:

VB:
Option Explicit
Dim bin As String
Sub binary_evaluation()
bin = Sheets("feuil1").Cells(1, 1).Value
Evaluate (bin)
End Sub

J'ai mis un espion sur la evaluate(bin) et sa valeur est erreur 2015

manu
 

job75

XLDnaute Barbatruc
Bonjour manu_tella, le forum,

Vous êtes vraiment gonflé(e) de présenter une telle macro, elle est totalement incohérente !!!

S'il n'y a que des AND OR et NOT à convertir utilisez :
VB:
Sub Calcul()
Dim tablo, i&, txt$
With Sheets("Feuil1").[A1].CurrentRegion.Resize(, 3)
    tablo = .Value 'matrice, plus rapide
    For i = 1 To UBound(tablo)
        txt = tablo(i, 1)
        txt = Replace(Replace(Replace(txt, "AND", "*"), "OR", "+"), " ", "")
        txt = Replace(Replace(txt, "NOT1", "NOT(1)"), "NOT0", "NOT(0)") 'ajoute les parenthèses s'il n'y en a pas
        tablo(i, 2) = txt
        tablo(i, 3) = Evaluate(txt)
    Next i
    .Value = tablo
End With
End Sub
A+
 

manu_tella

XLDnaute Junior
Bonjour,

Merci pour la réponse et désolé si je vous ai offusqué en présentant ces quelques lignes ce n’était pas mon intention, je voulais juste illustrer par l'exemple ma question.
Votre code fonctionne, il m'a beaucoup aidé et je vous en remercie mais j’aurais également aimé comprendre pourquoi mon idée de faire calculer à excel la chaîne de caractères du type (1 OR 0) ne fonctionne pas voila tout.

Je vais continuer à chercher car je suis persuadé que cela peut fonctionner.

Encore merci pour votre aide.

cordialement,

manu
 

Discussions similaires

Statistiques des forums

Discussions
312 177
Messages
2 085 972
Membres
103 073
dernier inscrit
MSCHOE16