XL 2010 Convertir une variable dans une fonction

Magic_Doctor

XLDnaute Barbatruc
Bonjour,

J'ai bricolé une fonction toute simple qui marche bien. Elle me renvoie soit le nombre de décimales après la virgule du chiffre traité, soit l'ensemble des chiffres après la virgule.
Si je rentre dans la fonction, par exemple, 25,000587, j'obtiens bien 000587 sous forme de chaîne (qui apparaîtra, bien évidemment, à gauche de la cellule du résultat.
Maintenant, si je rentre dans la fonction 125,298, j'obtiens bien 298, mais toujours sous forme de chaîne, et je voudrais, à ce moment là, que ce soit un chiffre (qui devrait apparaître à droite de la cellule du résultat).
J'ai essayé, sans succès, par différents moyens de régler ce problème.
VB:
Function ChiffresAfterVirgule(dNum As Double, opt As Byte)
'Renvoie le nombre de chiffres après la virgule ou tous les chiffres après la virgule
'- dNum : le chiffre à traiter
'- opt : si opt = 1 --> le nombre de chiffres après la virgule
'        si opt <> 1 --> tous les chiffres après la virgule
'Ex : 125,587349 | opt = 1 --> 6
'                  opt <> 1 --> 587349

Dim SepDec$, tmp, posDec, nb As Double, cap$

  SepDec = Application.International(xlDecimalSeparator)
  tmp = CStr(dNum)
  posDec = InStr(tmp, SepDec)
  nb = Len(tmp) - Len(Right(tmp, posDec)) 'nombre de chiffres après la virgule
  cap = Right(dNum, nb) 'chiffres après la virgule
 
'*******************************************************************************************************************
  'If Left(cap, 1) <> "0" Then cap = CDbl(cap)                'ne fait strictement rien
  'If Left(cap, 1) <> "0" Then TypeName(cap) = "Double"       'ne marche pas
'*******************************************************************************************************************
 
  ChiffresAfterVirgule = IIf(opt = 1, IIf(posDec = 0, 0, nb), IIf(posDec = 0, 0, cap))
  
End Function
 

patricktoulon

XLDnaute Barbatruc
bonjour a tous
VB:
Sub testX()
MsgBox GetDecimale(125.0000587349, True)
MsgBox GetDecimale(125.0000587349)
MsgBox GetDecimale(10, True)
MsgBox GetDecimale("10,53200", True)
End Sub

Function GetDecimale(nombre As String, Optional Nb As Boolean = False) As Long
Dim E&, D, dec
dec = Split(nombre, Application.International(xlDecimalSeparator))
E = dec(0)
If UBound(dec) = 1 Then D = Val(dec(1)) Else D = ""
GetDecimale = Array(D, Len(D))(Abs(Nb))
End Function

le soucis c'est que l'on perd les zéro au début de la décimale donc nb sera faux dans ces cas là
pour nb il faut travailler en string

A noter quelque chose d'amusant tout de même
c'est l'auto conversion (string/long) de la fonction elle même



Function GetDecimale(nombre As String, Optional Nb As Boolean = False) As Long
'...
'...
'... Else D = ""
autrement dit je met un empty ou string vide dans un long
dans la sub test j'ai bien 0 décimale pour "10" ;)

a noter aussi que si je fait
If UBound(dec) = 1 Then D = dec(1) Else D = ""
pour nb j'ai bien 10 pour le nombre de décimales
 
Dernière édition:

mapomme

XLDnaute Barbatruc
Supporter XLD
Bonjour à toutes et tous :) :) ,

Une version avec une sauce à la pomme.

Elle doit gérer les nombres du type =PI() ou =1/3.
1593253741672.png




VB:
Function PartieDecimale(x As Double, Optional Taille)
Dim sep, v
   sep = Mid(1.1, 2, 1): v = InStr(x, sep)
   If v = 0 Then
      PartieDecimale = ""
   Else
      v = Mid(x, v + 1)
      On Error Resume Next
      If Left(v, 1) <> "0" Then
         If IsError(CLng(v)) Then PartieDecimale = v & "+" Else PartieDecimale = CLng(v)
      Else
         PartieDecimale = v
      End If
   End If
   If Not IsMissing(Taille) Then
      If Right(PartieDecimale, 1) = "+" Then PartieDecimale = Len(PartieDecimale) - 1 & "+" Else PartieDecimale = Len(PartieDecimale)
   End If
