Fonction qui récupère un chiffre décimal dans une chaîne

Magic_Doctor

XLDnaute Barbatruc
Bonjour,

Je suis à la recherche d'une telle fonction. J'ai trouvé celle-ci de BOISGONTIER :
Code:
Function NumDansCadena(chaine As String, n As Byte) As Double
'Récupère un chiffre dans une chaîne de caractères
'BOISGONTIER
'- chaine : la chaîne de caractères qui comprend 1, voire davantage de chiffres séparés par du texte
'- n : la position du chiffre dans la chaîne s'il y en a plusieurs
'Exemple : NumDansCadena("250 tomates dans 12 cagettes",2) --> 12

    Dim Obj, a

    Set Obj = CreateObject("vbscript.regexp")
    Obj.Global = True
    Obj.Pattern = "\d+"
    Set a = Obj.Execute(chaine)
    If a.Count > 0 Then NumDansCadena = a(n - 1) Else NumDansCadena = ""
    
End Function
Elle marche très bien, à condition que les chiffres soient entiers. Comment la modifier pour qu'elle fonctionne avec des chiffres décimaux ?

merci pour toute aide.
 

Magic_Doctor

XLDnaute Barbatruc
Re : Fonction qui récupère un chiffre décimal dans une chaîne

Bonsoir david84, mapomme,

Merci pour vos réponses, ça marche super.

Comme la syntaxe de la fonction de BOIGONTIER m'intrigue, j'ai voulu faire une petite modification en déclarant la variable "n" comme optionnelle. En effet, la plupart du temps il n'y a qu'un chiffre dans la chaîne. J'ai donc écrit ceci :
Code:
Function NumDansCadena(chaine As String, Optional n As Byte) As Double
'Récupère un chiffre dans une chaîne de caractères
'BOISGONTIER / david84
'- chaine : la chaîne de caractères qui comprend 1, voire davantage de chiffres séparés par du texte
'- n : la position du chiffre dans la chaîne s'il y en a plusieurs

    Dim Obj, a

    Set Obj = CreateObject("vbscript.regexp")
    Obj.Global = True
    Obj.Pattern = "\d+[,\.]?\d*"
    Set a = Obj.Execute(chaine)
    
    If a.Count > 0 Then
        If IsMissing(n) Then
            NumDansCadena = a(0)
        Else
            NumDansCadena = a(n - 1)
        End If
    Else
        NumDansCadena = ""
    End If
    
End Function
Où me suis-je encore bien planté ?
 

david84

XLDnaute Barbatruc
Re : Fonction qui récupère un chiffre décimal dans une chaîne

Re et le bonsoir à mapomme,
A tester de ton côté mais je pense que
Code:
Function NumDansCadena2(chaine As String, Optional n As Byte = 1) As Double  
Dim Obj As Object, a As Object
  Set Obj = CreateObject("vbscript.regexp")
  Obj.Global = True
  Obj.Pattern = "\d+(" & Application.DecimalSeparator & "\d+)?"
  Set a = Obj.Execute(chaine)
  NumDansCadena2 = a(n - 1)
End Function
suffit.
J'ai modifié le pattern en ne prenant en compte que le séparateur de décimal comme mapomme l'a proposé (inutile de prendre en compte le point puisque le résultat ramené est un Double et non un String).
A+
 

mapomme

XLDnaute Barbatruc
Supporter XLD
Re : Fonction qui récupère un chiffre décimal dans une chaîne

Bonjour à tous,

J'ai confondu deux notions:

  • Application.DecimalSeparator
  • Application.International(xlDecimalSeparator)

D'après ce que j'en ai expérimenté, Application.DecimalSeparator contient un séparateur décimal défini par l'utilisateur (soit via VBA soit par le menu Options / options avancées d'Excel). Ce séparateur est utilisé par Excel seulement si la case à cocher "Utiliser les séparateurs système" est décochée (ou en VBA -> Application.UseSystemSeparators = False)

On peut donc (par exemple) avoir comme séparateur décimal système (défini au niveau de Windows) la virgule et comme séparateur décimal de l'application (Application.DecimalSeparator) le point.

  • si Application.UseSystemSeparators = True, alors Excel utilisera la virgule.
  • si Application.UseSystemSeparators = False, alors Excel utilisera le point.
