lasarus_compotents/RXLib/rxdb/rxdbgridexportpdf.pas

1055 lines
29 KiB
ObjectPascal

{ RxDBGridExportPdf unit
Copyright (C) 2005-2017 Lagunov Aleksey alexs75@yandex.ru and Lazarus team
original conception from rx library for Delphi (c)
This library is free software; you can redistribute it and/or modify it
under the terms of the GNU Library General Public License as published by
the Free Software Foundation; either version 2 of the License, or (at your
option) any later version with the following modification:
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent modules,and
to copy and distribute the resulting executable under terms of your choice,
provided that you also meet, for each linked independent module, the terms
and conditions of the license of that module. An independent module is a
module which is not derived from or based on this library. If you modify
this library, you may extend this exception to your version of the library,
but you are not obligated to do so. If you do not wish to do so, delete this
exception statement from your version.
This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License
for more details.
You should have received a copy of the GNU Library General Public License
along with this library; if not, write to the Free Software Foundation,
Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
}
unit RxDBGridExportPdf;
{$mode objfpc}{$H+}
interface
{$IF (FPC_FULLVERSION >= 30004)}
uses
Classes, SysUtils, DB, rxdbgrid, rxlclutils, Graphics, fpPDF, contnrs, fpparsettf,
fpTTF;
type
TRxDBGridExportPdfOption = (repExportTitle,
repExportColors,
repExportFooter,
repOverwriteExisting,
repExportImages
);
TRxDBGridExportPdfOptions = set of TRxDBGridExportPdfOption;
{ TPdfExportOptions }
TPdfExportOptions = class(TPersistent)
private
FOwner: TPersistent;
FOptions: TPDFOptions;
FPaperOrientation: TPDFPaperOrientation;
FPaperType: TPDFPaperType;
protected
procedure AssignTo(Dest: TPersistent); override;
public
constructor Create(AOwner: TPersistent);
published
property PaperType:TPDFPaperType read FPaperType write FPaperType default ptA4;
property PaperOrientation:TPDFPaperOrientation read FPaperOrientation write FPaperOrientation default ppoPortrait;
property Options:TPDFOptions read FOptions write FOptions;
end;
type
TRxDBGridExportPDF = class;
TExportFonts = class;
{ TExportFontItem }
TExportFontItem = class
private
FFontColor: TColor;
FFontName: string;
FFontSize: Integer;
FFontStyle: TFontStyles;
FOwner:TExportFonts;
FDefaultFont: boolean;
//
FPdfFont:integer;
FTTFFontInfo: TFPFontCacheItem;
function GetBold: boolean;
function GetItalic: boolean;
procedure SetFontSize(AValue: Integer);
public
constructor Create(AOwner:TExportFonts; AFontName:string; AFontStyle: TFontStyles);
destructor Destroy; override;
procedure Activate;
property FontStyle: TFontStyles read FFontStyle;
property FontSize:Integer read FFontSize write SetFontSize;
property FontColor:TColor read FFontColor write FFontColor;
property Bold:boolean read GetBold;
property Italic:boolean read GetItalic;
property DefaultFont:boolean read FDefaultFont;
property FontName:string read FFontName;
end;
{ TExportFonts }
TExportFonts = class
private
FDefaultFontBold: TExportFontItem;
FDefaultFontNormal: TExportFontItem;
FOwner:TRxDBGridExportPDF;
FList:TFPList;
function GetCount: integer;
function GetItem(Index: integer): TExportFontItem;
public
constructor Create(AOwner:TRxDBGridExportPDF);
destructor Destroy; override;
procedure Clear;
function AddItem(AFontName: string; AFontStyle:TFontStyles = []): TExportFontItem;
function FindItem(AFontName: string; AFontStyle:TFontStyles = []):TExportFontItem;
property DefaultFontNormal:TExportFontItem read FDefaultFontNormal;
property DefaultFontBold:TExportFontItem read FDefaultFontBold;
property Count:integer read GetCount;
property Item[Index:integer]:TExportFontItem read GetItem;
end;
{ TRxDBGridExportPDF }
TRxDBGridExportPDF = class(TRxDBGridAbstractTools)
private
FPageMargin: TRxPageMargin;
FPageHeight:integer;
FPageWidth:integer;
FAuthorPDF: string;
FFileName: string;
FOpenAfterExport: boolean;
FOptions: TRxDBGridExportPdfOptions;
FProducerPDF: string;
FPdfOptions:TPdfExportOptions;
FCurPage: TPDFPage;
FTitleColor: TColor;
FWorkPages:TFPList;
FWorkPagesNeedCount:integer;
FFontItems:TExportFonts;
function GetPdfOptions: TPdfExportOptions;
procedure SetPageMargin(AValue: TRxPageMargin);
procedure SetPdfOptions(AValue: TPdfExportOptions);
function ActivateFont(AFont:TFont; AOwnerFont:TFont):TExportFontItem;
protected
FPDFDocument:TPDFDocument;
FCurSection: TPDFSection;
FDataSet:TDataSet;
FPosY : integer;
procedure InitFonts;
procedure DoSetupDocHeader;
procedure DoSetupFonts;
//
procedure WriteTextRect(AExportFont:TExportFontItem; X, Y, W, H:integer; AText:string; ATextAlign:TAlignment);
procedure DrawRect(X, Y, W, H: integer; ABorderColor, AFillColor: TColor);
procedure DrawImage(X, Y, W, H: integer; ABmp:TBitmap; ATextAlign:TAlignment);
procedure StartNewPage;
procedure DoExportPage;
procedure DoExportTitle;
procedure DoExportBody;
procedure DoExportFooter;
procedure DoSaveDocument;
function DoExecTools:boolean;override;
function DoSetupTools:boolean; override;
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
published
property FileName:string read FFileName write FFileName;
property Options:TRxDBGridExportPdfOptions read FOptions write FOptions;
property PdfOptions:TPdfExportOptions read GetPdfOptions write SetPdfOptions;
property OpenAfterExport:boolean read FOpenAfterExport write FOpenAfterExport default false;
property AuthorPdf:string read FAuthorPDF write FAuthorPDF;
property ProducerPdf:string read FProducerPDF write FProducerPDF;
property PageMargin:TRxPageMargin read FPageMargin write SetPageMargin;
property TitleColor:TColor read FTitleColor write FTitleColor default clSilver;
end;
{$ENDIF}
implementation
{$IF (FPC_FULLVERSION >= 30004)}
uses Grids, rxdconst, FileUtil, Forms, Controls, LCLIntf, LazFileUtils, FPReadBMP,
RxDBGridExportPdfSetupUnit, LazUTF8;
const
cInchToMM = 25.4;
function ConvetUnits(AUnits:TPDFFloat):TPDFFloat; inline;
begin
Result := (AUnits * cInchToMM) / gTTFontCache.DPI;
end;
function ColorToDdfColor(C:TColor):TARGBColor;
var
A:array [1..4] of byte absolute C;
begin
if C = clWindow then
Result:=clWhite
else
Result:={A[1] shl 24 +} A[1] shl 16 + A[2] shl 8 + A[3];
end;
type
THackExDBGrid = class(TRxDBGrid);
{ TExportFonts }
function TExportFonts.GetCount: integer;
begin
Result:=FList.Count;
end;
function TExportFonts.GetItem(Index: integer): TExportFontItem;
begin
Result:=TExportFontItem(FList[Index]);
end;
constructor TExportFonts.Create(AOwner: TRxDBGridExportPDF);
begin
inherited Create;
FOwner:=AOwner;
FList:=TFPList.Create;
end;
destructor TExportFonts.Destroy;
begin
Clear;
FreeAndNil(FList);
inherited Destroy;
end;
procedure TExportFonts.Clear;
var
I: Integer;
begin
for I:=0 to FList.Count-1 do
TExportFontItem(FList[i]).Free;
FList.Clear;
end;
function TExportFonts.AddItem(AFontName: string; AFontStyle: TFontStyles
): TExportFontItem;
var
S1, S2, S3: String;
begin
Result:=FindItem(AFontName, AFontStyle);
if Assigned(Result) then exit;
Result:=TExportFontItem.Create(Self, AFontName, AFontStyle);
S1:=ExtractFileDir(Result.FTTFFontInfo.FileName);
S2:=ExtractFileName(Result.FTTFFontInfo.FileName);
S3:=AFontName;
FOwner.FPDFDocument.FontDirectory:=S1;
Result.FPdfFont:=FOwner.FPDFDocument.AddFont(S2, S3);
end;
function TExportFonts.FindItem(AFontName: string; AFontStyle: TFontStyles
): TExportFontItem;
var
K: TExportFontItem;
i: Integer;
begin
Result:=nil;
if AFontName = 'default' then
begin
if Graphics.fsBold in AFontStyle then
Result:=FDefaultFontBold
else
Result:=FDefaultFontNormal;
end
else
begin
for i:=0 to FList.Count-1 do
begin
K:=TExportFontItem(FList[i]);
if (K.FontName = AFontName) and (K.FontStyle = AFontStyle) then
begin
Result:=K;
exit;
end
end;
end;
end;
{ TExportFontItem }
function TExportFontItem.GetBold: boolean;
begin
Result:=Graphics.fsBold in FFontStyle;
end;
function TExportFontItem.GetItalic: boolean;
begin
Result:=Graphics.fsItalic in FFontStyle;
end;
procedure TExportFontItem.SetFontSize(AValue: Integer);
begin
if AValue = 0 then
FFontSize:=10
else
FFontSize:=AValue;
end;
constructor TExportFontItem.Create(AOwner: TExportFonts; AFontName: string;
AFontStyle: TFontStyles);
begin
inherited Create;
FOwner:=AOwner;
FOwner.FList.Add(Self);
FFontStyle:=AFontStyle;
FFontName:=AFontName;
FTTFFontInfo:=gTTFontCache.Find(AFontName, Graphics.fsBold in AFontStyle, Graphics.fsItalic in AFontStyle);
if not Assigned(FTTFFontInfo) then
raise Exception.CreateFmt('fpTTF:in gTTFontCache not found font "%s" info.', [AFontName]);
end;
destructor TExportFontItem.Destroy;
begin
inherited Destroy;
end;
procedure TExportFontItem.Activate;
begin
FOwner.FOwner.FCurPage.SetFont(FPdfFont, FontSize);
FOwner.FOwner.FCurPage.SetColor(ColorToDdfColor(FontColor), false);
end;
{ TPdfExportOptions }
procedure TPdfExportOptions.AssignTo(Dest: TPersistent);
begin
if Dest is TPdfExportOptions then
begin
TPdfExportOptions(Dest).FOptions := FOptions;
TPdfExportOptions(Dest).FPaperOrientation:=FPaperOrientation;
TPdfExportOptions(Dest).FPaperType:=FPaperType;
end
else
inherited AssignTo(Dest);
end;
constructor TPdfExportOptions.Create(AOwner: TPersistent);
begin
inherited Create;
FOwner:=AOwner;
FPaperType:=ptA4;
FPaperOrientation:=ppoPortrait;
end;
{ TRxDBGridExportSpreadSheet }
function TRxDBGridExportPDF.GetPdfOptions: TPdfExportOptions;
begin
Result:=FPdfOptions;
end;
procedure TRxDBGridExportPDF.SetPageMargin(AValue: TRxPageMargin);
begin
FPageMargin.Assign(AValue);
end;
procedure TRxDBGridExportPDF.SetPdfOptions(AValue: TPdfExportOptions);
begin
FPdfOptions.Assign(AValue);
end;
function TRxDBGridExportPDF.ActivateFont(AFont: TFont; AOwnerFont: TFont
): TExportFontItem;
begin
Result:=FFontItems.FindItem(AFont.Name, AFont.Style);
{ if not Assigned(Result) then
Result:=SelectFont(AOwnerFont);
if not Assigned(Result) then
Result:=FFontItems.FDefaultFontNormal;
}
if Assigned(Result) then
begin
Result.FontSize:=AFont.Size;
Result.FontColor:=AFont.Color;
Result.Activate
end
else
raise Exception.CreateFmt('Font "%s" not found', [AFont.Name]);
end;
procedure TRxDBGridExportPDF.WriteTextRect(AExportFont: TExportFontItem; X, Y,
W, H: integer; AText: string; ATextAlign: TAlignment);
var
FTW, FTH, FTH1, FTH2: Single;
X1: TPDFFloat;
Y1, fX, fY: TPDFFloat;
fW, fH: Extended;
begin
fX := ConvetUnits(X);
fY := ConvetUnits(Y+2);
fW := ConvetUnits(W);
fH := ConvetUnits(H);
//Calc text width
FTW:=ConvetUnits(AExportFont.FTTFFontInfo.TextWidth(AText, AExportFont.FontSize));
//Calc text height
FTH1 := AExportFont.FTTFFontInfo.FontData.CapHeight * AExportFont.FontSize * gTTFontCache.DPI / (72 * AExportFont.FTTFFontInfo.FontData.Head.UnitsPerEm);
FTH2 := Abs(AExportFont.FTTFFontInfo.FontData.Descender) * AExportFont.FontSize * gTTFontCache.DPI / (72 * AExportFont.FTTFFontInfo.FontData.Head.UnitsPerEm);
FTH := (FTH1 * 25.4) / gTTFontCache.DPI + (FTH2 * 25.4) / gTTFontCache.DPI;
case ATextAlign of
taLeftJustify:
begin
// Y1:=fY - FTH2;
X1:=fX + ConvetUnits(constCellPadding);
while (FTW > fW) and (UTF8Length(AText) > 0) do
begin
AText:=UTF8Copy(AText, 1, UTF8Length(AText)-1);
FTW:=ConvetUnits(AExportFont.FTTFFontInfo.TextWidth(AText, AExportFont.FontSize));
end
end;
taRightJustify:
begin
// Y1:=fY - FTH2;
X1:=fX + fW - FTW - ConvetUnits(constCellPadding);
if X1 < fX then
X1:=fX;
end;
taCenter:
begin
// Y1:=fY - FTH2;
X1:=fX + fW / 2 - FTW / 2 - ConvetUnits(constCellPadding);
if X1 < fX then
X1:=fX;
end;
end;
Y1:=fY + FTH2;
FCurPage.WriteText(X1, Y1 {- fH}, AText);
end;
procedure TRxDBGridExportPDF.DrawRect(X, Y, W, H: integer; ABorderColor,
AFillColor: TColor);
var
fX, fY, fW, fH: Extended;
begin
if (AFillColor = clNone) and (ABorderColor = clNone) then exit;
if ABorderColor <> clNone then
FCurPage.SetColor(ColorToDdfColor(ABorderColor), true);
if (AFillColor <> clNone) and (repExportColors in FOptions) then
FCurPage.SetColor(ColorToDdfColor(AFillColor), false);
fW:= ConvetUnits(W);
fH:= ConvetUnits(H);
fX:= ConvetUnits(X);
fY:= ConvetUnits(Y) + fH;
FCurPage.DrawRect(fX, fY, fW, fH, 1, (AFillColor <> clNone) and (repExportColors in FOptions), (ABorderColor <> clNone));
end;
procedure TRxDBGridExportPDF.DrawImage(X, Y, W, H: integer; ABmp: TBitmap;
ATextAlign: TAlignment);
var
S:TMemoryStream;
IDX: Integer;
fW, fH, fX, fY, X1, Y1, fW1, fH1: TPDFFloat;
begin
S:=TMemoryStream.Create;
try
ABmp.SaveToStream(S);
S.Position:=0;
IDX := FPDFDocument.Images.AddFromStream(S, TFPReaderBMP, False);
fW1 := ConvetUnits(FPDFDocument.Images[IDX].Width);
fH1 := ConvetUnits(FPDFDocument.Images[IDX].Height);
fX:=ConvetUnits(X);
fY:=ConvetUnits(Y + constCellPadding);
fW:=ConvetUnits(W);
fH:=ConvetUnits(H);
case ATextAlign of
taLeftJustify:
begin
Y1:=fY;
X1:=fX + ConvetUnits(constCellPadding);
end;
taRightJustify:
begin
Y1:=fY;
X1:=fX + fW - fW1 - ConvetUnits(constCellPadding);
if X1 < fX then
X1:=fX;
end;
taCenter:
begin
Y1:=fY;
X1:=fX + fW / 2 - fW1 / 2 - ConvetUnits(constCellPadding);
if X1 < fX then
X1:=fX;
end;
end;
Y1:=Y1 + fW1;
FCurPage.DrawImage(X1, Y1, fW1, fH1, IDX);
finally
S.Free;
end;
end;
procedure TRxDBGridExportPDF.StartNewPage;
var
P: TPDFPage;
i: Integer;
begin
FWorkPages.Clear;
for i:=0 to FWorkPagesNeedCount - 1 do
begin
P := FPDFDocument.Pages.AddPage;
P.PaperType := FPdfOptions.PaperType;
//P.UnitOfMeasure := uomPixels;
P.UnitOfMeasure := uomMillimeters; //normal work only whis mm ??
FCurSection.AddPage(P);
FWorkPages.Add(P);
end;
FPosY:=FPageMargin.Top;
end;
procedure TRxDBGridExportPDF.DoExportTitle;
var
i, X, CP, K, KY, TH1, X1, W1, WNext: Integer;
C, FStartCol: TRxColumn;
CT: TRxColumnTitle;
H: LongInt;
KL: TMLCaptionItem;
begin
X:=FPageWidth + FPageMargin.Right;
H:=THackExDBGrid(FRxDBGrid).RowHeights[0];
CP:=-1;
FCurPage:=nil;
for i:=0 to FRxDBGrid.Columns.Count - 1 do
begin
C:=FRxDBGrid.Columns[i];
if C.Visible then
begin
if X + C.Width > FPageWidth - FPageMargin.Right then
begin
Inc(CP);
FCurPage:=TPDFPage(FWorkPages[CP]);
X:=FPageMargin.Left;
FStartCol:=C;
end;
CT:=C.Title as TRxColumnTitle;
if CT.CaptionLinesCount > 0 then
begin
KY:=FPosY;
for K:=0 to CT.CaptionLinesCount - 1 do
begin
TH1:=CT.CaptionLine(K).Height * RxDBGrid.DefaultRowHeight;
if K < CT.CaptionLinesCount-1 then
begin
if i < FRxDBGrid.Columns.Count-1 then
WNext:=FRxDBGrid.Columns[i+1].Width
else
WNext:=0;
if (not Assigned(CT.CaptionLine(K).Next)) or (X + C.Width + WNext > FPageWidth - FPageMargin.Right) then
begin
KL:=CT.CaptionLine(K);
X1:=X;
W1:=C.Width;
while Assigned(KL.Prior) and (KL.Col <> FStartCol) do
begin
KL:=KL.Prior;
X1:=X1 - KL.Col.Width;
W1:=W1 + KL.Col.Width;
end;
DrawRect(X1, KY, W1, TH1, FRxDBGrid.BorderColor, FTitleColor);
WriteTextRect(ActivateFont(C.Title.Font, FRxDBGrid.TitleFont), X1, KY, W1, TH1, CT.CaptionLine(K).Caption, C.Title.Alignment);
end;
KY:=KY + TH1;
end
else
begin
DrawRect(X, KY, C.Width, FPosY + H - KY, FRxDBGrid.BorderColor, FTitleColor);
WriteTextRect(ActivateFont(C.Title.Font, FRxDBGrid.TitleFont), X, KY, C.Width, FPosY + H - KY, CT.CaptionLine(K).Caption, C.Title.Alignment);
end;
end;
end
else
begin
DrawRect(X, FPosY, C.Width, H, FRxDBGrid.BorderColor, FTitleColor);
WriteTextRect(ActivateFont(C.Title.Font, FRxDBGrid.TitleFont), X, FPosY, C.Width, H, C.Title.Caption, C.Title.Alignment);
end;
X:=X + C.Width;
end;
end;
Inc(FPosY, H); // DefaultRowHeight);
end;
procedure TRxDBGridExportPDF.DoExportBody;
procedure DoWriteRow;
var
i, X, CP: Integer;
C: TRxColumn;
B: TBitmap;
AImageIndex: LongInt;
begin
X:=FPageWidth + FPageMargin.Right;
CP:=-1;
FCurPage:=nil;
for i:=0 to FRxDBGrid.Columns.Count - 1 do
begin
C:=FRxDBGrid.Columns[i];
if C.Visible then
begin
if X + C.Width > FPageWidth - FPageMargin.Right then
begin
Inc(CP);
FCurPage:=TPDFPage(FWorkPages[CP]);
X:=FPageMargin.Left;
end;
DrawRect(X, FPosY, C.Width, FRxDBGrid.DefaultRowHeight, FRxDBGrid.BorderColor, C.Color);
if Assigned(C.Field) then
begin
if (repExportImages in FOptions) and Assigned(C.ImageList) then
begin
AImageIndex := StrToIntDef(C.KeyList.Values[C.Field.AsString], C.NotInKeyListIndex);
if (AImageIndex > -1) and (AImageIndex < C.ImageList.Count) then
begin
B:=TBitmap.Create;
try
B.Width:=C.ImageList.Width;
B.Height:=C.ImageList.Height;
B.Canvas.Brush.Color:=clWhite;
B.Canvas.FillRect(0, 0, B.Width, B.Height);
C.ImageList.StretchDraw(B.Canvas, AImageIndex, Rect(0, 0, B.Width, B.Height));
DrawImage(X, FPosY, C.Width, FRxDBGrid.DefaultRowHeight, B, C.Alignment);
finally
B.Free
end;
end
end
else
WriteTextRect(ActivateFont(C.Font, FRxDBGrid.Font), X, FPosY, C.Width, FRxDBGrid.DefaultRowHeight, C.Field.DisplayText, C.Alignment);
end;
X:=X + C.Width;
end;
end;
end;
begin
while not FDataSet.EOF do
begin
DoWriteRow;
FDataSet.Next;
Inc(FPosY, FRxDBGrid.DefaultRowHeight);
if FPosY > FPageHeight - FPageMargin.Bottom then
exit;
end;
end;
procedure TRxDBGridExportPDF.DoSetupFonts;
//Find default font name
function DefFontName:string;
const
DefFontNames : array [1..3] of string =
('Liberation Sans', 'Arial', 'FreeSans');
var
i: Integer;
begin
for i:=1 to 3 do
if Assigned(gTTFontCache.Find(DefFontNames[i], false, false)) then
begin
Result:=DefFontNames[i];
exit;
end;
raise Exception.Create('Not found Sans font');
end;
var
i: Integer;
sDefFontName:string;
begin
InitFonts;
sDefFontName:=DefFontName;
FFontItems.FDefaultFontNormal:=FFontItems.AddItem(sDefFontName, []);
FFontItems.FDefaultFontBold:=FFontItems.AddItem(sDefFontName, [Graphics.fsBold]);
for i:=0 to FRxDBGrid.Columns.Count-1 do
begin
if FRxDBGrid.Columns[i].Font.Name <> 'default' then
FFontItems.AddItem(FRxDBGrid.Columns[i].Font.Name, FRxDBGrid.Columns[i].Font.Style);
if FRxDBGrid.Columns[i].Footer.Font.Name <> 'default' then
FFontItems.AddItem(FRxDBGrid.Columns[i].Footer.Font.Name, FRxDBGrid.Columns[i].Footer.Font.Style);
if FRxDBGrid.Columns[i].Title.Font.Name <> 'default' then
FFontItems.AddItem(FRxDBGrid.Columns[i].Title.Font.Name, FRxDBGrid.Columns[i].Title.Font.Style);
end;
end;
procedure TRxDBGridExportPDF.DoExportFooter;
procedure WriteFooterRow(AFooterRow:Integer);
var
i, X, CP: Integer;
S: String;
C: TRxColumn;
begin
X:=FPageWidth + FPageMargin.Right;
CP:=-1;
FCurPage:=nil;
for i:=0 to FRxDBGrid.Columns.Count - 1 do
begin
C:=FRxDBGrid.Columns[i];
if C.Visible then
begin
if X + C.Width > FPageWidth - FPageMargin.Right then
begin
Inc(CP);
FCurPage:=TPDFPage(FWorkPages[CP]);
X:=FPageMargin.Left;
end;
DrawRect(X, FPosY, C.Width, FRxDBGrid.DefaultRowHeight, FRxDBGrid.BorderColor, FRxDBGrid.FooterOptions.Color);
if FRxDBGrid.FooterOptions.RowCount = 1 then
S:=C.Footer.DisplayText
else
begin
if C.Footers.Count > AFooterRow then
S:=C.Footers[AFooterRow].DisplayText
else
S:='';
end;
if (S<>'') then
WriteTextRect(ActivateFont(C.Footer.Font, FRxDBGrid.Font), X, FPosY, C.Width, FRxDBGrid.DefaultRowHeight, S, C.Footer.Alignment);
X:=X + C.Width;
end;
end;
Inc(FPosY, FRxDBGrid.DefaultRowHeight);
end;
var
j: Integer;
begin
if FRxDBGrid.FooterOptions.RowCount = 1 then
WriteFooterRow(1)
else
begin
for j:=0 to FRxDBGrid.FooterOptions.RowCount-1 do
begin
if FPosY > FPageHeight - FPageMargin.Bottom then
StartNewPage;
WriteFooterRow(j);
end;
end;
end;
procedure TRxDBGridExportPDF.DoSetupDocHeader;
var
W, i: Integer;
C: TRxColumn;
begin
FPDFDocument.Infos.Title := Application.Title;
FPDFDocument.Infos.Author := FAuthorPDF;
FPDFDocument.Infos.Producer := FProducerPDF;
FPDFDocument.Infos.ApplicationName := ApplicationName;
FPDFDocument.Infos.CreationDate := Now;
FPDFDocument.Options:=FPdfOptions.FOptions + [poPageOriginAtTop];
FPDFDocument.DefaultOrientation:=FPdfOptions.PaperOrientation;
//calc need count pages for all columns
FWorkPagesNeedCount:=1;
if FPdfOptions.FPaperType <> ptCustom then
begin
if FPdfOptions.PaperOrientation = ppoPortrait then
begin
FPageWidth := PDFPaperSizes[FPdfOptions.FPaperType, 1];
FPageHeight := PDFPaperSizes[FPdfOptions.FPaperType, 0];
end
else
begin
FPageWidth := PDFPaperSizes[FPdfOptions.FPaperType, 0];
FPageHeight := PDFPaperSizes[FPdfOptions.FPaperType, 1];
end;
W:=FPageWidth + FPageMargin.Right;
FWorkPagesNeedCount:=0;
for i:=0 to FRxDBGrid.Columns.Count - 1 do
begin
C:=FRxDBGrid.Columns[i];
if C.Visible then
begin
if W + C.Width > FPageWidth - FPageMargin.Right then
begin
Inc(FWorkPagesNeedCount);
W:=FPageMargin.Left;
end;
W:=W + C.Width;
end;
end;
end;
end;
procedure TRxDBGridExportPDF.DoExportPage;
begin
StartNewPage;
if repExportTitle in FOptions then
DoExportTitle;
DoExportBody;
end;
function TRxDBGridExportPDF.DoExecTools: boolean;
var
P: TBookMark;
begin
Result:=false;
FDataSet:=FRxDBGrid.DataSource.DataSet;
FDataSet.DisableControls;
{$IFDEF NoAutomatedBookmark}
P:=FDataSet.GetBookmark;
{$ELSE}
P:=FDataSet.Bookmark;
{$ENDIF}
FPDFDocument:=TPDFDocument.Create(nil);
FFontItems:=TExportFonts.Create(Self);
FWorkPages:=TFPList.Create;
try
FPDFDocument.StartDocument;
DoSetupFonts;
DoSetupDocHeader;
FCurSection := FPDFDocument.Sections.AddSection; // we always need at least one section
FDataSet.First;
repeat
DoExportPage;
until FDataSet.EOF;
if repExportFooter in FOptions then
begin
if FPosY > FPageHeight - FPageMargin.Bottom then
StartNewPage;
DoExportFooter;
end;
DoSaveDocument;
Result:=true;
finally
{$IFDEF NoAutomatedBookmark}
FDataSet.GotoBookmark(P);
FDataSet.FreeBookmark(P);
{$ELSE}
FDataSet.Bookmark:=P;
{$ENDIF}
FDataSet.EnableControls;
FreeAndNil(FWorkPages);
FreeAndNil(FPDFDocument);
FreeAndNil(FFontItems);
end;
if Result and FOpenAfterExport then
OpenDocument(FileName);
end;
function TRxDBGridExportPDF.DoSetupTools: boolean;
begin
RxDBGridExportPdfSetupForm:=TRxDBGridExportPdfSetupForm.Create(Application);
RxDBGridExportPdfSetupForm.FileNameEdit1.FileName:=FileName;
RxDBGridExportPdfSetupForm.cbOpenAfterExport.Checked:=FOpenAfterExport;
RxDBGridExportPdfSetupForm.cbExportColumnHeader.Checked:=repExportTitle in FOptions;
RxDBGridExportPdfSetupForm.cbExportColumnFooter.Checked:=repExportFooter in FOptions;
RxDBGridExportPdfSetupForm.cbExportCellColors.Checked:=repExportColors in FOptions;
RxDBGridExportPdfSetupForm.CheckBox6.Checked:=repExportImages in FOptions;
RxDBGridExportPdfSetupForm.ColorBox1.Selected:=FTitleColor;
RxDBGridExportPdfSetupForm.RadioGroup1.ItemIndex:=Ord(FPdfOptions.PaperOrientation = ppoLandscape);
RxDBGridExportPdfSetupForm.ComboBox1.ItemIndex:=Ord(FPdfOptions.PaperType)-1;
RxDBGridExportPdfSetupForm.CheckBox1.Checked:=poOutLine in FPdfOptions.Options;
RxDBGridExportPdfSetupForm.CheckBox2.Checked:=poCompressText in FPdfOptions.Options;
RxDBGridExportPdfSetupForm.CheckBox3.Checked:=poCompressFonts in FPdfOptions.Options;
RxDBGridExportPdfSetupForm.CheckBox4.Checked:=poCompressImages in FPdfOptions.Options;
RxDBGridExportPdfSetupForm.CheckBox5.Checked:=poUseRawJPEG in FPdfOptions.Options;
Result:=RxDBGridExportPdfSetupForm.ShowModal = mrOk;
if Result then
begin
FileName:=RxDBGridExportPdfSetupForm.FileNameEdit1.FileName;
FOpenAfterExport:=RxDBGridExportPdfSetupForm.cbOpenAfterExport.Checked;
FTitleColor:=RxDBGridExportPdfSetupForm.ColorBox1.Selected;
if RxDBGridExportPdfSetupForm.cbExportColumnHeader.Checked then
FOptions:=FOptions + [repExportTitle]
else
FOptions:=FOptions - [repExportTitle];
if RxDBGridExportPdfSetupForm.cbExportColumnFooter.Checked then
FOptions:=FOptions + [repExportFooter]
else
FOptions:=FOptions - [repExportFooter];
if RxDBGridExportPdfSetupForm.cbExportCellColors.Checked then
FOptions:=FOptions + [repExportColors]
else
FOptions:=FOptions - [repExportColors];
if RxDBGridExportPdfSetupForm.CheckBox6.Checked then
FOptions:=FOptions + [repExportImages]
else
FOptions:=FOptions - [repExportImages];
if RxDBGridExportPdfSetupForm.RadioGroup1.ItemIndex = 0 then
FPdfOptions.PaperOrientation:=ppoPortrait
else
FPdfOptions.PaperOrientation:=ppoLandscape;
FPdfOptions.PaperType:=TPDFPaperType(RxDBGridExportPdfSetupForm.ComboBox1.ItemIndex+1);
if RxDBGridExportPdfSetupForm.CheckBox1.Checked then
FPdfOptions.Options:=FPdfOptions.Options + [poOutLine]
else
FPdfOptions.Options:=FPdfOptions.Options - [poOutLine];
if RxDBGridExportPdfSetupForm.CheckBox2.Checked then
FPdfOptions.Options:=FPdfOptions.Options + [poCompressText]
else
FPdfOptions.Options:=FPdfOptions.Options - [poCompressText];
if RxDBGridExportPdfSetupForm.CheckBox3.Checked then
FPdfOptions.Options:=FPdfOptions.Options + [poCompressFonts]
else
FPdfOptions.Options:=FPdfOptions.Options - [poCompressFonts];
if RxDBGridExportPdfSetupForm.CheckBox4.Checked then
FPdfOptions.Options:=FPdfOptions.Options + [poCompressImages]
else
FPdfOptions.Options:=FPdfOptions.Options - [poCompressImages];
if RxDBGridExportPdfSetupForm.CheckBox5.Checked then
FPdfOptions.Options:=FPdfOptions.Options + [poUseRawJPEG]
else
FPdfOptions.Options:=FPdfOptions.Options - [poUseRawJPEG];
end;
RxDBGridExportPdfSetupForm.Free;
end;
procedure TRxDBGridExportPDF.DoSaveDocument;
var
F: TFileStream;
begin
F := TFileStream.Create(FFileName,fmCreate);
try
FPDFDocument.SaveToStream(F);
finally
F.Free;
end;
end;
procedure TRxDBGridExportPDF.InitFonts;
var
FontDirList: TStringList;
procedure CreateFontDirList;
{$IFDEF WINDOWS}
var
s: String;
{$ENDIF}
begin
{$IFDEF WINDOWS}
s := SHGetFolderPathUTF8(20); // CSIDL_FONTS = 20
if s <> '' then
FontDirList.Add(s);
{$ENDIF}
{$IFDEF linux}
//tested on Fedora 24
FontDirList.Add('/usr/share/cups/fonts/');
FontDirList.Add('/usr/share/fonts/');
FontDirList.Add('/usr/share/wine/fonts/');
FontDirList.Add('/usr/local/lib/X11/fonts/');
FontDirList.Add(GetUserDir + '.fonts/');
{$ENDIF}
end;
begin
FontDirList := TStringList.Create;
CreateFontDirList;
if gTTFontCache.Count = 0 then
begin
gTTFontCache.BuildFontCacheIgnoresErrors:=true;
CreateFontDirList;
gTTFontCache.SearchPath.Assign(FontDirList);
FreeAndNil(FontDirList);
gTTFontCache.BuildFontCache;
end;
end;
constructor TRxDBGridExportPDF.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
FPageMargin:=TRxPageMargin.Create;
FPdfOptions:=TPdfExportOptions.Create(Self);
FTitleColor:=clSilver;
FCaption:=sToolsExportPDF;
FOpenAfterExport:=false;
end;
destructor TRxDBGridExportPDF.Destroy;
begin
FreeAndNil(FPdfOptions);
FreeAndNil(FPageMargin);
inherited Destroy;
end;
{$ENDIF}
end.