IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

PL/SQL Oracle Discussion :

Affichage des montants avec le bon format


Sujet :

PL/SQL Oracle

  1. #1
    Membre régulier
    Homme Profil pro
    Expert Oracle
    Inscrit en
    Mai 2009
    Messages
    92
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations professionnelles :
    Activité : Expert Oracle

    Informations forums :
    Inscription : Mai 2009
    Messages : 92
    Points : 70
    Points
    70
    Par défaut Affichage des montants avec le bon format
    Salut tout le monde

    J'aurais besoin de votre aide pour afficher le bon format d'un montant que j'ai déjà calculé.

    Le souci se pose bien sûr au moment de l'affichage, le montant doit avoir un nombre de chiffre après la virgule, comme ce nombre de chiffre peut varier, je me demandais comment je pourrais faire pour bien gérer mon affichage.

    L'exemple suivant expliquera tout: soit N le nombre de chiffre après la virgule, si N = 2, le montant devra être 1002,00, si N = 3 le montant sera alors 1002,000 etc.

    En vous remerciant d'avance.

  2. #2
    Membre confirmé

    Profil pro
    Inscrit en
    Septembre 2004
    Messages
    507
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2004
    Messages : 507
    Points : 503
    Points
    503
    Par défaut
    Une possibilité:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    SELECT RPAD (TO_CHAR (TRUNC (mon_nombre, n)),
                 LENGTH (CEIL (mon_nombre)) + n + 1,
                 '0' )
      FROM DUAL

  3. #3
    Modérateur
    Avatar de Waldar
    Homme Profil pro
    Sr. Specialist Solutions Architect @Databricks
    Inscrit en
    Septembre 2008
    Messages
    8 453
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Sr. Specialist Solutions Architect @Databricks
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2008
    Messages : 8 453
    Points : 18 386
    Points
    18 386
    Par défaut
    En agissant directement sur le format celà à l'air de fonctionner :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    with Test_nm AS
    (
    select level as lvl, round(dbms_random.value(1, 1000), 5) as nm, round(dbms_random.value(1, 3)) as nb
    from dual
    connect by level <= 10
    )
    select lvl, nm, nb, to_char(nm, 'FM999D' || case nb when 1 then '9' when 2 then '99' when 3 then '999' end) as nm_char
    from Test_nm;
     
    LVL	NM		NB	NM_CHAR
    1	110.3196	2	110,32
    2	864.80176	2	864,8
    3	159.15888	3	159,159
    4	95.15295	1	95,2
    5	493.41549	2	493,42
    6	708.08456	2	708,08
    7	336.03994	2	336,04
    8	587.04549	1	587,
    9	673.23854	3	673,239
    10	620.45914	1	620,5

  4. #4
    Membre confirmé

    Profil pro
    Inscrit en
    Septembre 2004
    Messages
    507
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2004
    Messages : 507
    Points : 503
    Points
    503
    Par défaut
    J'ai compris qu'on a un nombre avec m décimales, et on veut en afficher n.
    Si m est inférieur à n, je ne sais pas si votre exemple fonctionne.

  5. #5
    Modérateur
    Avatar de Waldar
    Homme Profil pro
    Sr. Specialist Solutions Architect @Databricks
    Inscrit en
    Septembre 2008
    Messages
    8 453
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Sr. Specialist Solutions Architect @Databricks
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2008
    Messages : 8 453
    Points : 18 386
    Points
    18 386
    Par défaut
    J'ai peut-être mal compris le problème, quelques exemples ne seraient pas de trop !

  6. #6
    Membre régulier
    Homme Profil pro
    Expert Oracle
    Inscrit en
    Mai 2009
    Messages
    92
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations professionnelles :
    Activité : Expert Oracle

    Informations forums :
    Inscription : Mai 2009
    Messages : 92
    Points : 70
    Points
    70
    Par défaut
    Merci les gars pour vos conseils.

    Pour les exemples, en voici une liste:

    N = 2; Nombre = 100; L'affichage devra être = 100,00
    N = 3; Nombre = 100.12; L'affichage devra être = 100,120
    N = 2; Nombre = 100.123; L'affichage devra être = 100,12
    N = 0; Nombre = 100.124; L'affichage devra être = 100
    N = 1; Nombre = 100; L'affichage devra être = 100,0
    etc.

    Pour l'instant j'utilise le code suivant:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    SELECT  DECODE( N,
                    0, NVL(TO_CHAR(nombre, 'FM9G999G999G999G999G999G990')       , '0'),
                    1, NVL(TO_CHAR(nombre, 'FM9G999G999G999G999G999G990D0')     , '0'),
                    2, NVL(TO_CHAR(nombre, 'FM9G999G999G999G999G999G990D90')    , '0'),
                    3, NVL(TO_CHAR(nombre, 'FM9G999G999G999G999G999G990D990')   , '0')) 
    FROM    DUAL
    3 c'est le nombre maximum de chiffres après la virgule que peut avoir une devise dans n'importe quel pays. Cette formule marche bien, mais puisque j'ai pas mal de montants à afficher, je ne voudrais pas m'amuser à écrire ce bout de code pour chaque montant ! Tout autre moyen plus simple sera le bienvenu

  7. #7
    Invité
    Invité(e)
    Par défaut
    ben moi je ferais une fonction de formatage qui construirait ta chaine 'FM9G999G999G999G999G999G990D999...90' suivant le nombre de chiffres passé en paramètres

  8. #8
    Modérateur
    Avatar de Waldar
    Homme Profil pro
    Sr. Specialist Solutions Architect @Databricks
    Inscrit en
    Septembre 2008
    Messages
    8 453
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Sr. Specialist Solutions Architect @Databricks
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2008
    Messages : 8 453
    Points : 18 386
    Points
    18 386
    Par défaut
    Votre formule est bien, si vous voulez gagner un peu de place il suffit de factoriser les éléments en commun :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    SELECT NVL(TO_CHAR(nombre, 'FM9G999G999G999G999G999G990' || decode(N, 1, 'D0', 2, 'D90', 3, 'D990')), '0')
      FROM DUAL;

  9. #9
    Membre régulier
    Homme Profil pro
    Expert Oracle
    Inscrit en
    Mai 2009
    Messages
    92
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations professionnelles :
    Activité : Expert Oracle

    Informations forums :
    Inscription : Mai 2009
    Messages : 92
    Points : 70
    Points
    70
    Par défaut
    Je prends les 2 dernières propositions, ça me sera très utile de créer une fonction de formatage des montants avec la formule simplifiée.

    Toute autre suggestion sera la bienvenue.

    Encore une fois merci de votre aide.

  10. #10
    Expert éminent
    Avatar de pachot
    Homme Profil pro
    Developer Advocate YugabyteDB
    Inscrit en
    Novembre 2007
    Messages
    1 821
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : Suisse

    Informations professionnelles :
    Activité : Developer Advocate YugabyteDB
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Novembre 2007
    Messages : 1 821
    Points : 6 443
    Points
    6 443
    Billets dans le blog
    1
    Par défaut
    Bonjour,

    Une autre solution, une table avec les formats genre:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    N FORMAT_STRING
    - -------------
    0 FM9G999G999G999G999G999G990
    1 FM9G999G999G999G999G999G990D0
    2 FM9G999G999G999G999G999G990D90
    3 FM9G999G999G999G999G999G990D990
    Et il suffit de faire une jointure (externe pour ne pas perdre d'enregistrements) avec cette table pour récupérer le format
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    select to_char(T.nombre,f.format_string) from T left outer join FORMAT_TABLE f on t.n=f.n
    A mon avis c'est plus facile à paramétrer, et plus performant (pas d'appels au pl/sql à chaque enregistrement)

    Cordialement,
    Franck.

  11. #11
    Membre régulier
    Homme Profil pro
    Expert Oracle
    Inscrit en
    Mai 2009
    Messages
    92
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations professionnelles :
    Activité : Expert Oracle

    Informations forums :
    Inscription : Mai 2009
    Messages : 92
    Points : 70
    Points
    70
    Par défaut
    Merci Franck, la table des formats me paraît une très bonne idée, je vais essayer de la mettre en place, en plus ça pourrait me servir dans mes prochains programmes vu j'aurais toujours des montants à calculer et à afficher !

    Par contre il va falloir que je pense 2 fois avant de faire une autre jointure, sinon mon code risque d'avoir des conséquences sur les performances (surtout que l'environnement sur lequel je travaille est relativement lent en temps normal), je vais comme même tester et voir

  12. #12
    Expert éminent sénior Avatar de mnitu
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Octobre 2007
    Messages
    5 611
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Marne (Champagne Ardenne)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Octobre 2007
    Messages : 5 611
    Points : 11 252
    Points
    11 252
    Par défaut
    La question est: qu’est-ce que détermine le changement du format ? Si c’est un paramétrage de l’application ou de la transaction qui utilise le select, la meilleur solution consiste dans l’utilisation d’une variable initialisée avec le format à utiliser :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    mni@MERCURE>variable fmt varchar2(50);
    mni@MERCURE>exec :fmt := 'FM9G999G999G999G999G999G990D90';
     
    Procédure PL/SQL terminée avec succès.
     
    mni@MERCURE>select to_char(110.3196,:fmt) mnt from dual;
     
    MNT
    ----------------------------------------
    110.32

  13. #13
    Membre régulier
    Homme Profil pro
    Expert Oracle
    Inscrit en
    Mai 2009
    Messages
    92
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations professionnelles :
    Activité : Expert Oracle

    Informations forums :
    Inscription : Mai 2009
    Messages : 92
    Points : 70
    Points
    70
    Par défaut
    Bon finalement j'ai opté pour la solution de la fonction avec un select factorisé, le corps de ma fonction est du genre:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
        BEGIN
            SELECT  'FM9G999G999G999G999G999G990'   ||
                    DECODE( exposant_devise,
                            1, 'D0'  ,
                            2, 'D90' ,
                            3, 'D990')
            INTO    format_montant
            FROM    DUAL;
        END;
     
        montant_a_afficher :=  TO_CHAR(montant, format_montant);
     
        RETURN (montant_a_afficher);
    J'ai voulu créer une table pour récupérer le format, mais puisque le max de chiffre après la virgule que peux avoir une devise est de 3, j'ai jugé que c'est pas nécessaire car il n'y aura aucun maintien à faire plus tard !

    En tout cas je vous remercie tous pour votre aide

  14. #14
    Expert éminent sénior Avatar de mnitu
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Octobre 2007
    Messages
    5 611
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Marne (Champagne Ardenne)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Octobre 2007
    Messages : 5 611
    Points : 11 252
    Points
    11 252
    Par défaut
    Je n'aime pas, il y a un select en trop dans cette procédure.

  15. #15
    Membre confirmé

    Profil pro
    Inscrit en
    Septembre 2004
    Messages
    507
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2004
    Messages : 507
    Points : 503
    Points
    503
    Par défaut
    Euh... il me semble que la solution que j'ai donnée au départ fonctionne pour tous les cas, même si n>3.

  16. #16
    Membre régulier
    Homme Profil pro
    Expert Oracle
    Inscrit en
    Mai 2009
    Messages
    92
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations professionnelles :
    Activité : Expert Oracle

    Informations forums :
    Inscription : Mai 2009
    Messages : 92
    Points : 70
    Points
    70
    Par défaut
    Il faut pas oublier que le format des montants je ne le connais que lors de l'exécution, pas avant, en plus du fait qu'il peut changer d'un compte à l'autre ! du coup je ne peux pas paramétrer la transaction et je suis obligé à un moment de faire soit un select, soit un GET d'une table, soit des IF ELSIF...

  17. #17
    Modérateur
    Avatar de Waldar
    Homme Profil pro
    Sr. Specialist Solutions Architect @Databricks
    Inscrit en
    Septembre 2008
    Messages
    8 453
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Sr. Specialist Solutions Architect @Databricks
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2008
    Messages : 8 453
    Points : 18 386
    Points
    18 386
    Par défaut
    Citation Envoyé par GoLDoZ Voir le message
    Euh... il me semble que la solution que j'ai donnée au départ fonctionne pour tous les cas, même si n>3.
    Il y a un soucis quand il n'y a pas de décimales et le nombre est tronqué mais pas arrondi, ce qui peut aussi être un problème :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    WITH Test_nm AS
    (
    SELECT level AS lvl, round(dbms_random.value(1, 1000), 5) AS nm, round(dbms_random.value(0, 3)) AS nb
    FROM dual
    connect BY level <= 10
    )
    SELECT lvl, nm, nb,
           to_char(nm, 'FM990' || case nb when 1 then 'D0' when 2 then 'D90' when 3 then 'D990' end) AS nm_char1,
           RPAD (TO_CHAR (TRUNC (nm, nb)), LENGTH (CEIL (nm)) + nb + 1, '0' ) AS nm_char2
    FROM Test_nm;
     
    LVL	NM		NB	NM_CHAR1	NM_CHAR2
    1	114.31413	1	114,3		114,3
    2	593.51819	0	594		5930
    3	979.01075	1	979,0		97900
    4	349.27126	1	349,3		349,2
    5	421.77444	1	421,8		421,7
    6	351.89864	2	351,90		351,89
    7	 96.636		2	 96,64		 96,63
    8	380.066		1	380,1		38000
    9	437.77706	3	437,777		437,777
    10	529.68979	1	529,7		529,6
    Par contre on peut conserver l'idée du padding au niveau du format pour que celà fonctionne avec n'importe quel nombre de décimale :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    WITH Test_nm AS
    (
    SELECT level AS lvl, round(dbms_random.value(1, 1000), 5) AS nm, round(dbms_random.value(0, 3)) AS nb
    FROM dual
    connect BY level <= 10
    )
    SELECT lvl, nm, nb,
           to_char(nm, 'FM990' || case nb when 1 then 'D0' when 2 then 'D90' when 3 then 'D990' end) AS nm_char1,
           to_char(nm, 'FM990' || case nb when 0 then '' else 'D' || trim(lpad(' ', nb, '9')) ||'0' end) AS nm_char2
    FROM Test_nm;
     
    LVL	NM		NB	NM_CHAR1	NM_CHAR2
    1	908.13345	1	908,1		908,1
    2	 87.03653	2	 87,04		 87,04
    3	819.28339	0	819		819
    4	637.40467	1	637,4		637,4
    5	208.90982	1	208,9		208,9
    6	847.93625	2	847,94		847,94
    7	722.36724	0	722		722
    8	356.63798	3	356,638		356,638
    9	214.87942	2	214,88		214,88
    10	489.12254	2	489,12		489,12

  18. #18
    Membre confirmé

    Profil pro
    Inscrit en
    Septembre 2004
    Messages
    507
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2004
    Messages : 507
    Points : 503
    Points
    503
    Par défaut
    Citation Envoyé par Waldar Voir le message
    Il y a un soucis quand il n'y a pas de décimales et le nombre est tronqué mais pas arrondi, ce qui peut aussi être un problème
    Bien vu Waldar.

    Je réécris ma formule en tenant compte de cela:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    WITH test_nm AS
         (SELECT     LEVEL AS lvl, ROUND (DBMS_RANDOM.VALUE (1, 1000), 3) AS nm,
                     ROUND (DBMS_RANDOM.VALUE (0, 5)) AS nb
                FROM DUAL
          CONNECT BY LEVEL <= 10)
    SELECT lvl, nm, nb,
           RPAD (TO_CHAR (ROUND (nm, nb)), LENGTH (CEIL (nm)) + case nb when 0 then 0 else nb + 1 end, '0')
      FROM test_nm;
     
    LVL	NM	        NB	NM_CHAR
    1	415.593	        1	415.6
    2	347.325	        5	347.32500
    3	588.907	        2	588.91
    4	578.814	        4	578.8140
    5	700.182	        4	700.1820
    6	201.903	        2	201.90
    7	923.214	        3	923.214
    8	610.298	        4	610.2980
    9	717.06	        3	717.060
    10	365.851	        4	365.8510
    NB: j'ai inversé le 3 et le 5 dans le WITH pour vérifier le padding à droite.

  19. #19
    Modérateur
    Avatar de Waldar
    Homme Profil pro
    Sr. Specialist Solutions Architect @Databricks
    Inscrit en
    Septembre 2008
    Messages
    8 453
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Sr. Specialist Solutions Architect @Databricks
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2008
    Messages : 8 453
    Points : 18 386
    Points
    18 386
    Par défaut
    Il reste encore un petit problème pour les nombres entiers (ou arrondis entiers) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    WITH Test_nm AS
    (
    SELECT 1 as lvl, 195.001 as nm, 1 as nb from dual union all
    SELECT 2       , 195          , 4       from dual 
    )
    SELECT lvl, nm, nb,
           to_char(nm, 'FM990' || case nb when 0 then '' else 'D' || trim(lpad(' ', nb, '9')) ||'0' end) AS nm_char1,
           RPAD (TO_CHAR (ROUND (nm, nb)), LENGTH (CEIL (nm)) + case nb when 0 then 0 else nb + 1 end, '0') as nm_char2
    FROM Test_nm;
     
    LVL	NM	NB	NM_CHAR1	NM_CHAR2
    1	195.001	1	195,0		19500
    2	195	4	195,0000	19500000

  20. #20
    Membre confirmé

    Profil pro
    Inscrit en
    Septembre 2004
    Messages
    507
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2004
    Messages : 507
    Points : 503
    Points
    503
    Par défaut
    Effectivement...

    A coups de DECODE j'arrive à mes fins mais ce n'est plus très lisible. Ta solution d'agir directement sur le format est bien plus simple.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. affichage des caracteres avec loadVars
    Par 10dmz-4amx dans le forum Flash
    Réponses: 2
    Dernier message: 18/11/2006, 17h08
  2. [Wamp] Problème d'affichage des pages avec WAMP
    Par FredLam dans le forum EDI, CMS, Outils, Scripts et API
    Réponses: 4
    Dernier message: 01/11/2006, 19h19
  3. Problème d'affichage des graphes avec Tomcat
    Par _Janu_ dans le forum BIRT
    Réponses: 11
    Dernier message: 20/09/2006, 15h30
  4. probleme d'affichage des informations avec quickrep
    Par hamadi_insat dans le forum Bases de données
    Réponses: 1
    Dernier message: 14/09/2006, 19h31
  5. Affichage des montant en format 00.00
    Par fraizas dans le forum Langage
    Réponses: 1
    Dernier message: 27/02/2006, 17h05

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo