Adding Pages to subreports in code
I have a situation where I need to be able to add pages to subreports
at runtime.
That is, I'm loading a PDF file page-by-page, converting to emf, and
loading the emf to a full-page ppImage.
Because the PDF may have 1-?? pages, I need to be able to add a page on
the fly.
I guess the alternative would be to do something like:
1) have a "subreport" cds with fields:
filename- the PDF filename
pgNo - counter for page0-n in filename
2) In main ppReport, OnGroupHeader1BeforePrint
- get PDF file name from current record
- clear cds
- get pagecount from actual pdf file
- for pNo=0 to pagecount
insert rec in CDS ( filename, pNo)
(that is, create a record for each page in the PDF, so I can use the
pNo to load and render the appropriate page).
3) use the cds for the subreport, break on pNo
4) in subreport before print,
- load the pdf,
- render the appropriate pdf pageno to emf
- copy the emf to ppImage1
Hmm, if the subreport is in a GroupFooter, probably better to load PDF
once in GroupFooterBeforePRint then release in AfterPrint.
Anyway... Is there a simpler solution?
Thanks!
Cheers,
EdB
This discussion has been closed.
Comments
There are likely numerous ways of doing this however I would recommend
feeding the subreport the metafiles via JITPipeline as the easiest method.
I would start by converting all PDF pages to EMF first, then using a
JITPipeline connected to your subreport, load each EMF into a DBImage
using the OnGetFieldAsPicture event.
Nico Cizik
Digital Metaphors
http://www.digital-metaphors.com
Hmm, sounds slick - thanks!
I'm concerned about memory allocation - the print run might require 50+
pages to be printed, which would call on 50+ pdfs.
Also, this is the program I fiddle with duplex settings between pages...
I'll let you know how it goes!
Thanks again.
EdB
I have a test project where I tried a variation of your suggestion.
It's working, but I have two problems
1) printing "current page" from print preview.
When a PDF page is displayed in print preview, actually performing a
"print current page" spits out a blank sheet.
I load the PDF in the GroupHeaderBeforePrint (so I only have to go to
file server once to pick up file).
The subreport is in the group footer.
This means when the 'current page' is sent to printer device,
GroupHeaderBeforePrint isn't called, and thus there isn't actually a
file loaded in the WPCubed ViewPDF object to render to printer canvas.
I'm trying to avoid loading the file in the footer (to avoid going to
file server multiple times). Any suggestions?
2) I'm having difficulty getting the subreport to start on an odd page.
There are actually two supreports, each in a separate group. It gets
complicated to describe, but here goes:
I'm printing work orders and operations, each of which can have 0-n
materials, and each material might have a pdf assigned (with 1-n pages).
e.g.:
WONO, OpNo, MATL, pdfName, cadFname
1000, 10, abc, null, null
1000, 20, null, null, cad1.dwg
1000, 30, def, def.pdf, null
1000, 40, ghi, null, null
1000, 50, jkl, jkl.pdf, null
Report Groups:
0, Break on [wono] - NewPage+StartOnOdd+ResetPageNum
(footer holds section subreport for CAD drawing 0 or 1 pages)
1, break on [wono] - NewPage
(footer contains section Subreport for PDFs 0-n pages)
2. break on [OpNo] - HDR shows operation details
My detail band shows material information, and the detail band is
hidden if there are no materials for any given operation (eg op 20
above).
The CAD stuff is pretty straightforward -
GroupFooter[0].visible:=
(the cad file can print on the "back" of a single page work order, so
I don't care if it prints on Odd or Even page, as long as it starts on
new page.
The PDF stuff loads the PDF once, sets the JIT pipeline record count to
PDF page count, and grabs pdfPage[pipeline.recordIndex] as required.
It isn't clear to me how best to force this PDF subreport to start each
document on an odd page.
Cheers,
EdB
1. I'm a bit unclear about how you are loading the EMF images. At the
bottom you mention that you are using a JITPipeline, but you also
mention that you are "loading the PDF in the GroupHeaderBeforePrint" If
you are properly using a JITPipeline, there should be no need to load
the image inside the GroupHeaderBeforePrint event. The report will
automatically pull the proper image as the pipeline traverses.
Steps:
1. Place a JITPipeline on the form. Double click it and add a new image
field (dtGraphic).
2. Connect the JITPipeline to your subreport.
3. Place a DBImage inside your subreport (properly sized) and set it's
datafield to the image field you created for the JITPipeline.
4. Implement the JITPipeline.OnGetFieldAsPicture and set the result
equal to the image you would like to display for that record number.
Once this is working, you are running withing the design of
ReportBuilder and all other features such as "Print Current Page" should
function as well.
2. You might try using a TppPageBreak component and toggling its
visibility based on which page you are on. For instance, if the end of
a group is on an even page, set its Visible to True.
Nico Cizik
Digital Metaphors
http://www.digital-metaphors.com
Hi Nico,
I'ts not a single image - it's a PDF file that I'm carving into
multiple EMF files in memory at runtime.
For any given work order, I'm effectively preparing a list of pdf file
names (each of which which might be multipage) in the
GroupHeaderBeforePrint.
In the GroupFooterBandBeforePrint, I load one PDF file from the list
(ViewPDF.LoadFromFile) , and set the JITPipeLine recordCount to the PDF
pagecount (then delete that filename from the list).
The JITPipeLine has a single string field: fName.
The subreport has a DBImage, with fieldname set to fName.
The DBImage GetPicture method has :
lPicture := ppJITPipeline1.GetFieldAsPicture('fName');
if lPicture <> nil then
aPicture.Assign(lPicture)
else
aPicture.Graphic:=nil;
The JITPipeline1 GetFieldAsPicture method has:
pgNo := ppJITPipeline1.RecordIndex;
mf:=FWPViewPDF.GetMetafilePrn(pgNo);
FPicture.Metafile.Assign(mf);
Result := FPicture;
mf.Free;
The GroupFooterAfterPrint clears the ViewPDF object.
This works great, and only hits the file server to load the PDF once.
When I do a "Print Current" - the ViewPDF object has been cleared, so
there's nothing to render to printer canvas.
It looks to me that any other way of setting this up is going to have
to load the PDF file from disk for every page (then "print" the
appropriate page based on recordindex) instead of loading it once and
generating the EMFs "per page" as required.
---------------
Note: I solved the 'start on odd page' issue - in a "boneheaded
3:00am-let's-try-this-move" I'd been trying to set a group within the
subreport, instead of on the main report
---------------
Thanks!
EdB
Thanks for the further explanation and I now understand how you are
currently creating the report, however as you mentioned, using this
method does not allow the GroupHeaderBeforePrint event to fire when
printing a single page. ReportBuilder simply was not designed to load
report content from this event.
Unfortunately if you would like to support printing single pages, you
will either need to load the images elsewhere or use a different event.
Nico Cizik
Digital Metaphors
http://www.digital-metaphors.com
As I suspected...
Well, the customer says they would "never print a single page like
that" (HA! Prove it to me and I still won't believe it!) so it isn't a
problem.
I'd rather minimize the hit on the (getting creaky) file server than
worry about confusing an end user when a page comes out blank.
Thanks again!
Last question:
Even though I'm doing this in the "wrong" event, it *does* show how to
use WPCubed's WPViewPDF library to load a PDF file and insert into an
RB printing job.
Do you want my demo program?
(I'm currently adding the CADSoftTools library to it as well).
Cheers,
EdB
Yes, we would definitely like to take a look at an example of this if
you have one available. Thanks!
Nico Cizik
Digital Metaphors
http://www.digital-metaphors.com
Ok, it might take a couple of days...
Two things:
1) My current test project uses ClientDataSet and ppDBPipeline for the
source of data - would you prefer I remove CDS and use JITPipeline in
the demo?
2) currently the display in "print preview" is lower-quality than I'd
like - it renders to printer quite nicely though.
I haven't had time to figure out why the print preview quality is low
(although I suspect it has to do with the metafile creation being
forced to screen WxH resolution - I haven't found a way to force the
metafile to be "bigger" than destination canvas).
Shall I send it before I resolve this?
Cheers,
EdB
1. Either way will work.
2. Not a problem. We will take a look at it and evaluate what needs to
be done.
Nico Cizik
Digital Metaphors
http://www.digital-metaphors.com