Ecrire des nombres en lettre C#, VB.Net et VBA

Contenu du snippet

Des codes "perfectibles" existent ici ou là.
Par perfectibles j'entends:
   -quelques coquilles
   -ou utlisant une pratique contreversée
   -ou encore mélageant VB6 et VB.Net

C'est pourquoi je vous propose ici mes versions.
En .Net, j'ai fait une extension de classe, la méthode est ajoutée aux méthodes d'un double

C#

Code de test

            List<string> lesNombres = new List<string>();
            lesNombres.Add(3210987654321.2.ToLettres());
            lesNombres.Add(123456789012345.123456789.ToLettres());//ce nombre n'existe pas en double, c'est 123456789012345.12 qui est transmis à la méthode
            lesNombres.Add(1234.123456789.ToLettres());
            lesNombres.Add((-4321.987654321).ToLettres());
            lesNombres.Add(1e16.ToLettres());//ce nombre est trop grand
            lesNombres.Add(0.12345678961.ToLettres());//il y a trop de chiffres dérrière la virgule, le resultat sera arrondi
            lesNombres.Add(6795432.456.ToLettres(Pays.Belgique, Devise.Euro));
            lesNombres.Add(400400400400400.0.ToLettres());
            lesNombres.Add(0.4.ToLettres());

la classe

using System;
using System.Collections.Generic;

namespace test
{
    public static class NombreEnLettres
    {
        private static string[] jusqueSeize = { "zéro", "un", "deux", "trois", "quatre", "cinq", "six", "sept", "huit", "neuf", "dix", "onze", "douze", "treize", "quatorze", "quinze", "seize" };

        private static string[] dizaines = { "rien", "dix", "vingt", "trente", "quarante", "cinquante", "soixante", "soixante", "quatre-vingt", "quatre-vingt"};

        private static List<string> resultat;