Application.DecimalSeparator ne renvoit donc pas toujours le séparateur décimal présentement utilisé par Excel.


La propriété "Application.International(xlDecimalSeparator)" retourne le séparateur qui est réellement utilisé et affiché par Excel.


J'ai donc modifié ma fonction de recherche de nombre décimal dans une chaine comme suit:
VB:
Function InStrDecN(xStr, xN)
Dim i, x, sep
  InStrDecN = "": sep = Application.International(xlDecimalSeparator)
  x = xStr
  For i = 1 To Len(x)
    Select Case Mid(x, i, 1)
      Case "0" To "9", sep
      Case Else
      Mid(x, i, 1) = " "
    End Select
  Next i
  x = Split(Application.WorksheetFunction.Trim(x))
  On Error Resume Next
  InStrDecN = Val(Replace((x(xN - 1)), sep, "."))
End Function
 

Pièces jointes

  • Magic_Doctor- Décimal dans chaine- v3.xlsm
    17.3 KB · Affichages: 29
Dernière édition:

mapomme

XLDnaute Barbatruc
Supporter XLD
Re : Fonction qui récupère un chiffre décimal dans une chaîne

Re,

Une version plus aboutie avec un paramètre optionnel qui permet à l'utilisateur d'indiquer le séparateur décimal à utiliser pour extraire les décimaux. On peut imaginer avoir un Excel utilisant la virgule comme séparateur et un texte ayant le point comme séparateur décimal.

Si le paramètre optionnel est omis, on prend le séparateur décimal actuellement utilisé et affiché par Excel.

La fonction devient:
Code:
Function InStrDecN(xStr, xN, Optional MyDecimalSeparator)

Voir fichier joint.
 

Pièces jointes

  • Magic_Doctor- Décimal dans chaine- v3a.xlsm
    17.8 KB · Affichages: 36

david84

XLDnaute Barbatruc
Re : Fonction qui récupère un chiffre décimal dans une chaîne

Merci mapomme pour ces précisions.

Pourquoi utilises-tu Left dans sep = Left(MyDecimalSeparator, 1) ? sep = MyDecimalSeparator ne suffit-il pas ?
Une paire de parenthèses que tu peux enlever : Val(Replace((x(xN - 1)), sep, ".")).

Après on peut faire autrement et traiter tel quel les données captées avec le séparateur sélectionné sans la nécessité de les modifier via un Replace mais l'inconvénient est que l'on récupérera des chaînes de caractères et non des nombres.

A+
 

mapomme

XLDnaute Barbatruc
Supporter XLD
Re : Fonction qui récupère un chiffre décimal dans une chaîne

Bonjour david84 :),

(...) Pourquoi utilises-tu Left dans sep = Left(MyDecimalSeparator, 1) ? sep = MyDecimalSeparator ne suffit-il pas ? (...)
Certes mais pourquoi faire simple quand on peut faire abscons :eek:? (en fait j'étais parti d'une précédente procédure, fait un copier/coller et ne me suis pas assez relu.

( ...) Une paire de parenthèses que tu peux enlever : Val(Replace((x(xN - 1)), sep, ".")) (...)
Même motif, même punition pour ce deuxième point ! Pas assez de temps consacré à la relecture...
 

david84

XLDnaute Barbatruc
Re : Fonction qui récupère un chiffre décimal dans une chaîne

En RegExp et en reprenant l'idée de mapomme :
Code:
Function NumDansChaine(chaine As String, Optional n As Byte = 1, _Optional MyDecimalSeparator)
Dim Obj As Object, a As Object, sep
  If IsMissing(MyDecimalSeparator) Then
    sep = Application.International(xlDecimalSeparator)
  Else
    sep = MyDecimalSeparator
  End If

  Set Obj = CreateObject("vbscript.regexp")
  Obj.Global = True
  Obj.Pattern = "\d+(\" & sep & "\d+)?"
  If Obj.test(chaine) Then
    Set a = Obj.Execute(chaine)
    If n - 1 < a.Count Then NumDansChaine = Val(Replace(a(n - 1), sep, ".")) Else NumDansChaine = ""
  Else
    NumDansChaine = ""
  End If
End Function

A+
 

Statistiques des forums

Discussions
314 628
Messages
2 111 337
Membres
111 105
dernier inscrit
Joffrette