Symbian Developer Library

SYMBIAN OS V6.1 EDITION FOR C++

[Index] [Glossary] [Previous] [Next]



How to format currency values


From 6.1 onward

From 6.1, the TLocale class provides the FormatCurrency() functions that can format currency values into a descriptor. The functions can handle both small and large values. They render the currency amount as text, using the current locale's formatting requirements. These include items such as:

There are four overloaded variants of FormatCurrency(), two of which are suitable for rendering currency values that fit into a TInt type, and the other two of which are suitable for rendering very large currency values that fit into a TInt64 type.

Both pairs of functions behave in the same way, and the following code fragments will also apply to the TInt64 variants.

The first code fragment uses the void FormatCurrency(TDes&,TInt); variant.

...
TLocale locale;

TInt amount;
TBuf<64> buffer;

locale.set();
locale.FormatCurrency(buffer,amount);
...

On return, the descriptor buffer contains the currency value formatted as text using the currency symbol and formatting appropriate to the current locale. Note, however, that the caller is responsible for ensuring that the descriptor buffer is large enough. Too small a buffer results in a USER 11 panic.

The second code fragment uses the void FormatCurrency(TDes&,TDesOverflow&,TInt); variant.

class TestOverflow : public TDesOverflow
    {
    void Overflow(TDes& aBufferThatOverflowed);
    };

void TestOverflow::Overflow(TDes& aBufferThatOverflowed)
    {
    _LIT(KTextOverflow,"Overflowed");
    aBufferThatOverflowed = KTextOverflow;
    }

...
TLocale locale;
TestOverflow ovfl;

TInt amount;
HBufC* bufPtr;

bufPtr = HBufC::NewL(10);

locale.set();
locale.FormatCurrency(*bufPtr,ovfl,amount);
...

In this fragment, if the formatted text cannot fit into the buffer, *bufPtr, then TestOverflow::Overflow() is called which simply sets the text "Overflowed" into the buffer. In practice, application code would probably perform more sophisticated recovery which might include re-allocating the buffer and re-trying the FormatCurrency() operation.

[Top]


Before 6.1

Before 6.1, the FormatCurrency() function is not available and the procedure for formatting a currency value needs more code and explicitly uses more of the functionality of the TLocale class.

In the following example code fragments, the formatting is done by a function called foo(). This function takes a descriptor that, on return, holds the formatted currency value. The function assumes that the descriptor is big enough to hold the formatted text. The example holds the currency value as a TReal value.

foo() uses the AppendNum() and Append() descriptor functions to format and append the currency value and symbol to aBuffer using an object of class TRealFormat to determine the character representation of the currency value.

The code formats the following locale-dependent aspects of currency information:

void foo(TDes& aBuffer, TReal aCurrencyAmount)
    {
            // get system locale settings
    TLocale locale;
    TRealFormat realFormat;
    realFormat.iType=EFixed;

            // convert number to the general form "nnn.ddd" where
            // "n" is the integer and "d" is the decimal portion.
            // iWidth is the maximum number of characters allowed to represent the number
    realFormat.iWidth=30;
    realFormat.iDecimalPlaces=locale.CurrencyDecimalPlaces();
    realFormat.iPoint=locale.DecimalSeparator();
    realFormat.iTriad=locale.ThousandsSeparator();
    realFormat.iTriLen=(locale.CurrencyTriadsAllowed() ? 1 : 0);
    ...

Note the following points:

...
_LIT(KTxtOpenBracket,"(");
_LIT(KTxtCloseBracket,")");
_LIT(KTxtSpace," ");
TCurrencySymbol symbol;

    // Get system wide currency symbol setting
symbol.Set();

    // Append an open bracket, if the amount is negative and the locale demands it.
if ((aCurrencyAmount<0) && (locale.CurrencyNegativeInBrackets()))
    {
    aBuffer.Append(KTxtOpenBracket);
    }

    // Position the currency symbol before the currency value, and insert space between the
    // symbol and the amount if the locale demands them.
if (locale.CurrencySymbolPosition() == ELocaleBefore)
    {
    aBuffer.Append(symbol);
    if (locale.CurrencySpaceBetween())
        {
        aBuffer.Append(KTxtSpace);
        }
    }

    // Append negative currency value and remove the sign if the locale demands
    // negative values in brackets
if ((locale.CurrencyNegativeInBrackets()) && (aCurrencyAmount<0))
    {
    aBuffer.AppendNum(-aCurrencyAmount,realFormat);
    }
else
    {
    aBuffer.AppendNum(aCurrencyAmount,realFormat);
    }

    // Position the currency symbol after the currency value, and insert space between the
    // amount and the symbol if the locale demands them.
if (locale.CurrencySymbolPosition() == ELocaleAfter)
    {
    if (locale.CurrencySpaceBetween())
        {
        aBuffer.Append(KTxtSpace);
        }
    aBuffer.Append(symbol);
    }

    // Finally, append the closing bracket, if the value is negative and
    // the locale demands brackets around negative values.
if ((aCurrencyAmount<0) && (locale.CurrencyNegativeInBrackets()))
    {
    aBuffer.Append(KTxtCloseBracket);
    }
}

Note that the currency symbol cannot be set using the TLocale class. Use User::SetCurrencySymbol() to do this.