Groovy currency formatting - groovy

I'm writing some rows to a text file using groovy (grails 1.3.7) and I want to format the currency like this example output:
$100,000,000.00
$9,123,123.25
$10.20
$1,907.23
So basically right-justified, or left padded, with the dollar sign in front of the number so they all line up like the above. The first number is the longest we would expect to see. Right now I have an amount variable that is simply defined with a def and not string or number or anything specific like that but I can obviously change that if need be. Thanks!

You probably want to use NumberFormat.getCurrencyInstance(). This will return a NumberFormat object that uses the standard currency representation for your default Locale (or optionally, the one you pass in).
To right justify, you can use String.padLeft().
Example:
def formatter = java.text.NumberFormat.currencyInstance
def values = [0, 100000000, 9123123.25, 10.20, 1907.23]
def formatted = values.collect { formatter.format(it) }
def maxLen = formatted*.length().max()
println formatted.collect { it.padLeft(maxLen) }.join("\n")
//output
$0.00
$100,000,000.00
$9,123,123.25
$10.20
$1,907.23

In grails soemthing like this will format it nicely with comma separators.
<g:formatNumber number="${150000}" type="currency" currencyCode="USD"/>
For right aligning I would use style:
<td style='text-align:right;...'>

Related

How set a standard format specifier to be used throughout a module when using f-strings?

I am using f-strings for formatting strings and injecting variable values into the string, is there a way to set a format-spec for an entire module in python?
I am aware of Standard Format Specifiers which can be used to specify formats for each string, but how do I do it at once for the whole module?
Eg:
f""" Some random string {value1}, some more text {value2:.2f} ... """
Here I am specifying the format for value2, but I want to set a format for all globally.
f"""% profits are {profit}"""
Had I set format spec to {profit:.2f} this will be set to two decimal places, but I want to set that :.2f globally so that number decimal places can be changed with one variable update.
Something like format-spec = ':.2f' and all the f-string injected values should be displayed as floats with two decimals (if its a numbers).
If I understand you correctly, you want to define a string format one time that is usable throughout a script. I would create a function, callable from anywhere in your script that produces the formatted string as shown below:
def create_string(v_str: str, v_num: float) -> str:
return f""" Some random string {v_str}, some more text {v_num:.2f} ... """
You can then use the create_string function from anywhere in your script and produce the desired output as illustrated below:
print(create_string('Some words here', 2.56))
which yields:
Some random string Some words here, some more text 2.56 ...

Extract string after numerics in SAS

I need to extract the string after the numbers. Although the problem is that the number of digits at the front of the string is inconsistent. What I need is something similar like the Flash Fill in Excel. But I'll be doing it for 100K+ rows so Excel might not be able to handle the data. For example:
12345678aaa#mail.com
12345bbb#mail.com
123456789ccc#mail.com
I want the create another variable with the extracted string such as the following:
aaa#mail.com
bbb#mail.com
ccc#mail.com
Is this possible?
Thank you in advance!
You can use regular expression substitution (PRXCHANGE), or a careful use of the VERIFY function.
Example:
data have;
input email $char25.; datalines;
12345678aaa#mail.com
12345bbb#mail.com
123456789ccc#mail.com
1234567890123456789012345
;
data want;
set have;
mail1 = prxchange('s/^\d+//',-1,email);
if email in: ('0','1','2','3','4','5','6','7','8','9') then
mail2 = substr(email||' ',verify (email||' ', '0123456789'));
run;
Example above should be OK,
but assuming that some email addresses could have numbers, 123abc001#mail.com for instance, my code below should help:
data have;
input email $char25.; datalines;
12345678abc01#mail.com
12345bcde#mail.com
123456789cdefg1#mail.com;
PROC SQL;
CREATE TABLE WORK.QUERY_FOR_HAVE_0003 AS
SELECT t1.email,
/* want */
(substrn(t1.email,INDEXC( t1.email, SUBSTRN(COMPRESS(t1.email, 'abcdefghijklmnopqrstuvwxyz', 'k'), 1, 1))))
AS want
FROM WORK.HAVE t1;
QUIT;
Firstly, we use COMPRESS functionm to leave only char values;
Then SUBSTRN - to have the first character appearing in email address;
After than INDEXC - returns position of the character;
Finally SUBSTRN again - leaves the rest of the email, starting from the position provided from step before.
final look:
[1]: https://i.stack.imgur.com/hFftg.png

Formatting "key: value" strings with middle spaces

