Yesterday I saw a post on the Brazilian ColdFusion list CF-BRASIL where a colleague was asking for any function to convert a value into the Brazilian currency “Reais” in the form of text. I remembered that I wrote a custom tag for that in 2002, but it had some problems writing the cents. Well, I worked on it tonight and accomplished to make a component which I called “rpMoneyBrExt.cfc“. Since I’m tired, I didn’t test it thoroughly, but I made it sure to write the cents correctly now. So if you want to use, troubleshoot or modify it, be my guest, just send me your changes and keep my copyright notice. Download the component and a test template rpMoneyExtBr

Here is how you call the component:{code type=coldfusion}
<cfscript>
amt = "420392235497.32";
money = createObject("component", "rpMoneyExtBr");
writeOutput("<br>" & amt);
writeOutput("<br>" & money.convert(amt));
</cfscript>
{/code}
Here is the component:{code type=coldfusion}
<cfcomponent displayname="rpMoneyBrExt" hint="Converts a value into a written currency text" output="false">
<cfprocessingdirective pageencoding="utf-8" />
<cfscript>
/*
Author & copyright: Ricardo Parente
Version: 1.0
Date: July 31st 2008
Platform: ColdFusion 8
Disclaimer: You are free to use this component "as is" or modify it in any way, just send me your changes.
Contact: rparente(at)cfdevelopers.net
*/
this.reu = structNew();
this.rec = structNew();
this.reDi = arrayNew(1);
this.reu.male = arrayNew(1);
this.reu.male = ["Um", "Dois", "Três", "Quatro", "Cinco", "Seis", "Sete", "Oito", "Nove", "Dez", "Onze", "Doze", "Treze", "Quatorze", "Quinze", "Dezesseis", "Dezessete", "Dezoito", "Dezenove"];
this.reu.female = arrayNew(1);
this.reu.female = ["Uma", "Duas", "Três", "Quatro", "Cinco", "Seis", "Sete", "Oito", "Nove", "Dez", "Onze", "Doze", "Treze", "Quatorze", "Quinze", "Dezesseis", "Dezessete", "Dezoito", "Dezenove"];
this.reDi = ["", "Vinte", "Trinta", "Quarenta", "Cinquenta", "Sessenta", "Setenta", "Oitenta", "Noventa"];
this.rec.male = arrayNew(1);
this.rec.male = ["Cento", "Duzentos", "Trezentos", "Quatrocentos", "Quinhentos", "Seiscentos", "Setecentos", "Oitocentos", "Novecentos"];
this.rec.female = arrayNew(1);
this.rec.female = ["Cento", "Duzentas", "Trezentas", "Quatrocentas", "Quinhentas", "Seiscentas", "Setecentas", "Oitocentas", "Novecentas"];
</cfscript>
<cffunction name="convert" access="remote" output="false" returntype="string">
<cfargument name="amount" type="string" required="false" default="0" hint="amount to be converted" />
<cfargument name="singular" type="string" required="false" default="Real" hint="Name of the currency in the singular" />
<cfargument name="plural" type="string" required="false" default="Reais" hint="Name of the currency in the plural" />
<cfargument name="isMale" type="boolean" required="false" default="true" hint="currency is male or female" />
<cfargument name="hasComplement" type="boolean" required="false" default="false" hint="complete the phrase with [de Real]" />
<cfscript>
// set variables
var extenso = "";
var result = "";
var finalComp = "";
var rvar = "";
var rBlh = "";
var rMlh = "";
var rMil = "";
var rCrz = "";
var rCnt = "";
var cents = 0;
if (arguments.amount eq 0) return "*** ZERO REAIS ***"; // if value passed is zero, return
//find out if user passed value with decimal comma or decimal dot
if (find(",", arguments.amount) or find(".", arguments.amount)){
arguments.amount = reReplace(arguments.amount, "[,.]", "@", "one");
cents = listLast(arguments.amount, "@");
arguments.amount = listFirst(arguments.amount, "@");
if (not isNumeric(arguments.amount)) return "Não numérico";
}
// format integer part to work
rvar = numberFormat(evaluate(val(arguments.amount)),"000,000,000,009");
if (arguments.hasComplement) finalComp = " de " & arguments.singular;
// split the number into sections
rblh = listFirst(rvar, ",");
rmlh = listGetAt(rvar, 2, ",");
rmil = listGetAt(rvar, 3, ",");
rcrz = listFirst(listGetAt(rvar, 4, ","), ".");
rcnt = cents;
// does billion exist ?
result = result & mountText(rblh, "Bilhão", "Bilhões", arguments.isMale);
if (len(trim(result))) result = result & closeClass(rmlh + rmil + rcrz);
// does Milhao exist ?
result = result & mountText(rmlh, "Milhão", "Milhões", arguments.isMale);
if (len(trim(result))) {
if (int(rmlh) neq 0) result = result & closeClass(rmil + rcrz);
}
// does Mil exist ?
result = result & mountText(rmil, "Mil", "Mil", arguments.isMale);
if (len(trim(result))) {
if (int(rmil) neq 0) {
result = result & ", ";
} else {
result = result & " ";
}
}
// Create Real
result = result & mountText(rcrz, "", "", arguments.isMale);
if ( (val(rblh) + val(rmlh) + val(rmil) + val(rcrz)) eq 1) {
result = result & arguments.singular;
} else {
result = result & arguments.plural;
}
if (len(trim(result)) and (int(rcnt) neq 0)) result = result & " e ";
// centavos
result = result & mountText("0" & rcnt, "Centavo", "Centavos", arguments.isMale);
if (int(rcnt) gt 0) result = result & finalcomp;
return result;
</cfscript>
</cffunction>
<cffunction name="mountText" access="remote" output="false" returntype="string">
<cfargument name=”sValue” type=”numeric” required=”true” />
<cfargument name=”singular” type=”string” required=”false” default=”” hint=”word in the singular” />
<cfargument name=”plural” type=”string” required=”false” default=”” hint=”word in the plural” />
<cfargument name=”isMale” type=”boolean” required=”false” default=”true” />
<cfscript>
var Rc = 0;
var Rd = 0;
var Rdi = 0;
var Ru = 0;
var result = "";
if (arguments.sValue eq 0) return "";
Rc = left(arguments.sValue, 1);
Rd = right(arguments.sValue, 2);
Rdi = mid(arguments.sValue, 2, 1);
Ru = right(arguments.sValue, 1);
if (Rc neq 0) {
if (Rd eq 0 and Rc eq 1) {
result = result & "Cem";
} else {
result = result & iif(arguments.isMale, de(this.rec.male[Rc]), de(this.rec.female[Rc]));
}
if (Rd neq 0) {
result = result & " e ";
}
}
if (Rd lt 20 and Rd neq 0) {
result = result & iif(arguments.isMale, de(this.reu.male[Rd]), de(this.reu.female[Rd]));
} else if (Rd gte 20) {
result = result & this.reDi[Rdi];
if (Ru neq 0) result = result & " e " & iif(arguments.isMale, de(this.reu.male[Ru]), de(this.reu.female[Ru]));
}
return (result & " " & iif(arguments.sValue eq 1, de(arguments.singular), de(arguments.plural)));
</cfscript>
</cffunction>
<cffunction name="closeClass" access="remote" output="false" returntype="string">
<cfargument name="sValue" type="numeric" required="false" default="0" hint="value to tranform" />
<cfscript>
var result = "";
if (arguments.sValue eq 0) {
result = " de ";
} else result = ", ";
return result;
</cfscript>
</cffunction>
</cfcomponent>{/code}

2 thoughts on “Writing Brazilian Currency In Text Format

  1. Ricardo boa tarde,

    Meu amigo muito boa essa classe, bastante util.

    Porém no método mountText() está faltando os argumentos: sValue e isMale.

    De resto, está funcionando perfeitamente.

    Abraços

Leave a Reply