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:
If all images are the same size and on a standard format, just name the image as <#table.field> and do nothing more.
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.
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.