I'm showing key-value pair in a QListWidget. Since key names have different lengths, numbers start in different positions:
TestParameter1: 1.2345
Param2: 6.7890
If it wasn't for the key name, I know that I can use format to introduce spaces with a syntax like '{:7.4f}'.format(value).
Is there any easy way (I mean, not switching to a table or creating my own implementation os a QListView) of achieving something like...?:
TestParameter1: 1.2345
Param2: 6.7890
I suggest you take a further look at string formatting here.
The first thing that comes to mind is to either use the \t (tab) to align as necessary; or to use something on the lines of the below as stated in the python docs.
>>> for align, text in zip('<^>', ['left', 'center', 'right']):
... '{0:{fill}{align}16}'.format(text, fill=align, align=align)
...
'left<<<<<<<<<<<<'
'^^^^^center^^^^^'
'>>>>>>>>>>>right'
>>>

NPOI: Achieve Currency format as if formatted by Excel

I have seen some questions (like this one) here asking about if a cell in Excel can be formatted by NPOI/POI as if formatted by Excel. As most of you, I have to deal with issues with Currency and DateTime. Here let me ask how the formatting can be achieved as if it has been formatted by Excel? (I will answer this question myself as to demonstrate how to do it.)
Setting: Windows 10, English, Region: Taiwan
Excel format: XLSX (version 2007 and later)
(Sorry about various edit of this question as I have pressed the 'Enter' button at unexpected time.)
If you format a cell as Currency, you have 4 choices:
The internal format of each style is as follow:
-NT$1,234.10
<numFmt formatCode=""NT$"#,##0.00" numFmtId="164"/>
[RED]NT$1,234.10
<numFmt formatCode=""NT$"#,##0.00;[Red]"NT$"#,##0.00" numFmtId="164"/>
-NT$1,234.10
<numFmt formatCode=""NT$"#,##0.00_);("NT$"#,##0.00)" numFmtId="7"/>
[RED]-NT$1,234.10
<numFmt formatCode=""NT$"#,##0.00_);[Red]("NT$"#,##0.00)" numFmtId="8"/>
Note: There is a pair of double quote (") comes before and after NT$.
(To get internal format of XLSX, just unzip it. The Style information is available in <unzip dir>\xl\Styles.xml Check out this answer if you need more information.)
(FYI: In formatCode, the '0' represent a digit. The '#' also represent a digit, but will not appear if the number is not large enough. So any number less than 1000 will not have the comma inside it. The '_' is a space holder. In format 3, '1.75' appears as 'NT$1.75 '. The last one is a space.)
(FYI: In numFmtId, for case 1 and case 2, number 164 is for user-defined. For case 3 and 4, number 7 and 8 are build-in style.)
For developers using POI/NPOI, you may find out if you format your currency column using Build In Format using 0x7 or 0x8, you can get only the third or fourth choice. You cannot get the first or second choice.
To get the first choice, you build upon style 0x7 "$#,##0.00);($#,##0.00)". You need to add the currency symbol and the pair of double quotes in front of it.
styleCurrency.DataFormat = workbook.CreateDataFormat().GetFormat("\"NT$\"#,##0.00");
Apply this format to a cell with number. Once you open the Excel result file, right click to check formatting, you will see the first choice.
Please feel free to comment on this post.
var cell5 = row.CreateCell(5, CellType.Numeric);
cell5.SetCellValue(item.OrderTotal);
var styleCurrency = workbook.CreateCellStyle();
styleCurrency.DataFormat= workbook.CreateDataFormat().GetFormat(string.Format("\"{0}\"#,##0.00", item.CurrencySymbol));//styleCurrency;
cell5.CellStyle = styleCurrency;
styleCurrency = null;
Iterate over loop for multiple currency.
Function to GetCurrencySymbol against currency Code on C#
private string GetCurencySymbol(string isOcurrencyCode)
{
return CultureInfo.GetCultures(CultureTypes.AllCultures).Where(c => !c.IsNeutralCulture)
.Select(culture =>
{
try
{
return new RegionInfo(culture.LCID);
}
catch
{
return null;
}
})
.Where(ri => ri != null && ri.ISOCurrencySymbol == isOcurrencyCode)
.Select(ri => ri.CurrencySymbol).FirstOrDefault();}

Grails - sortableColumn - Forcing numerical sorting on numerical strings

I have number stored in my database as Strings, and I would like to sort them numerically using Grails sortableColumns. Is there anyway to do this ?
Storing numbers as formatted strings prevents them from taking advantage of native numerical sorting. Have a look at the Grails formatNumber tag that can use your desired locale to display decimal separators so you can use the actual numeric data and not have to store the formatted string for display purposes.
If the domain class you want to sort has both the formatted and unformatted numeric data, you could try something like this, substituting the sort column param as necessary:
def list = {
if (params?.sort == 'formattedNumber') {
params.sort = 'rawNumber'
}
[ records : Record.list(params) ]
}
If your domain class only has the formatted string you can try parsing it to BigDecimal (or whatever the matching numeric type is) but this may not work properly if your server's locale does not match the string format's decimal separator locale.
def list = {
def records = (params?.sort == 'formattedNumber') Record.list().sort{ it.formattedNumber.toBigDecimal() : Record.list(params)
}
[ records : records ]
}

Resources