        /// <summary>
        /// Méthode d'extension de la classe double écrivant le nombre en lettres
        /// </summary>
        /// <param name="Nombre">Nombre à écrire</param>
        /// <param name="LePays">Pays d'utilisation, pour spécificitées régionnales</param>
        /// <param name="LaDevise">Devise à utliser</param>
        /// <returns></returns>
        public static string ToLettres(this double Nombre, Pays LePays = Pays.France, Devise LaDevise = Devise.Aucune)
        {

            resultat = new List<string>();

            switch (Math.Sign(Nombre))
            {
                case -1:
                    resultat.Add("moins ");
                    Nombre *= -1;
                    break;

                case 0:
                    return jusqueSeize[0];
            }

            if (Nombre >= 1e16)
                return "Nombre trop grand";

            
            Int64 partieEntiere = (Int64)(Nombre);
            double partieDecimale = Nombre - partieEntiere;

            string[] milliers = { "", "mille", "million", "milliard", "billion", "billiard" };

            if (partieEntiere > 0)
            {
                List<int> troisChiffres = new List<int>();//liste qui scinde la partie entière en morceaux de 3 chiffres

                while (partieEntiere > 0)
                {
                    troisChiffres.Add((int)(partieEntiere % 1000));
                    partieEntiere /= 1000;
                }

                double reste = Nombre - partieEntiere;



                for (int i = troisChiffres.Count - 1; i >= 0; i--)
                {
                    int nombre = troisChiffres[i];

                    if (nombre > 1)//valeurs de milliers au pluriel
                    {
                        resultat.Add(Ecrit3Chiffres(troisChiffres[i], LePays, i==0));
                        if (i > 1)// mille est invariable et "" ne prend pas de s 
                            resultat.Add(milliers[i] + "s");
                        else if (i == 1)
                            resultat.Add(milliers[i]);
                    }
                    else if (nombre == 1)
                    {
                        if (i != 1) resultat.Add("un");//on dit un million, mais pas un mille
                        resultat.Add(milliers[i]);
                    }
                    //on ne traite pas le 0, car on ne dit pas X millions zéro mille Y.
                }
            }
            else
                resultat.Add(jusqueSeize[0]);
            
            switch(LaDevise)
            {
                case Devise.Dollar:
                    resultat.Add("$");
                    break;

                case Devise.Euro:
                    resultat.Add("€");
                    break;

                case Devise.FrancSuisse:
                    resultat.Add("CHF");
                    break;

            }

            if (LaDevise != Devise.Aucune)
            {
                partieDecimale = Math.Round(partieDecimale, 2);
                if (partieDecimale != 0)
                {
                    resultat.Add("et");
                    resultat.Add(Ecrire2Chiffres((int)(partieDecimale * 100), LePays));
                    resultat.Add("centimes");
                }
            }
            else
            {
                milliers = new[] { "millième", "millionième", "milliardième" };

                //avec l'imprécision des nombres à virgules flotantes,  1234562.789 - 1234562 donne 0.78900000010617077 il faut donc compter le nombre de chiffres décimaux du nombre original et arrondir le resultat de la soustraction 
                string[] morceaux = Nombre.ToString("G25").Split(new []{'.',','});//par défaut ToString arrondi à 10^-8, le format G25 oblige à écrire 25 caractères s'ils sont présents soit (au pire) 15 avant la virgule, la virgule et 9 après, split permet de découper le string obtenu

                if (morceaux.Length == 2)//il y a une partie décimale
                {
                    resultat.Add("et");

                    int lenghtPartieDecimale = morceaux[1].Length;
                    if (lenghtPartieDecimale > 9)
                        lenghtPartieDecimale = 9;//on se limite à 10^-9

                    partieDecimale = Math.Round(partieDecimale, lenghtPartieDecimale);

                    int i = 0;
                    while (partieDecimale > 0)
                    {
                        partieDecimale = partieDecimale * 1000;
                        int valeur = (int)partieDecimale;
                        lenghtPartieDecimale -= 3;
                        if (lenghtPartieDecimale < 0)
                            lenghtPartieDecimale = 0;
                        partieDecimale = Math.Round(partieDecimale - valeur, lenghtPartieDecimale);

                        if (valeur != 0)
                        {
                            resultat.Add(Ecrit3Chiffres(valeur, LePays, false));
                            if (valeur > 1)
                                resultat.Add(milliers[i++] + "s");
                            else
                                resultat.Add(milliers[i++]);

                        }
                    }


                }
            }



            return string.Join(" ", resultat);
        }

        /// <summary>
        /// Ecrit les nombres de 0 à 999
        /// </summary>
        /// <param name="Nombre">Nombre à écrire</param>
        /// <param name="LePays">Pays d'utilisation, pour spécificitées régionnales</param>
        /// <param name="RegleDuCent">pour 400 cent prend un s alors que pour 400 000 ou 0.400 non </param>
        private static string Ecrit3Chiffres(int Nombre, Pays LePays, bool RegleDuCent)
        {
            if (Nombre == 100)
                return "cent";

            if(Nombre < 100)
                return Ecrire2Chiffres(Nombre, LePays);

            int centaine = Nombre / 100;
            int reste = Nombre % 100;

            if (reste == 0)
                if (RegleDuCent)//Cent prend un s quand il est multiplié et non suivi d'un nombre, comme le cas de 100 est déjà traité on est face à un multiple
                    return jusqueSeize[centaine] + " cents";
                else
                    return jusqueSeize[centaine] + " cent";// par contre s'il est suivi de mille, millions, millièmes etc... pas de s

            if (centaine == 1)
                return "cent " + Ecrire2Chiffres(reste, LePays);//on ne dit pas un cent X, mais cent X

            return jusqueSeize[centaine] + " cent " + Ecrire2Chiffres(reste, LePays);
        }

