cs_Patrice99
Messages postés1221Date d'inscriptionjeudi 23 août 2001StatutMembreDernière intervention 9 septembre 2018 16 juil. 2009 à 12:01
Val utilise toujours le point quel que soit le séparateur décimal en vigueur : donc normalement le code de renfiled devrait fonctionner en france et dans les pays anglophones... sauf si on précise un séparateur décimal différent de virgule et point (rare !) et qu'on demande de traiter une chaine avec une virgule par exemple.
La solution est de lire le séparateur en vigueur, de regarder si elle est présente dans la chaine, et si oui de la remplacer par le point puis d'utiliser Val. Attention, la fonction IsNumeric peut être très longue : mieux vaut remplacer systématiquement le séparateur par le point et d'utiliser Val.
Renfield
Messages postés17287Date d'inscriptionmercredi 2 janvier 2002StatutModérateurDernière intervention27 septembre 202174 16 juil. 2009 à 11:19
sûr qu'il y a souvent un gouffre entre les bonnes moeurs et ce qui est fait dans le monde reel ^^
peug
Messages postés232Date d'inscriptionmercredi 25 octobre 2000StatutMembreDernière intervention 5 octobre 2012 16 juil. 2009 à 11:16
oui ok pour IsNumeric c'est juste mais j'ai lu ton article mais j'ai été confronté à un problème similaire où un client a envoyé son fichier data d'un vieux logiciel où le stockage n'était pas correcte (comme tu le relate d'ailleurs) et boom patatrac, en France, "123.456,7" renvoyait 123.456
D'où comme tu le soulignes, d'enregistrer de manière internationale !
Renfield
Messages postés17287Date d'inscriptionmercredi 2 janvier 2002StatutModérateurDernière intervention27 septembre 202174 16 juil. 2009 à 11:11
j'avoue ne pas saisir.
Si la chaine est conforme aux parametres regionnaux du poste, IsNumeric la reconnaitra, quels que soient les parametres utilisés.
Sinon, on a affaire a une chaine formatée en utilisant le format international, et Val s'en sortira haut la main.
La seule alternative est une donnée mal formée, compte tenu des parametres du poste. Dans ce cas, ton code la trafique et tente d'en récupérer une valeur correcte.
Ce genre de manipulation est à éviter et met à jour une mauvaise conception a un endroit où a un autre.
Comme je le dit dans mon article, on doit toujours transmettre les données de manière internationale, sauf si le destinataire est un humain dont on peut présumer des parametres régionnaux. Auquel cas, on formatte la donnée de manière à ce qu'elle lui paraisse lisible et non ambigüe.
peug
Messages postés232Date d'inscriptionmercredi 25 octobre 2000StatutMembreDernière intervention 5 octobre 2012 16 juil. 2009 à 11:03
Salut Renfiedl,
mais si le séparateur de millier est le point, ca marche pas dans ton cas. Ex : "123.456,7" renvoi 123.456
D'où dans ma fonction les "InStrRev"
Renfield
Messages postés17287Date d'inscriptionmercredi 2 janvier 2002StatutModérateurDernière intervention27 septembre 202174 16 juil. 2009 à 10:56
possible également :
Public Function fctVal(ByVal Chaine As String) As Double
If IsNumeric(Chaine) Then
fctVal = CDbl(Chaine)
Else
fctVal = Val(Chaine)
End If
End Function
peug
Messages postés232Date d'inscriptionmercredi 25 octobre 2000StatutMembreDernière intervention 5 octobre 2012 16 juil. 2009 à 10:22
Salut,
Tenez, comme ca marche très bien et c'est rapide:
Public Function fctVal(ByVal Chaine As String) As Double
If Trim(Chaine) = "" Then
fctVal = 0
Exit Function
End If
Dim i As Long
Dim j As Long
i = InStrRev(Chaine, ".")
j = InStrRev(Chaine, ",")
If j > i Then
i = j
End If
Dim lD As Long
lD = Val(Mid(Chaine, i + 1))
Chaine = Mid$(Chaine, 1, i - 1)
Dim strTmp As String
Dim charTmp As String
For i = 1 To Len(Chaine)
charTmp = Mid(Chaine, i, 1)
If Asc(charTmp) >= 48 And Asc(charTmp) <= 57 Then
strTmp = strTmp & charTmp
ElseIf charTmp "+" Or charTmp "-" Then
' Le signe...
strTmp = strTmp & charTmp
ElseIf charTmp " " Or charTmp "." Or charTmp = "," Then
End If
Next i
fctVal = Val(strTmp) & "." & lD
End Function
cs_Patrice99
Messages postés1221Date d'inscriptionjeudi 23 août 2001StatutMembreDernière intervention 9 septembre 2018 17 févr. 2007 à 09:25
Pour info, Application.International(xlDecimalSeparator) c'est du VBA Excel.
azerty58220
Messages postés2Date d'inscriptionmercredi 27 septembre 2006StatutMembreDernière intervention12 février 2007 12 févr. 2007 à 10:57
Application.International(xlDecimalSeparator)
est aussi bien efficace...
mynyroger
Messages postés20Date d'inscriptionmardi 25 février 2003StatutMembreDernière intervention 1 février 2010 25 avril 2006 à 10:12
On revient à ce que j'ai écrit le 25/09/2005 !
tawass
Messages postés2Date d'inscriptionmardi 17 février 2004StatutMembreDernière intervention25 avril 2006 25 avril 2006 à 09:53
En effet Renfield, c'est plutôt:
"chaine_de_caracteres2 = chaine_de_caracteres2 + test"
A ce moment là on est bon!
Renfield
Messages postés17287Date d'inscriptionmercredi 2 janvier 2002StatutModérateurDernière intervention27 septembre 202174 20 avril 2006 à 19:41
tu peux utiliser la fonction Replace...
ta boucle est fausse, elle concatène a chaine_de_caracteres, une version ou les virgules sont remplacées par un point...
ex:
12,4512.45
tawass
Messages postés2Date d'inscriptionmardi 17 février 2004StatutMembreDernière intervention25 avril 2006 20 avril 2006 à 18:48
Ma solution reste simple et doit pouvoir passer partout: je
scan ma chaine de caractères (caractère par caractère) et je remplace chaque virgule par un point à la reconstruction de la nouvelle chaine.
For i = 1 To Len(chaine_de_caracteres)
test = Mid(chaine_de_caracteres, i, 1)
If test = "," Then
test = "."
End If
chaine_de_caracteres = chaine_de_caracteres + test
Next
wisjo
Messages postés1Date d'inscriptionlundi 24 mai 2004StatutMembreDernière intervention15 septembre 2005 15 sept. 2005 à 17:46
C'est bien joli les "replace" mais ça ne marche pas pour les fonctions du genre "importXML" qui s'appuie sur les variables d'environnement.
ex: valeur dans le fichier xml: 0.30 -> insertion dans une table sur un PC avec virgule comme séparateur décimal: 30
cs_jipef
Messages postés55Date d'inscriptionlundi 23 août 2004StatutMembreDernière intervention 1 août 2008 13 sept. 2005 à 08:55
en debut de ton code :
If InStr(1, CStr(CDbl(TimeValue("09:01:01"))), ",") > 0 Then
SeparateurDecimal = "Virgule"
Else
SeparateurDecimal = "POINT"
End If
ensuite dans ton code tu utilise cdouble("123,45")
'===================================
Public Function Cdouble(Chaine As String) As Double
'===================================
Dim Pos%
If Chaine = "" Then
Cdouble = 0
Exit Function
End If
If UCase(SeparateurDecimal) UCase("virgule") Or UCase(SeparateurDecimal) "," Then
Pos = InStr(1, Chaine, ",")
If Pos <> 0 Then
' rien faire c'est virgule pour virgule !!!
Cdouble = CDbl(Chaine)
Exit Function
Else
Pos = InStr(1, Chaine, ".")
If Pos <> 0 Then
Mid(Chaine, Pos, 1) = ","
End If
End If
Else ' point décimal
Pos = InStr(1, Chaine, ",")
If Pos <> 0 Then ' VIRGULE 0 CHANGER PAR POINT
Mid(Chaine, Pos, 1) = "."
Else
' ne rien faire POINT pour POINT
Cdouble = CDbl(Chaine)
Exit Function
End If
End If
' maintenant on peut convertir !! si > 0
If Val(Chaine) > 0 Then
On Error GoTo SORTIE
Cdouble = CDbl(Chaine)
Else
Cdouble = 0
End If
Exit Function
SORTIE:
Cdouble = 0
End Function
Pour la saisie tu testes et tu remplace la touche "." par ","
CQFD
signe Jipef
cs_pit1
Messages postés32Date d'inscriptiondimanche 15 juin 2003StatutMembreDernière intervention17 janvier 2007 12 sept. 2005 à 16:56
Attention au séparateur des milliers, il peut aussi être . ou , ou espace! Un replace tout bête pourrait rendre la chaine de charactères illisibles, vu qu'il pourra contenir DEUX séparateurs de décimales ...
cuq
Messages postés345Date d'inscriptionmardi 3 juin 2003StatutMembreDernière intervention21 mars 20082 12 sept. 2005 à 11:12
Pardon BrNews je voulai parlé de SetThreadLocal et pas de SetLocalInfo ( la ca va je maitrise)Duex petits lien en Anglais de Microsoft sur le problème ) Ca c'est pour celui qui ne connaitrait pas vraiment le problème . Ca donne un peu plus d'infos mais pas la solution :
Considération a prendre en compte lors de l'écriture d'un programme qui se veut international
BruNews
Messages postés21040Date d'inscriptionjeudi 23 janvier 2003StatutModérateurDernière intervention21 août 2019 12 sept. 2005 à 10:22
SetLocalInfo modifie le registre, simplement elle évite de manipuler la BDR par code.
Il est très clair qu'un prog ne devrait jamais toucher aux params utilisateur mas au contraire s'adapter, il ne peut y avoir aucun doute là dessus. S'il ne le peut pas et que les temps de traitement sont cruciaux, on fait convertirr les données avant et/ou après par une dll en C et le prob est réglé à la base. Traiter des milliers de lignes en vb me semble une ineptie, ça n'a jamais été conçu pour cela.
cuq
Messages postés345Date d'inscriptionmardi 3 juin 2003StatutMembreDernière intervention21 mars 20082 12 sept. 2005 à 09:58
Bonjour A Tous,
On l'avait dit c'est un sujet brulant. Et je pense que vous n'avez pas bien mes différents commentaires . Le problème de replace ou autres méthodes consitant à changer la "," en "." c'est dans le cas de grand traitement "milliers" de lignes à lire vous augmentez le temps de traitement ( j'ai pas vraiment de % de temps en plus à fournir mais le test serait intéressant pour variament être plus explicit). et ces Replaces ou autres à la lecture seront aussi nécessaires à l'écriture pour "Corriger" la sortie de FORMAT. Donc encore une fois au risque de me répéter je ne présente ici que MA solution qui n'st pas LA solution mais qui dans ce cas de figure me semble la plus appropriée. LA solution avec un L et un A majuscule serait de pouvoir spécifié les paramètres juste au niveau de l'appli. J'ai testé SetLocalInfo mais sans grand succès (manque de connaisssnace) Si quequ'un peut en dire plus sur cette fonction . C'est une piste
mynyroger
Messages postés20Date d'inscriptionmardi 25 février 2003StatutMembreDernière intervention 1 février 2010 12 sept. 2005 à 09:44
BJ Renfield
Bien sûr que j'emploie Replace, mais j'ai noté la fonction la plus lisible pour les débutants.
Ce site est bien pour cela non?
J'ai surtout voulu dire que le logiciel doit être indépendant, car il est possible d'utiliser simultanément plusieurs logiciels.
Le faît de modifier le registre ? salut les dégats.
Renfield
Messages postés17287Date d'inscriptionmercredi 2 janvier 2002StatutModérateurDernière intervention27 septembre 202174 12 sept. 2005 à 09:07
Utilise en ce cas la fonction Replace ^^
mynyroger
Messages postés20Date d'inscriptionmardi 25 février 2003StatutMembreDernière intervention 1 février 2010 12 sept. 2005 à 08:55
Slt :
Confronté à ce problème, voici ma solution indépendante :
xx = votre donnée
For x = 1 to len(xx)
if mid(x,1,1) "." then mid(x,1,1) ","
next
Ou inversement si vous désirez des "."
cs_marcA
Messages postés12Date d'inscriptionlundi 14 avril 2003StatutMembreDernière intervention 3 août 2010 12 sept. 2005 à 08:32
Bonjour,
Le problème en imposant le symbole décimal, c'est quand l'application plante.
Un collègue a eu un problème avec une application il y a deux semaines car l'application qui modifie les paramètres régionaux avait planté et n'avait donc pas restauré les paramètres. A moins qu'il n'y ait un système pour voir quand une application plante, c'est une technique à éviter à tout prix pour moi.
Marc Allard
Manolitoos
Messages postés14Date d'inscriptionsamedi 10 septembre 2005StatutMembreDernière intervention 4 avril 2008 10 sept. 2005 à 12:11
Bonjour à tous,
Tout d'abord je voulais te dire, Cuq, que je te comprend bien puisque j'ai eu un problème à les Paramètres Régionaux sous windows : au lieu d'avoir ? comme symbole monnétaire j'avais $.
Pour le séparateur décimal je pense que la solution est celle que BruNews à écrite :
- au démarrage de ton application, tu places le séparateur en "."
- à la fermeture tu restore en ","
Le paramètre est stocké dans le base de registre, clé suivante :
HKCU/Control Panel/International
puis sous cette clé voir la valeur chaîne sDecimal.
Je pense qu'en lisant la valeur de cette clé, en la plaçant dans une variable temporaire, en paramétrant ensuite la valeur sur le "." au démarrage de ton application, serait une bonne solution.
Il te reste ensuite, à la fermeture de ton application, à restorer la clé à l'aide de cette variable temporaire.
Bon courage...
bouv
Messages postés1411Date d'inscriptionmercredi 6 août 2003StatutMembreDernière intervention 3 mars 20191 10 sept. 2005 à 09:13
On peut même faire plus propre avec :
Public Function Valider_Nombre(Valeur_A_Valider)
Select Case sDecimal
Case "."
Valider_Nombre = Replace(Valeur_A_Valider, ",", sDecimal)
Case ","
Valider_Nombre = Replace(Valeur_A_Valider, ".", sDecimal)
End Select
End Function
bouv
Messages postés1411Date d'inscriptionmercredi 6 août 2003StatutMembreDernière intervention 3 mars 20191 10 sept. 2005 à 09:10
Je campe toujours sur ma position et ma méthode est très proche de celle de marcA. De plus la dernière remarque de PIT1 est également à prendre en compte.
Essai donc ça :
Dim dTest As Double
Dim sDecimal As String
dTest = 1 / 2
sDecimal = Mid$(CStr(dTest), 2, 1)
A chaque fois que l'on rencontre une valeur on fait un appel de la fonction suivante :
Public Function Valider_Nombre(Valeur_A_Valider)
Valider_Nombre = Replace(Valeur_A_Valider, ".", sDecimal)
Valider_Nombre = Replace(Valider_Nombre, ",", sDecimal)
End Function
Essai par exemple avec :
Msgbox Valider_Nombre(1.25)
Msgbox Valider_Nombre(3,42)
Bonne prog
++
cs_pit1
Messages postés32Date d'inscriptiondimanche 15 juin 2003StatutMembreDernière intervention17 janvier 2007 9 sept. 2005 à 20:16
Je suis du même avis que MarcA. Il suffit d'écrire une fonction qui fait la conversion (éventuellement avec un variable statique pour la "," et une pour le ".", cela évite de tester à chaque fois la base de régistre ou avec csng quel est le séparateur des décimales).
Pas question de tripoter dans les settings locale. Que ce passe t'il avec les autres application en mémoire, que ce passe t'il si l'appli plante avant de restaurer les settings ???
cuq
Messages postés345Date d'inscriptionmardi 3 juin 2003StatutMembreDernière intervention21 mars 20082 9 sept. 2005 à 08:54
Merci Patrice99
Enfin un qui me comprend ou qui a simplement les mêmes problèmes.
:)
cs_Patrice99
Messages postés1221Date d'inscriptionjeudi 23 août 2001StatutMembreDernière intervention 9 septembre 2018 9 sept. 2005 à 08:39
La plupart du temps, il suffit de lire les nombres réels en tant que string, de remplacer le séparateur décimal par le bon, puis d'utiliser les fonctions classiques de VB6 ou VBA, même dans une requête Access cela fonctionne. Cependant, il existe quand même des cas où l'on est obligé de changer à la volée le séparateur décimal dans le registre : par exemple j'utilise OWC 9 et je charge des enregistrements en une seule instruction dans le tableur OWC : hé bien je suis obligé d'utiliser le . comme séparateur décimal.
cs_marcA
Messages postés12Date d'inscriptionlundi 14 avril 2003StatutMembreDernière intervention 3 août 2010 9 sept. 2005 à 08:25
Bonjour,
Personellement, je suis pour rechercher le symbole décimal, (Par exemple valeur 1.1).
On fait un csng ("1.1") et csng ("1,1").
On compage la longueur des deux et le plus long donne le signe décimal.
Par exemple, si csng("1.1") donne 11 (longueur 2) et csng ("1,1") donne 1,1 (longueur 3).
Ainsi, on sait que c'est la "," le séparateur décimal.
Après, pour toute entrée utilisateur, on fait un Replace (entree, ".", ",") et on a plus de problème.
On peut aussi faire une fois avec le replace (entree, ".", ",") et l'autre fois (entree, ",", ".") et le plus long est le bon. Ainsi, si l'utilisateur change son symbole décimal pendant que le programme fonctionne, le programme fonctionne toujours.
Marc Allard
cuq
Messages postés345Date d'inscriptionmardi 3 juin 2003StatutMembreDernière intervention21 mars 20082 9 sept. 2005 à 08:22
Salut,
Je comprend pas vraiment ce que tu veux dire par "norme US".
Et au contraire de toi je pense que dans mon cas VB s'adapte très mal aux régional settings . Non plus exactement c'est ce Séparateur décimal qui est la cause de tout.
Pour les fichiers texte tu n'as pas à te discipliner .
SI tu prends des formats Texte existant des standard du marché comme par exemple:
DXF pour les données CAO géométriques 2D
IGES pour les données CAO géométriques 3D
GPS , WRML, STEP , STL qui sont des formats standards et beaucoup d'autres.
Dans ces fichiers le séparateur est le point. Pour nous (Français et européen en général le séparateur est la virgule) .
Donc en VB si tu veux lire, convertir ces données texte en valeur type double par exemple la conversion par val retournera une mauvaise valeur. Sauf si tu utilise Replace ) mais dans ce cas tu complique et ralenti ton code ) de plus très souvent le séparateur de champ dans ces fichiers est ... la virgule. Donc tu ne peut pas faire un seul replace sur une ligne relue mais X relpace après avoir isolé chaque valeur . Ou alors deux replace un pour le séparateur de champ un pour la décimal. Enfin je m'égare mais voila le type de problème. Même chose à l'écriture.
Enfin faut être confronté au problème pour bien comprendre. 5 ou alors c'est moi qui me fait chier depuis pas mal de temps mais à ce point là je doute )
Renfield
Messages postés17287Date d'inscriptionmercredi 2 janvier 2002StatutModérateurDernière intervention27 septembre 202174 9 sept. 2005 à 08:00
OK pour l'utilisation de l'API...
Je ne suios pas plus d'accord que sur l'autre source, sur ce procede...
VB s'adapte pas trop mal aux regional settings...
Reste a faciliter la saisie :
- le . du pave numerique, et la touche , insereront un separateur
- les dates (ne pas les oublier !) transformeront - / . en separateur de date
prendre les donnees d'un SGBD ne posera pas de soucis, si les champs sont bien types...
pour un fichier texte, il faudra se discipliner : adopter une convention
prendre la "norme US", par exemple...
BruNews
Messages postés21040Date d'inscriptionjeudi 23 janvier 2003StatutModérateurDernière intervention21 août 2019 8 sept. 2005 à 19:37
J'ai testé SetThreadLocale dans Excel mais pas moyen d'arriver à sortir un "." en séparateur.
Le plus simple reste SetLocaleInfo() comme dit plus haut.
cuq
Messages postés345Date d'inscriptionmardi 3 juin 2003StatutMembreDernière intervention21 mars 20082 8 sept. 2005 à 19:37
Bon ben pour setlocalThread j'ai pas tout compris mais ce serait pas plus pour basculer en mode system locale. ou Default user locale. et ca semble n'avoir d'influence que sur des fonctions du type findRessource Bref A rien compris
:
pour GetLocalInfo ( oui c'est pour récupérer la valeur de la décimal sans passer par le registre un petit exemple pour les autres :
Const LOCALE_SDECIMAL = &HE
Private Declare Function GetLocaleInfo Lib "kernel32" Alias "GetLocaleInfoA" (ByVal Locale As Long, ByVal LCType As Long, ByVal lpLCData As String, ByVal cchData As Long) As Long
Private Declare Function SetThreadLocale Lib "kernel32" (ByVal LCID As Long) As Boolean
Private Sub Form_Load()
MsgBox "la décimal est le ou la : " & GetInfo(LOCALE_SDECIMAL)
End Sub
Public Function GetInfo(ByVal lInfo As Long) As String
Dim Buffer As String, Ret As String
Buffer = String$(256, 0)
Ret = GetLocaleInfo(LOCALE_USER_DEFAULT, lInfo, Buffer, Len(Buffer))
If Ret > 0 Then
GetInfo = Left$(Buffer, Ret - 1)
Else
GetInfo = ""
End If
End Function
cuq
Messages postés345Date d'inscriptionmardi 3 juin 2003StatutMembreDernière intervention21 mars 20082 8 sept. 2005 à 19:06
Private Type NUMBERFMT
NombreDecimal As Long ' nombre de décimal
ZeroTete As Long ' Afficher les zéro en en tête (Marche pas ?)
Groupe As Long ' Groupement des digit ( 3 pour les milliers)
SeparateurDecimal As String ' Separateur des Decimals
SeparateurMillier As String ' Separateur des miliers ( Voir Groupe )
PositionSigneNegatif As Long ' Position du signe négatif
End Type
Private Declare Function GetNumberFormat Lib "kernel32" Alias "GetNumberFormatA" (ByVal Locale As Long, ByVal dwFlags As Long, ByVal lpValue As String, lpFormat As NUMBERFMT, ByVal lpNumberStr As String, ByVal cchNumber As Long) As Long
Private Sub Form_Load()
Dim Buffer As String, NF As NUMBERFMT
Buffer = String(255, 0)
With NF
.NombreDecimal = 3
.ZeroTete = 1
.Groupe = 3
.SeparateurDecimal = "."
.SeparateurMillier = " "
.PositionSigneNegatif = 1
End With
GetNumberFormat ByVal 0&, 0, "-0015545.242315654", NF, Buffer, Len(Buffer)
MsgBox Buffer
End Sub
Enfin ca reste lourd à mon avis si tu doit l'employer toute les 2 lignes de code et j'ai pas testé au niveau performance
Tu as un exemple pour SetThreadLocale
Cuq
BruNews
Messages postés21040Date d'inscriptionjeudi 23 janvier 2003StatutModérateurDernière intervention21 août 2019 8 sept. 2005 à 19:00
Pour ne pas changer tout le système vu que ça pose problème (et c'est juste), vous pouvez employer:
SetThreadLocale
cuq
Messages postés345Date d'inscriptionmardi 3 juin 2003StatutMembreDernière intervention21 mars 20082 8 sept. 2005 à 18:48
En regradant un peu j'ai vu GetNumberFormat a voir c'est peut être la solution
cuq
Messages postés345Date d'inscriptionmardi 3 juin 2003StatutMembreDernière intervention21 mars 20082 8 sept. 2005 à 18:41
Ok ca c'est une bonne info. Mais je n'ai jamais vu SetLocalInfo il y a un GetLocalInfo oui pas l'écriture tu as pris cette info ou ? sur l'API guide de allapi.net Y a pas de référence ?
T'as un exemple ? Mais bon ca reste le même truc ce qu'il faudrait c'est un SetLocalApliInfo :)
Cuq
BruNews
Messages postés21040Date d'inscriptionjeudi 23 janvier 2003StatutModérateurDernière intervention21 août 2019 8 sept. 2005 à 18:19
Alors pour changer, pas besoin d'aller dans le registre, API fera mieux et plus vite:
SetLocaleInfo(1024, 0x0E, ".");
Votre code ici.
SetLocaleInfo(1024, 0x0E, ",");
et voila remis en ordre.
cuq
Messages postés345Date d'inscriptionmardi 3 juin 2003StatutMembreDernière intervention21 mars 20082 8 sept. 2005 à 17:39
Voila une bonne remarque. Et voila pourquoi ce sujet est sensible.
Je pense que tu n'as jamais éte confronté au problème avant d'écrire ton commentaire.
Oui c'est égoiste et oui c'est à l'appli d'être indépendante mais dans ce cas je n'ai pas trouvé de solution. de solution simple :)
dans mon type d'appli j'utilise souvent les fonctions VAL, FORMAT et autres de ce type ces fonctions étant directement dépendantes des paramètres régionaux pour s'affranchir du problème il faudrait ré-écrire toutes ces fonctions pour les rendre indépendantes de ce paramètre. Si comme moi tu es amené à relire beaucoup de ligne avec beaucoup de traitement ré-écrire ces fonctions c'est au détriment de la rapidité de ton logiciel.
De plus le problème c'est vraiment la virgule tu trouveras souvent la question de changer la virgule en point mais pas l'inverse. C'est un problème on va dire Francais ou europeen pas Anglo Saxon Voila pourquoi les §$%% de chez Microsoft n'on pas gérer ce problème. Maintenant la plus part des formats texte que tu doit relire utilise le point . Format d'echange standard comme IGES, DXF, WRML , GPS .... Format d'origine US . Donc si tu travail sur ce type de fichier tu as le problème.
Et dernier point tu remarqueras que si tu changes la virgule en point cela passe n'est pas très pénalisant .
Enfin je ne dit pas que c'est LA solution c'est MA solution que j'utilise depuis plusieurs années sans rencontrer de problème ni de retour des utilisateurs. Donc le constat est le suivant nous n'avons pas les mêmes utilisateurs.
Maintenant le truc Idéal serait de changer le paramètre pas au niveau de l'utilisateur mais au niveau de l'appli . J'ai longtemps cherché je cherche encore .... Si vous avez un avis une idée je suis preneur.
Mais comme indiqué dans le texte de départ ce sujet est polémique .Il est polémique pour une raison comme tu le dit c'est égoiste et pas pro donc ce genre de sentiment déclenche la polémique et les sarcasmes seulement voilà On le sait , je le sais et si j'ai pris cette solution c'est que justement c'était la meilleru à mon avis.
En attendant la suite ... Cuq
bouv
Messages postés1411Date d'inscriptionmercredi 6 août 2003StatutMembreDernière intervention 3 mars 20191 8 sept. 2005 à 16:50
Slt, je ne regarde pas le code mais je trouve ta manière de procédé plutôt mauvaise.
Imagine que moi je décide de faire tout mes progs en utilisant la virgule comme séparateur décimal, et que comme toi je force l'inscription dans le registre. Imagine ensuite qu'une même personne utilise nos 2 applis. Que va-t-il se passer ?
Ta solution :
1 - Est égoïste
2 - N'en est pas une (puisque je viens de te montrer une faille)
3 - N'est pas pro (s'est au développeur de s'adapter et nom à l'OS).
A mon sens il faut stocker le séparateur décimal du PC dans une variable au lancement de l'appli et utiliser ensuite. Ainsi tu ne touche pas au parametres du PC et ton appli reste compatible avec tout les PC.
cs_franckydeluka
Messages postés228Date d'inscriptionmardi 5 avril 2005StatutMembreDernière intervention 4 janvier 20081 8 sept. 2005 à 10:25
Salut,
comme le dit Brunews si ton prog a besoin du point decimal tu le parametre dans ton form_load puis tu l'enleve dans le form_unload
regarde sur cette source tu telecharge le module :
sinon bien vu quand même mais tu peux améliorer.
ah oui pour les commentaires essaie de mettre tout en français parce qu'on parle pas tous forcément anglais
A+
Francky Deluca.
BruNews
Messages postés21040Date d'inscriptionjeudi 23 janvier 2003StatutModérateurDernière intervention21 août 2019 8 sept. 2005 à 09:52
Si ton prog a besoin du point décimal:
- Ecrire "." dans BDR
- PostMessage(HWND_BROADCAST, WM_SETTINGCHANGE, 0, 0)
- Faire tes traitements
- Remettre ancien séparateur décimal
- PostMessage(HWND_BROADCAST, WM_SETTINGCHANGE, 0, 0)
Evitera intervention utilisateur puisque devait se faire obligatoirement.
16 juil. 2009 à 12:01
La solution est de lire le séparateur en vigueur, de regarder si elle est présente dans la chaine, et si oui de la remplacer par le point puis d'utiliser Val. Attention, la fonction IsNumeric peut être très longue : mieux vaut remplacer systématiquement le séparateur par le point et d'utiliser Val.
16 juil. 2009 à 11:19
16 juil. 2009 à 11:16
D'où comme tu le soulignes, d'enregistrer de manière internationale !
16 juil. 2009 à 11:11
Si la chaine est conforme aux parametres regionnaux du poste, IsNumeric la reconnaitra, quels que soient les parametres utilisés.
Sinon, on a affaire a une chaine formatée en utilisant le format international, et Val s'en sortira haut la main.
La seule alternative est une donnée mal formée, compte tenu des parametres du poste. Dans ce cas, ton code la trafique et tente d'en récupérer une valeur correcte.
Ce genre de manipulation est à éviter et met à jour une mauvaise conception a un endroit où a un autre.
Comme je le dit dans mon article, on doit toujours transmettre les données de manière internationale, sauf si le destinataire est un humain dont on peut présumer des parametres régionnaux. Auquel cas, on formatte la donnée de manière à ce qu'elle lui paraisse lisible et non ambigüe.
16 juil. 2009 à 11:03
mais si le séparateur de millier est le point, ca marche pas dans ton cas. Ex : "123.456,7" renvoi 123.456
D'où dans ma fonction les "InStrRev"
16 juil. 2009 à 10:56
Public Function fctVal(ByVal Chaine As String) As Double
If IsNumeric(Chaine) Then
fctVal = CDbl(Chaine)
Else
fctVal = Val(Chaine)
End If
End Function
a lire:
http://blogs.codes-sources.com/renfield/archive/2009/04/14/param-tres-r-gionnaux-en-g-n-ral-et-avec-vb6.aspx
16 juil. 2009 à 10:22
Tenez, comme ca marche très bien et c'est rapide:
Public Function fctVal(ByVal Chaine As String) As Double
If Trim(Chaine) = "" Then
fctVal = 0
Exit Function
End If
Dim i As Long
Dim j As Long
i = InStrRev(Chaine, ".")
j = InStrRev(Chaine, ",")
If j > i Then
i = j
End If
Dim lD As Long
lD = Val(Mid(Chaine, i + 1))
Chaine = Mid$(Chaine, 1, i - 1)
Dim strTmp As String
Dim charTmp As String
For i = 1 To Len(Chaine)
charTmp = Mid(Chaine, i, 1)
If Asc(charTmp) >= 48 And Asc(charTmp) <= 57 Then
strTmp = strTmp & charTmp
ElseIf charTmp "+" Or charTmp "-" Then
' Le signe...
strTmp = strTmp & charTmp
ElseIf charTmp " " Or charTmp "." Or charTmp = "," Then
End If
Next i
fctVal = Val(strTmp) & "." & lD
End Function
17 févr. 2007 à 09:25
12 févr. 2007 à 10:57
est aussi bien efficace...
25 avril 2006 à 10:12
25 avril 2006 à 09:53
"chaine_de_caracteres2 = chaine_de_caracteres2 + test"
A ce moment là on est bon!
20 avril 2006 à 19:41
ta boucle est fausse, elle concatène a chaine_de_caracteres, une version ou les virgules sont remplacées par un point...
ex:
12,4512.45
20 avril 2006 à 18:48
scan ma chaine de caractères (caractère par caractère) et je remplace chaque virgule par un point à la reconstruction de la nouvelle chaine.
For i = 1 To Len(chaine_de_caracteres)
test = Mid(chaine_de_caracteres, i, 1)
If test = "," Then
test = "."
End If
chaine_de_caracteres = chaine_de_caracteres + test
Next
15 sept. 2005 à 17:46
ex: valeur dans le fichier xml: 0.30 -> insertion dans une table sur un PC avec virgule comme séparateur décimal: 30
13 sept. 2005 à 08:55
If InStr(1, CStr(CDbl(TimeValue("09:01:01"))), ",") > 0 Then
SeparateurDecimal = "Virgule"
Else
SeparateurDecimal = "POINT"
End If
ensuite dans ton code tu utilise cdouble("123,45")
'===================================
Public Function Cdouble(Chaine As String) As Double
'===================================
Dim Pos%
If Chaine = "" Then
Cdouble = 0
Exit Function
End If
If UCase(SeparateurDecimal) UCase("virgule") Or UCase(SeparateurDecimal) "," Then
Pos = InStr(1, Chaine, ",")
If Pos <> 0 Then
' rien faire c'est virgule pour virgule !!!
Cdouble = CDbl(Chaine)
Exit Function
Else
Pos = InStr(1, Chaine, ".")
If Pos <> 0 Then
Mid(Chaine, Pos, 1) = ","
End If
End If
Else ' point décimal
Pos = InStr(1, Chaine, ",")
If Pos <> 0 Then ' VIRGULE 0 CHANGER PAR POINT
Mid(Chaine, Pos, 1) = "."
Else
' ne rien faire POINT pour POINT
Cdouble = CDbl(Chaine)
Exit Function
End If
End If
' maintenant on peut convertir !! si > 0
If Val(Chaine) > 0 Then
On Error GoTo SORTIE
Cdouble = CDbl(Chaine)
Else
Cdouble = 0
End If
Exit Function
SORTIE:
Cdouble = 0
End Function
Pour la saisie tu testes et tu remplace la touche "." par ","
CQFD
signe Jipef
12 sept. 2005 à 16:56
12 sept. 2005 à 11:12
Considération a prendre en compte lors de l'écriture d'un programme qui se veut international
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vbcon98/html/vbconspecialcondsiderationswhenwritinginternationalcode.asp
et
Idem mais pour la lecture et l'écriture dans les fichiers.
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vbcon98/dt_vbconSpecialCondsiderationsWhenWritingInternationalCodeC.asp
12 sept. 2005 à 10:22
Il est très clair qu'un prog ne devrait jamais toucher aux params utilisateur mas au contraire s'adapter, il ne peut y avoir aucun doute là dessus. S'il ne le peut pas et que les temps de traitement sont cruciaux, on fait convertirr les données avant et/ou après par une dll en C et le prob est réglé à la base. Traiter des milliers de lignes en vb me semble une ineptie, ça n'a jamais été conçu pour cela.
12 sept. 2005 à 09:58
On l'avait dit c'est un sujet brulant. Et je pense que vous n'avez pas bien mes différents commentaires . Le problème de replace ou autres méthodes consitant à changer la "," en "." c'est dans le cas de grand traitement "milliers" de lignes à lire vous augmentez le temps de traitement ( j'ai pas vraiment de % de temps en plus à fournir mais le test serait intéressant pour variament être plus explicit). et ces Replaces ou autres à la lecture seront aussi nécessaires à l'écriture pour "Corriger" la sortie de FORMAT. Donc encore une fois au risque de me répéter je ne présente ici que MA solution qui n'st pas LA solution mais qui dans ce cas de figure me semble la plus appropriée. LA solution avec un L et un A majuscule serait de pouvoir spécifié les paramètres juste au niveau de l'appli. J'ai testé SetLocalInfo mais sans grand succès (manque de connaisssnace) Si quequ'un peut en dire plus sur cette fonction . C'est une piste
12 sept. 2005 à 09:44
Bien sûr que j'emploie Replace, mais j'ai noté la fonction la plus lisible pour les débutants.
Ce site est bien pour cela non?
J'ai surtout voulu dire que le logiciel doit être indépendant, car il est possible d'utiliser simultanément plusieurs logiciels.
Le faît de modifier le registre ? salut les dégats.
12 sept. 2005 à 09:07
12 sept. 2005 à 08:55
Confronté à ce problème, voici ma solution indépendante :
xx = votre donnée
For x = 1 to len(xx)
if mid(x,1,1) "." then mid(x,1,1) ","
next
Ou inversement si vous désirez des "."
12 sept. 2005 à 08:32
Le problème en imposant le symbole décimal, c'est quand l'application plante.
Un collègue a eu un problème avec une application il y a deux semaines car l'application qui modifie les paramètres régionaux avait planté et n'avait donc pas restauré les paramètres. A moins qu'il n'y ait un système pour voir quand une application plante, c'est une technique à éviter à tout prix pour moi.
Marc Allard
10 sept. 2005 à 12:11
Tout d'abord je voulais te dire, Cuq, que je te comprend bien puisque j'ai eu un problème à les Paramètres Régionaux sous windows : au lieu d'avoir ? comme symbole monnétaire j'avais $.
Pour le séparateur décimal je pense que la solution est celle que BruNews à écrite :
- au démarrage de ton application, tu places le séparateur en "."
- à la fermeture tu restore en ","
Le paramètre est stocké dans le base de registre, clé suivante :
HKCU/Control Panel/International
puis sous cette clé voir la valeur chaîne sDecimal.
Je pense qu'en lisant la valeur de cette clé, en la plaçant dans une variable temporaire, en paramétrant ensuite la valeur sur le "." au démarrage de ton application, serait une bonne solution.
Il te reste ensuite, à la fermeture de ton application, à restorer la clé à l'aide de cette variable temporaire.
Bon courage...
10 sept. 2005 à 09:13
Public Function Valider_Nombre(Valeur_A_Valider)
Select Case sDecimal
Case "."
Valider_Nombre = Replace(Valeur_A_Valider, ",", sDecimal)
Case ","
Valider_Nombre = Replace(Valeur_A_Valider, ".", sDecimal)
End Select
End Function
10 sept. 2005 à 09:10
Essai donc ça :
Dim dTest As Double
Dim sDecimal As String
dTest = 1 / 2
sDecimal = Mid$(CStr(dTest), 2, 1)
A chaque fois que l'on rencontre une valeur on fait un appel de la fonction suivante :
Public Function Valider_Nombre(Valeur_A_Valider)
Valider_Nombre = Replace(Valeur_A_Valider, ".", sDecimal)
Valider_Nombre = Replace(Valider_Nombre, ",", sDecimal)
End Function
Essai par exemple avec :
Msgbox Valider_Nombre(1.25)
Msgbox Valider_Nombre(3,42)
Bonne prog
++
9 sept. 2005 à 20:16
Pas question de tripoter dans les settings locale. Que ce passe t'il avec les autres application en mémoire, que ce passe t'il si l'appli plante avant de restaurer les settings ???
9 sept. 2005 à 08:54
Enfin un qui me comprend ou qui a simplement les mêmes problèmes.
:)
9 sept. 2005 à 08:39
9 sept. 2005 à 08:25
Personellement, je suis pour rechercher le symbole décimal, (Par exemple valeur 1.1).
On fait un csng ("1.1") et csng ("1,1").
On compage la longueur des deux et le plus long donne le signe décimal.
Par exemple, si csng("1.1") donne 11 (longueur 2) et csng ("1,1") donne 1,1 (longueur 3).
Ainsi, on sait que c'est la "," le séparateur décimal.
Après, pour toute entrée utilisateur, on fait un Replace (entree, ".", ",") et on a plus de problème.
On peut aussi faire une fois avec le replace (entree, ".", ",") et l'autre fois (entree, ",", ".") et le plus long est le bon. Ainsi, si l'utilisateur change son symbole décimal pendant que le programme fonctionne, le programme fonctionne toujours.
Marc Allard
9 sept. 2005 à 08:22
Je comprend pas vraiment ce que tu veux dire par "norme US".
Et au contraire de toi je pense que dans mon cas VB s'adapte très mal aux régional settings . Non plus exactement c'est ce Séparateur décimal qui est la cause de tout.
Pour les fichiers texte tu n'as pas à te discipliner .
SI tu prends des formats Texte existant des standard du marché comme par exemple:
DXF pour les données CAO géométriques 2D
IGES pour les données CAO géométriques 3D
GPS , WRML, STEP , STL qui sont des formats standards et beaucoup d'autres.
Dans ces fichiers le séparateur est le point. Pour nous (Français et européen en général le séparateur est la virgule) .
Donc en VB si tu veux lire, convertir ces données texte en valeur type double par exemple la conversion par val retournera une mauvaise valeur. Sauf si tu utilise Replace ) mais dans ce cas tu complique et ralenti ton code ) de plus très souvent le séparateur de champ dans ces fichiers est ... la virgule. Donc tu ne peut pas faire un seul replace sur une ligne relue mais X relpace après avoir isolé chaque valeur . Ou alors deux replace un pour le séparateur de champ un pour la décimal. Enfin je m'égare mais voila le type de problème. Même chose à l'écriture.
Enfin faut être confronté au problème pour bien comprendre. 5 ou alors c'est moi qui me fait chier depuis pas mal de temps mais à ce point là je doute )
9 sept. 2005 à 08:00
Je ne suios pas plus d'accord que sur l'autre source, sur ce procede...
VB s'adapte pas trop mal aux regional settings...
Reste a faciliter la saisie :
- le . du pave numerique, et la touche , insereront un separateur
- les dates (ne pas les oublier !) transformeront - / . en separateur de date
prendre les donnees d'un SGBD ne posera pas de soucis, si les champs sont bien types...
pour un fichier texte, il faudra se discipliner : adopter une convention
prendre la "norme US", par exemple...
8 sept. 2005 à 19:37
Le plus simple reste SetLocaleInfo() comme dit plus haut.
8 sept. 2005 à 19:37
:
pour GetLocalInfo ( oui c'est pour récupérer la valeur de la décimal sans passer par le registre un petit exemple pour les autres :
Const LOCALE_SDECIMAL = &HE
Private Declare Function GetLocaleInfo Lib "kernel32" Alias "GetLocaleInfoA" (ByVal Locale As Long, ByVal LCType As Long, ByVal lpLCData As String, ByVal cchData As Long) As Long
Private Declare Function SetThreadLocale Lib "kernel32" (ByVal LCID As Long) As Boolean
Private Sub Form_Load()
MsgBox "la décimal est le ou la : " & GetInfo(LOCALE_SDECIMAL)
End Sub
Public Function GetInfo(ByVal lInfo As Long) As String
Dim Buffer As String, Ret As String
Buffer = String$(256, 0)
Ret = GetLocaleInfo(LOCALE_USER_DEFAULT, lInfo, Buffer, Len(Buffer))
If Ret > 0 Then
GetInfo = Left$(Buffer, Ret - 1)
Else
GetInfo = ""
End If
End Function
8 sept. 2005 à 19:06
NombreDecimal As Long ' nombre de décimal
ZeroTete As Long ' Afficher les zéro en en tête (Marche pas ?)
Groupe As Long ' Groupement des digit ( 3 pour les milliers)
SeparateurDecimal As String ' Separateur des Decimals
SeparateurMillier As String ' Separateur des miliers ( Voir Groupe )
PositionSigneNegatif As Long ' Position du signe négatif
End Type
Private Declare Function GetNumberFormat Lib "kernel32" Alias "GetNumberFormatA" (ByVal Locale As Long, ByVal dwFlags As Long, ByVal lpValue As String, lpFormat As NUMBERFMT, ByVal lpNumberStr As String, ByVal cchNumber As Long) As Long
Private Sub Form_Load()
Dim Buffer As String, NF As NUMBERFMT
Buffer = String(255, 0)
With NF
.NombreDecimal = 3
.ZeroTete = 1
.Groupe = 3
.SeparateurDecimal = "."
.SeparateurMillier = " "
.PositionSigneNegatif = 1
End With
GetNumberFormat ByVal 0&, 0, "-0015545.242315654", NF, Buffer, Len(Buffer)
MsgBox Buffer
End Sub
Enfin ca reste lourd à mon avis si tu doit l'employer toute les 2 lignes de code et j'ai pas testé au niveau performance
Tu as un exemple pour SetThreadLocale
Cuq
8 sept. 2005 à 19:00
SetThreadLocale
8 sept. 2005 à 18:48
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/intl/nls_8d0z.asp
En regradant un peu j'ai vu GetNumberFormat a voir c'est peut être la solution
8 sept. 2005 à 18:41
T'as un exemple ? Mais bon ca reste le même truc ce qu'il faudrait c'est un SetLocalApliInfo :)
Cuq
8 sept. 2005 à 18:19
SetLocaleInfo(1024, 0x0E, ".");
Votre code ici.
SetLocaleInfo(1024, 0x0E, ",");
et voila remis en ordre.
8 sept. 2005 à 17:39
Je pense que tu n'as jamais éte confronté au problème avant d'écrire ton commentaire.
Oui c'est égoiste et oui c'est à l'appli d'être indépendante mais dans ce cas je n'ai pas trouvé de solution. de solution simple :)
dans mon type d'appli j'utilise souvent les fonctions VAL, FORMAT et autres de ce type ces fonctions étant directement dépendantes des paramètres régionaux pour s'affranchir du problème il faudrait ré-écrire toutes ces fonctions pour les rendre indépendantes de ce paramètre. Si comme moi tu es amené à relire beaucoup de ligne avec beaucoup de traitement ré-écrire ces fonctions c'est au détriment de la rapidité de ton logiciel.
De plus le problème c'est vraiment la virgule tu trouveras souvent la question de changer la virgule en point mais pas l'inverse. C'est un problème on va dire Francais ou europeen pas Anglo Saxon Voila pourquoi les §$%% de chez Microsoft n'on pas gérer ce problème. Maintenant la plus part des formats texte que tu doit relire utilise le point . Format d'echange standard comme IGES, DXF, WRML , GPS .... Format d'origine US . Donc si tu travail sur ce type de fichier tu as le problème.
Et dernier point tu remarqueras que si tu changes la virgule en point cela passe n'est pas très pénalisant .
Enfin je ne dit pas que c'est LA solution c'est MA solution que j'utilise depuis plusieurs années sans rencontrer de problème ni de retour des utilisateurs. Donc le constat est le suivant nous n'avons pas les mêmes utilisateurs.
Maintenant le truc Idéal serait de changer le paramètre pas au niveau de l'utilisateur mais au niveau de l'appli . J'ai longtemps cherché je cherche encore .... Si vous avez un avis une idée je suis preneur.
Mais comme indiqué dans le texte de départ ce sujet est polémique .Il est polémique pour une raison comme tu le dit c'est égoiste et pas pro donc ce genre de sentiment déclenche la polémique et les sarcasmes seulement voilà On le sait , je le sais et si j'ai pris cette solution c'est que justement c'était la meilleru à mon avis.
En attendant la suite ... Cuq
8 sept. 2005 à 16:50
Imagine que moi je décide de faire tout mes progs en utilisant la virgule comme séparateur décimal, et que comme toi je force l'inscription dans le registre. Imagine ensuite qu'une même personne utilise nos 2 applis. Que va-t-il se passer ?
Ta solution :
1 - Est égoïste
2 - N'en est pas une (puisque je viens de te montrer une faille)
3 - N'est pas pro (s'est au développeur de s'adapter et nom à l'OS).
A mon sens il faut stocker le séparateur décimal du PC dans une variable au lancement de l'appli et utiliser ensuite. Ainsi tu ne touche pas au parametres du PC et ton appli reste compatible avec tout les PC.
8 sept. 2005 à 10:25
comme le dit Brunews si ton prog a besoin du point decimal tu le parametre dans ton form_load puis tu l'enleve dans le form_unload
regarde sur cette source tu telecharge le module :
http://www.vbfrance.fr/code.aspx?id=3258
elle est très bien faite.
sinon bien vu quand même mais tu peux améliorer.
ah oui pour les commentaires essaie de mettre tout en français parce qu'on parle pas tous forcément anglais
A+
Francky Deluca.
8 sept. 2005 à 09:52
- Ecrire "." dans BDR
- PostMessage(HWND_BROADCAST, WM_SETTINGCHANGE, 0, 0)
- Faire tes traitements
- Remettre ancien séparateur décimal
- PostMessage(HWND_BROADCAST, WM_SETTINGCHANGE, 0, 0)
Evitera intervention utilisateur puisque devait se faire obligatoirement.