Find your content:

Search form

You are here

What is a concise function that formats a (String) decimal into a currency format in Apex?

 
Share

goal:
write the most concise function that formats a (String) decimal into a currency format in Apex. Feel free to trainwreck the code for points, I've kept mine exploded for readability purposes.


Attribution to: ebt

Possible Suggestion/Solution #1

670 characters

public static String currency(String input){
    if(input == null){return '0.00';}
    if(input.indexOf('.') == -1){input = input+'.00';}
    if(input.length() == 5){return input+'0';}
    String newValue = input.substring(input.indexOf('.'));
    newValue = String.valueOf(Decimal.valueOf(newValue).setScale(2));
    newValue = newValue.substring(newValue.indexOf('.'));
    input = input.substring(0,input.indexOf('.'));
    Integer sz = input.length();
    Integer n=0;
    for(Integer i = sz - 1;i > -1;i--){
        if(n!= 0 && math.mod(n,3) == 0)
            newValue = input.substring(i,i+1)+','+newValue;
        else
            newValue = input.substring(i,i+1)+newValue;
        n++; 
    }
    return newValue;
}
//unit test, doesnt count
static testmethod void test_currency(){
    system.assertEquals('2,105.00',currency('2105.0'));
    system.assertEquals('320.00',currency('320.0'));
    system.assertEquals('1,500.26',currency('1500.256'));
    system.assertEquals('0.00',currency('0.0'));
    system.assertEquals('0.00',currency(null));
    system.assertEquals('10,000,123.56',currency('10000123.558'));
} 

Attribution to: ebt

Possible Suggestion/Solution #2

The following should do the trick, with the assumption that your locale for currency formatting is correct. Edited to handle null being passed, and zero values after the decimal.

public static String currency(String input) {
    if ( input == null ) {
        return '0.00';
    }

    Decimal d1 = Decimal.valueOf(input).setScale(2);
    String str = d1.format();
    if( !str.contains('.' ) ) {
        str = str + '.00';
    }

    return str;
}

Attribution to: David Gillen

Possible Suggestion/Solution #3

Of course, it all depends on your use case. Most of the time, you don't need to do this in Apex since the value is destined either for display on a VisualForce page or storage via a Currency field. That said, you'd be able to do this in pure Apex if it weren't for the type restriction on the String.format(...) method. Requiring a List<String> for the arguments prevents you from doing it in pure Apex, at least easily.

If the point of the Apex code is to provide a value for display in a VisualForce page, then Apex really need not do anything but provide the raw decimal value:

<apex:outputText value="Total: {0, number, currency}">
  <apex:param value="{!aDecimalValue}"/>
</apex:outputText>

No need for a dummy SObject with a currency field, although that certainly works.


Attribution to: Doug Bitting

Possible Suggestion/Solution #4

Rarely should you ever need to format variables like that in Apex. Since that's typically a view issue, I tend to rely on apex:outputField for that scenario in Visualforce. Kibitzer has the right idea.


Attribution to: James Loghry

Possible Suggestion/Solution #5

UPDATE: More robust solution from @jkraybill elsewhere.

Here's one that's shorter AND is locale safe:

public static String currency(String i) {
    String s = ( Decimal.valueOf(i==null||i.trim()==''?'0':i).setScale(2) + 0.001 ).format();
    return s.substring(0,s.length()-1);
}

Check out Number Format in the list of supported locales. There's "1.000,00" and "1 000.00" amongst others. Not everyone uses "1,000.00" so we shouldn't assume that in a formatter. Decimal's format() method is locale aware.


Attribution to: RickMeasham

Possible Suggestion/Solution #6

@RickMeasham's method is a good one, but I ran into a couple rounding issues with negative values and fractional values. Here's my edited version of the method that passes the tests I needed it to (not rendering -0.001 as "-0.00", not rendering -1.10 as "-1.09").

