Home Subreports

Adding Pages to subreports in code

edited August 2014 in Subreports

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

Comments

  • edited August 2014
    Hi Ed,

    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.

    Best Regards,

    Nico Cizik
    Digital Metaphors
    http://www.digital-metaphors.com
  • edited August 2014
    Nico Cizik (Digital Metaphors) wrote:


    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
  • edited August 2014
    Ed Blanchard wrote:



    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







  • edited August 2014
    Hi Ed,

    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.


    Best Regards,

    Nico Cizik
    Digital Metaphors
    http://www.digital-metaphors.com
  • edited August 2014
    Nico Cizik (Digital Metaphors) wrote:


    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
  • edited August 2014
    Hi Ed,

    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.

    Best Regards,

    Nico Cizik
    Digital Metaphors
    http://www.digital-metaphors.com
  • edited August 2014
    Nico Cizik (Digital Metaphors) wrote:


    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
  • edited September 2014
    Hi Ed,

    Yes, we would definitely like to take a look at an example of this if
    you have one available. Thanks!

    Best Regards,

    Nico Cizik
    Digital Metaphors
    http://www.digital-metaphors.com
  • edited September 2014
    Nico Cizik (Digital Metaphors) wrote:


    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
  • edited September 2014
    Hi Ed,

    1. Either way will work.

    2. Not a problem. We will take a look at it and evaluate what needs to
    be done.

    Best Regards,

    Nico Cizik
    Digital Metaphors
    http://www.digital-metaphors.com
This discussion has been closed.