Recent

Author Topic: [Solved] Aligning Columns of Numeric Data  (Read 1148 times)

PJW

  • New Member
  • *
  • Posts: 23
[Solved] Aligning Columns of Numeric Data
« on: November 29, 2020, 02:27:40 am »
I had a printed report that worked perfectly until I was asked to change the way negative numbers are formatted.   There are two options  <999,999.99> and 999,999.99-

Note the TRAILING negative sign instead of leading!

I came up with the following, which works perfectly for the first case, but fails horribly with the trailing negative.  It's as if the measured width of the '-' is greater than when actually printed as the positive numbers are about a half character to the left of the negative ones.

How is this typically done?

At this point I'm thinking of removing the trailing character and printing it separately, but that just seems wrong.

(Life was so much easier in the days when we only had fixed pitch fonts!)

Code: Pascal  [Select][+][-]
  1.    
  2.     // Handle Right Adjusted Numbers
  3.     if vTyp = 'R' then begin
  4.         X := StartPos + ( ( FieldWidth - Canvas.TextWidth( nData ) ) );
  5.         CH := nData[ Length(nData) ];
  6.         if ( CH = '>' ) or ( CH = '-') then begin
  7.                     // Do Nothing
  8.         end else begin
  9.             X := X - Canvas.TextWidth( CH );
  10.         end;
  11.     end;
  12.        
  13.     // And finally print the field
  14.     Canvas.TextOut( X, Y, nData );
  15.  

« Last Edit: November 29, 2020, 06:50:59 pm by PJW »

lucamar

  • Hero Member
  • *****
  • Posts: 4219
Re: Aligning Columns of Numeric Data
« Reply #1 on: November 29, 2020, 04:08:37 am »
You can avoid the problem by suffixing positives with a space. In most fonts that's about the same width as a minus
Turbo Pascal 3 CP/M - Amstrad PCW 8256 (512 KB !!!) :P
Lazarus/FPC 2.0.8/3.0.4 & 2.0.12/3.2.0 - 32/64 bits on:
(K|L|X)Ubuntu 12..18, Windows XP, 7, 10 and various DOSes.

PJW

  • New Member
  • *
  • Posts: 23
Re: Aligning Columns of Numeric Data
« Reply #2 on: November 29, 2020, 05:20:36 am »
> You can avoid the problem by suffixing positives with a space. In most fonts that's about the same width as a minus

That was the first thing I tried and why I started looking for another solution.  Remember the "-" is not the only character that could be there.  It could also be a '>' when negative numbers are enclosed in brackets, which has a totally different width.

I still don't understand why my code didn't work.  I believe it means that the width of the '-' measured separately is different than it's width when included in a string.  Perhaps something to do with intercharacter spacing?

I ended up trying what I didn't want to do, just to get the code working for now until I find a better solution.  Turns out it wasn't as ugly as I thought it would be.
 
Bean Counters can be real picky as to how their numbers look.


Code: Pascal  [Select][+][-]
  1.     if vTyp = 'R' then begin
  2.       X := StartPos + ( ( FieldWidth - Canvas.TextWidth( nData ) ) );
  3.       CH := nData[ Length(nData) ];
  4.       if ( CH = '>' ) or ( CH = '-') then begin
  5.         SetLength( nData, length(nData)-1 );
  6.         X := StartPos + ( ( FieldWidth - Canvas.TextWidth( nData ) ) );
  7.         Canvas.TextOut( (StartPos + FieldWidth), Y, CH)
  8.       end;
  9.     end;
  10.        
  11.     // And finally print the field
  12.     Canvas.TextOut( X, Y, nData );

« Last Edit: November 29, 2020, 05:27:39 am by PJW »

440bx

  • Hero Member
  • *****
  • Posts: 3944
Re: Aligning Columns of Numeric Data
« Reply #3 on: November 29, 2020, 12:07:50 pm »
I still don't understand why my code didn't work.  I believe it means that the width of the '-' measured separately is different than it's width when included in a string.  Perhaps something to do with intercharacter spacing?

I ended up trying what I didn't want to do, just to get the code working for now until I find a better solution.  Turns out it wasn't as ugly as I thought it would be.
The reason your code doesn't work is because you have not calculated the proper X coordinates and alignments for the different types of numbers you need to print/display. 

There is a simple example of how to align text at https://forum.lazarus.freepascal.org/index.php/topic,42224.msg294497.html#msg294497

Based on what you stated in your post, you need to calculate the maximum width a number can take.  From what you've shown that seems to be a number such as <999,999,999>.  Calculate the width of "9>" subtract from that the width of "9", that will give you the width of ">" including the inter character spacing. With that you can calculate the X coordinate of all numbers and the X coordinate of where the ">" should always go.  Using the width of ">" and "-", you can calculate the X coordinate where the "-" should go.   Using SetTextAlign TA_RIGHT will make things reasonably simple.

Another way of doing it is using GetCharacterPlacement (I don't have an example handy).  Using that API, you can control the position of every character and the intercharacter spacing.  I've occasionally used it to convert a proportional font into a fixed font, particularly for numbers since, they are much nicer looking (and readable) in proportional fonts than they are in the typical fixed fonts.  (Hex dumps look much better that way .)

Sadly, I only know how to do these things using the Windows API but, I am sure there are forum members who can show you the "Lazarus" way of doing it.

HTH.
(FPC v3.0.4 and Lazarus 1.8.2) or (FPC v3.2.2 and Lazarus v3.2) on Windows 7 SP1 64bit.

PJW

  • New Member
  • *
  • Posts: 23
Re: Aligning Columns of Numeric Data
« Reply #4 on: November 29, 2020, 06:47:22 pm »
Thank you to those that replied.  I will certainly look at your suggestions for future projects. 

However in this case, the solution was even simpler... I was so convinced that the issue had to do with the character width of the '-' being measured incorrectly that I totally missed what should have been an obvious bug in my code that caused it to measure the width of the wrong character.

I discovered this while trying to explain how the procedure worked to another person step by step.  I find this often helps with finding bugs.  The other person doesn't even have to be a programmer as I usually discover the issue myself while trying to explain it.  :)

The code is now working and I hope the accountants are happy with their report. 

lucamar

  • Hero Member
  • *****
  • Posts: 4219
Re: Aligning Columns of Numeric Data
« Reply #5 on: November 29, 2020, 06:59:02 pm »
I discovered this while trying to explain how the procedure worked to another person step by step.  I find this often helps with finding bugs.  The other person doesn't even have to be a programmer as I usually discover the issue myself while trying to explain it.  :)

The other person doesn't even have to exist, as those of us who live (and work) alone well know. You can even explain it to yourself: the important thing is to talk it through. ;D

It should be taught as a basic technique in any debugging course :D
« Last Edit: November 29, 2020, 07:01:07 pm by lucamar »
Turbo Pascal 3 CP/M - Amstrad PCW 8256 (512 KB !!!) :P
Lazarus/FPC 2.0.8/3.0.4 & 2.0.12/3.2.0 - 32/64 bits on:
(K|L|X)Ubuntu 12..18, Windows XP, 7, 10 and various DOSes.

 

TinyPortal © 2005-2018