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

Perplexing issues using SubReports to generate a single PDF file.

edited November 2003 in Subreports
Hi,

I'm using D6 with update 2, Report Builder v6.03 and TExtraDevices.

I added code to print multiple reports to a single PDF using subreports. I
used the example from the TExtraDevices faq. It compiles and works as normal
until I print my reports to a single PDF. Then odd things begin to happen.

After printing to PDF, viewing the reports (with a TppViewer) the reports
don't generate properly as they did before printing to PDF. Some reports are
blank and others that were two pages now generates data only on the first
page. The second page generates but the data is missing. These all worked
great before printing. That's not all when I try to quit the application it
refused to close. I have to Program Reset Ctrl-F2 to get out. This is very
unusual. Then I get an error message. I use Eurekalog with my app and it
generates detailed log info about the error. It is as follows;

Exception...
Date : 11/18/2003 21:41:09
Address: 0042025E
Module : VIPWin1.exe
Type : EAccessViolation
Message: Access violation at address 0042025E in module 'VIPWin1.exe'.
Read of address 4070C008

----------------------------------------------------------------------------
--
|Address |Module |Unit |Class
|Procedure/Method|Line|
----------------------------------------------------------------------------
--
|00544525|VIPWin1.exe|ppClass.pas |TppCustomReport |RemoveBand
|5124|
|00544514|VIPWin1.exe|ppClass.pas |TppCustomReport |RemoveBand
|5123|
|00515D6A|VIPWin1.exe|ppBands.pas |TppBasicBand |Destroy |840
|
|004B002F|VIPWin1.exe|Controls.pas|TControl |Destroy
|3158|
|00475206|VIPWin1.exe|Graphics.pas|TBrush |Destroy
|1811|
|004AFF94|VIPWin1.exe|Controls.pas|TControl |Destroy
|3143|
|004B3621|VIPWin1.exe|Controls.pas|TWinControl |Destroy
|5345|
|004B3568|VIPWin1.exe|Controls.pas|TWinControl |Destroy
|5324|
|0049A068|VIPWin1.exe|Forms.pas |TScrollingWinControl|Destroy
|2024|
|0049A040|VIPWin1.exe|Forms.pas |TScrollingWinControl|Destroy
|2021|
|0049AD43|VIPWin1.exe|Forms.pas |TCustomForm |Destroy
|2585|
|00498F6F|VIPWin1.exe|Forms.pas | |DoneApplication
|1325|
|00409ED1|VIPWin1.exe|SysUtils.pas| |DoExitProc
|3248|
----------------------------------------------------------------------------
--

This doesn't seem to make sense because the master report and subreport
objects that were created were released at the end of the print process.

E.G.

//cleanup
for i := 0 to SubList.Count - 1 do
begin
TppSubReport(SubList[i]).SetReportProperty(nil);
TppSubReport(SubList[i]).Free;
end;
FreeAndNil(SubList);
FreeAndNil(MasterRpt);

If I comment out this section then the app will close correctly but the
reports still don't generate correctly as they did before master/subreports.

I'm perplexed... I have tried everything that I can think of.

Anyone have any ideas or suggestions?

Below is a snip of the code that I'm using.

Thanks in advance...

type
PRptList = ^RList;
RList = record
Rpt: TppReport;
TestId: Integer;
end;


procedure PrintBtnClick(Sender: TObject);
var
ReportNamePrefix, ReportName, DeviceType: String;
RptList: TList;
RptRecord: PRptList;
begin
try
if (PrinterNameCmb.Items[PrinterNameCmb.ItemIndex] = 'Single PDF') then
RptList := TList.Create;

DeviceType := 'Printer';

if (RptList <> nil) then
begin
ReportName := 'Multiple_Report_Single_PDF';

New(RptRecord);
RptRecord^.Rpt := R100;
RptRecord^.TestId := 0;
RptList.Add(RptRecord);

New(RptRecord);
RptRecord^.Rpt := R101;
RptRecord^.TestId := 2;
RptList.Add(RptRecord);

New(RptRecord);
RptRecord^.Rpt := R102;
RptRecord^.TestId := 4;
RptList.Add(RptRecord);

New(RptRecord);
RptRecord^.Rpt := R103;
RptRecord^.TestId := 3;
RptList.Add(RptRecord);

New(RptRecord);
RptRecord^.Rpt := R104;
RptRecord^.TestId := 1;
RptList.Add(RptRecord);

