TFlexCelPdfExport and adding images...

Hello,

Exporting a grid to PDF. Working OK. I need to add some images to the end of the PDF file, have the images visible in the PDF file. TFlexCelPdfExport.AttachFile does not seem to accomplish the goal.

  procedure ExportToPdf;
  var
   xls:TXlsFile;
  begin
   xls:=nil;
   try
    xls:=TXlsFile.Create(1, true);
    if not Assigned(xls) then
     Exit;

    AdvGridExcelExport.Export(xls);
    xls.SetPrintMargins(TXlsMargins.Create(0, 0, 0, 0, 0, 0));
    aPdf.Workbook:=xls;
    aPdf.BeginExport(fs);
    aPdf.ExportAllVisibleSheets(false, '');

//  aPdf.AttachFile('C:\0001.jpg',TStandardMimeType.Jpeg,'',TPdfAttachmentKind.Supplement);

    aPdf.EndExport;
   finally
    FreeAndNil(xls);
   end;
  end;

Suggestions?

Thanks,

Mark

Hi,
The attach command is for attaching files inside the PDF. They can be any file, not just images, but they will show only in the attachments pane, not as a part of the document. You can find an example here: Exporting to PDF/A (Delphi) | FlexCel Studio for VCL and FireMonkey documentation

And to see the attached file, you need to open the "Attachment" pane in Acrobat:

If I understood correctly, what you want to do is just to add some images to the document? (not attach files, but just add images). If that is the case, then I see 3 possibilities:

  1. You can just add the images to the grid before exporting the grid.

  2. You can just add the image to xls object you are exporting. After the line:

AdvGridExcelExport.Export(xls);

You can use xls.AddImage to add the images. You can find an example here: Getting started (Delphi) | FlexCel Studio for VCL and FireMonkey documentation

  1. You can add it to the pdf document, using the AfterGeneratePage event. You can find an example here: Exporting Excel files to PDF (Delphi) | FlexCel Studio for VCL and FireMonkey documentation
    Specifically, in the part that prints "confidential" in every page (there is a checkbox at the bottom of the app that does this):
procedure TFExportPdf.PdfExport_AfterGeneratePage(const sender: TObject; const e: TPageEventArgs);
var
  ABrush: TUIBrush;
  AFont: TUIFont;
  x0: RealNumber;
  y0: RealNumber;
  sf: TUISize;
const
  s = 'Confidential';
begin
  if not cbConfidential.Checked then
    exit;

  ABrush := TUISolidBrush.CreateNew(TUIColor.FromArgb($1E, $19, $19, $19));  //Red=Green=Blue is a shade of gray. Alpha=30 means it is transparent (255 is pure opaque, 0 is pure transparent).
  try
    AFont := TUIFont.CreateNew('Arial', $48);
    try
      x0 := ((e.DataFile.PageSize.Width * 72) / 100) / 2;  //PageSize is in inches/100, our coordinate system is in Points, that is inches/72
      y0 := ((e.DataFile.PageSize.Height * 72) / 100) / 2;
      sf := e.DataFile.MeasureString(s, AFont);
      e.DataFile.Rotate(x0, y0, $2D);
      e.DataFile.DrawString(s, AFont, ABrush, x0 - (sf.Width / 2), y0 + (sf.Height / 2));  //the y coord means the bottom of the text, and as the y axis grows down, we have to add sf.height/2 instead of substracting it.
    finally
      FreeAndNil(AFont);
    end;
  finally
    FreeAndNil(ABrush);
  end;
end;

This code will print confidential in every page, you would need to check it is the last page too if you want only the image in one page. It also draws a semi-transparent text, (the TUIColor has an alpha component), and also draws a string (you would draw an image instead, using DrawImage instead of DrawString as in the example code). There is an example of using DrawImage to draw an image to a pdf here: Creating pdf files with the PDF API (Delphi) | FlexCel Studio for VCL and FireMonkey documentation

