2012-11-13 10 views
6

Mam tabelę opłat z kwotą i kodem waluty (USD, JPY, CAD, EUR itp.) I szukam najłatwiejszego sposobu prawidłowego sformatowania waluty. Używając mojego lokalnego kodu kultury (USA) i biorąc mój decimal.ToString ("c") pobiera mi 0,00 USD, ale chciałbym, aby poprawny znak waluty i liczba miejsc po przecinku na podstawie kodu.Format dziesiętny jako waluta na podstawie kodu waluty

Czy istnieją do tego biblioteki? Mogę oczywiście napisać instrukcję zmiany i reguły niestandardowe dla każdego z nich, ale uważam, że musiało to być zrobione wcześniej.

Aktualizacja:

Mam zmodyfikowany kod przykładowy Jon B w następujący sposób

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; 
} 

To pozwala mi iść Amount.ToString (waluta [ "JPY"]), a format wyświetli separator przecinka w moim lokalnym kontekście, ale automatycznie ustaw prawidłowy symbol waluty i miejsca dziesiętne.

Daj mi znać, jeśli ktoś ma czystszy sposób robienia tego, albo wkrótce oznaczy odpowiedź Jona jako poprawną.

+0

@AakashM - Właściwie to nie istnieje. Nazywa się "CultureInfo". –

+0

Wychodząc z poprzednich komentarzy, zauważam, że ["RegionInfo" zna kod waluty dla waluty regionu] (http://msdn.microsoft.com/en-us/library/system.globalization.regioninfo.isocurrencysymbol.aspx), więc Framework ma pewną wiedzę na ten temat. Podejrzewam, że będziesz musiał powtórzyć iterację, ponieważ nie widzę żadnego wyszukiwania opartego na kodzie waluty. – AakashM

+0

@Ramhound 'CultureInfo' mówi, jak sformatować walutową ilość w danej kulturze. Nie oznacza to, że symbolem JPY jest ¥. – AakashM

Odpowiedz

2

Można zbudować słownika jechać z symbolem waluty ISO (USD) na symbol waluty ($):

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; 
} 

To podstawowy pomysł, musisz dostosować to do swoich potrzeb.

Zauważ, że z pewnością można użyć klasy CultureInfo do konwersji na ciąg znaków dla określonej kultury, ale jak zaznaczono w komentarzu Aleksieja, spowoduje to, że każdy ciąg będzie trochę inny (np. 1,00 vs 1,00). Niezależnie od tego, czego używasz, zależy od Twoich potrzeb.

+0

To wygląda bardzo blisko - Nie wszystkie waluty mają 2 miejsca po przecinku (najmniejszy przyrost jena to 1), czy jest to również w informacji o regionie? – Superman

+1

Wygląda na to, że odnosząc się do ci.NumberFormat.CurrencyDecimalDigits dostaje mi wszystko, czego potrzebuję - dzięki! – Superman

+0

@Superman dobrze wiedzieć! –

5

powinny być wykonywane przez przepuszczenie CultureInfo:

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

+ 0. Nie sądzę, że da to wynik @Superman, który wygląda na rozsądny - część formatowania liczbowego wyniku nie będzie pasować, jeśli 2 wartości walutowe będą używały innego separatora dziesiętnego (np. USD i EUR będą wynosić 1,23 USD i 1,23 EUR - jedna z liczb będzie wyglądać 123 dla czytelnika w zależności od lokalizacji użytkownika). –

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"); 
    } 
} 

Oto wyniki nazywając formatCurrency na kilka różnych kodów walutowych:

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

Niezła realizacja. –

+0

Dzięki @weston za ulepszenie mojego kodu :) – jignesh

+2

Świetny fragment, ale lepiej użyć 'c.Nazwa' zamiast' c.LCID', ponieważ można uzyskać specyficzne dla maszyny [CultureNotFoundExceptions] (https://msdn.microsoft. com/en-us/library/system.globalization.culturenotfoundexception (v = vs.110) .aspx) –