Home General
New Blog Posts: Merging Reports - Part 1 and Part 2

Calculate width by code

edited November 2005 in General
Hello,

I have a code based report in which components (TPpLabel, TppDbText..)
are created by code.
Once created I tried to position them using your Tech Tip
"Calculating the widths of components at run-time"
I only sligthly modified it to read field size (I am printing data from
database tables) from the data dictionary, instead of relying on
lComponent.Caption as in the example.
The problem is that the calculated width is too large
For example a field is 80 character size and the function calculates,
say, 564 pixel that, once printed, are a quite too large.
Do I need to use a printer.canvas ?
But if so isn't the example a little flawed ?
I am using D7 and RB 9.02

Thanks!
Bye
Nicola

Comments

  • edited November 2005
    Hi Nicola,

    The example is correct however it calculates based on a screen pixel based
    canvas. This measurement when translated to the printer canvas will loose
    much of its accuracy. (printers usually print with 600 dots per inch and
    most screens are set to 96 pixels per inch). Try using the printer canvas
    and see if you get a more accurate result.

    --
    Regards,

    Nico Cizik
    Digital Metaphors
    http://www.digital-metaphors.com

    Best Regards,

    Nico Cizik
    Digital Metaphors
    http://www.digital-metaphors.com
  • edited November 2005
    Hi Nico,


    I tried something like this:

    uses
    ppPrintr;
    ...
    liTextWidth := ppPrinter.Canvas.TextWidth(MyString);

    But the results are still larger than needed...
    My code loads an external report as a template and then creates
    components in the detail/header bands inside it.
    I tried changing units (from screen pixels to printer pixels) of this
    external template but I saw no changes in the output...
    It seems that I need to scale down liTextWidth but I am uncertain which
    parameter to use...


    Nico Cizik (Digital Metaphors) ha scritto:
  • edited November 2005
    Hi Nicola,

    Be sure you are assigning the correct font to the canvas before making the
    measurement. I believe this can have an effect on the size of the text
    measured.

    --
    Regards,

    Nico Cizik
    Digital Metaphors
    http://www.digital-metaphors.com

    Best Regards,

    Nico Cizik
    Digital Metaphors
    http://www.digital-metaphors.com
  • edited November 2005
    Hi Nico,

    This is the (pseudo)code I use

    lCanvas := ppPrinter.Canvas;
    lCanvas.Font := lCustomText.Font;
    FieldSize := GetFieldSizeFromCatalog;
    Campione := StringOfChar('A', FieldSize);
    liTextWidth := lCanvas.TextWidth(Campione);

    So I did this assignment

    lCanvas.Font := lCustomText.Font;

    Is this correct? (lCustomText is the TppDbText)
    Thanks in advance
    Bye

    Nico Cizik (Digital Metaphors) ha scritto:
  • edited November 2005
    Hi Nicola,

    Yes, this looks correct. Are you getting better results. As a test I
    created a simple app that measures the caption of a Label on a report.
    Below was my code...

    procedure TForm1.Button1Click(Sender: TObject);
    var
    liWidth: Integer;
    begin

    ppPrinter.Canvas.Font := ppLabel1.Font;
    liWidth := ppPrinter.Canvas.TextWidth(ppLabel1.Caption);

    ShowMessage(IntToStr(liWidth));

    end;

    The width of the label component (which is a little larger than the text
    itself) on the report was 250 printer pixels. The return value for the text
    width was 248. Pretty accurate.

    --
    Regards,

    Nico Cizik
    Digital Metaphors
    http://www.digital-metaphors.com

    Best Regards,

    Nico Cizik
    Digital Metaphors
    http://www.digital-metaphors.com
  • edited November 2005
    Does the PpReport.units property matter in this context ?


    Nico Cizik (Digital Metaphors) ha scritto:
  • edited November 2005
    Hi Nicola,

    No, using the printer canvas will always return printer pixels. You can use
    the utility functions provided in ppUtils.pas to convert these values to
    other units.

    You will probably need to use a combination of ppToMMThousandths and
    ppFromMMThousandths functions.

    --
    Regards,

    Nico Cizik
    Digital Metaphors
    http://www.digital-metaphors.com

    Best Regards,

    Nico Cizik
    Digital Metaphors
    http://www.digital-metaphors.com
  • edited November 2005
    Hi Nico,

    Total confusion here...
    For test I tried to put manually with the report designer a TppDbText on
    the same report in which I am creating components by code.
    So I can compare the runtime generated TppDbText with the manual one (I
    arranged my program in a way that it creates components after the
    already present in the report)
    In the manual created TppDbText I putted enough space for three
    characters (Arial 8 font) so I can see his width in printer pixels that
    is "reported" by the report designer: it is 106 pixels.
    When my code runs it calculates for the same field (3 characters) a
    little less, 90 pixel.
    The very strange thing is the actual printed output!
    My generated component holds 13 characters instead of the only 3 I expected.
    in the runtime generated component I forced the same font (arial 8) and
    autosize=false
    Are there any other properties that may cause a "stretch" of the
    TppDbText ??
  • edited November 2005
    Hi Nicola,

    I'm also a bit confused about what you are ultimately trying to do. Perhaps
    a detailed description of what your report looks like and exactly what you
    would like to see happen. During the report generation, the acutal text
    component will not be re-sized based on the text being displayed. This is
    going on in the drawcommand object. My suggestion is to manually retrieve
    the text directly off the database and measure it to get an accurate result.

    --
    Regards,

    Nico Cizik
    Digital Metaphors
    http://www.digital-metaphors.com

    Best Regards,

    Nico Cizik
    Digital Metaphors
    http://www.digital-metaphors.com
  • edited November 2005
    Hi Nico,

    What I need to do is quite simple:

    1. load a report template.
    This template has a title, a footer and a detail
    The detail contains no components at all (in the final version)

    2. at runtime the user can choose which fields she wants in the report
    browsing a database catalog (e.g. the fields of a particular table)

    3. the program creates the requested TppComponent in the detail band.
    I am trying to size each component to fit the maximum length allowed for
    each of them
    For example
    The user chooses the field "EMP"."SURNAME"
    The program looks up in the database catalog and see that EMP.SURNAME
    field is 40 character long, so it will create a TppDbText linked to the
    EMP.SURNAME 40 character long.

    This is what I need to accomplish
    The SQL manipulation part works fine, even the TPpComponent creation
    works, only the sizes are wrong....
  • edited November 2005
    Hi Nicola,

    Thanks for the explaination.

    When creating the TppDBText components, have you tries simply setting the
    AutoSize property to True? This should dynamically size the DBText width to
    the size of the text being pulled from the database (I believe using the
    same technique we've been trying).

    --
    Regards,

    Nico Cizik
    Digital Metaphors
    http://www.digital-metaphors.com

    Best Regards,

    Nico Cizik
    Digital Metaphors
    http://www.digital-metaphors.com
  • edited November 2005
    Hi Nico,

    Thanks for responding, I understand that is difficult for you help me
    without seeing mu code..
    Yes I alread tried autosize=true
    But even so it doesn't work well.
    The left position is too large
    Remember the example?
    The left position of each TppDbText in the list is setted using the
    width as increment.
    My components are too large spreaded, even when I don't set the width,
    using only autosize=true

    Nico Cizik (Digital Metaphors) ha scritto:
  • edited November 2005
    I found an important detail that explains lot of my problems..

    In your example "Calculating the widths of components at run-time"
    the screen pixel property was used.
    See:
    ..
    {set components screen pixel left}
    lCustomText.spLeft := liPosition;
    ..

    There is also a comment but, you know, I missed to read it... -)

    I changed spLeft into Left and now my results sound much better to me...

    Thanks
    Bye
    Nicola
  • edited November 2005
    Hi Nicola,

    Fantastic! Glad you got it working.

    --
    Regards,

    Nico Cizik
    Digital Metaphors
    http://www.digital-metaphors.com

    Best Regards,

    Nico Cizik
    Digital Metaphors
    http://www.digital-metaphors.com
This discussion has been closed.