• 0

[Javascript] Format a string to currency (GBP)


Question

I've never looked into regular expressions and unfortunately do not have time - this has to be completed by Tuesday morning BST. What I'm trying to do is simply convert a string into a currency format, to 2 decimal places.

E.g.

1234567.89202304304053050000

=

£1,234,567.89

I could just check the length of the string - how many characters it is - and then just place the commas in the correct places, ensuring only 2 characters are left after the decimal point (I think), but it seems regular expressions or something else (?) would be more efficient?

This is what I have so far, but it only seems to work some times - other times it does not format the string to 2 decimal places:


    function FormatCurrency(strNumberToFormat) 
    {
        if (strNumberToFormat.toString() != "NaN")
        {

            if (strNumberToFormat.toString().indexOf(".") != -1)
            {
                if ((strNumberToFormat.toString().split('.')[1].substring(0, 1) == strNumberToFormat.toString().split('.')[1].substring(1, 2)) && parseFloat(strNumberToFormat.toString().split('.')[1].substring(1, 2)) < 5)
                {
                    strNumberToFormat = parseFloat(strNumberToFormat.toString().split('.')[0] + "." + strNumberToFormat.toString().split('.')[1].substring(0, 1) + strNumberToFormat.toString().split('.')[1].substring(0, 1));
                }
                else if ((strNumberToFormat.toString().split('.')[1].substring(0, 1) == strNumberToFormat.toString().split('.')[1].substring(1, 2)) && parseFloat(strNumberToFormat.toString().split('.')[1].substring(1, 2)) >= 5)
                {
                    strNumberToFormat = parseFloat(strNumberToFormat.toString().split('.')[0] + "." + strNumberToFormat.toString().split('.')[1].substring(0, 1) + (parseFloat(strNumberToFormat.toString().split('.')[1].substring(1, 2)) + 1));
                }
            }
            strNumberToFormat.toFixed(2);
            strNumberToFormat += "";
            straValue = strNumberToFormat.split(".");
            strFirstPartOfResult = straValue[0];
            strSecondPartOfResult = straValue.length > 1 ? "." + straValue[1] : "";
            var objRegex = /(\d+)(\d{3})/;

            while (objRegex.test(strFirstPartOfResult))
            {
                strFirstPartOfResult = strFirstPartOfResult.replace(objRegex, "$1" + "," + "$2");
            }
            return "£" + strFirstPartOfResult + strSecondPartOfResult;
        }
        else
        {
            return "£--";  
        }
    }

It was a bit different before but instead of looking for a solid solution, I've just been adding to it to cater times it hasn't worked correctly (i.e. if I saw a number which had been formatted to 2 decimal places, I'd add a bit of code to do so).

I would be extremely grateful if somebody or some people could please help me formulate a solid function which will format a string to GBP currency (up to 2 decimal places), before Tuesday morning BST.

Thank you in advance,

Calum.

Link to comment
Share on other sites

3 answers to this question

Recommended Posts

  • 0

How exactly does your example conversion work? Why are you limiting the number of decimals in the result? I would expect an input of "123456789202304304053050000" to output "? 123,456,789,202,304,304,053,050,000"... no?

Link to comment
Share on other sites

  • 0

How exactly does your example conversion work? Why are you limiting the number of decimals in the result? I would expect an input of "123456789202304304053050000" to output "? 123,456,789,202,304,304,053,050,000"... no?

Sorry about the confusion, I've edited it since :) There should have been a decimal point before '89'.

I think I posted this thread without thinking properly first :blush:

I took a step back and rewrote my function. I now have the following and it seems to work very nicely:


    function FormatCurrency(strNumberToFormat)
    {
            strNumberToFormat = parseFloat(strNumberToFormat).toFixed(2);
            strNumberToFormat += '';
            intFirstPartTemp = strNumberToFormat.split('.');
            intFirstPart = intFirstPartTemp[0];
            intSecondPart = intFirstPartTemp.length > 1 ? '.' + intFirstPartTemp[1] : '';
            var objRegex = /(\d+)(\d{3})/;
            while (objRegex.test(intFirstPart)) {
                    intFirstPart = intFirstPart.replace(objRegex, '$1' + ',' + '$2');
            }
            return intFirstPart + intSecondPart;
    }

I need to maybe work on it a bit more and work on variable names but it seems to do the trick :p Now I need to test it.

Link to comment
Share on other sites

  • 0

That's starting to look much better already! :) Perhaps just a few more suggestions:

  • Don't trust user input! I recommend you to filter out any unexpected characters from your input string before doing any work.
  • I'd avoid using regular expressions where they're not needed. In this example, you can perfectly group the thousands in the first part with nothing but a loop.

I decided to have a go with this myself, so here's my attempt. Don't get me wrong though - I don't mean your code is incorrect and that you should use mine instead. I just post how I would have done it using things like the modulo operator and efficient for-loops. If there's something you find useful, feel free to copy it.

function FormatCurrency(sNumberInput) {
	// Remove any characters other than numbers and periods from the string, then parse the number
	var nNumberToFormat = parseFloat( String(sNumberInput).replace(/[^0-9\.]/g, '') );
	// Escape when this number is invalid (parseFloat returns NaN on failure, we can detect this with isNaN)
	if( isNaN(nNumberToFormat) ) return '?--';

	// Split number string by decimal separator (.)
	var aNumberParts = nNumberToFormat.toFixed(2).split('.');

	// Get first part = integer part
	var sFirstPart = aNumberParts[0];
	// Determine the position after which to start grouping
	var nGroupingStart = sFirstPart.length % 3;
	// Shift three to the right when first group is empty
	nGroupingStart += (nGroupingStart == 0) ? 3 : 0;
	// Start first result with ungrouped first part
	var sFirstResult = sFirstPart.substr(0, nGroupingStart);
	// Add grouped parts by looping through the remaining numbers
	for(var i=nGroupingStart, len=sFirstPart.length; i < len; i += 3) {
		sFirstResult += ',' + sFirstPart.substr(i, 3);
	}

	// Get second part = fractional part
	var sSecondResult = aNumberParts[1] ? '.' + aNumberParts[1] : '';

	// Combine the parts and return the result
	return '? ' + sFirstResult + sSecondResult;
}

Link to comment
Share on other sites

This topic is now closed to further replies.
  • Recently Browsing   0 members

    • No registered users viewing this page.