Table of Contents

Images (Delphi)

Note

This demo is available in your FlexCel installation at <FlexCel Install Folder>\Demo\Delphi\Modules\20.Reports\65.Images and also at https:​//​github.​com/​tmssoftware/​TMS-​FlexCel.​VCL-​demos/​tree/​master/​Delphi/​Modules/​20.​Reports/​65.​Images

Overview

Inserting images from a database on a FlexCel report is simple, just insert a blank image and name it as <#table.field>. All the complexity is handled by FlexCel. But when you need more options, there are always things you can do.

Concepts

  • Using the Image Size (<#IMGSIZE(Zoom, AspectRatio)>) tag. This tag only works when written on an image name, and allows you to define which size the inserted image will have. Use this tag only if the image dimension changes on the database. If all images are the same size (most common scenario) just set the size of the image at design time, as it is faster.

  • Using an Alias on the config sheet. As the image name has a small length, we defined the report variables <#Photo>, <Photo100>, etc. on the config sheet.

  • Using the ImgPos, ImgFit and ImgDelete tags. On the second sheet of this report you can see those tags in action.

  • Using the TFlexCelReport.GetImageData event. This is a last resort option. If you need to do some further processing on the image, you can do it on this event. The preferred order of option then is:

    1. If all images are the same size and on a standard format, just name the image as <#table.field> and do nothing more.

    2. If you need to adjust dynamically the image dimensions, use Image Size tag. It can be a little slower than 1, as the image has to be processed to calculate its dimensions.

    3. If you need to define a custom image size, or the image is on a proprietary format you need to convert, use TFlexCelReport.GetImageData event.

Files

UMainForm.pas

unit UMainForm;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics,
  FlexCel.VCLSupport, FlexCel.Core, FlexCel.XlsAdapter, FlexCel.Report, FlexCel.Render,
  {$if CompilerVersion >= 23.0} System.UITypes, {$IFEND}
  ShellApi,
  Controls, Forms, Dialogs, StdCtrls, ExtCtrls;

type
  TMainForm = class(TForm)
    btnCancel: TButton;
    btnGo: TButton;
    SaveDialog: TSaveDialog;
    Label1: TLabel;
    procedure btnCancelClick(Sender: TObject);
    procedure btnGoClick(Sender: TObject);
  private
    procedure RunReport;
    function GetDataPath: string;
    procedure GetImageData(const sender: TObject;
      const e: TGetImageDataEventArgs);
    { Private declarations }
  public
    { Public declarations }
  end;

var
  MainForm: TMainForm;

implementation
uses IOUtils, DemoData;

{$R *.dfm}

procedure TMainForm.btnCancelClick(Sender: TObject);
begin
  Close;
end;

procedure TMainForm.btnGoClick(Sender: TObject);
begin
  RunReport;

end;

function TMainForm.GetDataPath: string;
begin
  Result := TPath.Combine(TPath.GetDirectoryName(ParamStr(0)), '..\..');
end;

procedure TMainForm.GetImageData(const sender: TObject; const e: TGetImageDataEventArgs);
var
  RealImageData, e_ImageData: TBytes;
  MemStream, OutStream: TMemoryStream;
  bmp, newbmp: TUIImage;
begin
  if (SameText(e.ImageName, '<#PhotoCode>')) then
  begin
    RealImageData := TImageUtils.StripOLEHeader(e.ImageData); //On access databases, images are stored with an OLE
                                                              //header that we have to strip to get the real image.
                                                              //This is done automatically by flexcel in most cases,
                                                              //but here we have the original image format.

    if Length(RealImageData) = 0 then exit;

    MemStream := TMemoryStream.Create;
    try
      MemStream.Write(RealImageData[0], Length(RealImageData));
      MemStream.Position := 0;

      bmp := TUIImage.FromStream(MemStream);
      try
        newbmp := bmp.ConvertToGrayscale;
        try
          OutStream := TMemoryStream.Create;
          try
            newbmp.Save(OutStream, TXlsImgType.Png);
            OutStream.Position := 0;
            e.Width := newbmp.Width;
            e.Height := newbmp.Height;
            SetLength(e_ImageData, OutStream.Size);
            if Length(e_ImageData) > 0 then OutStream.Read(e_ImageData[0], Length(e_ImageData));
            e.ImageData := e_ImageData;
          finally
            OutStream.Free;
          end;
        finally
          newbmp.Free;
        end;
      finally
        bmp.Free;
      end;

    finally
      MemStream.Free;
    end;
  end;
end;

procedure TMainForm.RunReport;
var
  Report: TFlexCelReport;
begin
  if not SaveDialog.Execute then exit;

  Report := TFlexCelReport.Create(true);
  try
    Report.GetImageData := GetImageData;
    Report.AddTable(DemoTables);
    Report.SetValue('Date', Now);
    Report.Run(
      TPath.Combine(GetDataPath, 'Images.template.xls'),
      SaveDialog.FileName);
  finally
    Report.Free;
  end;

  if MessageDlg('Do you want to open the generated file?', mtConfirmation, [mbYes, mbNo], 0) = mrYes then
  begin
    ShellExecute(0, 'open', PCHAR(SaveDialog.FileName), nil, nil, SW_SHOWNORMAL);
  end;


end;

end.