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

Viewing & Printing an embedded PDF File

edited October 2014 in General
Hi,

I have a request from a client who would like to be able to print a
pre-compiled PDF file from within their application. (Not to save to a
PDF, but to bring up a report that shows the content of an existing
PDF), with the option to print.

They don't want to use external viewers such as Adobe reader - they want
this all done from within my application.

I was wondering if there is any way to achieve this with reportbuilder.
Is it possible to embed a PDF file within a report?

Thanks & Regards

Adam.

Comments

  • edited October 2014
    Hi Adam,

    From the description, I would try embedding a PDF viewer in your
    application. One option is to use ActiveX/COm interface to Adobe Acrobat.
    This is installed with Acrobat and you can easily import it into Delphi.
    Couple of links to examples..
    http://delphi.about.com/cs/howto/ht/htpdf.htm

    http://edn.embarcadero.com/article/22101


    Best regards,

    -
    Nard Moseley
    Digital Metaphors
    www.digital-metaphors.com

    Best regards,

    Nard Moseley
    Digital Metaphors
    www.digital-metaphors.com
  • edited October 2014
    Adam H. wrote:


    I've been working with WPCubed's WPViewPDF lib:
    http://www.wpcubed.com/pdf/products/pdfviewer/

    I've managed to incoporate loading and printing of PDF files as a
    sub-report.

    When a PDF document is required, it is loaded into WPViewPDF object.
    The subreport has a single ppGraphic (full page size) with a
    jitPipeline feeding it, and the pipeline recordCount is set to the PDF
    pagecount.

    As each page/"record" of the subreport is printed, that corresponding
    PDF page is converted to an EMF file (as memory stream) and and is
    loaded into ppGraphic.

    The way I'm doing it, the 'preview' is of medium quality, but the print
    is very good quality. I haven't had time to investigate how to improve
    the preview quality (note that WPViewPDF does very nice rendering
    normally - my problem is that the way I'm loading/displaying, the
    rendering is done as though the document has screen resolution - not
    original document resolution).

    I've promised Nico a sample program - I got a bit busy, but will try
    and send it to him this weekend.

    Cheers,
    EdB
  • edited October 2014
    Hi Nard,

    Thanks for your reply. Unfortunately I was hoping to embed the PDF file
    into a report for viewing with Reportbuilder as there are other pages
    that reportbuilder will also print to view this.

    Ed has an idea on how to do this so I'll check out his approach.

    Thanks & Regards

    Adam.
  • edited October 2014
    Hi Ed,


    Thanks very much for that - exactly what I'm trying to achieve.

    So basically we need to utilise graphics in this instance. Good idea
    with EMF - I was thinking something similar but using a different
    format. EMF makes much more sense when it comes to quality.

    Thanks again for your help.

    Best Regards

    Adam.
  • edited October 2014
    Adam H. wrote:


    If you're going to work with WPCubed's stuff, this should save you some
    time...

    This is part of my demo (set up to test for a particular project). t's
    basically a manufacturing work order, with a lot of operations - the
    PDFs are sign-off sheets or assembly instructions - and need to be
    printed *after* the main work order. There could be 0-n PDF docs, and
    each PDF can have 1-n pages.

    In the test project, I read a number of detail records and build a list
    of PDFs that need to be printed AFTER the main report. "Build a list"
    means populate a local ClientDataSet with a string field called PDFName.

    A ppDBPipeline is configured with a single field, cleverly called
    "jppFldName",

    The subreport lives in the group footer band, is assigned to the
    ppDBPipeLine, and has a single, page-wide and page-high ppDBGraphic
    with DataField = jppFldName,



    In Form Create:
    DocList := TStringList.Create;
    FPicture := TPicture.Create;
    FCurDocName :='';

    // get PDF viewer ready for use in conversion
    FWPViewPDF := TWPViewPDF.Create(Self);
    FWPViewPDF.Name := 'WPViewPDF1';
    FWPViewPDF.Parent := Self;
    FWPViewPDF.Visible := False;
    FWPViewPDF.ViewControls := [];
    FWPViewPDF.ViewOptions := [];
    FWPViewPDF.SecurityOptions := [wpDisableSave, wpDisableCopy,
    wpDisableForms, wpDisableEdit, wpDisablePDFSecurityOverride];
    FWPViewPDF.AllowMovePages := False;


    FWPViewPDF.ViewerStart('', your_lic_name, your_lic_key,
    your_lic_code);
    FWPViewPDF.Command(140{COMPDF_NoViewer}, 1);
    FWPViewPDF.Command(132{COMPDF_DisableAntiAlias}, 0);

    // testing for view quality
    FWPViewPDF.Command(141, 1); // use gdi
    FWPViewPDF.Command(145, 0); // use gdi


    In GroupHeaderBand BeforePrint:
    // < process detail records for current work order and >
    // < build list of PDF files to print (the "docList") >
    // < set GroupFooterBand visibility >


    // if this is first page of this group break
    if (ppReport1.Groups[0].FirstPageNo = ppReport1.AbsolutePageNo) then

    begin
    wono:=ppDBPipeline1['work_order_no'];
    DocList.Clear;
    cds2.SetRange([wono],[wono]);
    cds2.First;
    while not cds2.Eof do begin
    DocList.Add(cds2CalcWOBDwgFn.AsString);
    cds2.Next;
    end;
    cds2.CancelRange;
    end;

    ppGroupFooterBand1.Visible := (docList.Count>0);



    In GroupFooter BeforePrint:
    // DocList holds a list of PDF filenames

    if DocList.Count>0 then begin
    FCurDocName:= DocList[0];

    // delete the first (current) doc
    FDocList.Delete(0);

    FWPViewPDF.LoadFromFile(FCurDocName);

    ppJITPipeline1.RecordCount:= FWPViewPDF.PageCount;procedure


    procedure TForm1.ppGroupFooterBand1AfterPrint(Sender: TObject);
    begin
    FWPViewPDF.Clear;
    end;



    procedure TForm1.ppDBImage1GetPicture(Sender: TObject; aPicture:
    TPicture);
    var
    lPicture: TPicture;
    begin

    // call DataPipeline.GetFieldAsPicture method
    lPicture := ppJITPipeline1.GetFieldAsPicture('jppFldFName');

    if lPicture <> nil then
    aPicture.Assign(lPicture)
    else
    aPicture.Graphic:=nil;

    end;


    function TForm1.ppJITPipeline1GetFieldAsPicture( aFieldName: String):
    TPicture;
    var
    fName: string;
    pgNo: Integer;
    mf : TMetafile;
    begin

    // note that because the WPViewPDF object loads the PDF file in the
    // GroupFooter, we ignore aFieldName - and just use the RecordIndex
    // to get the approproiate page

    result:=nil;
    pgNo := ppJITPipeline1.RecordIndex;
    mf:=FWPViewPDF.GetMetafilePrn(pgNo);
    FPicture.Metafile.Assign(mf);
    Result := FPicture;
    mf.Free;
    end;


    NOTE: the way I've defined this, if a user is looking at a rendered pdf
    page and sends to printer, they will get a blank page (because the
    FViewPDF has been cleared by this time). I did it this way to avoid
    loading the entire PDF for every page (load it ONCE in footer before
    print).

    Hope this helps - have fun!


    Cheers,
    EdB
  • edited October 2014
    Thanks Ed! Appreciate the example.

    You've been very helpful.

    Cheers

    Adam.
This discussion has been closed.