2012-11-13 10 views
6

Ho una tabella di addebiti con l'importo e il codice di valuta (USD, JPY, CAD, EUR ecc.) E sto cercando il modo più semplice per formattare correttamente la valuta. Usando il mio codice cultura locale (USA) e prendendo il mio decimale. ToString ("c") mi dà $ 0,00 in uscita, ma mi piacerebbe il segno di valuta corretto e il numero di decimali in base al codice.Formato decimale come valuta basata sul codice di valuta

Esistono librerie per questo? Naturalmente posso scrivere un'istruzione switch e regole personalizzate per ognuno, ma ho pensato che fosse già stato fatto prima.

Aggiornamento:

Ho modificato il codice di esempio di Jon B come segue

static IDictionary<string, string> GetCurrencyFormatStrings() 
{ 
    var result = new Dictionary<string, string>(); 

    foreach (var ci in CultureInfo.GetCultures(CultureTypes.AllCultures)) 
    { 
     try 
     { 
      var ri = new RegionInfo(ci.Name); 
      result[ri.ISOCurrencySymbol] = 
        string.Format("{0}#,#0.{1};({0}#,#0.{1})", 
           ri.CurrencySymbol, 
           new string('0', 
           i.NumberFormat.CurrencyDecimalDigits)); 
     } 
     catch { } 
    } 

    return result; 
} 

Questo mi permette di andare semplicemente Amount.ToString (valuta [ "JPY"]), e il formato sarà in uscita il separatore di virgola nel mio contesto locale, ma inserire automaticamente il simbolo di valuta corretto e le posizioni decimali.

Fatemi sapere se qualcuno ha un modo più pulito per farlo, o contrassegnerò brevemente la risposta di Jon come corretta.

+0

@AakashM - In realtà esiste. Si chiama 'CultureInfo'. –

+0

Ritirando i miei commenti precedenti, noto che ['RegionInfo' conosce il codice valuta per la valuta di una regione] (http://msdn.microsoft.com/en-us/library/system.globalization.regioninfo.isocurrencysymbol.aspx), quindi il Framework ha qualche conoscenza di questi. Ho il sospetto che tu debba ripetere l'iterazione, poiché non vedo alcuna ricerca basata sul codice valuta. – AakashM

+0

@Ramhound 'CultureInfo' ti spiega come formattare una quantità di valuta in una determinata cultura. Non ti dice che il simbolo per JPY è ¥. – AakashM

risposta

2

Si potrebbe costruire un dizionario di passare da simbolo di valuta ISO (USD) a simbolo di valuta ($):

static void Main(string[] args) 
{ 
    var symbols = GetCurrencySymbols(); 

    Console.WriteLine("{0}{1:0.00}", symbols["USD"], 1.5M); 
    Console.WriteLine("{0}{1:0.00}", symbols["JPY"], 1.5M); 

    Console.ReadLine(); 
} 

static IDictionary<string, string> GetCurrencySymbols() 
{ 
    var result = new Dictionary<string, string>(); 

    foreach (var ci in CultureInfo.GetCultures(CultureTypes.AllCultures)) 
    { 
     try 
     { 
      var ri = new RegionInfo(ci.Name); 
      result[ri.ISOCurrencySymbol] = ri.CurrencySymbol;      
     } 
     catch { } 
    } 

    return result; 
} 

Questo è il base idea, dovrai modificarla in base alle tue esigenze.

Nota che puoi certamente usare la classe CultureInfo per convertire in una stringa per una cultura specifica, ma come notato nel commento di Alexei, ciò farà sì che ogni stringa sia leggermente diversa (come 1,00 vs 1,00). Qualunque cosa tu usi dipende dalle tue esigenze.

+0

Questo sembra abbastanza vicino - Non tutte le valute hanno 2 posizioni decimali (l'incremento più piccolo in yen è 1), questo è anche nelle informazioni sulla regione? – Superman

+1

Sembra che il riferimento a ci.NumberFormat.CurrencyDecimalDigits mi dia tutto ciò di cui ho bisogno - grazie! – Superman

+0

@Superman buono a sapersi! –

5

dovrebbe essere fatto facendo passare il CultureInfo:

CultureInfo ci = new CultureInfo("en-GB"); 
amount.ToString("C", ci); 
+4

+ 0. Non penso che darà risultati ragionevoli a @Superman - la parte di formattazione del numero dell'output non corrisponderà se 2 valori di valuta utilizzano separatori decimali diversi (ad esempio, USD e EUR sarebbero qualcosa come $ 1,23 e "Eur" 1,23 - uno dei numeri sembrerà 123 al lettore a seconda del locale del lettore). –

16
public static class DecimalExtension 
{ 
    private static readonly Dictionary<string, CultureInfo> ISOCurrenciesToACultureMap = 
     CultureInfo.GetCultures(CultureTypes.SpecificCultures) 
      .Select(c => new {c, new RegionInfo(c.LCID).ISOCurrencySymbol}) 
      .GroupBy(x => x.ISOCurrencySymbol) 
      .ToDictionary(g => g.Key, g => g.First().c, StringComparer.OrdinalIgnoreCase); 

    public static string FormatCurrency(this decimal amount, string currencyCode) 
    { 
     CultureInfo culture; 
     if (ISOCurrenciesToACultureMap.TryGetValue(currencyCode, out culture)) 
      return string.Format(culture, "{0:C}", amount); 
     return amount.ToString("0.00"); 
    } 
} 

Ecco i risultati della chiamata FormatCurrency per alcuni codici di valuta diverse:

decimal amount = 100; 

amount.FormatCurrency("AUD"); //$100.00 
amount.FormatCurrency("GBP"); //£100.00 
amount.FormatCurrency("EUR"); //100,00 € 
amount.FormatCurrency("VND"); //100,00 ? 
amount.FormatCurrency("IRN"); //? 100.00 
+0

Bella implementazione. –

+0

Grazie a @weston per migliorare il mio codice :) – jignesh

+2

Grande frammento, ma è meglio usare 'c.Name' invece di' c.LCID' perché è possibile ottenere [CultureNotFoundExceptions] specifico della macchina (https://msdn.microsoft. com/it-it/library/system.globalization.culturenotfoundexception (v = vs.110) aspx) –