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

Wrong behavior when calculating summaries for groupfooters in preview

edited April 2007 in General
Hi!

I?m using the ReportBuilder Enterprise Edition Version 9.03.

The Report:
My actual task is to create a report that displays grouped data in the
Detailband. Addtionally every group has its own header in the
GroupHeaderBand and some statistical values in the GroupFooterBand.
Because the statistical values of the group are too complex to be
calculated by simple CalcFields I calculate them manually in RAP, by
adding the needed values in each DetailBeforeGenerate-Event to global
variables.
the Report ist set to TwoPass (for page numbers) and CachePages = True,
the mentioned group is set to 'Keep group together' and 'Reprint group
headers on subsequent pages'.

The Problem:
At first sight everything works fine:
-When all Datarows can by displayed on one single page the footer?s values
are calcualted correctly.
-When moving page by page through the preview the values are also
correctly calculated, even if there are too much DataRows to show on one
single page.

My Problem occurs, when I jump directly to a specific page for example the
last page that definitely contains a GroupFooter with the summary values.
In this case only the DataRows of the last page are added to my
calculations by the DetailBeforeGenerate-Event, but if there are also rows
of this group on the previous page/s these are not effected, which leads
to wrong values in the calculations.

Strange thing is, that I found out that in the FirstPass everything works
fine, because page by page is caculated in the Report. Because of
CachePages is set to true, in my opinion it would not be neccesary to
caculate even one page again afterwards. But the Problem is, that in the
SecondPass as the user goes through the Preview manually, everything is
calculated again (and in my described case it is calculated wrong).

How can I solve this problem?

Regards

Ralf



--- posted by geoForum on http://delphi.newswhat.com