End Function
 

Pièces jointes

  • Magic_Doctor- Partie décimale- v1.xlsm
    21.4 KB · Affichages: 8

patricktoulon

XLDnaute Barbatruc
A noter encore quelque chose d'amusant
quand on code dans vbe un décimal en double et non en string
(10.53200/"10,53200")
on ne peut aller au dela de 3 décimales si les chiffre a droite sont des zéro
et le séparateur doit être une virgule en string
demo4.gif




on a là aussi un bel exemple d'auto conversion car dans la fonction le point ou virgule est bien reconnu
avec Application.International(xlDecimalSeparator)
 

job75

XLDnaute Barbatruc
le soucis c'est que l'on perd les zéro au début de la décimale
Très juste donc utiliser :
VB:
Function ChiffresAfterVirgule(dNum As Double, opt As Byte)
If InStr(dNum, Application.DecimalSeparator) = 0 Then ChiffresAfterVirgule = "": Exit Function
ChiffresAfterVirgule = Mid(dNum, InStr(dNum, Application.DecimalSeparator) + 1)
If opt = 1 Then ChiffresAfterVirgule = Len(ChiffresAfterVirgule) Else _
    If Left(ChiffresAfterVirgule, 1) <> "0" Then ChiffresAfterVirgule = CDbl(ChiffresAfterVirgule)
End Function
 

Magic_Doctor

XLDnaute Barbatruc
Bonsoir,

Merci pour vos réponses que j'ai bien lues. J'ai fait quelques modifications tenant compte de vos conseils avertis.
Peut-être ne me suis-je pas bien exprimé. Je voudrais, suivant le choix :
- soit l'INTÉGRALITÉ des nombres après la virgule (s'il y en a) de la variable analysée par la fonction.
Si cette variable est, par exemple, 12,78542 --> 78542
Si cette variable est, par exemple, 56,00258 --> 00258
Pourquoi ? C'est le dernier argument optionnel de la fonction qui donnera l'explication.
- soit le nombre de chiffres après la virgule. Par exemple : 758,758955 --> 6
Le dernier argument de la fonction ("NbEnt") est optionnel et il ne peut être qu'un nombre entier. Si je choisi, par exemple, le nombre entier 15, la fonction me retournera ce nombre suivi des décimales du nombre "dNum". Prenons un exemple :
dNum = 45,998025
NbEnt = 15
Résultat : 15,998025
Si NbEnt = 0 --> 0,998025

Je suis à 2 doigts de résoudre ce problème, mais je tourne en rond...
VB:
Function ChiffresAfterVirgule(dNum As Double, Optional opt As Boolean = True, Optional NbEnt As String)

'Renvoie le nombre de chiffres après la virgule ou tous les chiffres après la virgule
'- dNum : le chiffre à traiter
'- opt : si opt = True ou omis (opt est True par défaut) --> l'INTÉGRALITÉ des chiffres après la virgule (par ex : 574225 ou 000086574)
'        si opt = False --> le nombre de chiffres après la virgule
'- NbEnt : un nombre entier qui, dans le résultat de la fonction, sera suivi d'une virgule puis des décimaux après la virgule de la variable "dNum"
'Ex : 125,587349 | opt = True (ou omis) --> 587349
'                  opt = False --> 6
'     si dNum = 2045,0657 et NbEnt = 5 --> 5,0657

Dim SepDec$, tmp$, posDec As Long, nb As Long, cap$

  SepDec = Application.International(xlDecimalSeparator)
  tmp = CStr(dNum)
  posDec = InStr(tmp, SepDec)
  nb = IIf(posDec = 0, 0, Len(tmp) - Len(Right(tmp, posDec))) 'nombre de chiffres après la virgule
  cap = Right(dNum, nb) 'chiffres après la virgule
 
  If Not IsMissing(NbEnt) Then cap = CStr(NbEnt) & "," & cap 'on créé une chaîne avec comme préfixe la valeur entière choisie pour la variable "NbEnt" &
  '                                                           comme suffixe les chiffres après la virgule de la variable "dNum", précédés d'une virgule
 
  ChiffresAfterVirgule = IIf(IsMissing(opt) = True And IsMissing(NbEnt) = False, cap, IIf(opt = True And IsMissing(NbEnt) = True, cap, nb))

