One page multiple times
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
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
This discussion has been closed.
Comments
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
Nico Cizik
Digital Metaphors
http://www.digital-metaphors.com
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
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
Nico Cizik
Digital Metaphors
http://www.digital-metaphors.com
"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
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
Nico Cizik
Digital Metaphors
http://www.digital-metaphors.com
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
I don't see how I can install it into Delphi 2005.
Thanks,
Valdimar
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
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
Nico Cizik
Digital Metaphors
http://www.digital-metaphors.com
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
email for update instructions.
--
Regards,
Nico Cizik
Digital Metaphors
http://www.digital-metaphors.com
Nico Cizik
Digital Metaphors
http://www.digital-metaphors.com
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.
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
Nico Cizik
Digital Metaphors
http://www.digital-metaphors.com
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