Microsoft 365 InStr, c'est bien, mais trop court ! !

DenisHen

XLDnaute Nouveau
Bonjour à la communauté...
Voilà, j'ai un tableau avec des string construit comme :
VB:
Tableau(1)="4/12/4"
Tableau(....)="..."
Tableau(6)="4/18/4"
Tableau(....)="..."
Tableau(33)="44.2/16/44.2"
Tableau(44)="44.2/16/4"
Je cherche donc avec un Do While dans mon tableau, du début à la fin, jusq'à trouvé un InStr <> 0, puis je sors.
Mon problème est que si je cherche "44.2/16/4", InStr le trouve en premier dans "44.2/16/44.2" : Tableau(33), alors que j'aimerais le trouver dans Tableau(44).
Ce qui est normal, mais j'aimerais trouver l'exacte chaine, de la bonne longueur. D'où mon sujet, c'est trop court, ou trop long ! !
J'avais pensé à un Mid, mais je n'y arrive pas...
Il faut savoir aussi que la chaine recherchée sera TOUJOURS de la bonne longueur, et je dois trouver l'exacte réplique, bref, les deux chaines doivent être de la même taille...
Et oui, je parle bien ici de double vitrage... ;)
Si quelqu'un a une astuce, un conseil, voir même la solution... Je suis preneur...
Bien à toi la communauté.
Denis...
 
Dernière édition:

DenisHen

XLDnaute Nouveau
Salut @jurassic pork et @TooFatBoy et merci pour votre réponse.
Alors comment faire, du coup ? Ben j'ai fini par trouver, grace à vous...
J'ai donc placer ça en début de macro :
VB:
  TextSrc = Replace(CalTxt.Value, ",", ".") 'Car avec Excel, le "point" du pavé numérique peu être une virgule
  TextSrc = Replace(TextSrc, " /", "/")
  TextSrc = Replace(TextSrc, "/ ", "/")
  TextSrc = Replace(TextSrc, "( ", " ")
  TextSrc = Replace(TextSrc, " )", " ")
  TextSrc = Replace(TextSrc, "(", " ")
  TextSrc = Replace(TextSrc, ")", " ")
Et ça à l'air de fonctionner...
Pour l'instant, mais mes collègues vont trouver des trésors pour flinguer cette macro...
Encore un SUPER grand merci à vous ! ! !
Denis...
 

patricktoulon

XLDnaute Barbatruc
re
bonjour(juste en passant)
à mon avis faudra pas qu'il aillent chercher très loin pour pétarder ta macro
je pense que tu devrais d'abords decider de ce que tu recherche
  1. l'exact(=)
  2. contenue dans (instr ou like avec condition et replacement eventuels et les éventuels jokers)
ces 2 besoins vont forcement modifier la méthodes

si je reprends ton exemple de départ
Tableau(33)="44.2/16/44.2"
Tableau(44)="44.2/16/4"
la seule méthode qui pourrait te donner le 44 c'est la méthode = (exacte)
avec les autres méthodes tu aura certainement des ratés

faut pas attendre d'excel qui puisse deviner tes intentions

exemple de problème dans ta conception
tu dis faire des replaces
exemple avec les parenthèses
TextSrc = Replace(TextSrc, "( ", " ")
TextSrc = Replace(TextSrc, " )", " ")
et bien le like "*" & chaine recherchée &"*" te donnera forcement le premier
et voilà tu peux donc éliminer l'utilisation de like de même que "Instr " d'ailleurs

voilà simplement en t'expliquant je viens de pétarder ta macro ,sans même avoir écrit une ligne de code

je pense que je n'ai pas besoins de t'en dire plus pour que tu te rende compte que ton problème n'est pas une méthode ou une autre mais bel et bien ta conception(dans ta tête )sur comment traiter ce besoins
 

TooFatBoy

XLDnaute Barbatruc
If ContientMot(TextSrc, Worksheets("Prix").Cells(Lign, 12).Value) Then
Est-ce que tu n'aurais pas inversé les deux paramètres ??? 🤔

Je peux te proposer ceci :
VB:
Function ChercheVitrage(CalTxt As Range)
'
    ChercheVitrage = 0

    TextSrc = Replace(CalTxt.Value, ",", ".")   ' Car avec Excel, le "point" du pavé numérique peut être une virgule
    TextSrc = Replace(TextSrc, " ", "")         ' Car des collègues saisissent parfois "44.2 / 16 / 44.2"

    Lign = 3
    Do While Worksheets("Prix").Cells(Lign, 2).Value <> ""                      ' Feuille contenant les prix des vitrages
        If ContientMot(TextSrc, Worksheets("Prix").Cells(Lign, 2).Value) Then   ' Colonne 2 contient le libellé du vitrage
            ChercheVitrage = Val(Worksheets("Prix").Cells(Lign, 3).Value)       ' Colonne 3 contient le prix de ce vitrage
            Exit Function
        End If
        Lign = Lign + 1
    Loop

End Function

Function ContientMot(ByVal Mot As String, ByVal Phrase As String) As Boolean
' Recherche Mot dans Phrase

    ContientMot = " " & Phrase & " " Like "* " & Mot & " *"

