Number to word conversion tool
Currently there is no out-of-box feature available in PowerApps and Flow to convert a numerical value into word and hence this blog walks you through how to build one. This blog is an extension of Brian Dang's 'Expanded Word Form for place value' blog.
Scenario:
A scenario I came across was to take a numerical dollar value and convert that into a word form to be printed on pre-printed checks. Hence I created a screen which has the numerical value, the word form and the full name of the person. This blog only focuses on the numerical to word conversion piece.
Video:
Formulas:
Set(WholeNumberVar, First(Split(TextInput.Text,".")));If(!IsBlank(Find(".",TextInput.Text)),Set(DecimalNumberVar,Last(Split(TextInput.Text,"."))),"");
Clear(expandedForm);
// Create a table that separates each digit to include its Value and Position. Make a placeholder for its Place and Period.
ForAll(RenameColumns(Split(WholeNumberVar.Result,""),"Result","Char"),
Collect(expandedForm,
{
Value: Value(Char),
Position:
// Determine the position of each character as a difference between the length of the number and how many digits have already been collected.
Len(WholeNumberVar.Result)-CountRows(expandedForm),
Place: 0,
Period: 0
}
)
);
// Update the Place and Period using the Position.
ForAll(RenameColumns(expandedForm,"Position","Pos"),
Patch(expandedForm,LookUp(expandedForm,Pos=Position),
{
Place:
// Determine if a given column is a one, ten, or hundred based on its position.
Switch(true,
Mod(Pos-1,3)=0,1,
Mod(Pos+1,3)=0,10,
100
),
Period:
// Determine what Period a digit belongs to based on its position.
RoundUp(Pos/3,0)-1
}
)
)
If(IsBlank(Find(".",TextInput.Text)),
Concatenate(
Concat(
GroupBy(expandedForm,"Period","PeriodGroup"),
// Read the hundred in the period.
LookUp(PlaceValue_1,Digit=LookUp(PeriodGroup,Place=100).Value,Word & " ") &
// For 10-19, read the tens and ones together, otherwise separately.
If(LookUp(PeriodGroup,Place=10).Value=1,
LookUp(PlaceValue_1,Digit=Value(Concat(Filter(PeriodGroup,Place<>100),Text(Value))),Word & " "),
Concat(Filter(PeriodGroup,Place<>100),LookUp(PlaceValue_1,Digit=Value && Column=Place,Word & " "))
) &
// Read the period.
Coalesce(LookUp(Period_1,Group=Period,Name & ", "),"")),"dollars"),
Concatenate(
Concat(
GroupBy(expandedForm,"Period","PeriodGroup"),
// Read the hundred in the period.
LookUp(PlaceValue_1,Digit=LookUp(PeriodGroup,Place=100).Value,Word & " ") &
// For 10-19, read the tens and ones together, otherwise separately.
If(LookUp(PeriodGroup,Place=10).Value=1,
LookUp(PlaceValue_1,Digit=Value(Concat(Filter(PeriodGroup,Place<>100),Text(Value))),Word & " "),
Concat(Filter(PeriodGroup,Place<>100),LookUp(PlaceValue_1,Digit=Value && Column=Place,Word & " "))
) &
// Read the period.
Coalesce(LookUp(Period_1,Group=Period,Name & ", "),"")
),Concatenate("dollars & ",DecimalNumberVar.Result,"/100 cents")))
Here's what the expandedForm collection looks like
Conclusion:
As mentioned in the video this app is an extension of Brian Dang's app which uses Components. Attached is a zipped file contains a copy of both the Excel spreadsheet and the MSAPP file which you can use.
Comments
-
Number to word conversion tool
for anyone who got the same error:
RenameColumns(Split(WholeNumberVar.Value, ""), "Result", "Char") the function renamecolumn have some invalid argument
change it .Result to .Value and it should be fine
-
Number to word conversion tool
does anyone have a solution to this yet?
RenameColumns(Split(WholeNumberVar.Value, ""), "Result", "Char") the function renamecolumn have some invalid argument
please let me know
-
-
Number to word conversion tool
RenameColumns(Split(WholeNumberVar.Value, ""), "Result", "Char") the function renamecolumn have some invalid argument
-
Number to word conversion tool
Halo, this is really nice. But when it comes to my app, it is not giving correct result whenever I try putting 20+ digits. Need help
-
Number to word conversion tool
I want convert cents values also in the text. How can I update this code?
-
Number to word conversion tool
Is the issue only with the "3" or is it a problem with "40" being "4," "50" being "5," etc.?
-
Number to word conversion tool
I need your help 😕 It's showing as "three" instead of "thirty"
Can you help identify what's wrong with my code? I just copy pasted it
Set(varWholeNumber, First(Split(varMKTAvailGrandTotal,".")));If(!IsBlank(Find(".",varMKTAvailGrandTotal)),Set(varDecimalNumber,Last(Split(varMKTAvailGrandTotal,"."))),"");
Clear(expandedForm);
// Create a table that separates each digit to include its Value and Position. Make a placeholder for its Place and Period.
ForAll(RenameColumns(Split(varWholeNumber.Value,""),"Value","Char"),
Collect(expandedForm,
{
Value: Value(Char),
Position:
// Determine the position of each character as a difference between the length of the number and how many digits have already been collected.
Len(varWholeNumber.Value)-CountRows(expandedForm),
Place: 0,
Period: 0
}
)
);// Update the Place and Period using the Position.
ForAll(RenameColumns(expandedForm,"Position","Pos"),
Patch(expandedForm,LookUp(expandedForm,Pos=Position),
{
Place:
// Determine if a given column is a one, ten, or hundred based on its position.
Switch(true,
Mod(Pos-1,3)=0,1,
Mod(Pos+1,3)=0,10,
100
),
Period:
// Determine what Period a digit belongs to based on its position.
RoundUp(Pos/3,0)-1
}
)
);Clear(expandedForm_Decimal);// Create a table that separates each digit to include its Value and Position. Make a placeholder for its Place and Period.
ForAll(RenameColumns(Split(varDecimalNumber.Value,""),"Value","Char"),
Collect(expandedForm_Decimal,
{
Value: Value(Char),
Position:
// Determine the position of each character as a difference between the length of the number and how many digits have already been collected.
Len(varDecimalNumber.Value)-CountRows(expandedForm_Decimal),
Place: 0,
Period: 0
}
)
);// Update the Place and Period using the Position.
ForAll(RenameColumns(expandedForm_Decimal,"Position","Pos"),
Patch(expandedForm_Decimal,LookUp(expandedForm_Decimal,Pos=Position),
{
Place:
// Determine if a given column is a one, ten, or hundred based on its position.
Switch(true,
Mod(Pos-1,3)=0,1,
Mod(Pos+1,3)=0,10,
100
),
Period:
// Determine what Period a digit belongs to based on its position.
RoundUp(Pos/3,0)-1
}
)
);//Text to read as words
Set(varAmountInWords,
If(IsBlank(Find(".",varMKTAvailGrandTotal)),
Concatenate(
Concat(
GroupBy(expandedForm,"Period","PeriodGroup"),// Read the hundred in the period.
LookUp(PlaceValue_1,Value(Dig)=LookUp(PeriodGroup,Value(Place)=100).Value,Word & " ") &// For 10-19, read the tens and ones together, otherwise separately.
If(Value(LookUp(PeriodGroup,Value(Place)=10).Value)=1,
LookUp(PlaceValue_1,Value(Dig)=Value(Concat(Filter(PeriodGroup,Value(Place)<>100),Text(Value))),Word & " "),
Concat(Filter(PeriodGroup,Value(Place)<>100),LookUp(PlaceValue_1,Value(Dig)=Value(Value) && Value(Col)=Value(Place),Word & " "))
) &// Read the period.
Coalesce(LookUp(Period_1,Value(Group)=Value(Period),Name & " "),"")),"Pounds"),
Concatenate(
Concat(
GroupBy(expandedForm,"Period","PeriodGroup"),// Read the hundred in the period.
LookUp(PlaceValue_1,Value(Dig)=Value(LookUp(PeriodGroup,Value(Place)=100).Value),Word & " ") &// For 10-19, read the tens and ones together, otherwise separately.
If(Value(LookUp(PeriodGroup,Value(Place)=10).Value)=1,
LookUp(PlaceValue_1,Value(Dig)=Value(Concat(Filter(PeriodGroup,Value(Place)<>100),Text(Value))),Word & " "),
Concat(Filter(PeriodGroup,Value(Place)<>100),LookUp(PlaceValue_1,Value(Dig)=Value(Value) && Value(Col)=Value(Place),Word & " "))
) &// Read the period.
Coalesce(LookUp(Period_1,Value(Group)=Value(Period),Name & ", "),"")
),Concatenate("Pounds & ",Concat(
GroupBy(expandedForm_Decimal,"Period","PeriodGroup"),
// Read the period.
Coalesce(LookUp(Period_1,Value(Group)=Value(Period),Name & " "),""))),
Concatenate(
Concat(
GroupBy(expandedForm_Decimal,"Period","PeriodGroup"),// Read the hundred in the period.
LookUp(PlaceValue_1,Value(Dig)=Value(LookUp(PeriodGroup,Value(Place)=100).Value),Word) &// For 10-19, read the tens and ones together, otherwise separately.
If(Value(LookUp(PeriodGroup,Value(Place)=10).Value)=1,
LookUp(PlaceValue_1,Value(Dig)=Value(Concat(Filter(PeriodGroup,Value(Place)<>100),Text(Value))),Word & " "),
Concat(Filter(PeriodGroup,Value(Place)<>100),LookUp(PlaceValue_1,Value(Dig)=Value(Value) && Value(Col)=Value(Place),Word & " "))
) &// Read the period.
Coalesce(LookUp(Period_1,Value(Group)=Value(Period),Name & ", "),"")
),"Pence")))); -
Number to word conversion tool
Very good!
How would I do, in the cents part, instead of displaying the number, display it in full writing?
Thanks!
-
Number to word conversion tool
I took the existing codes and stored the output in a variable with the ability to specify the type of currency
thanks @darogael and @Adam-Artelia
Text input chose between USD or another currency Lbl_Cur.Text
output stored in variable called NumWord
Onchange of DataCardValue124.Text
Set(Varcurrency ,If(Lbl_Cur.Text="USD"," Dollars "," Yemeni Rial ")); Set(VarcurrencyDiv,If(Lbl_Cur.Text="USD"," Cents "," Fils ")); Set(WholeNumberVar, First(Split(DataCardValue124.Text,".")));If(!IsBlank(Find(".",DataCardValue124.Text)),Set(DecimalNumberVar,Last(Split(DataCardValue124.Text,"."))),""); Clear(expandedForm); // Create a table that separates each digit to include its Value and Position. Make a placeholder for its Place and Period. ForAll(RenameColumns(Split(WholeNumberVar.Result,""),"Result","Char"), Collect(expandedForm, { Value: Value(Char), Position: // Determine the position of each character as a difference between the length of the number and how many digits have already been collected. Len(WholeNumberVar.Result)-CountRows(expandedForm), Place: 0, Period: 0 } ) ); // Update the Place and Period using the Position. ForAll(RenameColumns(expandedForm,"Position","Pos"), Patch(expandedForm,LookUp(expandedForm,Pos=Position), { Place: // Determine if a given column is a one, ten, or hundred based on its position. Switch(true, Mod(Pos-1,3)=0,1, Mod(Pos+1,3)=0,10, 100 ), Period: // Determine what Period a digit belongs to based on its position. RoundUp(Pos/3,0)-1 } ) );Clear(expandedForm_Decimal); // Create a table that separates each digit to include its Value and Position. Make a placeholder for its Place and Period. ForAll(RenameColumns(Split(DecimalNumberVar.Result,""),"Result","Char"), Collect(expandedForm_Decimal, { Value: Value(Char), Position: // Determine the position of each character as a difference between the length of the number and how many digits have already been collected. Len(DecimalNumberVar.Result)-CountRows(expandedForm_Decimal), Place: 0, Period: 0 } ) ); // Update the Place and Period using the Position. ForAll(RenameColumns(expandedForm_Decimal,"Position","Pos"), Patch(expandedForm_Decimal,LookUp(expandedForm_Decimal,Pos=Position), { Place: // Determine if a given column is a one, ten, or hundred based on its position. Switch(true, Mod(Pos-1,3)=0,1, Mod(Pos+1,3)=0,10, 100 ), Period: // Determine what Period a digit belongs to based on its position. RoundUp(Pos/3,0)-1 } ) ); //end of the main code Set(NumberTowords, If(IsBlank(Find(".",DataCardValue124.Text)), Concatenate( Concat( GroupBy(expandedForm,"Period","PeriodGroup"), // 1 Read the hundred in the period. LookUp(PlaceValue_1,Digit=LookUp(PeriodGroup,Place=100).Value,Word & " ") & // 2 For 10-19, read the tens and ones together, otherwise separately. If(LookUp(PeriodGroup,Place=10).Value=1, LookUp(PlaceValue_1,Digit=Value(Concat(Filter(PeriodGroup,Place<>100),Text(Value))),Word & " "), Concat(Filter(PeriodGroup,Place<>100),LookUp(PlaceValue_1,Digit=Value && Column=Place,Word & " ")) ) & // 3 Read the period. Coalesce(LookUp(Period_1,Group=Period,Name & ","),"")),Varcurrency), Concatenate( Concat( GroupBy(expandedForm,"Period","PeriodGroup"), // 4 Read the hundred in the period. LookUp(PlaceValue_1,Digit=LookUp(PeriodGroup,Place=100).Value,Word & " ") & // 5 For 10-19, read the tens and ones together, otherwise separately. If(LookUp(PeriodGroup,Place=10).Value=1, LookUp(PlaceValue_1,Digit=Value(Concat(Filter(PeriodGroup,Place<>100),Text(Value))),Word & " "), Concat(Filter(PeriodGroup,Place<>100),LookUp(PlaceValue_1,Digit=Value && Column=Place,Word & " ")) ) & // 6 Read the period. Coalesce(LookUp(Period_1,Group=Period,Name & ","),"") ),Concatenate(Varcurrency," & ", Concat( GroupBy(expandedForm_Decimal,"Period","PeriodGroup"), // 2 Read the period. Coalesce(LookUp(Period_1,Group=Period,Name & " "),""))), Concatenate( Concat( GroupBy(expandedForm_Decimal,"Period","PeriodGroup"), // 3 Read the hundred in the period. LookUp(PlaceValue_1,Digit=LookUp(PeriodGroup,Place=100).Value,Word) & // 4 For 10-19, read the tens and ones together, otherwise separately. If(LookUp(PeriodGroup,Place=10).Value=1, LookUp(PlaceValue_1,Digit=Value(Concat(Filter(PeriodGroup,Place<>100),Text(Value))),Word & " "), Concat(Filter(PeriodGroup,Place<>100),LookUp(PlaceValue_1,Digit=Value && Column=Place,Word & " ")) ) & // 5 Read the period. Coalesce(LookUp(Period_1,Group=Period,Name & ", "),"") ),VarcurrencyDiv))) ); //to remove extra ", million" & ", billion" & ... Set(NumWord, Substitute(Substitute(Substitute(Substitute(Substitute(NumberTowords,",thousand,",""),",million",""),",billion",""),",trillion",""),",quadrillion","") );
*This post is locked for comments