SendPrintJob(ReportName, DeviceType, RptList);
end
finally
//cleanup
if (RptList <> nil) then
begin
for i := 0 to (RptList.Count - 1) do
begin
RptRecord := RptList.Items[i];
Dispose(RptRecord);
end;
FreeAndNil(RptList);
end;
end;
end;


procedure SendPrintJob(DocName, TheDeviceType: String; RptList: TList);
var
DeviceDialog: TSaveDialog;
SubList: TList;
MasterRpt: TppReport;
SubRpt: TppSubReport;
RptName: String;
RptRecord: PRptList;
FDoPrintDevice: Boolean;
begin
//set the documentname for print manager in case user wants to cancel they
will need a recognizable name
//TheDeviceType = 'Printer' for Print to Priner or multiple report to
Single PDF file
//TheDeviceType = 'PDFFile' for printing single report to PDF file
if (TheDeviceType = 'Printer') then
begin
if (PrinterNameCmb.Items[PrinterNameCmb.ItemIndex] = 'Single PDF')
then
begin
//Show save dialog
DeviceDialog := TSaveDialog.Create(Self);

DeviceDialog.FileName := DocName + '.pdf';
DeviceDialog.DefaultExt := 'pdf';
DeviceDialog.Filter := 'PDF files (*.pdf)|*.pdf';
if (DeviceDialog.Execute) then
begin
FDoPrintDevice := True;
end;

if (FDoPrintDevice) then
begin
//create subreport list and master rpt. Add all reports in the
RPTList as sub reports to the master report
SubList := TList.Create;
MasterRpt := TppReport.Create(Self);
MasterRpt.CreateDefaultBands;
MasterRpt.RemoveBand(MasterRpt.HeaderBand);
MasterRpt.RemoveBand(MasterRpt.FooterBand);
for i := 0 to RptList.Count - 1 do
begin
SubRpt := TppSubReport.Create(Self);
SubRpt.Band := MasterRpt.DetailBand;

RptRecord := RptList[i];
SubRpt.SetReportProperty(TppReport(RptRecord.Rpt));
SubRpt.PrintBehavior := pbSection;
SubRpt.Report.PassSetting := psTwoPass;
SubRpt.ResetPageNo := False;

//use the tag to hold the studyidtestid this will be use
in each report OnBeforePrint event
SubRpt.Tag := StrToInt(IntToStr(active_study_value) +
IntToStr(RptRecord.TestId));

SubRpt.OnPrint := TppReport(RptRecord.Rpt).BeforePrint;
SubList.Add(SubRpt);
end;
MasterRpt.TextFileName := DeviceDialog.FileName;
MasterRpt.AllowPrintToFile := True;
MasterRpt.ShowPrintDialog := False;
MasterRpt.DeviceType := 'PDFFile';

//setup printer orientation
if (PortraitRB.Checked) then
MasterRpt.PrinterSetup.Orientation := poPortrait
else
MasterRpt.PrinterSetup.Orientation := poLandscape;

//setup printer paper size
case PaperSizeCmb.ItemIndex of
0: MasterRpt.PrinterSetup.PaperName := 'Letter';
1: MasterRpt.PrinterSetup.PaperName := 'Legal';
end;

//call to DoReport routine
DoReport(0,0,MasterRpt);

//cleanup
for i := 0 to SubList.Count - 1 do
begin
TppSubReport(SubList[i]).SetReportProperty(nil);
TppSubReport(SubList[i]).Free;
end;
FreeAndNil(SubList);
FreeAndNil(MasterRpt);
FDoPrintDevice := False;

end;
//cleanup
FreeAndNil(DeviceDialog);
end
else
begin
//this other stuff doesn't matter for example
end;
end;
end;

procedure DoReport(MasterRpt: TppReport);
begin
if (MasterRpt <> nil) then
begin
MasterRpt.Print;
end
else
begin
//this other stuff doesn't matter for example
end;
end;

--
John Frick
Computer & Database Programming Services
Voice: 503-251-0452 ext 9
Fax: 503-343-5154
Email: cdps@gorge.net

