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

One page multiple times

edited July 2006 in General
Hi,

I have a report that is one page long.
It summarizes statistics for an ID in a table.
I have a combobox for the user to select which ID to summarize. I've added a
total to the combobox but now I would also like to add 'All' which would
iterate through the box and print a page for each ID.
Of course I could do this through a loop of my previous code but then I
would end up with multiple preview windows or multiple PDF's. I would like
to be able to iterate through the IDs and add a page to my report ending up
with a multi-page document.

How would I go about doing this?

Thank you,
Valdimar Kristj?nsson
valdimar@stiki.is

Comments

  • edited July 2006
    Hi Valdimar,

    1. I would recommend creating a grouped report (with NewPage set to True)
    that is connected to a dataset that contains all the ID's. This report
    essentially displays all the ID's.

    2. Take a look a the AutoSearch demos located in the
    \RBuilder\Demos\AutoSearch\... directory. It is possible to create an
    autosearch criteria without showing our built-in dialog. Using this to
    filter the results to a single ID would be your best approach.

    --
    Regards,

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

    Best Regards,

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

    Thanks, but this would create a bigger problem for me.
    I don't actually have a master dataset with all the id's.
    I'm calculating a lot of statistics from many tables and putting these
    statistics into a matrix of my own.
    I then create each table I want to use (for each ID) at runtime and connect
    them to the datapipeline.
    What I would like to be able to do is print that to a report page (in
    memory) and then start adding more pages.
    In the end I would like to be able to print/save the multipage report.

    Something like this would be nice.
    Pseudo code:

    procedure PrintReport;
    var
    TempPage : TppPage;
    PageList : TList;
    begin
    for i := 0 to MyPageCount do
    begin
    TempPage := CreateReportPage;
    MyReport.Page.Add(TempPage)
    end;
    MyReport.Print;
    end;

    How would I return a TppPage component from a function like CreateReportPage
    above?

    Thank you,
    Valdimar

  • edited July 2006
    Hi Valdimar,

    Sorry for the delay.

    ReportBuilder is not designed to simply add pages as you describe below. I
    would recommend creating a simple main report with only a Detail Band, then
    for each new page you would like to add, place a Section style subreport
    inside the detail band (either at design or runtime) to add another page to
    the report. You could for instance design these pages before hand and save
    them as template files (.rtm), then load them once the new subreports have
    been created.

    Check out the Code Based thread in the Tech-Tips newsgroup for some good
    articles on how to create reports in code.

    --
    Regards,

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

    Best Regards,

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

    "ReportBuilder is not designed to simply add pages as you describe below."
    Of course it's not simple :)
    I would recommend making it simple.

    I'm not sure I understand you completely.
    I have a template file that has a headerband, detail band (with three sub
    reports) and a footer band.

    Should I then create a new template file with only a detail band? What is a
    Section style subreport?
    This is what I'm doing in rough terms:
    ___________________________________
    Open the main table.

    Create a matrix for holding all the statistics for the user selected ID.
    Create a temp table for the first subreport.
    Create a temp table for the second subreport.
    Create TeeChartSeries for the third subreport.

    Print a page
    _______________________________________

    Now everytime I print a page it renders it to the screen.
    I would like to print one page for each ID (preferably to PDF) but I would
    then need to create hundreds of temporary datasets in memory to be able to
    render all the pages at once.
    I would like to render one page at a time and then merge them into one PDF
    at the end. That way I only have 2 temporary tables in memory at any given
    time making rendering faster (less load on my computer).

    I've read all of the code based thread in the Tech-Tips newsgroup but my
    problem isn't creating the report in code since I already managed that.

    Thank you,
    Valdimar

  • edited July 2006
    Hi Valdimar,

    There are two main options when trying to combine multiple small reports
    into a single one. The first is to use Section subreports in a main report
    and to load each small report template into these subreports as I described
    in my previous posts. It seems this will not be the best option in your
    case.

    Second, it is possible to generate all your reports to Archive file (.raf)
    then use the Archive Merge Utility (available free from our website) to
    merge all the archive files into a single one for printing or viewing. The
    Archive Merge Utility can be downloaded from the following site...

    http://www.digital-metaphors.com/download/report_component_library.html

    Finally as an alternative, take a look at the following example of creating
    a PDF device descendent that overrides the startjob and endjob events to
    combine multiple reports into a single PDF. This does not give the option
    of previewing the reports, however it may be what you are looking for.

    http://www.digital-metaphors.com/tips/MultipleReportsAsOnePDF.zip

    --
    Regards,

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

    Best Regards,

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

    You are right, the first option doesn't really work well for my situation
    although I'm still unclear what Section subreports are. As you might have
    seen from another post of mine the Archive option is out of the question.
    The Archive components just crash Delphi for me.
    The last one is exactly what I'm looking for although the demo isn't very
    clear to me yet.

    The demo uses something called TppFileUtils which I can't find in the help
    file and I don't know in what unit it is so I can't add it to my uses list.

    It isn't alot of code so I'll paste it here:

    var
    lPDFDevice: TmyPDFDevice;
    begin
    lPDFDevice := TmyPDFDevice.Create(nil);

    // lPDFDevice.PDFSettings := ppReport1.PDFSettings; // optionally assign
    PDFSettings from report
    lPDFDevice.PDFSettings.OpenPDFFile := True;
    lPDFDevice.FileName := TppFileUtils.GetApplicationFilePath +
    'myReport.PDF';

    lPDFDevice.EndPrintJob := False;
    lPDFDevice.Publisher := ppReport1.Publisher;

    ppReport1.PrintToDevices;

    lPDFDevice.Reset;
    lPDFDevice.Publisher := ppReport1.Publisher;
    lPDFDevice.StartPrintJob := False;
    lPDFDevice.EndPrintJob := True;

    ppReport1.PrintToDevices;

    lPDFDevice.Free
    end;

    What I'm not clear on is where I would create each of my page. This code
    calls PrintToDevices twice so I'm not quite sure where to put my report
    creating loop. Could you show me in this code where I could put something
    like:

    for i := 0 to MyReportPageCount -1 do
    CreateReportPage(i);

    Thanks,
    Valdimar

  • edited July 2006
    The Archive merge utility is made with Delphi 5 in mind.
    I don't see how I can install it into Delphi 2005.

    Thanks,
    Valdimar

  • edited July 2006
    I've tried using this code and I think I'm getting it:

    procedure MultiPrint;
    var
    lPDFDevice: TmyPDFDevice;//I moved this to the public declarations of the
    form.
    i : integer;
    begin
    if assigned(lPDFDevice) then
    lPDFDevice.Free//Freeing this as it was before gave me an access
    violation as does this.

    lPDFDevice := TmyPDFDevice.Create(nil);

    lPDFDevice.PDFSettings.OpenPDFFile := True;
    lPDFDevice.FileName :=
    IncludeTrailingPathDelimiter(ExtractFilePath(application.ExeName))+'myReport.PDF';
    //TppFileUtils.GetApplicationFilePath + 'myReport.PDF';

    lPDFDevice.EndPrintJob := False;
    lPDFDevice.Publisher := ppReport1.Publisher;

    for i := 2 to 5 do//CmboBxInstitutions.Items.Count -1 do
    begin
    EmptyAnalysisMatrix;
    OpenTables(CmboBxInstitutions.Items[i]);
    PrintAPage; //PrintAPage includes a call to ppReport1.PrintToDevices
    end;

    lPDFDevice.Reset;
    lPDFDevice.Publisher := ppReport1.Publisher;
    lPDFDevice.StartPrintJob := False;
    lPDFDevice.EndPrintJob := True;

    //Here it opens the PDF document
    ppReport1.PrintToDevices;
    end;

    This seems to be working close to what I want but the results are far from
    pleasing.
    I still just get a single report in my PDF file but when I look at the
    thumbnails in the Acrobat viewer there is a second empty page and an error
    that the thumbnails can't be viewed.
    Freeing the lPDFDevice always seems to give me an error (see comments in
    code).

    Thanks,
    Valdimar


  • edited July 2006
    Hi Valdimar,

    1. Section subreports are intended to be used to display multiple reports
    as a single one. Unlike child and fixed subreports, they act as indipendent
    reports within the main report. See below.

    Copied from the RB help file...

    The value of the PrintBehavior property determines how a subreport prints
    within the master report. These are the possible values:

    pbFixed: A single page prints based on the dimensions and position of
    the subreport component.
    pbChild: The report prints to completion, using the subreport components
    width as the page width and stretching over
    pbSection: Several pages until printing is complete. The report prints as
    a separate section, starting a new page when it begins and finishing the
    last page when it ends. The PrinterSetup property is used to determine the
    page size and printer settings.

    2. Have you updated your version of ReportBuilder to 9.03? This is a free
    upgrade and is highly recommended before moving forward with your
    application. The Archive Merge utility is not something that is installed,
    it is a delphi component that can be used in your code to merge multiple
    archive files into one. If you take a look at the source you will see this
    can be done very easily. As far as I know, this component can be used with
    any version of Delphi.

    3. I believe you are making the PDF example more difficult than it needs to
    be. Basically the idea behind the example is that the custom PDF device
    allows you to control the StartJob and EndJob routines. Once the EndJob
    routine is called, the report will finish printing. You need to keep this
    value set to False until you are finished with your loop. The example
    manually combines only the two reports on the form. If you would like to
    use a loop you would probably need to do something like the following...

    Note that this is just psuedo code and has not been tested.

    var
    lPDFDevice: TmyPDFDevice;
    liIndex: Integer;
    begin

    lPDFDevice := TmyPDFDevice.Create(nil);

    // lPDFDevice.PDFSettings := ppReport1.PDFSettings; // optionally assign
    PDFSettings from report
    lPDFDevice.PDFSettings.OpenPDFFile := True;
    lPDFDevice.FileName := TppFileUtils.GetApplicationFilePath +
    'myReport.PDF';

    lPDFDevice.EndPrintJob := False;
    lPDFDevice.Publisher := ppReport1.Publisher;

    for liIndex := 0 to Count do
    begin
    {Update your data}

    ppReport1.PrintToDevices;

    lPDFDevice.Reset;
    //lPDFDevice.Publisher := ppReport1.Publisher; //Don't need this
    since you are using only one report object.
    lPDFDevice.StartPrintJob := False;

    {Check for last report}
    if liIndex = Count then
    lPDFDevice.EndPrintJob := True
    else
    lPDFDevice.EndPrintJob := False;
    end;

    lPDFDevice.Free

    end;

    --
    Regards,

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

    Best Regards,

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

    Now were getting somewhere :)
    The code you wrote worked like a charm. I just had to add
    ppReport1.PrintToDevices after the loop.

    begin
    lPDFDevice := TmyPDFDevice.Create(nil);

    lPDFDevice.PDFSettings.OpenPDFFile := True;
    lPDFDevice.FileName :=
    IncludeTrailingPathDelimiter(ExtractFilePath(application.ExeName))+'myReport.PDF';
    //TppFileUtils.GetApplicationFilePath + 'myReport.PDF';

    lPDFDevice.EndPrintJob := False;
    lPDFDevice.Publisher := ppReport1.Publisher;

    for i := 0 to CmboBxInstitutions.Items.Count -1 do
    begin
    EmptyAnalysis;
    CmboBxInstitutions.ItemIndex := i;
    OpenTables(CmboBxInstitutions.Text);
    ConnectTheTables;
    ppReport1.PrintToDevices;
    lPDFDevice.Reset;
    lPDFDevice.StartPrintJob := False;
    if i = CmboBxInstitutions.Items.Count -1 then
    lPDFDevice.EndPrintJob := True
    else
    lPDFDevice.EndPrintJob := False;
    end;
    ppReport1.PrintToDevices;
    lPDFDevice.Free;
    end;

    This is all working smoothly.

    Thanks alot for all your help.

    I went to your website but couldn't find an update to version 9.3. Could you
    post a link?

    Thanks again,
    ReportBuilder rules :)

    Valdimar

  • edited July 2006
    Contact info@digital-metaphors.com with your serial number and purchasing
    email for update instructions.

    --
    Regards,

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

    Best Regards,

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

    I guess I spoke to soon about everything working fine.

    This is what I'm doing (pseudo)

    for i := 0 to PageCount -1 do
    begin
    CreateTheTempTables;
    AssignTablesToDataPipelines;
    CreateChartsFromData;
    PrintToDevices;
    FreeAllTheTables;
    end;

    It seems that the charts are always the same.
    I'm pretty used to working with TeeChart so the problem is definately not
    there.
    I have 3 charts in a subreport: chart1,chart2 & chart3.
    On each round of the loop I create one pie for chart1 and another for
    chart2. Then I create 4 bars for chart3.
    These seem to be the same all through the report (all pages).

    I'm using Ser.ParentChart := ppTeeChart1.Chart; to assign the series to
    the charts and deleting them (freeing) every round.

    Thank you,
    Valdimar

    p.s.
    I contacted info@digital-metaphors.com and am waiting for their reply.

  • edited July 2006
    Hi Valdimar,

    Have you updated your version of ReportBuilder to 9.03 yet? I believe this
    was a problem that was fixed for later versions.

    --
    Regards,

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

    Best Regards,

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

    I've got the update and the charts are working.
    Thanks for all your help.

    I wish Borland could be so efficient in their support.

    Regards,
    Valdimar

    P.S.
    I'm continuing my PDF and Icelandic characters post

This discussion has been closed.