.NET Number and Currency Formatting

Custom Excel like auto formatting of numbers in .NET. Demonstrates how to take an entirely improperly formatted number and reformat it any way you like. Provides an alternative way to incorporate internationalization formatting for commas and decimals.

I recently published a JavaScript version of this number/currency reformatting code.  Some have asked for a server side version in .NET.

To see the formatting in action, JavaScript, Excel, Auto Format Numbers and International Currency.

Essentially, you pass in your comma delimiter, decimal delimiter, and number of places to the right of the decimal and the method takes care of the rest.  I use this single formatting method to handle percentages, research calculation indexes, currency, standard numerical formats, and various other unusual number format requests that may or may not fit well with the CultureInfo settings.

It can easily turn 123456789 into any of the following:

0.123456789
123.456789
1,234,567.89
-1,234.56789
123456789

It will also turn values that aren't real numbers into
properly formatted empty numbers.

0.000000000
0.0000
0

Feel free to tweak the code to add in custom rounding
or any other feature needed for your application.

Here's the code:

using System;
using System.Text;
using System.Text.RegularExpressions;
 

public class Utility
{

 public static double ToDouble(string originalValue,int roundPlaces)
 {

  double returnValue=0;

  try
  {

   originalValue = originalValue.Trim();

   if (originalValue.Length < 1)
   {
     return 0;
   }

   if (roundPlaces < 100)
   {
     returnValue = System.Math.Round(System.Double.Parse(originalValue),
                                     roundPlaces);
   }
   else { returnValue = System.Double.Parse(originalValue); }

  }
  catch  { return 0; }
  return returnValue;
 }
 

 public static string FormatEmptyNumber(string decimalDelimiter,
                                        int decimalPlaces)
 {

    string preDecimal = "0";
    string postDecimal = "";

    for (int i = 0; i < decimalPlaces; i++)
    {
      if (i == 0) { postDecimal += decimalDelimiter; }
      postDecimal += "0";
    }
    return preDecimal + postDecimal;

 }
     
 public static string FormatNumber(string value,
                                   string commaDelimiter,
                                   string decimalDelimiter,
                                   int decimalPlaces)
 {
    string minus = "";
    string preDecimal = "";
    string postDecimal = "";
    Regex regex = null;
    string returnValue = "";
    string pattern = "(-?[0-9]+)([0-9]{3})";

    try
    {

      value = value.Trim();

      if (decimalPlaces < 1) { decimalDelimiter = ""; }

      if (value.LastIndexOf("-") == 0)
      {
        minus = "-";
        value = value.Replace("-", "");
      }

      preDecimal = value;

      // preDecimal doesn't contain a number at all.
      // Return formatted zero representation.

      if (preDecimal.Length < 1)
      {
        return minus + FormatEmptyNumber(decimalDelimiter,
                                         decimalPlaces);
      }

      // preDecimal is 0 or a series of 0's.
      // Return formatted zero representation.

      if (commaDelimiter.Length > 0)
      {
        preDecimal = preDecimal.Replace(commaDelimiter, "");
      }
      if (decimalDelimiter.Length > 0)
      {
        preDecimal = preDecimal.Replace(decimalDelimiter, "");
      }

      if (ToDouble(preDecimal, 0) < 1)
      {
          return minus + FormatEmptyNumber(decimalDelimiter,
                                           decimalPlaces);
      }

      // predecimal has no numbers to the left.
      // Return formatted zero representation.

      if (preDecimal.Length == decimalPlaces)
      {
        return minus + "0" + decimalDelimiter + preDecimal;
      }

      // predecimal has fewer characters than the
      // specified number of decimal places.
      // Return formatted leading zero representation.

      if (preDecimal.Length < decimalPlaces)
      {
        if (decimalPlaces == 2)
        {
           return minus + FormatEmptyNumber(decimalDelimiter,
                                            decimalPlaces - 1)
                                             + preDecimal;
        }

        return minus + FormatEmptyNumber(decimalDelimiter,
                                         decimalPlaces - 2)
                                         + preDecimal;
      }

      // predecimal contains enough characters to
      // qualify to need decimal points rendered.
      // Parse out the pre and post decimal values
      // for future formatting.

      if (preDecimal.Length > decimalPlaces)
      {
         postDecimal = decimalDelimiter + preDecimal.Substring(
                                          preDecimal.Length - decimalPlaces);
         preDecimal = preDecimal.Substring(0, preDecimal.Length - decimalPlaces);
      }

      // Place comma oriented delimiter every 3 characters
      // against the numeric represenation of the "left" side
      // of the decimal representation.  When finished, return
      // both the left side comma formatted value together with
      // the right side decimal formatted value.

      regex = new Regex(pattern);

      while (Regex.IsMatch(preDecimal, pattern))
      {
         preDecimal = regex.Replace(preDecimal, "$1" + commaDelimiter + "$2");
      }

    }
    catch (Exception) { returnValue = ToDouble("0", 0).ToString(); }
    return minus + preDecimal + postDecimal;
 }
}



By Robbe Morris   Popularity  (5563 Views)
Picture
Biography - Robbe Morris
Robbe has been a Microsoft MVP in C# since 2004. He is also the co-founder of NullSkull.com which provides .NET articles, book reviews, software reviews, and software download and purchase advice.  Robbe also loves to scuba dive and go deep sea fishing in the Florida Keys or off the coast of Daytona Beach. Microsoft MVP