Comments

  • edited November 2003

    1. Try a simple test in which you do not create the report dynamically.

    2. In the code to create the report do not call Report.RemoveBand. Instead
    free the band or set the Band.Report property to nil. (RemoveBand is used
    internally). This code may be causing a problem.

    example:

    myReport.CreateDefaultBands;
    myReport.HeaderBand.Free;
    myReport.FooterBand.Free;

    or

    {alternative to the above CreateDefaultBands}
    lDetailBand := TppDetailBand.Create(Self);
    lDetailBand.Report := myReport;
    lDetailBand.Height := 2;

    3. When you free the report, the report will free the bands and objects
    within the report, including the subreports.

    myReport.Free;




    --
    Nard Moseley
    Digital Metaphors
    http://www.digital-metaphors.com

    Best regards,

    Nard Moseley
    Digital Metaphors
    www.digital-metaphors.com
  • edited November 2003
    Hi Nard,

    Your solution did fix the removeband issue however it didn't resolve the
    report pages issue.

    Maybe we should forward this the RemoveBand solution to Jim Waler so that he
    can update his TExtraDevices faq example.

    Anyhow,

    After printing to a single PDF using subreports, my reports still don't
    generate properly. I have a report that had two pages before printing to PDF
    and afterwards it only generates the first page.

    The data on the first page matches but the second page doesn't generate at
    all. The AbsolutePageCount= 2 before printing and afterwards (subsequent
    generation) AbsolutePageCount=1.

    The data pipeline is still the same and the underlying data hasn't changed.

    Even more strange is if I print the report again (PDF or Paper), both pages
    get generated. It's only in the viewer that the second page is missing. I
    have tried Reset and ResetDevices hoping that it would fix the problem but
    it still persists.

    Any ideas?

    Thanks...

    My reports are setup PassSetting = psTwoPass and CachePages = False

  • edited November 2003

    If you want the reports to print with PassSetting of psTwoPass and
    CachePages False, you need to configure the main report to have these
    settings. The main report controls how all of the subreports are generated -
    it is not possible to mix and match.

    As a test try commenting out all event-handler code associated with the
    report. Make sure that you do not have any code the manipulates the datasets
    while the reports are generating.




    --
    Nard Moseley
    Digital Metaphors
    http://www.digital-metaphors.com

    Best regards,

    Nard Moseley
    Digital Metaphors
    www.digital-metaphors.com
  • edited November 2003
    Hi Nard,

    I don't think that I was very clear.

    Here's what I know for sure.

    I have static reports. A summary report that grows depending on the amount
    of data, the rest of my reports never exceed a single page.

    Theses reports are viewed using TppViewer and generated with command
    .PrintToDevices.

    Before printing to a single PDF (master with sub-reports) everything works
    just as it always has for the last 3 years.

    When I want to print these reports into a single PDF file, I dynamically
    create a new report and add all the reports as sub-reports.

    I used the TExtraDevices faq for a code example of how to do this. My code
    is almost line for line with the example. You can view the code I am using.
    It is in the first post.

    The command MainRpt.Print is used to generate a single PDF of all the
    reports as requested.

    The objects that were created during the process are then released
    (object.free) as per the TExtraDevices faq.

    Any subsequent requests to view the reports via the viewer I.E. calls to
    .PrintToDevices causes very odd things to happen like,

    The static summary report that prior to printing PDF had an
    AbsolutePageCount = 2 now has an AbsolutePageCount = 1 and only one page if
    viewable in the viewer.

    Sometimes the page is completely blank. Sometimes it contains the correct
    data that should be on the first page, but no second page is generated and
    the AbsolutePageCount is still 1.

    At this point if I send the reports to the printer they all print fine and
    if I print the reports to a single PDF again they print fine. So subsequent
    calls to the code used to generate a single PDF work just fine. These calls
    all use the Print command and not PrintToDevices.

    Sometimes when switching reports in the viewer (I.E. my code uses page
    up/page dn keypress events to call PrintToDevice for the appropriate report)
    some of the report pages will come up blank and when that occurs then I
    cannot exit the application by any means except ctrl-f2.

    I have tried .Reset and .ResetDevices but neither
    had any effect.

    The only difference is the MasterRpt and SubReport code and the odd effects
    that occur on subsequent call to PrintToDevices

    Now any Ideas?

    Thanks...

  • edited November 2003

    Try downloading a trial version of RB 7.03 for D6 and performing the same
    test. There was a patch to RB 7.02 that fixes a case in which stand alone
    reports are used as reference style subreports.

    Backup your existing installation and your existing reports prior to
    installing RB 7.03.


    --
    Nard Moseley
    Digital Metaphors
    http://www.digital-metaphors.com

    Best regards,

    Nard Moseley
    Digital Metaphors
    www.digital-metaphors.com
This discussion has been closed.