End Function
 

Dranreb

XLDnaute Barbatruc
Bonsoir.
Moi je dirais :
VB:
Function ChiffresAfterVirgule(ByVal dNum As Double, Optional ByVal Opt As Boolean = True, Optional ByVal NbEnt As Long) As Double
'Renvoie le nombre de chiffres après la virgule ou tous les chiffres après la virgule
'- dNum : le chiffre à traiter
'- opt : si opt = True ou omis (opt est True par défaut) --> l'INTÉGRALITÉ des chiffres après la virgule (par ex : 574225 ou 000086574)
'        si opt = False --> le nombre de chiffres après la virgule
'- NbEnt : un nombre entier qui, dans le résultat de la fonction, sera suivi d'une virgule puis des décimaux après la virgule de la variable "dNum"
'Ex : 125,587349 | opt = True (ou omis) --> 587349
'                  opt = False --> 6
'     si dNum = 2045,0657 et NbEnt = 5 --> 5,0657
   If Opt Then
      ChiffresAfterVirgule = Len(Split(Str$(dNum) & ".", ".")(1))
   Else
      dNum = Abs(dNum): dNum = dNum - Int(dNum)
      ChiffresAfterVirgule = NbEnt + dNum
      End If
   End Function
 

Dranreb

XLDnaute Barbatruc
Je le redonne parce que j'avais interverti les résultats selon Opt et parce qu'on n'avait pas les bonnes décimales si NbEnt était négatif :
VB:
Function ChiffresAfterVirgule(ByVal dNum As Double, Optional ByVal Opt As Boolean = True, Optional ByVal NbEnt As Long) As Double
'Renvoie le nombre de chiffres après la virgule ou tous les chiffres après la virgule
'- dNum : le chiffre à traiter
'- opt : si opt = True ou omis (opt est True par défaut) --> l'INTÉGRALITÉ des chiffres après la virgule (par ex : 574225 ou 000086574)
'        si opt = False --> le nombre de chiffres après la virgule
'- NbEnt : un nombre entier qui, dans le résultat de la fonction, sera suivi d'une virgule puis des décimaux après la virgule de la variable "dNum"
'Ex : 125,587349 | opt = True (ou omis) --> 587349
'                  opt = False --> 6
'     si dNum = 2045,0657 et NbEnt = 5 --> 5,0657
   If Opt Then
      dNum = Abs(dNum): If NbEnt < 0 Then dNum = -dNum
      ChiffresAfterVirgule = NbEnt + (dNum - Int(dNum))
   Else
      ChiffresAfterVirgule = Len(Split(Str$(dNum) & ".", ".")(1))
      End If
   End Function
 

Dranreb

XLDnaute Barbatruc
Remarque: avec Opt:=False, donne le nombre de décimale de sa reconversion en décimal tronquée. ChiffresAfterVirgule(0.1, False, 0) donne 1, pas 55 comme dans sa vraie valeur qui est de 0,1000000000000000055511151231257827021181583404541015625
(soit 3602879701896397 / 2^55 ou encore, en hexadécimal +&H1,999999999999A × 2^-&H004)
 

patricktoulon

XLDnaute Barbatruc
re
j'avoue etre un peu perdu là
a ajouter un entier pour pouvoir avoir tout les chiffre âpres la virgule sous la forme d'un long ou double
le len du décimal
j'ai du mal a croire qu'il faille pédaler autant que ça
VB:
Sub test()
    Dim nombre As String
    nombre = 125.000532
    MsgBox " il y a " & ChiffresAfterVirgule(nombre, True) & " chiffres apres la virgule"
    MsgBox "la valeur des decimales =" & ChiffresAfterVirgule(nombre)
End Sub

Function ChiffresAfterVirgule(nombre As String, Optional opt = False) As Double
       Dim DecString$
    DecString = Mid(nombre, InStrRev(nombre, ",") + 1)
    If opt Then ChiffresAfterVirgule = Len(DecString) Else ChiffresAfterVirgule = Val("0." & DecString)
End Function
on travaille en string mais les retours sont bien des numériques
 

Discussions similaires