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
 

Roblochon

XLDnaute Accro
bonjour,

ChiffresAfterVirgule = IIf(opt = 1, nb, CLng(cap))

Mettre le paramètre opt en optional avec une valeur par default serait plus sympa.
Lui changé le type (boolean) et le nom également
exemple :
ChiffresAfterVirgule(dnum as double, optional Valeur as boolean = True) as long

Si Valeur = True la valeur des chiffres après la virgule sinon le nombre

Pas besoin de retourner un double (pas de virgule dans les chiffres après la virgule) un long est plus cohérent.

cordialement
 

dysorthographie

XLDnaute Occasionnel
bonjour,
VB:
Function ChiffresAfterVirgule(dNum As Double, Optional Nb As Boolean = False) As Long
Dim SepDec As String, T
SepDec = Application.International(xlDecimalSeparator)
 T = Val(Split(dNum & SepDec, SepDec)(1))
 If Nb = True Then T = Len(T)
 ChiffresAfterVirgule = T
End Function
Sub test()
Debug.Print ChiffresAfterVirgule(125.0000587349), ChiffresAfterVirgule(125.0000587349, True)
End Sub
 

Roblochon

XLDnaute Accro
Re,

Et sans le if NB ... :

Function ChiffresAfterVirgule(dNum As Double, Optional Nb As Boolean = False) As double
Dim SepDec As String, T
SepDec = Application.International(xlDecimalSeparator)
T = Val(Split(dNum & SepDec, SepDec)(1))
ChiffresAfterVirgule = Array(T, Len(T))(-Nb)
End Function


Cordialement
 

dysorthographie

XLDnaute Occasionnel
Maintenant comme notre ami veut un retour au format numérique 0,025 donerra 25 ce qui est une erreur !
Et 1 sera vue comme 1,0 et retournerra une longueur de 1 ce qui est également une erreur !

Personnellement j'aurais gardé le code originel mais en centrant la cellule à droite !
 
Dernière édition:

Roblochon

XLDnaute Accro
ChiffresAfterVirgule = Array(T, Len(T))(-Nb)
N'a rien changé à l'affaire. Mais comme il n'intervient pas, j'attends de voir ce qu'il voudrait exactement.
[edit] hello mapomme :) je répondais à dysorthographie :)
 

dysorthographie

XLDnaute Occasionnel
On est bien d'accord mon if et ton array son bien la même chose!

Ma remarque ressemblait plus à une auto critique !
 

job75

XLDnaute Barbatruc
VB:
Function ChiffresAfterVirgule(dNum As Double, opt As Byte)
If InStr(dNum, Application.DecimalSeparator) = 0 Then ChiffresAfterVirgule = "": Exit Function
ChiffresAfterVirgule = CDbl(Mid(dNum, InStr(dNum, Application.DecimalSeparator) + 1))
If opt = 1 Then ChiffresAfterVirgule = Len(CStr(ChiffresAfterVirgule))
End Function
 

dysorthographie

XLDnaute Occasionnel
Si la fonction n'est pas typée numérique alors le résultat dans la cellule sera centré à gauche !

Variant =1; integer=1
D'où ma remarque précédente.
 
Dernière édition:

job75

XLDnaute Barbatruc
Il faut que la fonction soit Variant puisqu'il faut lui donner la valeur "" quand dNum est entier.
 

dysorthographie

XLDnaute Occasionnel
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).
C'est uniquement parce la fonction retourne un variant et pas un numérique {integer, long ou double}

Le vrai problème c'est qu'il faut faire un choix entre 0000x et x!
 

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
 

Fichiers joints

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
 

Créez un compte ou connectez vous pour répondre

Vous devez être membre afin de pouvoir répondre ici

Créer un compte

Créez un compte Excel Downloads. C'est simple!

Connexion

Vous avez déjà un compte? Connectez vous ici.

Haut Bas