        /// <summary>
        /// Ecrit les nombres de 0 à 99
        /// </summary>
        /// <param name="Nombre">Nombre à écrire</param>
        /// <param name="LePays">Pays d'utilisation, pour spécificitées régionnales</param>
        /// <returns></returns>
        private static string Ecrire2Chiffres(int Nombre, Pays LePays)
        {
            if (LePays != Pays.France)
            {
                dizaines[7] = "septante";
                dizaines[9] = "nonante";
            }
            if (LePays == Pays.Suisse)
                dizaines[8] = "huitante";

            if (Nombre < 17)
                return jusqueSeize[Nombre];

            switch (Nombre)//cas particuliers de 71, 80 et 81
            {
                case 71://en France 71 prend un et
                    if (LePays == Pays.France)
                        return "soixante et onze";
                    break;

                case 80://en France et Belgique le vingt prend un s
                    if (LePays == Pays.Suisse)
                        return dizaines[8];
                    else
                        return dizaines[8] + "s";

                case 81://en France et Belgique il n'y a pas de et
                    if (LePays != Pays.Suisse)
                        return dizaines[8] + "-un";
                    break;
            }


            int dizaine = Nombre / 10;
            int unite = Nombre % 10;

            string laDizaine = dizaines[dizaine];

            if (LePays == Pays.France && (dizaine == 7 || dizaine == 9))
            {
                dizaine--;
                unite += 10;
            }


            switch (unite)
            {
                case 0:
                    return laDizaine;

                case 1:
                    return laDizaine + " et un";

                case 17://pour 77 à 79 et 97 à 99
                case 18:
                case 19:
                    unite = unite % 10;
                    return laDizaine + "-dix-" + jusqueSeize[unite];

                default:
                    return laDizaine + "-" + jusqueSeize[unite];
            }
        }
    }

    public enum Pays
    {
        France,
        Belgique,
        Suisse
    }

    public enum Devise
    {
        Aucune,
        Euro,
        FrancSuisse,
        Dollar
    }
}

VB.Net

