Demande d'aide concernant la fonction Replace

Bonjour à tous,
Les quelques connaissances que je possède en VBA ne me permettent pas de résoudre mon problème ; je fais donc appel à vous dans l'espoir que vous réussirez à m'aider à désembrouiller le schmilblick ^^

Tout d'abord, ce que je souhaite faire : une macro qui "lit" une cellule et qui en "analyse" le contenu. Pour chaque caractère non-alphabétique (hormis certains caractères particuliers à savoir ¤%' et l'espace), je veux qu'elle m'ajoute devant ledit caractère le signe %.

Pour ce faire, voici la macro que j'ai écrite :

Sub Remplace()
Selection = UCase(Selection)
Selection = Selection & "¤"
Selection = Replace(Selection, "À", "A")
Selection = Replace(Selection, "Â", "A")
Selection = Replace(Selection, "Ä", "A")
Selection = Replace(Selection, "É", "E")
Selection = Replace(Selection, "È", "E")
Selection = Replace(Selection, "Ê", "E")
Selection = Replace(Selection, "Ë", "E")
Selection = Replace(Selection, "Î", "I")
Selection = Replace(Selection, "Ï", "I")
Selection = Replace(Selection, "Ô", "O")
Selection = Replace(Selection, "Ö", "O")
Selection = Replace(Selection, "Ù", "U")
Selection = Replace(Selection, "Ü", "U")
Selection = Replace(Selection, "Û", "U")
Selection = Replace(Selection, "Ç", "C")
Selection = Replace(Selection, "Ñ", "N")
Selection = Replace(Selection, "OE", "OE")
I = 1
Do Until char = "¤"
    char = Mid(Selection, I, 1)
    If char Like "[!A-Z,!%,! ,!¤]" Then
    Selection = Replace(Selection, char, "%" & char, , 1)
    I = I + 1
    End If
    I = I + 1
Loop
Selection = Replace(Selection, "¤", "")
End Sub