End Function


Enfin, tant qu'on n'aura que des bouts de macros et pas de CAR (Classeur Anonymisé Représentatif), on continuera de piloter dans le noir et sans phares...
 
Dernière édition:

DenisHen

XLDnaute Nouveau
Bonjour à la communauté.
@patricktoulon : j'ai bien compris, mais pas mes collègues, qui pensent encore qu'ils ont le droit de faire absolument ce qu'ils veulent, car maintenant, il existe l'IA ! ! Oui, je sais, mais que veux-tu, c'est le coté obscure des macros, elle réfléchissent à ta place, ils pensent ne plus devoir penser, c'est très dommage...
@TooFatBoy : je n'avais pas pigé l'importance du CAR (que je ne connaissais pas d'ailleurs), je ne suis qu'un apprenti de 50 balais ;).
Donc, le voici.
Après avoir rencontrer des tonnes de problèmes avec la séparation du code (.xlam) et du classeur (.xlsx) à la place d'un classeur unique (.xlsm), et j'en rencontre encore (confidentialité, sécurité...), j'ai finalement opter pour cette combinaison, car parfois, on nous demande de livrer les fichier Excel, et le .xlam me donne cette option sans trop de difficulté, et en plus, grace au .xlam, je peux reprendre un ancien fichier .xlsx avec l'évolution du dernier .xlam.
Je ne sais toujours pas si mon choix est judicieux d'ailleur...
J'au une macro qui exporte le classeur Excel et qui supprime les toutes formules, donc qui ne laisse que les prix "de vente", sans les prix d'origine et sans les marges.
Maintenant que vous connaissez les coulisses, je suis ouvert à toutes propositions.
Denis, l'Ami gnorant...
 

Pièces jointes

  • ACR_Metal.xlam
    260.1 KB · Affichages: 6
  • Pour Excel-DownLoads.xlsx
    83.1 KB · Affichages: 10

patricktoulon

XLDnaute Barbatruc
re
bonnet blanc blanc bonnet(like vs instr)
VB:
Function ContientMot(ByVal Mot As String, ByVal Phrase As String) As Boolean
    ' Recherche Mot dans Phrase

    'méthode like
    'ContientMot = " " & Phrase & " " Like "* " & Mot & " *"
   
    'méthode instr
    ContientMot = InStr("_" & Phrase & "_", "_" & Mot & "_")
    'l'index de instr sera automatiquement converti en booleen
End Function

Sub test()
   
    MsgBox ContientMot("44.2/16/4", "44.2/16/44.2")

    MsgBox ContientMot("44.2/16/4", "44.2/16/4")

End Sub

maintenant je répète ;)
quel est le critère qui te fait choisir le second et pas le premier ?
cette question devrait avoir une réponse facile est simple non ?
 

TooFatBoy

XLDnaute Barbatruc
Menuiseries gamme aluminium thermolaqu(44,2 / 16 / 44,2) é (RAL 9007)
Si tes collègues saisissent n'importe quoi, ça ne va pas être facile de trouver un truc qui marche à tous les coups...

Le plus simple serait peut-être d'insérer une colonne entre G et H pour y indiquer le vitrage par une liste déroulante de choix dudit vitrage. (voir pièce jointe)
 

Pièces jointes

  • Pour Excel-DownLoads.xlsx
    49.5 KB · Affichages: 3
Dernière édition:

DenisHen

XLDnaute Nouveau
Bonjoue à la communauté.
@patricktoulon : je pensais l'avoir dis, désolé, je cherche l'exate réplique du mot cherché dans la phrase, si je cherche "44.2/16/44.2, il ne faut pas que "44.2/16/4" réponde "Trouvé". Raison pour laquelle le "Like" était une réelle bonne solution, encore merci à @Dranreb.
@TooFatBoy : j'ai volontairement écris "n'importe quoi" pour être sur que les résultat des testes prouveraient que le code est bon, même avec une saisie puorrie, et qu'il trouve l'exacte "Mot" dans la "Phrase".
J'ai déjà pensé à la création de cette colonne, mais j'espérais l'éviter, car si on change le double vitrage DANS la description (qui reste ce que l'on "vend", je ne suis pas certain que cette donnée sera mise à jour dans la nouvelle colonne... Le client nous dira un jour, "vous m'avez vendu du double vitrage P5A (le premier 44.6) et vous me fournissez du P2A (le 44.2). C'est la première raison pour laquelle je cherche dans la description et non dans une autre forme de saisie. Et je ne peut pas toucher aux colonnes avant la "L".
Encore merci à vous pour toute votre aide...
Denis, l'ami gnorant...
 

TooFatBoy

XLDnaute Barbatruc
si je cherche "44.2/16/44.2, il ne faut pas que "44.2/16/4" réponde "Trouvé".
Ca ne risque pas d'arriver... Mais l'inverse, oui.



