Formatting Numbers in Views

71 views
Skip to first unread message

F Bek

unread,
Dec 27, 2020, 6:37:44 AM12/27/20
to
Beginner's question.
DS 7.1.18

Now that I have a working view, how do I format the numbers to display in a certain way? Say #,###.##

Browsing the system, I could find an external class NUMBERFMTW that seems related, but cannot figure out how to use it, or if there is any other way.

Thanks for reading and eventually answering.

FB

Sergio Del Franco

unread,
Dec 27, 2020, 4:00:46 PM12/27/20
to
El Sunday, December 27, 2020 a la(s) 8:37:44 AM UTC-3, fbek...@gmail.com escribió:
> Now that I have a working view, how do I format the numbers to display in a certain way? Say #,###.##

Hi FB.
TextEdit has a typeconverter property. You can create a NumberToText subclass to format the numbers as you wish and use it in your views.

-- Sergio Del Franco.

F Bek

unread,
Dec 31, 2020, 4:27:26 AM12/31/20
to
Thanks Sergio for the tip, it was quite illuminating. Though it left me wondering how am I going to do that. I went browsing TextEdit and TypeConverter, and also read chapter 7 of 'the Dolphin Smalltalk Companion' book to form a plan. Working on it now and will post the code when done.

FB

F Bek

unread,
Jan 5, 2021, 9:48:18 AMJan 5
to
Really wondering why Dolphin 7.xx still doesn't have native support for number formatting!!

Anyway, this is the method I wrote to handle number formatting. It certainly does not do everything but still manages to offer a few options to group digits by a chosen number, using a chosen separator, and to round the number after a chosen number of decimals and use a chosen decimal separator - I've renamed this method a couple of times, but I'm still not really happy with the current name:

Number>>asTextWithFormatBy: groupNum groupWith: groupChar decimalWith: decimalChar decimalNum: decimals
"Format a number as ###,###.## | groupNum: anInteger; groupChar: aChar; decimalChar: aChar; decimals: anInteger"
| in out count numberToString |
numberToString := (self * (10 ** decimals) roundTo: 1) printString reverse.

[numberToString size > decimals] whileFalse: [numberToString := numberToString , '0' ]. "pad with zeros"

in := ReadStream on: numberToString.
out := WriteStream on: String new.
count := 1.
[count > decimals] whileFalse:
[out nextPut: in next.
count := count + 1].
out nextPut: decimalChar. "add the decimal part and decimal separator"

count := 1.
[in atEnd] whileFalse:
[out nextPut: in next.
(count = 0 and: [in atEnd not]) ifTrue: [out nextPut: groupChar].
count := (count + 1) \\ groupNum]. "add the integer part and the digits separator"
^out contents reverse asString.

The next step was to create a new converter class, (at the same level as the system's NumberToText, I did not see an immediate advantage of subclassing it, and leaving room to avoid potential clashes with future versions of Dolphin):

AbstractToTextConverter subclass: #FB_NumberToText
instanceVariableNames: ''
classVariableNames: ''
poolDictionaries: ''
classInstanceVariableNames: ''

FB_NumberToText class >> category: MVP-Type Converters-Text - this actually registers this class as an additional typeconverter option in TextEdit, making it available for selection.

Next, I've added this method; the choices are hard-coded for now; maybe they can be stored in Class variables and modified through the view?:

FB_NumberToText >> leftToRight: aNumber
"Answers the result of converting aNumber to a String"
^aNumber asTextWithFormatBy: 3 groupWith: $, decimalWith: $. decimalNum: 3 .

I've also added a rightToLeft method, as a copy-paste of the original method in NumberToText (yes, I could have inherited it if I subclassed).
With that, I had a working converter, that fits the current purpose. I'm sure there are ways to optimize and expand it still.

Thanks for reading and eventually commenting.
FB

Sergio Del Franco

unread,
Jan 9, 2021, 7:00:55 AMJan 9
to
El Tuesday, January 5, 2021 a la(s) 11:48:18 AM UTC-3, fbek...@gmail.com escribió:
> Really wondering why Dolphin 7.xx still doesn't have native support for number formatting!!
> Anyway, this is the method I wrote to handle number formatting.
[...]
> Number>>asTextWithFormatBy: groupNum groupWith: groupChar decimalWith: decimalChar decimalNum: decimals
> "Format a number as ###,###.## | groupNum: anInteger; groupChar: aChar; decimalChar: aChar; decimals: anInteger"
[...]

You should use Locale >> #printFloat:on:format::

String streamContents: [:stream |
Locale default
printFloat: 1234.56
on: stream
format: (
NUMBERFMTW new
Grouping: 3;
thousandSeparator: ',';
decimalSeparator: '.';
decimalPlaces: 3;
yourself
).
].

-- Sergio Del Franco

F Bek

unread,
Jan 9, 2021, 10:08:36 AMJan 9
to
Yes! This is what I was looking for!
Experimenting with the code now...

Thanks Sergio.

FB

F Bek

unread,
Jan 12, 2021, 6:22:12 PMJan 12
to
Implementing the new code, my number formatting method now reads like this:

Number >> asTextWithGrouping: groupNum groupSeparator: groupChar decimalSeparator: decimalChar decimalPlaces: decimals
"Format the number as ###,###.## | groupNum: anInteger; groupChar: aString; decimalChar: aString; decimals: anInteger"
^String streamContents: [:strm | Locale default printFloat: self asFloat on: strm format: (
NUMBERFMTW new Grouping: groupNum ; thousandSeparator: groupChar ;
decimalSeparator: decimalChar ; decimalPlaces: decimals ;
LeadingZero: 1 ; NegativeOrder: 1 ;
yourself). ].

The receiver of the method is still <Number>, although it really could be any other object, and I have considered moving it to <String> instead, where it logically belongs - but that would add an argument for passing the number being formatted, so I finally decided against the change. In the above, I have added the last 2 properties (LeadingZero & NegativeOrder) more as a mental note, and for future reference, if necessary.
I then modified the converter #leftToRight method to call the new method:

FB_NumberToText >> leftToRight: aNumber
"Answers the result of converting aNumber to a String"
^aNumber asTextWithGrouping: 3 groupSeparator: ',' decimalSeparator: '.' decimalPlaces: 2 .

The rest of he code remained the same. With those 2 changes, my formatter was functional again.

Now for a quick discussion - from a beginner's point of view:
Using Locale >> #printFloat:on:format: was interesting and revealing but did not really do much more than my humble converter, included in the previous message, was able to offer (except for the possibility to auto format numbers according to the Windows local default). It remains very short of a full number formatting solution, similar to Windows products, e.g. in Excel. Again, for a programming environment that targets Windows exclusively, I thought Dolphin would offer a way to tap into all of this readily. Now it seems I have to further expand the method if I need some additional functionality - unless I am missing something again. Nevertheless, I am happy with the result so far as it fits the current need.

Thanks Sergio for the assistance, happy hear your feedback.

FB

F Bek

unread,
Feb 12, 2021, 2:16:54 PMFeb 12
to
Note: with the new Dolphin version 7.2.4, a slight modification is required to the code:
replace <NUMBERFMTW> by <OS.NUMBERFMTW>.
__________
Reply all
Reply to author
Forward
0 new messages