Code de test

        Dim lesNombres As New List(Of String)()
        Dim nombreExemple As Double = 123.456
        lesNombres.Add(nombreExemple.ToLettres()) 'on peut appliquer la méthode d'extension sur une variable de type double
        lesNombres.Add(3210987654321.2.ToLettres()) 'on peut aussi l'appliquer directement sur un nombre (Attention, il faut une virgule, sinon le nombre est pris comme un entier et la méthode n'étend pas les entiers)
        lesNombres.Add(123456789012345.12.ToLettres()) 'ce nombre n'existe pas en double, c'est 123456789012345.12 qui est transmis à la méthode
        lesNombres.Add(1234.123456789.ToLettres())
        lesNombres.Add((-4321.987654321).ToLettres())
        lesNombres.Add(1.0E+16.ToLettres()) 'ce nombre est trop grand
        lesNombres.Add(0.12345678961.ToLettres()) 'il y a trop de chiffres dérrière la virgule, le resultat sera arrondi
        lesNombres.Add(6795432.456.ToLettres(Pays.Belgique, Devise.Euro))
        lesNombres.Add(400400400400400.0.ToLettres())
        lesNombres.Add(0.4.ToLettres())

Le module

 
En effet contrairement à C# ou l'extension se code dans l'équivalent d'une classe Shared, en VB.Net c'est dans un module

Imports System
Imports System.Collections.Generic

Public Module NombreEnLettres
    Private jusqueSeize() As String = {"zéro", "un", "deux", "trois", "quatre", "cinq", "six", "sept", "huit", "neuf", "dix", "onze", "douze", "treize", "quatorze", "quinze", "seize"}

    Private dizaines() As String = {"rien", "dix", "vingt", "trente", "quarante", "cinquante", "soixante", "soixante", "quatre-vingt", "quatre-vingt"}

    Private resultat As List(Of String)

    ''' <summary>
    ''' Méthode d'extension de la classe double écrivant le nombre en lettres
    ''' </summary>
    ''' <param name="Nombre">Nombre à écrire</param>
    ''' <param name="LePays">Pays d'utilisation, pour spécificitées régionnales</param>
    ''' <param name="LaDevise">Devise à utliser</param>
    ''' <returns></returns>
    <System.Runtime.CompilerServices.Extension> _
    Public Function ToLettres(ByVal Nombre As Double, Optional ByVal LePays As Pays = Pays.France, Optional ByVal LaDevise As Devise = Devise.Aucune) As String

        resultat = New List(Of String)()

        Select Case Math.Sign(Nombre)
            Case -1
                resultat.Add("moins ")
                Nombre *= -1

            Case 0
                Return jusqueSeize(0)
        End Select

        If Nombre >= 1.0E+16 Then
            Return "Nombre trop grand"
        End If


        Dim partieEntiere As Int64 = CLng(Math.Floor(Nombre))
        Dim partieDecimale As Double = Nombre - partieEntiere

        Dim milliers() As String = {"", "mille", "million", "milliard", "billion", "billiard"}

        If partieEntiere > 0 Then
            Dim troisChiffres As New List(Of Integer)() 'liste qui scinde la partie entière en morceaux de 3 chiffres

            Do While partieEntiere > 0
                troisChiffres.Add(CInt(Math.Floor(partieEntiere Mod 1000)))
                partieEntiere \= 1000
            Loop

            Dim reste As Double = Nombre - partieEntiere

            For i As Integer = troisChiffres.Count - 1 To 0 Step -1
                Dim leNombre As Integer = troisChiffres(i)

                If leNombre > 1 Then 'valeurs de milliers au pluriel
                    resultat.Add(Ecrit3Chiffres(troisChiffres(i), LePays, i = 0)) 'la régle du cent ne s'applique que pour i = 1
                    If i > 1 Then ' mille est invariable et "" ne prend pas de s
                        resultat.Add(milliers(i) & "s")
                    ElseIf i = 1 Then
                        resultat.Add(milliers(i))
                    End If
                ElseIf leNombre = 1 Then
                    If i <> 1 Then resultat.Add("un") 'on dit un million, mais pas un mille
                    resultat.Add(milliers(i))
                End If
                'on ne traite pas le 0, car on ne dit pas X millions zéro mille Y.
            Next i
        Else
            resultat.Add(jusqueSeize(0))
        End If

        Select Case LaDevise
            Case Devise.Dollar
                resultat.Add("$")

            Case Devise.Euro
                resultat.Add("€")

            Case Devise.FrancSuisse
                resultat.Add("CHF")

        End Select

        If LaDevise <> Devise.Aucune Then
            partieDecimale = Math.Round(partieDecimale, 2)
            If partieDecimale <> 0 Then
                resultat.Add("et")
                resultat.Add(Ecrire2Chiffres(CInt(Math.Floor(partieDecimale * 100)), LePays))
                resultat.Add("centimes")
            End If
        Else
            milliers = {"millième", "millionième", "milliardième"}

            'avec l'imprécision des nombres à virgules flotantes,  1234562.789 - 1234562 donne 0.78900000010617077 il faut donc compter le nombre de chiffres décimaux du nombre original et arrondir le resultat de la soustraction 
            Dim morceaux() As String = Nombre.ToString("G25").Split({"."c, ","c}) 'par défaut ToString arrondi à 10^-8, le format G25 oblige à écrire 25 caractères s'ils sont présents soit (au pire) 15 avant la virgule, la virgule et 9 après, split permet de découper le string obtenu

            If morceaux.Length = 2 Then 'il y a une partie décimale
                resultat.Add("et")

                Dim lenghtPartieDecimale As Integer = morceaux(1).Length
                If lenghtPartieDecimale > 9 Then
                    lenghtPartieDecimale = 9 'on se limite à 10^-9
                End If

                partieDecimale = Math.Round(partieDecimale, lenghtPartieDecimale)

                Dim i As Integer = 0
                Do While partieDecimale > 0
                    partieDecimale = partieDecimale * 1000
                    Dim valeur As Integer = CInt(Math.Floor(partieDecimale))
                    lenghtPartieDecimale -= 3
                    If lenghtPartieDecimale < 0 Then
                        lenghtPartieDecimale = 0
                    End If
                    partieDecimale = Math.Round(partieDecimale - valeur, lenghtPartieDecimale)

                    If valeur <> 0 Then
                        resultat.Add(Ecrit3Chiffres(valeur, LePays, False)) '0.400 ne prend pas d's car il est suivi de millièmes
                        If valeur > 1 Then
                            resultat.Add(milliers(i) & "s")
                            i += 1
                        Else
                            resultat.Add(milliers(i))
                            i += 1
                        End If

                    End If
                Loop


            End If
        End If



        Return String.Join(" ", resultat)
    End Function

    ''' <summary>
    ''' Ecrit les nombres de 0 à 999
    ''' </summary>
    ''' <param name="Nombre">Nombre à écrire</param>
    ''' <param name="LePays">Pays d'utilisation, pour spécificitées régionnales</param>
    '''<param name="RegleDuCent">pour 400 cent prend un s alors que pour 400 000 ou 0.400 non </param>
    Private Function Ecrit3Chiffres(ByVal Nombre As Integer, ByVal LePays As Pays, ByVal RegleDuCent As Boolean) As String
        If Nombre = 100 Then
            Return "cent"
        End If

        If Nombre < 100 Then
            Return Ecrire2Chiffres(Nombre, LePays)
        End If

        Dim centaine As Integer = Nombre \ 100
        Dim reste As Integer = Nombre Mod 100

        If reste = 0 Then
            If RegleDuCent Then 'Cent prend un s quand il est multiplié et non suivi d'un nombre, comme le cas de 100 est déjà traité on est face à un multiple
                Return jusqueSeize(centaine) & " cents"
            Else
                Return jusqueSeize(centaine) & " cent" 'pour 400 000 cent ne prend pas d's
            End If
        End If

        If centaine = 1 Then
            Return "cent " & Ecrire2Chiffres(reste, LePays) 'on ne dit pas un cent X, mais cent X
        End If

        Return jusqueSeize(centaine) & " cent " & Ecrire2Chiffres(reste, LePays)
    End Function

    ''' <summary>
    ''' Ecrit les nombres de 0 à 99
    ''' </summary>
    ''' <param name="Nombre">Nombre à écrire</param>
    ''' <param name="LePays">Pays d'utilisation, pour spécificitées régionnales</param>
    ''' <returns></returns>
    Private Function Ecrire2Chiffres(ByVal Nombre As Integer, ByVal LePays As Pays) As String
        If LePays <> Pays.France Then
            dizaines(7) = "septante"
            dizaines(9) = "nonante"
        End If
        If LePays = Pays.Suisse Then
            dizaines(8) = "huitante"
        End If

        If Nombre < 17 Then
            Return jusqueSeize(Nombre)
        End If

        Select Case Nombre 'cas particuliers de 71, 80 et 81
            Case 71 'en France 71 prend un et
                If LePays = Pays.France Then
                    Return "soixante et onze"
                End If

            Case 80 'en France et Belgique le vingt prend un s
                If LePays = Pays.Suisse Then
                    Return dizaines(8)
                Else
                    Return dizaines(8) & "s"
                End If

            Case 81 'en France et Belgique il n'y a pas de et
                If LePays <> Pays.Suisse Then
                    Return dizaines(8) & "-un"
                End If
        End Select


        Dim dizaine As Integer = Nombre \ 10
        Dim unite As Integer = Nombre Mod 10

        Dim laDizaine As String = dizaines(dizaine)

        If LePays = Pays.France AndAlso (dizaine = 7 OrElse dizaine = 9) Then
            dizaine -= 1
            unite += 10
        End If


        Select Case unite
            Case 0
                Return laDizaine

            Case 1
                Return laDizaine & " et un"

            Case 17, 18, 19 'pour 77 à 79 et 97 à 99
                unite = unite Mod 10
                Return laDizaine & "-dix-" & jusqueSeize(unite)

            Case Else
                Return laDizaine & "-" & jusqueSeize(unite)
        End Select
    End Function
End Module

Public Enum Pays
    France
    Belgique
    Suisse
End Enum

Public Enum Devise
    Aucune
    Euro
    FrancSuisse
    Dollar
End Enum


VBA

Le code de test

'code de test
Sub test()
        ActiveSheet.Range("A1") = ToLettres(123.456)
        ActiveSheet.Range("A2") = ToLettres(3210987654321.2)
        ActiveSheet.Range("A3") = ToLettres(123456789012345#)
        ActiveSheet.Range("A4") = ToLettres(1234.123456789)
        ActiveSheet.Range("A5") = ToLettres(-4321.987654321)
        ActiveSheet.Range("A6") = ToLettres(1E+16)    'ce nombre est trop grand
        ActiveSheet.Range("A7") = ToLettres(0.12345678961)  'il y a trop de chiffres dérrière la virgule, le resultat sera arrondi
        ActiveSheet.Range("A8") = ToLettres(6795432.456, Belgique, Euro) 'pour les options, on peut mettre les "mots clés"
        ActiveSheet.Range("A9") = ToLettres(400400400, 0, 0) 'pour les options, on peut mettre les chiffres correspondants aux "mots clés"
        ActiveSheet.Range("A10") = ToLettres(0.4)
End Sub

Le module

Option Explicit
Option Base 0

Public Enum Pays
    France
    Belgique
    Suisse
End Enum

Public Enum Devise
    Aucune
    Euro
    FrancSuisse
    Dollar
End Enum

Dim jusqueSeize As Variant

Dim dizaines As Variant

Dim resultat() As String

Dim troisChiffres() As Integer 'tableau qui scinde la partie entière en morceaux de 3 chiffres



'Fonction écrivant le nombre en lettres
'Nombre est le nombre à écrire
'LePays est le pays d'utilisation, pour spécificitées régionnales. Il s'agit d'un énumérable définit plus haut, les valeurs possiblis sont:
' France ou 0
' Belgique ou 1
' Suisse ou 2
'LaDevise la devise à utliser le cas échéant. Les valeurs possibles sont:
' Aucune ou 0
' Euro ou 1
' FrancSuisse ou 2
' Dollar ou 3
Public Function ToLettres(ByVal Nombre As Double, Optional ByVal LePays As Pays = Pays.France, Optional ByVal LaDevise As Devise = Devise.Aucune) As String

    ReDim resultat(0)
    ReDim troisChiffres(0)
    
    jusqueSeize = Array("zéro", "un", "deux", "trois", "quatre", "cinq", "six", "sept", "huit", "neuf", "dix", "onze", "douze", "treize", "quatorze", "quinze", "seize")
    
    Select Case Sgn(Nombre)
        Case -1
            AjouteResultat "moins "
            Nombre = Nombre * -1

        Case 0
            ToLettres = jusqueSeize(0)
            Exit Function

    End Select
    
    If Nombre >= 2147483647 Then 'j'utilise un long pour la partie entière et c'est la valeur maximun
        ToLettres = "Nombre trop grand"
        Exit Function
    End If

    dizaines = Array("rien", "dix", "vingt", "trente", "quarante", "cinquante", "soixante", "soixante", "quatre-vingt", "quatre-vingt")


    Dim PartieEntiere As Long
    PartieEntiere = CLng(Fix(Nombre))
    
    Dim partieDecimale As Double
    partieDecimale = Nombre - PartieEntiere

    Dim milliers As Variant
    milliers = Array("", "mille", "million", "milliard", "billion", "billiard")

    If PartieEntiere > 0 Then

        Do While PartieEntiere > 0
            AjouteTroisChiffres CInt(Fix(PartieEntiere Mod 1000))
            PartieEntiere = PartieEntiere \ 1000
        Loop

        Dim reste As Double
        reste = Nombre - PartieEntiere


        Dim i As Integer

        For i = UBound(troisChiffres) - 1 To 0 Step -1
            Dim leNombre As Integer
            leNombre = troisChiffres(i)

            If leNombre > 1 Then 'valeurs de milliers au pluriel
                AjouteResultat Ecrit3Chiffres(troisChiffres(i), LePays, i = 0) 'pour 400 000, cent ne prend pas de S alors que pour 400 si
                If i > 1 Then ' mille est invariable et "" ne prend pas de s
                    AjouteResultat milliers(i) & "s"
                ElseIf i = 1 Then
                    AjouteResultat milliers(i)
                End If
            ElseIf leNombre = 1 Then
                If i <> 1 Then 'on dit un million, mais pas un mille
                    AjouteResultat "un"
                End If
                AjouteResultat milliers(i)
            End If
            'on ne traite pas le 0, car on ne dit pas X millions zéro mille Y.
        Next i
    Else
        AjouteResultat jusqueSeize(0)
    End If

    Select Case LaDevise
        Case Devise.Dollar
            AjouteResultat "$"

        Case Devise.Euro
            AjouteResultat "€"

        Case Devise.FrancSuisse
            AjouteResultat "CHF"

    End Select

    If LaDevise <> Devise.Aucune Then
        partieDecimale = Round(partieDecimale, 2)
        If partieDecimale <> 0 Then
            AjouteResultat "et"
            AjouteResultat Ecrire2Chiffres(CInt(Fix(partieDecimale * 100)), LePays)
            AjouteResultat "centimes"
        End If
    Else
        milliers = Array("millième", "millionième", "milliardième")

        'avec l'imprécision des nombres à virgules flotantes,  1234562.789 - 1234562 donne 0.78900000010617077 il faut donc compter le nombre de chiffres décimaux du nombre original et arrondir le resultat de la soustraction
        Dim morceaux() As String
        morceaux = Split(CStr(Nombre), ",") 'par défaut ToString arrondi à 10^-8, le format G25 oblige à écrire 25 caractères s'ils sont présents soit (au pire) 15 avant la virgule, la virgule et 9 après, split permet de découper le string obtenu

        If UBound(morceaux) = 1 Then 'il y a une partie décimale
            AjouteResultat "et"

            Dim lenghtPartieDecimale As Integer
            lenghtPartieDecimale = Len(morceaux(1))
            
            If lenghtPartieDecimale > 9 Then
                lenghtPartieDecimale = 9 'on se limite à 10^-9
            End If

            partieDecimale = Round(partieDecimale, lenghtPartieDecimale)

            i = 0
            Do While partieDecimale > 0
                partieDecimale = partieDecimale * 1000
                Dim valeur As Integer
                valeur = CInt(Fix(partieDecimale))
                lenghtPartieDecimale = lenghtPartieDecimale - 3
                If lenghtPartieDecimale < 0 Then
                    lenghtPartieDecimale = 0
                End If
                partieDecimale = Round(partieDecimale - valeur, lenghtPartieDecimale)

                If valeur <> 0 Then
                    AjouteResultat Ecrit3Chiffres(valeur, LePays, False) '0.400 cent ne prend pas d's car il y a millième après
                    If valeur > 1 Then
                        AjouteResultat milliers(i) & "s"
                        i = i + 1
                    Else
                        AjouteResultat milliers(i)
                        i = i + 1
                    End If

                End If
            Loop


        End If
    End If



    ToLettres = Trim(Join(resultat, " "))
End Function

'Ecrit les nombres de 0 à 999
Private Function Ecrit3Chiffres(ByVal Nombre As Integer, ByVal LePays As Pays, RegleDuCent As Boolean) As String
    If Nombre = 100 Then
        Ecrit3Chiffres = "cent"
        Exit Function
    End If

    If Nombre < 100 Then
        Ecrit3Chiffres = Ecrire2Chiffres(Nombre, LePays)
        Exit Function
    End If

    Dim centaine As Integer
    centaine = Nombre \ 100
    Dim reste As Integer
    reste = Nombre Mod 100

    If reste = 0 Then 'Cent prend un s quand il est multiplié et non suivi d'un mot, comme le cas de 100 est déjà traité on est face à un multiple
        If RegleDuCent = True Then
            Ecrit3Chiffres = jusqueSeize(centaine) & " cents"
        Else 'pour 400 000 par exemple cent ne prend pas le s
            Ecrit3Chiffres = jusqueSeize(centaine) & " cent"
        End If
        Exit Function
    End If

    If centaine = 1 Then
        Ecrit3Chiffres = "cent " & Ecrire2Chiffres(reste, LePays) 'on ne dit pas un cent X, mais cent X
        Exit Function
    End If

    Ecrit3Chiffres = jusqueSeize(centaine) & " cent " & Ecrire2Chiffres(reste, LePays)
End Function

'Ecrit les nombres de 0 à 99
Private Function Ecrire2Chiffres(ByVal Nombre As Integer, ByVal LePays As Pays) As String
    If LePays <> Pays.France Then
        dizaines(7) = "septante"
        dizaines(9) = "nonante"
    End If
    If LePays = Pays.Suisse Then
        dizaines(8) = "huitante"
    End If

    If Nombre < 17 Then
        Ecrire2Chiffres = jusqueSeize(Nombre)
        Exit Function
    End If

    Select Case Nombre 'cas particuliers de 71, 80 et 81
        Case 71 'en France 71 prend un et
            If LePays = Pays.France Then
                Ecrire2Chiffres = "soixante et onze"
                Exit Function
            End If

        Case 80 'en France et Belgique le vingt prend un s
            If LePays = Pays.Suisse Then
                Ecrire2Chiffres = dizaines(8)
                Exit Function
            Else
                Ecrire2Chiffres = dizaines(8) & "s"
                Exit Function
            End If

        Case 81 'en France et Belgique il n'y a pas de et
            If LePays <> Pays.Suisse Then
                Ecrire2Chiffres = dizaines(8) & "-un"
                Exit Function
            End If
    End Select


    Dim dizaine As Integer
    dizaine = Nombre \ 10
    Dim unite As Integer
    unite = Nombre Mod 10

    Dim laDizaine As String
    laDizaine = dizaines(dizaine)

    If LePays = France And (dizaine = 7 Or dizaine = 9) Then
        dizaine = dizaine - 1
        unite = unite + 10
    End If


    Select Case unite
        Case 0
            Ecrire2Chiffres = laDizaine

        Case 1
            Ecrire2Chiffres = laDizaine & " et un"

        Case 17, 18, 19 'pour 77 à 79 et 97 à 99
            unite = unite Mod 10
            Ecrire2Chiffres = laDizaine & "-dix-" & jusqueSeize(unite)

        Case Else
            Ecrire2Chiffres = laDizaine & "-" & jusqueSeize(unite)
    End Select
End Function

'Ajoute une valeur au tableau
Sub AjouteResultat(ByVal Texte As String)
    If IsArray(resultat) Then
        Dim taille As Integer
        taille = UBound(resultat) + 1
    Else
        taille = 1
    End If
    
    ReDim Preserve resultat(taille)
    resultat(taille - 1) = Texte
End Sub

'ajoute une valeur au tableau
Sub AjouteTroisChiffres(ByVal Entier As Integer)
    If IsArray(troisChiffres) Then
        Dim taille As Integer
        taille = UBound(troisChiffres) + 1
    Else
        taille = 1
    End If
    
    ReDim Preserve troisChiffres(taille)
    troisChiffres(taille - 1) = Entier
End Sub

Les autres codes sources

Vous trouverez les autres sources aux adresses suivantes
http://www.commentcamarche.net/faq/11100-vb6-net-vba-transformer-chiffres-en-lettre
http://codes-sources.commentcamarche.net/source/39539-conversion-d-un-chiffre-en-lettre
http://codes-sources.commentcamarche.net/source/44435-conversion-des-nombres-en-lettre

Et même en javascript
http://codes-sources.commentcamarche.net/source/44435-conversion-des-nombres-en-lettre

Lisez bien les commentaires

A voir également

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.