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:
the appropriate currency symbol
whether the currency symbol is placed before or after the currency amount
whether there is space between the currency amount and the currency symbol
the number of decimal places
the way a negative currency value is rendered.
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.
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:
the number of decimal places
the decimal and thousands separators (iPoint
and
iTriad
)
whether triads are allowed or not
(iTriLen
)
An iTriLen
value of 1 signifies that triads are
allowed throughout the currency amount. A value of zero means that no triads
are allowed.
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:
Use CurrencySymbolPosition()
and
CurrencySpaceBetween()
to decide whether the currency symbol should
be placed before or after the currency amount and whether or not to insert a
space between the symbol and the amount.
Use CurrencyNegativeInBrackets()
to decide
whether or not negative currency amounts should be enclosed in brackets. If
this is the case, and the value is negative, an open bracket is appended and
any minus sign is removed by appending the currency value to the buffer as a
negative value.
Use CurrencySpaceBetween()
to decide whether or not to insert a space between the currency symbol and the currency value.
...
_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.