Le soucis arrive lors des tests (forcément, c'est à ça qu'ils servent ^^)
Quand je la teste avec, par exemple, az12er34ty15, elle me renvoie AZ%%1%2ER%3%4TY1%5 au lieu de AZ%1%2ER%3%4TY%1%5
En résumé, les deux signes % se retrouvent devant un seul 1 au lieu de se répartir (et plus j'ajoute de 1, plus les % se cumulent au niveau de la première instance)
En exécutant la macro pas à pas, je vois que le problème vient de l'instruction Replace mais je ne sais pas comment le résoudre.

Merci de l'aide que vous m'apporterez
Amicalement

Alex

8 réponses

  • Votes
  • Date
  • Date décroissante
  1. Bonjour

    Personnellement, au lieu de faire de 'Replace', j'aurais reconstruit la chaîne en recopiant les caractères tels quels ou modifiés selon les cas.
    Mais pour rester dans ta logique, ton problème vient du fait que le Replace se fait toujours sur le premier caractère rencontré. Pourtant, il y a bien le 4e paramètre de Replace qui sert à dire à partir d'où doit se faire la recherche : tu ne t'en sers pas.
    Si tu fais :
    Selection = Replace(Selection, char, "%" & char, I , 1)

    ça ne va faire de replace qu'à partir du Ième caractère et non pas à partir du premier
    1. Bonjour

      essaies ceci (une fonction sera plus souple à utiliser)

      Public Function RP(S As String) As String
      Dim I As Long, c As String, ls As Long, SS As String
      S = UCase(S)
      S = Replace(S, "À", "A")
      S = Replace(S, "Â", "A")
      S = Replace(S, "Ä", "A")
      S = Replace(S, "É", "E")
      S = Replace(S, "È", "E")
      S = Replace(S, "Ê", "E")
      S = Replace(S, "Ë", "E")
      S = Replace(S, "Î", "I")
      S = Replace(S, "Ï", "I")
      S = Replace(S, "Ô", "O")
      S = Replace(S, "Ö", "O")
      S = Replace(S, "Ù", "U")
      S = Replace(S, "Ü", "U")
      S = Replace(S, "Û", "U")
      S = Replace(S, "Ç", "C")
      S = Replace(S, "Ñ", "N")
      S = Replace(S, "OE", "OE")
      SS = ""
      ls = Len(S)
      For I = 1 To ls
      c = Mid(S, I, 1)
      If c Like "[!A-Z,!%,! ,!¤]" Then
      SS = SS & "%"
      End If
      SS = SS & c
      Next I
      RP = SS
      End Function

      Cdlmnt
      1. Merci à vous deux pour vos réponses aussi rapides !

        -> le père : je ne vois pas bien ce que tu entends par "reconstruire les chaînes telles quelles"
        Concernant le 4ème paramètre, j'ai essayé de m'en servir
        Résultat : %34TY15
        Je ne sais pas où est parti le reste de ma chaîne de test ...

        -> CCM81 : je vais essayer ta méthode
        En revanche, la boucle for n'est pas une bonne idée : comme je rajoute un caractère en milieu de chaîne, celle-ci est rallongée et la boucle garde en valeur de fin la longueur initiale
        D'où la boucle Do-Loop
        (J'ai tt de même essayé cette méthode mais pas moyen de faire prendre en compte la valeur réactualisée de Len à mon for :-S)

        Encore merci pour le coup de main

        Cordialement

        Alex
        1. Effectivement, l'utilisation de 4e paramètre n'est pas une bonne idée, j'aurais dû le vérifier avant de poster. L'aide de la fonction replace précise qu'elle remplace à partir d'un certain caractère, mais elle oublie de dire que cette fonction supprime tout ce qu'il y a avant !

          Quand je parlais de reconstruire la chaîne, je voulais parler de la méthode de ccm81. Et la boucle for est une bonne idée contrairement à ce que tu dis : la chaîne S n'est pas modifiée pendant la boucle puisque on construit une nouvelle chaîne SS.
          1. Ah la sale bête !
            Elle supprime purement et simplement ce qui précède :-S
            Je comprends mieux ; je craignais de mal me servir des différents arguments de cette fonction

            Concernant ce qu'a proposé CCM81, effectivement, ça fonctionne (si tu me lis, désolé d'avoir douté ;-) )
            Et j'étais à l'instant en train de me creuser la tête à essayer de comprendre pourquoi !
            En effet, il yavait le For-To qui me tracassait (et tu viens de répondre à ma question) mais aussi le fait qu'il rajoute le % après ce qu'il a appelé SS alors que j'essayais de le rajouter avant le caractère "hors liste"

            Dernière étape pour moi : qd mm faire une macro : au final, je ne serai pas le seul utilisateur de cette commande et cliquer sur un bouton et plus facile que devoir appeler une fonction (même si c'est pas bien compliqué ^^)
          2. Il te suffit d'appeler la fonction dans la procédure Click du bouton!
            Et d'ailleurs au passage, j'aurai bien déporté tes S =r eplace... dans une fonction chargée de nettoyer la chaine, fonction (S=Nettoie(S)) elle même utilisée par RP dont le code deviendrait plus simple!
            Cdlmnt
        2. En revanche, la boucle for n'est pas une bonne idée : comme je rajoute un caractère en milieu de chaîne, celle-ci est rallongée et la boucle garde en valeur de fin la longueur initiale
          Non, la boucle for sur le nombre de caractères de la chaine initiale S créee une "copie allongée" SS dont la valeur finale est renvoyée par la fonction
          https://www.cjoint.com/?3Hwtoohwmha

          Cdlmnt
          1. Mea Culpa CCM81 : en effet, tout tourne correctement
            Je vais voir ca ensuite pour "ranger" mon code ; pour l'instant, je préfère tout avoir à portée d'oeil et de souris

            Merci d'avoir pris la peine de me concocter un p'tit xls en démo :-)

            Un grand merci à tous les deux pour vos réponses excessivement rapides et utiles !

            Cordialement

            Alex
            1. Absolution accordée :-)

              Voilà ce que ça peut donner avec un bouton
              https://www.cjoint.com/?3HwtAHGRVKe

              Cdlmnt
              1. C'est clair, je te dois un pack ;-)
              2. En espérant ne pas abuser de ton temps, j'aimerais savoir s'il te serait possible de me redonner ces lignes de codes mais en version macro au lieu de la version fonction
                En effet, je n'arrive pas a les transformer moi même ni à les intégrer dans les lignes que j'ai déjà écrites
                D'avance, merci

                Cordialement

                Alex
            2. Dommage, mais voilà (la procédure s'applique à la cellule sélectionnée)
              Si la sélection contient plus d'une cellule, ça ne fait rien
              On peut bien sur modifier le code pour que la procédure s'applique à une plage

              Public Sub Remplace()
              Dim I As Long, c As String, ls As Long, S As String, SS As String
              If Selection.Cells.Count > 1 Then Exit Sub
              S = UCase(Selection)
              S = Replace(S, "À", "A")
              S = Replace(S, "Â", "A")
              S = Replace(S, "Ä", "A")
              S = Replace(S, "É", "E")
              S = Replace(S, "È", "E")
              S = Replace(S, "Ê", "E")
              S = Replace(S, "Ë", "E")
              S = Replace(S, "Î", "I")
              S = Replace(S, "Ï", "I")
              S = Replace(S, "Ô", "O")
              S = Replace(S, "Ö", "O")
              S = Replace(S, "Ù", "U")
              S = Replace(S, "Ü", "U")
              S = Replace(S, "Û", "U")
              S = Replace(S, "Ç", "C")
              S = Replace(S, "Ñ", "N")
              S = Replace(S, "OE", "OE")
              SS = ""
              ls = Len(S)
              For I = 1 To ls
              c = Mid(S, I, 1)
              If c Like "[!A-Z,!%,! ,!¤]" Then
              SS = SS & "%"
              End If
              SS = SS & c
              Next I
              Selection.Value = SS
              End Sub

              Cdlmnt
              1. Arrgh ! Je n'avais qu'une erreur : le
                Selection.Value = SS
                ; le reste était bon ... bah, c'est de ses erreurs qu'on apprend !
                Encore un grand merci pour le temps consacré !

                Cordialement

                Alex