Comments

  • edited April 2007
    Hi Ralf,

    When making calculations in ReportBuilder, you need to be sure you always
    use the OnCalc event of a TppVariable. Other events, such as the
    BeforeGenerate and BeforePrint have the possibility to fire multiple times
    per record and do not contain any logic to cache values as a user moves
    through a report. I would suggest placing TppVariables inside the
    GroupFooterBand and updating their values in the OnCalc events and see if
    that solves the problem.

    ----------------------------------------------------------------------
    TECH TIP: Performing Calculations
    ----------------------------------------------------------------------

    Calculations can be done either on the data access side
    or within ReportBuilder.

    When designing reports there are always decisions to be made as to how much
    processing to do on the data side versus the report side. Usually doing more
    on one side can greatly simplify the other. So it is often a personal choice
    based on the power and flexibility of the data and report tools being used.


    DataAccess
    ----------

    a. Use SQL - using SQL you can perform many common calculations:

    example: Select FirstName + ' ' + LastName As FullName,
    Quantity * Price AS Cost,


    b. Delphi TDataSets enable you to create a calculated TField object and use
    the DataSet.OnCalcFields event

    c. Perform any amount of data processing, summarizing, massaging etc. to
    build a result set (query or temp table) to feed to the report.


    ReportBuilder
    -------------

    Calculations in ReportBuilder are performed primarily using the TppVariable
    component.

    a. Set the Variable.DataType

    b. Code the calculations using the Variable.OnCalc event.

    c. Use the Timing dialog to control the timing of the OnCalc event. To
    access the Timing dialog, right click over the Variable component and select
    the Timing... option from the speed menu.

    d. Set the LookAhead property to True, when you need to display summary
    calculations in the title, header, group header, etc.

    e. To perform calculations based on the results of other calculations use
    the Calc Order dialog of the band. To access the Calc Order dialog, right
    click over the Band component and select the Calc Order... option from the
    speed menu.


    By using TppVariable components ReportBuilder will take care of caching
    intermediate results of accumlated calcs that cross pages.

    There are a number of calculation examples in the main demos.dpr project.

    ---

    Additional Notes:

    1. Do NOT use Band.BeforePrint or Band.AfterPrint. These events fire
    multiple times and therefore should not be used for calculations.

    2. Do NOT store results in variables that exist outside of the reports.
    For example - form level variables.


    --
    Regards,

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

    Best Regards,

    Nico Cizik
    Digital Metaphors
    http://www.digital-metaphors.com
  • edited April 2007
    Hi Ralf,

    Sorry, my previous post was a bit confusing. The problem does not relate to
    the actual components you are using to make the calculations but rather in
    the ReportBuilder events you are using to make them in. As you mentioned in
    your first post, during the first pass, everything is being caluculated
    correctly then during the second pass (if the entire report is not viewed
    page by page) errors can occur. Using the OnCalc event of a TppVariable
    (whether you actually use the TppVariable component or not) will ensure that
    this does not happen.

    Putting TppVariables aside, one thing to try would be to check which pass
    you are currently in before executing the code you have inside your
    DetailBand.BeforeGenerate event. If you only execute the calculation during
    the first pass, you may be able to avoid any problems.

    if Report.FirstPass then
    //execute BeforeGenerate code

    --
    Regards,

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

    Best Regards,

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

    I guess, I didn?t explain my problem good enough, but give me another try:

    First of all, I can?t calculate my summaries on the data layer (like you
    suggested via SQL) because at one hand I can?t manipulate the data
    request, I only get a DataTable from my other colleagues and that it. At
    the other hand it would not be possible to make my calculations via SQL
    because the calculated values are dimensioned values (I hope I translated
    that correct, but I?ll explain that later). Well, all I want to say here:
    I have to do my calc in the report directly.

    As I already told you (indirectly) I can not use Variable.DataType or
    DBCalc.Datatype controls to calculate my summaries because these values
    are dimensioned: The field I want to summarize is a string field and
    contains values like 'kg;-2;123' (== 1,23 Kilogram). Let me give you a
    concrete but simple example: Let assume there are three Datarows in the
    same group with the following values:

    'kg;-2;1'
    'g;-0;2000'
    'kg;-2;30'

    The correct summary that should be displayed would be '2,32 kg' or '2320 g'...

    I guess you understand now, why I don?t calculate my Groupsummaries via
    Variable.Datatype. Therefore I have a separate .dll that provides an
    object to calculate the correct values to my ReportDesigner.

    Calculating the summaries for my dimensioned fields with my dll works in
    five steps:

    1. CreateSumObject {No Problem => is done in GlobalOnCreate of the Report}

    2. InitGroup(GroupValues) {Initiaties the calculation with some neccesary
    group wide values; should be done in the group?s header}
    3. AddValue(SingleValue) {Adds the values of the Datarow; should be done
    in the Detailband or something like that}
    4. ReadSummaries {Read the actual summaries for the footer via properties
    from the SumObject and write them to the labels of the group?s footer}

    5. FreeSumObject {No Problem => is done in GlobalOnDestroy of the Report}

    Well, like I said in the previous post: The hole things works as long as
    preview on page after the other. If I jump to a specific page that has
    DataRows that are not displayed on this page, the calculation goes wrong,
    because the values of the previous page/s are not added to the group.

    I hope you have better insight into my problem now.

    Any suggestions? :-/

    Regards
    Ralf



    --- posted by geoForum on http://delphi.newswhat.com
  • edited April 2007
    Hi Nico!

    To the first part of your response: Using the OnCalc-Event of a TppVariable.
    I tried this idea already but recognized a strange behaviour again: I used
    three TppVariables in my report, one in the group header, one in the
    detail band and one in the group footer. The one in the header I set to
    CalcType Groupstart an the corresponing group, the one in the detail band
    I set to Traversal and the last one to Groupend.
    Then I observed the event firing and recognized that the TppVariable in
    the detail band was always fired before the one in the header. I tried out
    many settings and other arrangements (eg LookAhead or CalcOrder / all
    three TppVariables in the detail band), but it was always the same. Only
    the OnCalc in the Footer was fired correctly but at the beginning of a new
    group the OnCalc of the DetailBand was always fired one time before the
    OnCalc in the header, then the other details followed. I don??t know how to
    get the correct order for the TppVariables... Could you explain me how to
    set up the TppVariables, so I can use them for my problem (init,
    add...add, evaluate)?

    To the second suggestion of your response: Before I opened this thread I
    already played around with the Report.FirstPass and Report.SecondPass
    properties. I figured out that using a 'if not Report.SecondPass then' in
    the GroupFooterBeforeGenerate could prevent that the correct values were
    overwritten in the second pass. At the first sight this seemed to work,
    because in my test data I had only one group, but as I used more than one
    group in my data I recognized that after the report ended with the whole
    calculation ALL group summaries where reset to the values of the LAST
    group. This is a really strange behavior that I can??t comprehend.

    If you could explain at least one of these behaviours to me, then I could
    give the whole thing another try.

    I really hope you can help me solving this problem...

    Regards

    Ralf



    --- posted by geoForum on http://delphi.newswhat.com
  • edited April 2007
    Hi Ralf,

    If possible, please send a small example that demonstrates the behavior you
    describe below (or perhaps the original problem). I believe that if I can
    see what is happening first hand, I will have a better chance of
    understanding what you are trying to accomplish and provide you with a
    solution. Send the example to support@digital-metaphors.com in .zip format.

    --
    Regards,

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

    Best Regards,

    Nico Cizik
    Digital Metaphors
    http://www.digital-metaphors.com
  • edited April 2007
    Hi Nico!

    Thanks for your sample project and efforts. In fact your sample did not
    work properly on my environment at all and even your Report was not
    displayed correctly in my ReportDesigner, but at least I was able the
    check the structure of the report, your code and the idea behind it.
    Now everything works as expected.

    Big thanks to you and your team.

    Regards

    Ralf



    --- posted by geoForum on http://delphi.newswhat.com
This discussion has been closed.