About what to use, it depends on what you prefer. Option 1 might be the simpler, but it means you need to remove the image after exporting the grid.
I think I would personally prefer option 2 for simple images, but you need to know the cells in the grid where you want to add them. Option 3 is normally better if you only care about adding the images to the pdf but not to the exported xlsx too, and it is better if you need more control, for example to add an image to every even page, not just at the end. Also it uses "pdf coordinates" which are just "points" (1/20 of an inch) and might be simpler to calculate than "excel coordinates" which you need for option 2 (you need to know the row and column where you are going to put the image). But it depends on your needs. Sometimes you do know the row and column, but not the position of the image in the page. For that cases, option 2 will be simpler.

Hello,

Thanks for the great reply.

The operator will be using a camera to take pictures during the production process. The "data" is in the grid and the pictures taken, of the process, are to be added to the PDF export of the process data. One picture per page after the report (gird) data is printed to its pages. Part of the PDF but, not the grid.

#3 seems the nearest to the goal. I need to generate new pages for the images. I might need to use TAdvPDFLib (I use it in another area of the program) to generate the PDF "image" and then find a method to merge image file(s) on the end of the grid export file. There seems to be a few options

Mark

Just a png or jpeg will work, no need to generate a specific pdf image. FlexCel comes with a different API to create pdfs, but it should be able to do most of what you can do with PDFLib. You need to access the e.DataFile property on the AfterGeneratePage event, and it comes with a "TCanvas-like" api that can draw in the pdf file you are creating. You can draw images, write text, lines, etc.

Hello,

That can work too. I am unsure what format will be used from the camera. But, that part did not give me pause.

I guess I am confused help says:

Fires after each new page is generated on the pdf, and after all content is written to the page. (The page is written) You can use this event to add some text or images on top of the page contents.

and it comes with a "TCanvas-like" api that can draw in the pdf file you are creating. You can draw images, write text, lines, etc.

OK, how do I add pages to put a single image on one page, repeat?

Thanks for you help.

Mark

Fires after each new page is generated on the pdf, and after all content is written to the page. (The page is written) You can use this event to add some text or images on top of the page contents .

Sorry, I am not sure I understood what the confusion is, if you let me know I can write it more clearly. The idea is that the event fires after every page is completed, so you can draw more stuff over what FlexCel draws itself.

You can add a new page with AddPage, draw the images, and then call AddPage again.

The only thing that would be wrong is if you use some "page n of m" header, since the PdfExporter wouldn't know about those additional pages that you will add at the end. So it will say, write "page 1 of 5", "page 2 of 5"... and after "page 5 of 5" you add 2 extra pages. If you need to use that, you can still do it, but you can't use "ExportAllVisibleSheets". You would need to use ExportSheet instead and tell FlexCel the total number of pages you want to export.

Hello,

Got it.

How do I determine the "AfterGeneratePage" is for the last page, after the grid is rendered to the PDF?

And will AfterGeneratePage be called when I add a new page in the callback?

Thanks,

Mark

How do I determine the "AfterGeneratePage" is for the last page, after the grid is rendered to the PDF?

To know if in the last page, you could use:
if (sender as TFlexCelPdfExport).TotalPagesInSheet = e.CurrentPageInSheet

And will AfterGeneratePage be called when I add a new page in the callback?

No, you are working at a lower level here. TFlexCelPdfExport is the one calling the callback, but the event is using TPdfWriter, which is a lower-level class that is used by TFlexCelPdfExport to actually draw the Excel file into the pdf. You are calling methods in the TPdfWriter object, TFlexCelPdfExport won't notice it.

Hello,

Thanks.

I just reloaded the page to add that I could answer the second question, no it does not.
Loading an image, jpg in this instance, adding a new page and using DrawImage of TPdfWriter worked great.

Thanks for your help.

Mark

This topic was automatically closed 24 hours after the last reply. New replies are no longer allowed.