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 =...

manu_tella

XLDnaute Junior
Hello,

dans cette proposition les paramètres se listent automatiquement?
A vrai dire pour illustrer mon problème, des "légumes" j'en ai 150 variétés et ils sont "variables" impossible de les lister directement dans le code.

je pensais passer par une boucle classique de gestion des erreurs du type:

VB:
With CreateObject("Adodb.Connection")
    .Open "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & ThisWorkbook.FullName & ";Extended Properties=""Excel 12.0;HDR=No;"""
    For i = 1 To UBound(tablo, 2) '-1
        On Error GoTo errorhandler ' on 
        With .Execute("SELECT " & tablo(1, i) & " AS Resulta;")
            If Not .EOF Then tablo(1, i) = Abs(.Fields("Resulta"))
            .Close
        End With
        On Error GoTo 0
    Next i
    .Close
End With
P = tablo
Application.ScreenUpdating = True
MsgBox P.Columns.Count & " colonnes traitées en " & Format(Timer - t, "0.00 \sec")
Exit Sub

errorhandler:
MsgBox ("une erreur est survenue")
tablo(1, i) = 0 ' on force la valeur a 0 sur cette référence
Resume Next ' on revient dans la boucle
End Sub

par contre le retour dans la boucle se fait après 4 affichage de la msgbox... j'ai essayé de faire de mettre le "on error goto 0" juste après la ligne "With .Execute("SELECT " & tablo(1, i) & " AS Resulta;")" mais dans ce cas j'ai une erreur du type: variable objet ou variable with non définie

manu
 

job75

XLDnaute Barbatruc
Perso je gérerais les erreurs ainsi :
VB:
Dim nerr&
With CreateObject("Adodb.Connection")
    .Open "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & ThisWorkbook.FullName & ";Extended Properties=""Excel 12.0;HDR=No;"""
    On Error Resume Next
    For i = 1 To UBound(tablo, 2) '-1
        With .Execute("SELECT " & tablo(1, i) & " AS Resulta;")
            If Err Then Err = 0: nerr = nerr + 1: tablo(1, i) = 0: GoTo 1
            If Not .EOF Then tablo(1, i) = Abs(.Fields("Resulta"))
            .Close
        End With
1   Next i
    .Close
End With
P = tablo
Application.ScreenUpdating = True
MsgBox P.Columns.Count & " colonnes traitées en " & Format(Timer - t, "0.00 \sec")
If nerr Then MsgBox "Il y a eu " & nerr & " erreur(s)..."
End Sub
 

dysorthographie

XLDnaute Accro
VB:
tablo = P.Columns(3).Resize(, 2) 'matrice, plus rapide
With CreateObject("Adodb.Connection")
    .Open "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & ThisWorkbook.FullName & ";Extended Properties=""Excel 12.0;HDR=No;"""
    For i = 1 To UBound(tablo) - 1
    On Error Resume Next
        With .Execute("SELECT " & tablo(i, 1) & " AS Resulta;")
            If Not Err Then
                If Not .EOF Then tablo(i, 2) = Abs(.Fields("Resulta"))
            Else
                txtError = txtError & Range("B3").Offset(i).Value & " en erreur!" & vbCrLf
                tablo(i, 2) = 0
            End If
            On Error GoTo 0
            .Close
        End With
    Next i
    .Close
End With
 

manu_tella

XLDnaute Junior
Re,

En effet, tellement plus simple que de sortir de la boucle pour y re-rentrer....
J'ai fais un mix de vos 2 propositions pour garder l'aspect msgbox et le compteur par contre, je ne sais pas pour quelle(s) raison(s), les IF posaient problèmes alors j'ai fait du select case et c'est au TOP....

Merci beaucoup pour tous vos conseils et toutes vos propositions.
C'est quelque chose que j'utilise chaque jour ... mais que vais-je faire de tout ce temps gagné????? 😁

manu
 

Discussions similaires

Réponses
49
Affichages
1 K

Statistiques des forums

Discussions
315 102
Messages
2 116 222
Membres
112 690
dernier inscrit
noureddinee