2 votes

Détecter la culture des chiffres en VB.Net, c'est-à-dire le point ou la virgule pour le point décimal / le séparateur de milliers

En VB.Net, y a-t-il un moyen de détecter automatiquement la culture d'une représentation de chaîne d'un nombre? Je vais expliquer la situation:

Notre site web asp.net reçoit des flux de données xml pour les données des bateaux. La plupart du temps, le format des prix utilise soit un entier non-formaté simple par exemple "999000". C'est facile pour nous de traiter.

De temps en temps, il y a des virgules pour les séparateurs de milliers et des points pour le point décimal. Aussi, c'est bien car notre importation de données le comprend. Exemple "999,000.00".

Nous commençons à recevoir des données de France où certains des prix ont été saisis avec les points et les séparateurs de milliers à l'envers car c'est la façon dont cela se fait dans de nombreux pays européens. Par exemple "999.000,00". C'est là que notre système interpréterait cela comme neuf cent quatre-vingt-dix-neuf livres au lieu des neuf cent quatre-vingt-dix-neuf mille livres qui étaient prévues.

Malheureusement, le flux de données contient des prix dans un mélange de formats sans indicateur de culture sur chacun. Est-ce que quelqu'un connaît des fonctions .net intégrées qui détecteront automatiquement la culture d'un nombre de chaîne en fonction de l'emplacement du point et de la virgule?

3voto

iknownothing Points 106

J'ai trouvé un fil sur vbforums suggérant comment obtenir le séparateur décimal par culture.

J'ai créé un convertisseur qui convertit entre différents fichiers en utilisant oledb, objet excel, mysql et plus encore. Utiliser "decimalSeparator" était la solution pour obtenir le format de nombre correctement lorsque j'ai converti les fichiers Excel et Access.

Dim decimalSeparator As String = Globalization.CultureInfo.CurrentCulture.NumberFormat.NumberDecimalSeparator

cellValue = cellValue.Replace(".", decimalSeparator ).Replace(",", decimalSeparator )

2voto

Fulvio Points 744

Il n'existe pas de moyen intégré pour déterminer la CultureInfo à partir d'une chaîne numérique, autant que je sache. Et je doute sérieusement qu'il y en ait jamais un, car il n'existe pas de moyen sûr à 100% pour le faire.

Jusqu'à ce que vous trouviez une meilleure solution (par exemple : un changement du côté de l'expéditeur), je suppose que la meilleure chose à faire est de diminuer les chances d'erreur en deux étapes :

1) Nettoyage et normalisation des données d'entrée :

Dim input as String = " 99 9.000,00 "
' De cette façon, vous pouvez supprimer les caractères indésirables (tout ce qui n'est pas un chiffre, et les symboles suivants : ".", "-", ",")
Dim fixedInput as String = Regex.Replace(input, "[^\d-,\.]", "")
' fixedInput est maintenant "999.000,00"

2) Devinez vous-même le format :

Dim indexOfDot as Integer = fixedInput.IndexOf(".")
Dim indexOfComma as Integer = fixedInput.IndexOf(",")
Dim cultureTestOrder as List(Of CultureInfo) = new List(Of CultureInfo)
Dim parsingResult as Double?
Try
    If indexOfDot > 0 And indexOfComma > 0 Then
        ' Il y a à la fois le point et la virgule..vérifions leur ordre
        If indexOfDot > indexOfComma Then
            ' Le point vient après la virgule. Ce devrait être la Culture en-US
            parsingResult = Double.Parse(fixedInput, NumberStyles.Number, CultureInfo.GetCultureInfo("en-US"))
        Else
            ' Le point vient avant la virgule. Ce devrait être la Culture it-IT
            parsingResult = Double.Parse(fixedInput, NumberStyles.Number, CultureInfo.GetCultureInfo("it-IT"))
        End If
    Else If indexOfDot = fixedInput.Length-3 Then
        ' Il y a seulement le point ! Et il est suivi de exactement deux chiffres..ce devrait être la Culture en-US
        parsingResult = Double.Parse(fixedInput, NumberStyles.Number, CultureInfo.GetCultureInfo("en-US"))
    Else If indexOfComma = fixedInput.Length-3 Then
        ' Il y a seulement la virgule ! Et elle est suivie de exactement deux chiffres..ce devrait être la Culture it-IT
        parsingResult = Double.Parse(fixedInput, NumberStyles.Number, CultureInfo.GetCultureInfo("it-IT"))
    End If
Catch
End Try
If Not parsingResult.HasValue Then
    Try
        ' Il n'y a ni point ni virgule, ou l'analyse a échoué pour une raison quelconque. Essayons une analyse moins spécifique.
        parsingResult = Double.Parse(fixedInput, NumberStyles.Any, NumberFormatInfo.InvariantInfo)
    Catch
    End Try 
End If
If Not parsingResult.HasValue Then
    ' Conversion non possible, déclenchez une exception ou faites quelque chose d'autre
Else
    ' Utilisez parsingResult.Value

Vous n'êtes pas sûr à 100% de cette façon, mais cela devrait quand même être meilleur que votre code actuel (et fonctionne au moins comme prévu avec les données d'exemple que vous avez fournies).

1voto

dbasnett Points 4114

Sans connaître les détails de toutes les façons différentes dont la chaîne peut être formatée... Cela fonctionne pour les trois exemples que vous avez donnés

Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
    Dim v As String = "999.123,45"
    Debug.WriteLine(foo(v))

    v = "999,123.45"
    Debug.WriteLine(foo(v))

    v = "999123"
    Debug.WriteLine(foo(v))
End Sub

Private Function foo(value As String) As Double
    Dim style As NumberStyles = NumberStyles.AllowThousands Or NumberStyles.AllowDecimalPoint
    Dim culture As CultureInfo = CultureInfo.InvariantCulture
    Dim rv As Double
    If Double.TryParse(value, style, culture, rv) Then
        Debug.WriteLine(",.Converted '{0}' to {1}.", value, rv)
    Else
        Dim styleES As NumberStyles = NumberStyles.AllowThousands Or NumberStyles.AllowDecimalPoint
        Dim cultureES As CultureInfo = CultureInfo.CreateSpecificCulture("es-ES")

        If Double.TryParse(value, styleES, cultureES, rv) Then
            Debug.WriteLine(".,Converted '{0}' to {1}.", value, rv)
        Else
            Throw New ArgumentException
        End If
    End If
    Return rv
End Function

1voto

P. Lion Points 288

Cette variable est vraie si les paramètres régionaux du système d'exploitation utilisent un point comme séparateur décimal, fausse dans les autres cas.

Dim bAmerican as boolean = Cdec("0,2") > 1

Message original : https://www.linkedin.com/groups/8141257/8141257-6347113651027079171

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X