J'ai déjà pensé à la création de cette colonne, mais j'espérais l'éviter, car si on change le double vitrage DANS la description (qui reste ce que l'on "vend", je ne suis pas certain que cette donnée sera mise à jour dans la nouvelle colonne...
C'est bien pour ça que je n'ai pas mis la description du vitrage dans la description, mais dans la colonne d'à côté, si tu as bien vu ce que j'ai proposé.
Mais vu que tu ne veux pas d'une colonne supplémentaire, je ne saurais t'aider. Désolé.


@+
 

DenisHen

XLDnaute Nouveau
Merci tout de même @TooFatBoy pour toute ton aide, mais ce n'est pas que je ne veut pas de cette colonne, c'est que je ne peut pas l'avoir.
De plus, on ne vend pas systématiquement du vitrage (ou double ou triple), raison pour laquelle ma direction ne veut pas de cette colonne DANS le devis.
Mais je peut toujours la placer ailleurs, car ton idée reste judicieuse... Mais j'espérais l'éviter...
Maintenant, s'il n'y a pas d'autre solution...
Encore merci à la communauté, je vais continuer de penser avec sérieux à vos propositions...
 

fanch55

XLDnaute Barbatruc
Bonsoir à tous,
Je n'ai pas tout bien suivi mais si @DenisHen veut bien tester le code ci-dessous : 🤔
VB:
Function ChercheVitrage(CalTxt As Range)
    ChercheVitrage = 0
    textsrc = Replace(CalTxt.Value, ",", ".") 'Car avec Excel, le "point" du pavé numérique peu être une virgule
    textsrc = Replace(textsrc, " /", "/")
    textsrc = Replace(textsrc, "/ ", "/")
    textsrc = Replace(textsrc, "( ", " ")
    textsrc = Replace(textsrc, " )", " ")
    textsrc = Replace(textsrc, "(", " ")
    textsrc = Replace(textsrc, ")", " ")
    textsrc = Replace(textsrc, vbLf, " ")
    
    Dim Cel As Range
    With Worksheets("Prix")
        lr = .Cells(.Rows.Count, "L").End(xlUp).Row
        For Each Cel In .Range("L2:L" & lr)
            If InStr(" " & textsrc & " ", " " & Cel & " ") Then
                ChercheVitrage = Val(Cel.Offset(, 1))
                Exit For
            End If
        Next
    End With
End Function
 

jurassic pork

XLDnaute Junior
Hello,
voici ce que je propose en utilisant les expressions régulières :
VB:
Function ChercheVitrageJP(CalTxt As Range)
Dim res As String, matches As Object, Vitrage As String, CellVitrage As Range
   ChercheVitrageJP = 0
   With CreateObject("VBScript.RegExp")
      .Pattern = "[\d,\.]+\s*/[\d ,\.]+/[\d ,\.]+" ' motif
      Set matches = .Execute(CalTxt.Value)
      If matches.Count = 1 Then ' motif trouvé
         res = matches(0).Value
         Vitrage = Replace(Replace(res, " ", ""), ",", ".")
         Set CellVitrage = Range("ListeVitrage").Find(Vitrage) ' recherche dans plage nommée ListeVitrage
         If CellVitrage Is Nothing Then
            ChercheVitrageJP = 0
            MsgBox "Vitrage " & Vitrage & " non trouvé dans la liste des vitrages"
         Else
            ChercheVitrageJP = Val(CellVitrage.Offset(0, 1).Value) ' récupération du prix du vitrage
         End If
      End If
   End With
End Function

1 - on utilise le motif suivant :
Code:
.Pattern = "[\d,\.]+\s*/[\d ,\.]+/[\d ,\.]+"
[\d,\.]+ -> contenu comprenant des chiffres ou des virgules ou des points (au moins 1)
\s* 0 ou plus espace
/ le slash
[\d ,\.]+ contenu comprenant des chiffres ou des virgules ou des points ou des espaces (au moins 1)

2 - si le motif est trouvé dans le texte de la cellule je remplace dans le motif trouvé les espaces par rien et les virgules par des points . A noter que je n'ai plus les parenthèses car pas capturées.

3 - Je cherche le vitrage ainsi reconstitué dans la liste des vitrages (plage nommée ListeVitrage) avec un Find. Si trouvé je prends le prix sinon j'affiche une boîte de dialogue signalant que le vitrage n'a pas été trouvé dans la liste des vitrages ( à corriger si cela apparaît car il y a certainement une erreur de saisie)

En pièce jointe le classeur qui utilise la fonction RechercheVitrageJP qui se trouve dans le fichier .xlam joint. J'ai enlevé les formules matricielles en colonne AB (remplacées par des formules simples) car je n'ai pas compris l'intérêt. J'ai déclaré la plage L2:L21 de la feuille Prix en plage nommée ListeVitrage.
Si dans le texte le motif n'est pas trouvé , rien n'est signalé ou calculé (exemple 44,2 / 1a/44,2 )

Ami calmant, J.P
 

Pièces jointes

  • ACR_Metal.xlam
    283.8 KB · Affichages: 0
  • TestVitrageJP.xlsx
    82 KB · Affichages: 4
Dernière édition:

Discussions similaires

Membres actuellement en ligne

Statistiques des forums

Discussions
313 060
Messages
2 094 924
Membres
106 127
dernier inscrit
AS PRECY