public static String formatCurrency(Decimal i) {
    if (i == null || Math.abs(i) < 0.005) return '$0.00';
    String s = (i.setScale(2) + (i >= 0 ? 0.001 : -0.001)).format();
    return s.substring(0, s.length() - 1);
}

(EDIT: changed "<= 0.005" to "< 0.005" per @RickMeasham's advice below.)

(EDIT 2: actually realized, when I finished tests, that this updated method still had a few shortcomings related to rounding. I updated to delegate to Math.roundToLong per code below [which uses round half even, not half up as I stated in my comments erroneously]. It now passes all my unit tests, which you can see here: http://codepad.org/ycttSXjq)

private String formatCurrency(Decimal i) {
    if (i == null) return '0.00';
    i = Decimal.valueOf(Math.roundToLong(i * 100)) / 100;
    String s = (i.setScale(2) + (i >= 0 ? 0.001 : -0.001)).format();
    return s.substring(0, s.length() - 1);
}

Attribution to: jkraybill

Possible Suggestion/Solution #7

The original Solution posted above is slightly incorrect as it doesn't handle negative numbers..

Use this method instead..

public static String currency(String i)
{
    // - Error this doesn't handle negative number converts -15 to -14.999  instead of -15.001 before round
    //String s = ( Decimal.valueOf(i==null||i.trim()==''?'0':i).setScale(2) + 0.001 ).format();
    //return s.substring(0,s.length()-1);

    if (( i == null) || ( i == ''))
    {
        return '0';
    }
    else
    {
        string s;
        if ( Decimal.valueOf(i) >= 0 )
        {
            s =  ( Decimal.valueOf(i).setScale(2) + 0.001 ).format();
        }
        else
        {
            s = ( Decimal.valueOf(i).setScale(2) - 0.001 ).format();
        }
    return s.substring(0,s.length()-1);
    }
}

Attribution to: Benjamin Pirih

Possible Suggestion/Solution #8

Ok - first, I'm not actually recommending the following approach. It's more of an intellectual exercise - an exploration of a different path to a solution.

First, create the following Apex page:

< apex:page Controller="currencyfuncontroller" showHeader="false" sidebar="false" >
    < apex:outputField id="formattedamount" value="{!DummyOpportunity.Amount}" />
< /apex:page>

The controller is as follows:

public class currencyfuncontroller
{
   public Opportunity getDummyOpportunity()
   {
       String currencystring = 
         Apexpages.currentPage().getParameters().get('currencystring');
       Decimal currencyvalue = 0;
       try
       {
           currencyvalue = Decimal.ValueOf(currencystring);
       } catch(Exception ex) {}
       Opportunity op = new Opportunity(amount = currencyvalue);
       return op;
   }
}

Here's some simple code to use it:

ApexPages.PageReference pr = Page.currencyfun;
pr.getParameters().put('currencystring','1.56');
String contents = pr.GetContent().toString();
system.debug(contents);

You still need to parse out the actually currency value - but that's easy enough to do use a regular expression or some substring work, so I left it out here. I also cheated by using an exception handler instead of the (better) validation shown in other answers - just to keep things simple.

What does this approach accomplish?

  • The formatting now includes the correct currency symbol for the user's locale (and currency formatting should it differ from standard decimal formatting).
  • You could extend this to include a parameter for the currency to use and use that info to set the currency type for the opportunity. On multi-currency organizations this should provide automatic currency conversion to the current locale with the formatting (standard SFDC formatting on multi-currency organizations).

Again - If I really needed this I'd probably actually write the code to lookup currency symbols, examine the current and corporate currency, and do the necessary conversions and formatting directly. But that's quite a bit of code (especially on orgs using advanced currency management).

Ultimately my point is - the original question was asking for formatting a decimal string into currency format, and the job isn't really done until you have the correct currency symbol and multi-currency handling in place :-)


Attribution to: kibitzer
This content is remixed from stackoverflow or stackexchange. Please visit https://salesforce.stackexchange.com/questions/318

My Block Status

My Block Content