123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777 |
- {
- This file is part of the Free Component Library.
- Copyright (c) 2017 Michael Van Canneyt, member of the Free Pascal development team
- TFPReport descendent that stores it's design in a JSON structure.
- Can be used in an IDE
- See the file COPYING.FPC, included in this distribution,
- for details about the copyright.
- 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.
- **********************************************************************}
- unit fplazreport;
- {$mode objfpc}{$H+}
- interface
- uses
- Classes, SysUtils, fpreport, DOM, FPCanvas, fpTTF, fpreportdb, fpreportbarcode;
- Type
- TCustomPropEvent = procedure(Sender: TObject;Data : TDOMNode) of object;
- TConvertLogEvent = Procedure(Sender: TOBject;Const Msg : String) of Object;
- TNameConvertEvent = Procedure(Sender: TOBject;Const aName : UnicodeString; Var aNewName : String) of Object;
- TFontSubstitutionEvent = Procedure(Sender: TOBject;Const aFontName : String; Const aBold,aItalic: Boolean; var aFont : TFPFontCacheItem) of Object;
- { TFPLazReport }
- TFPLazReport = class(TFPReport)
- private
- FData: TComponent;
- FMasterData: TFPReportDataBand;
- FDetailHeader : TFPReportDataHeaderBand;
- FDetailFooter : TFPReportDataFooterBand;
- FDetailBand: TFPReportDataBand;
- FMemoClass: TFPReportElementClass;
- FOnConvertName: TNameConvertEvent;
- FOnLog: TConvertLogEvent;
- FOnSetCustomProps: TCustomPropEvent;
- FOnSubstituteFont: TFontSubstitutionEvent;
- FCounter : Integer;
- FNullBand : TFPReportChildBand;
- Protected
- class function Red(rgb: Integer): BYTE; virtual;
- class function Green(rgb: Integer): BYTE; virtual;
- class function Blue(rgb: Integer): BYTE; virtual;
- function FindBand(aPage: TFPReportCustomPage; aTop: double; AElement: TFPReportElement=Nil): TFPReportCustomBand; virtual;
- class function GetProperty(aNode: TDOMNode; const aName: String; const aValue: string='Value'): UTF8String; virtual;
- function ApplyFrame(aDataNode: TDOMNode; aFrame: TFPReportFrame): Boolean; virtual;
- procedure ApplyObjectProperties(ObjNode: TDOMNode; aObj: TFPReportElement); virtual;
- procedure ConvertPageProperties(aPage: TFPReportPage; aPageNode: TDOMNode); virtual;
- procedure SetData(AValue: TComponent);virtual;
- procedure SizeToLayout(aDataNode: TDOMNode; aObj: TFPReportElement);virtual;
- Function ConvertComponentName(Const aName : UnicodeString;Const AClassName : String) : String; virtual;
- function ConvertFont(aDataNode: TDomNode): TFPFontCacheItem; virtual;
- function ConvertBand(aBandNode: TDomNode;aPage: TFPReportCustomPage): TFPReportCustomBand; virtual;
- function ConvertMemo(ObjNode: TDOMNode; aPage: TFPReportCustomPage): TFPReportMemo; virtual;
- function ConvertPage(aPageNode: TDOMNode): TFPReportPage; virtual;
- function ConvertLine(ObjNode: TDOMNode; APage: TFPReportCustomPage): TFPReportShape; virtual;
- function ConvertImage(ObjNode: TDOMNode; APage: TFPReportCustomPage): TFPReportImage; virtual;
- function ConvertBarcode(ObjNode : TDOMNode; APage : TFPReportCustomPage) : TFPReportBarcode; virtual;
- Procedure Notification(AComponent: TComponent; Operation: TOperation); override;
- Procedure DoLog(Const Msg : String);
- Procedure DoLog(Const Fmt : String; Const Args : Array of const);
- Public
- constructor Create(AOwner: TComponent); override;
- function FixDataFields(aFieldName : string) : string;
- property MemoClass : TFPReportElementClass read FMemoClass write FmemoClass;
- Procedure LoadFromXML(LazReport : TXMLDocument);virtual;
- Procedure LoadFromFile(const aFileName : String);
- Published
- property DataContainer : TComponent read FData write SetData;
- property OnSetCustomproperties : TCustomPropEvent read FOnSetCustomProps write FOnSetCustomProps;
- Property OnLog : TConvertLogEvent Read FOnLog Write FOnLog;
- Property OnSubstituteFont : TFontSubstitutionEvent Read FOnSubstituteFont Write FOnSubstituteFont;
- Property OnConvertName : TNameConvertEvent Read FOnConvertName Write FOnConvertName;
- end;
- function MMToPixels(Const Dist: double) : Integer;
- function PixelsToMM(Const Dist: double) : TFPReportUnits;
- implementation
- uses dateutils, XMLRead,FPReadPNG,FPimage,FPReadGif,FPReadJPEG,fpbarcode;
- Resourcestring
- SLogUnknownClass = 'Ignoring unknown lazreport class type for object "%s": "%s".';
- SErrUnknownBandType = 'Unknown band type: "%s", substituting child band';
- SErrWrongEncoding = 'Unknown image encoding at pos %d : %s';
- SFontSubstitution = 'FontSubstitution';
- SErrUnknownImageType = 'Unknown image type encountered: "%s"';
- SWarnConvertName = 'Name conversion: "%s" to "%s"';
- SUnknownBarcodeType = 'Unknown barcode type: "%s"';
- SIgnoringAngleOnBarcode = 'Igoring angle on barcode';
- SIgnoringShowTextOnBarcode = 'Igoring showtext on barcode';
- SLogNullBandAssigned = 'Null (child) band assigned for element of type "%s" at pos %5.3f';
- function PixelsToMM(Const Dist: double) : TFPReportUnits;
- begin
- Result:=Dist*(1/3.76);
- end;
- function MMToPixels(Const Dist: double) : Integer;
- begin
- Result:=round(Dist*(3.76));
- end;
- function PageToMM(Const Dist: double) : TFPReportUnits;
- begin
- Result:=Dist*(1/2.83);
- end;
- { TFPLazReport }
- procedure TFPLazReport.SetData(AValue: TComponent);
- begin
- if FData=AValue then Exit;
- if Assigned(FData) then
- FData.RemoveFreeNotification(Self);
- FData:=AValue;
- if Assigned(FData) then
- FData.FreeNotification(Self);
- end;
- procedure TFPLazReport.Notification(AComponent: TComponent; Operation: TOperation);
- begin
- inherited Notification(AComponent, Operation);
- if Operation=opRemove then
- if (AComponent=FData) then
- FData:=Nil;
- end;
- procedure TFPLazReport.DoLog(const Msg: String);
- begin
- If Assigned(FOnLog) then
- FOnLog(Self,Msg);
- end;
- procedure TFPLazReport.DoLog(const Fmt: String; const Args: array of const);
- Var
- S : String;
- begin
- try
- S:=Format(Fmt,Args);
- except
- on E : Exception do
- S:=Format('Failed to format error message "%s" with %d arguments',[Fmt,Length(Args)]);
- end;
- DoLog(S);
- end;
- constructor TFPLazReport.Create(AOwner: TComponent);
- begin
- inherited Create(AOwner);
- MemoClass := TFPReportMemo;
- DataContainer := Owner;
- end;
- function TFPLazReport.FixDataFields(aFieldName: string): string;
- var
- k : Integer = 0;
- begin
- Result := aFieldName;
- if Assigned(FData) then
- while k < FData.ComponentCount do
- begin
- if FData.Components[k] is TFPReportDatasetData then
- Result := StringReplace(Result,TFPReportDatasetData(FData.Components[k]).Name+'.',TFPReportDatasetData(FData.Components[k]).Name+'.',[rfReplaceAll,rfIgnoreCase]);
- inc(k);
- end;
- Result := StringReplace(Result,'PAGE#','PageNo',[rfReplaceAll,rfIgnoreCase]);
- Result := StringReplace(Result,'[DATE]','[TODAY]',[rfReplaceAll,rfIgnoreCase]);
- end;
- Class function TFPLazReport.Blue(rgb: Integer): BYTE;
- begin
- Result := (rgb shr 16) and $000000ff;
- end;
- Class function TFPLazReport.Green(rgb: Integer): BYTE;
- begin
- Result := (rgb shr 8) and $000000ff;
- end;
- Class function TFPLazReport.Red(rgb: Integer): BYTE;
- begin
- Result := rgb and $000000ff;
- end;
- procedure TFPLazReport.LoadFromXML(LazReport: TXMLDocument);
- var
- i: Integer;
- BaseNode,lPages : TDOMNode;
- aPage: TFPReportPage;
- begin
- BaseNode := LazReport.DocumentElement.FindNode('LazReport');
- if not Assigned(BaseNode) then
- exit;
- lPages := BaseNode.FindNode('Pages');
- if Not Assigned(lPages) then
- exit;
- TwoPass:= GetProperty(lPages,'DoublePass') = 'True';
- with lPages.ChildNodes do
- for i := 0 to (Count - 1) do
- if (copy(Item[i].NodeName,0,4)='Page') and (Item[i].NodeName<>'PageCount') then
- begin
- aPage:=ConvertPage(Item[i]);
- AddPage(aPage);
- end;
- end;
- Class function TFPLazReport.GetProperty(aNode : TDOMNode;Const aName : String; Const aValue : string = 'Value') : UTF8String;
- var
- bNode: TDOMNode;
- begin
- Result := '';
- bNode := aNode.FindNode(aName);
- if Assigned(bNode) then
- if Assigned(bNode.Attributes.GetNamedItem(aValue)) then
- Result := UTF8Encode(bNode.Attributes.GetNamedItem(aValue).NodeValue);
- end;
- function TFPLazReport.FindBand(aPage : TFPReportCustomPage;aTop : double; AElement : TFPReportElement = Nil) : TFPReportCustomBand;
- var
- b : Integer;
- S : String;
- begin
- Result := nil;
- for b := 0 to aPage.BandCount-1 do
- begin
- if (aTop>=aPage.Bands[b].Layout.Top)
- and (aTop<=aPage.Bands[b].Layout.Top+aPage.Bands[b].Layout.Height) then
- begin
- Result := aPage.Bands[b];
- break;
- end;
- end;
- if (Result=Nil) then
- begin
- if (FNullBand=Nil) then
- begin
- FNullBand:=TFPReportChildBand.Create(Self);
- FNullBand.Name:='NullBand';
- FNullBand.Layout.Height:=aPage.Layout.Height;
- FNullBand.Parent:=aPage;
- end;
- Result:=FNullBand;
- end;
- if (Result=FNullBand) and Assigned(FOnLog) then
- begin
- if aElement = Nil then
- S:='<unknown>'
- else
- S:=aElement.ClassName;
- DoLog(SLogNullBandAssigned,[S,aTop]);
- end;
- end;
- Function TFPLazReport.ConvertBand(aBandNode : TDomNode;aPage: TFPReportCustomPage) : TFPReportCustomBand;
- Var
- Tmp : String;
- aBand : TFPReportCustomBand;
- aData : TFPreportData;
- begin
- tmp := GetProperty(aBandNode,'BandType');
- case tmp of
- 'btReportTitle':
- aBand := TFPReportTitleBand.Create(Self);
- 'btMasterData':
- begin
- aBand := TFPReportDataBand.Create(Self);
- tmp := GetProperty(aBandNode,'DatasetStr');
- if copy(tmp,1,1)='P' then
- tmp := copy(tmp,2,system.length(tmp));
- if Assigned(FData) then
- aData := TFPreportData(FData.FindComponent(tmp));
- if Assigned(aData) then
- TFPReportDataBand(aBand).Data := aData;
- FMasterData := TFPReportDataBand(aBand);
- end;
- 'btMasterHeader':
- begin
- aBand := TFPReportDataHeaderBand.Create(Self);
- end;
- 'btMasterFooter':
- begin
- aBand := TFPReportDataFooterBand.Create(Self);
- end;
- 'btDetailData':
- begin
- aBand := TFPReportDataBand.Create(Self);
- tmp := GetProperty(aBandNode,'DatasetStr');
- if copy(tmp,1,1)='P' then
- tmp := copy(tmp,2,system.length(tmp));
- if Assigned(FData) and (FData.FindComponent(tmp) <> nil) then
- aData:=TFPreportData(FData.FindComponent(tmp));
- if Assigned(aData) and (ReportData.FindReportDataItem(aData)=Nil) then
- ReportData.AddReportData(aData);
- TFPReportDataBand(aBand).Data:=aData;
- TFPReportDataBand(aBand).MasterBand := FMasterData;
- FDetailBand := TFPReportDataBand(aBand);
- if Assigned(FDetailHeader) then
- begin
- FDetailHeader.Data := AData;
- FDetailHeader := nil;
- end;
- if Assigned(FDetailFooter) then
- begin
- FDetailFooter.Data:=aData;
- FDetailFooter:=nil;
- end;
- end;
- 'btDetailHeader':
- begin
- aBand:=TFPReportDataHeaderBand.Create(Self);
- if Assigned(FDetailBand) then
- TFPReportDataHeaderBand(aBand).Data := FDetailBand.Data
- else
- FDetailHeader:=TFPReportDataHeaderBand(aBand);
- end;
- 'btDetailFooter':
- begin
- aBand := TFPReportDataFooterBand.Create(Self);
- if Assigned(FDetailBand) then
- TFPReportDataFooterBand(aBand).Data := FDetailBand.Data
- else
- FDetailFooter := TFPReportDataFooterBand(aBand);
- end;
- 'btPageHeader':
- aBand := TFPReportPageHeaderBand.Create(Self);
- 'btPageFooter':
- aBand := TFPReportPageFooterBand.Create(Self);
- 'btGroupHeader':
- begin
- aBand:=TFPReportGroupHeaderBand.Create(Self);
- tmp := GetProperty(aBandNode,'Condition');
- if copy(tmp,0,1)='[' then
- tmp := copy(tmp,2,system.length(tmp)-2);//remove []
- tmp := FixDataFields(tmp);
- TFPReportGroupHeaderBand(aBand).GroupCondition:=tmp;
- end;
- 'btGroupFooter':
- aBand := TFPReportGroupFooterBand.Create(Self);
- else
- begin
- DoLog(SErrUnknownBandType,[Tmp]);
- aBand := TFPReportChildBand.Create(Self);
- end;
- end;
- if Assigned(aBand) then
- begin
- TFPReportDataBand(aBand).StretchMode:=smActualHeight;
- aBand.Parent:=aPage;
- end;
- Result:=aBand;
- end;
- Function TFPLazReport.ConvertFont(aDataNode : TDomNode) : TFPFontCacheItem;
- Var
- i : Integer;
- FontFound, aBold, aItalic : Boolean;
- aFont : TFPFontCacheItem;
- RealFont,FontName : String;
- begin
- aBold := pos('fsBold',GetProperty(aDataNode,'Style'))>0;
- aItalic := pos('fsItalic',GetProperty(aDataNode,'Style'))>0;
- FontName:=GetProperty(aDataNode,'Name');
- aFont := gTTFontCache.Find(FontName,aBold,aItalic);
- FontFound := not Assigned(aFont);
- if not Assigned(aFont) then
- aFont := gTTFontCache.Find('LiberationSans',aBold,aItalic);
- if not Assigned(aFont) then
- aFont := gTTFontCache.Find('Arial',aBold,aItalic);
- if not Assigned(aFont) then
- aFont := gTTFontCache.Find('DejaVu',aBold,aItalic);
- with gTTFontCache do
- begin
- i:=0;
- While (aFont=Nil) and (i<Count) do
- begin
- aFont := Items[i];
- if Not ((pos('sans',lowercase(aFont.FamilyName)) > 0) and (aFont.IsItalic = AItalic)
- and (aFont.IsBold = ABold)) then
- aFont:=nil;
- Inc(i);
- end;
- end;
- if Not FontFound then
- begin
- // Allow user to override
- If Assigned(FOnSubstituteFont) then
- FOnSubstituteFont(Self,FontName,aBold,aItalic,aFont);
- // Log it
- if Assigned(FOnLog) then
- begin
- if Assigned(aFont) then
- RealFont:=aFont.FamilyName
- else
- RealFont:='<nil>';
- if aBold then
- RealFont:=RealFont+'[Bold]';
- if aItalic then
- RealFont:=RealFont+'[Italic]';
- DoLog(SFontSubstitution,[FOntName,RealFont]);
- end;
- end;
- Result:=aFont;
- end;
- Function TFPLazReport.ConvertMemo(ObjNode : TDOMNode;aPage : TFPReportCustomPage) : TFPReportMemo;
- Var
- aDataNode: TDOMNode;
- aBand: TFPReportCustomBand;
- aColor,aSize,aFlag : Integer;
- aFont: TFPFontCacheItem;
- begin
- aDataNode := ObjNode.FindNode('Size');
- aBand := FindBand(aPage,PixelsToMM(StrToFloatDef(GetProperty(aDataNode,'Top'),0)));
- Result := MemoClass.Create(Self) as TFPReportMemo;
- Result.Parent:=aBand;
- aDataNode := ObjNode.FindNode('Data');
- if Assigned(FOnSetCustomProps) then
- FOnSetCustomProps(Result,aDataNode);
- aDataNode := ObjNode.FindNode('Size');
- case GetProperty(ObjNode,'Alignment') of
- 'taRightJustify': Result.TextAlignment.Horizontal:=taRightJustified;
- 'taCenter': Result.TextAlignment.Horizontal:=taCentered;
- end;
- case GetProperty(ObjNode,'Layout') of
- 'tlCenter': Result.TextAlignment.Vertical:=tlCenter;
- 'tlTop': Result.TextAlignment.Vertical:=tlTop;
- 'tlBottom': Result.TextAlignment.Vertical:=tlBottom;
- end;
- Result.StretchMode:=smActualHeight;
- aFlag := StrToIntDef(GetProperty(ObjNode,'Flags'),0);
- if aFlag and 3 = 3 then
- Result.StretchMode:=smMaxHeight;
- Result.TextAlignment.TopMargin:=1;
- aDataNode := ObjNode.FindNode('Data');
- Result.Text:=FixDataFields(GetProperty(aDataNode,'Memo'));
- Result.UseParentFont := False;
- aDataNode := ObjNode.FindNode('Font');
- if Assigned(aDataNode) then
- aFont:=ConvertFont(aDataNode);
- if Assigned(aFont) then
- Result.Font.Name:=aFont.PostScriptName
- else
- Result.UseParentFont := true;
- aSize := StrToIntDef(GetProperty(aDataNode,'Size'),Result.Font.Size);
- if aSize>5 then
- dec(aSize);
- Result.Font.Size:=aSize;
- aColor := StrToIntDef(GetProperty(aDataNode,'Color'),0);
- Result.Font.Color:= RGBToReportColor(Red(aColor),Green(aColor),Blue(aColor));
- end;
- Function TFPLazReport.ConvertLine(ObjNode : TDOMNode; APage : TFPReportCustomPage) : TFPReportShape;
- Var
- aDataNode: TDOMNode;
- aBand: TFPReportCustomBand;
- begin
- aDataNode := ObjNode.FindNode('Size');
- aBand := FindBand(aPage,PixelsToMM(StrToFloatDef(GetProperty(aDataNode,'Top'),0)));
- Result := TFPReportShape.Create(Self);
- Result.Parent:=aBand;
- Result.ShapeType:=stLine;
- Result.Orientation:=orEast;
- end;
- Function TFPLazReport.ConvertImage(ObjNode : TDOMNode; APage : TFPReportCustomPage) : TFPReportImage;
- Var
- aDataNode: TDOMNode;
- aBand: TFPReportCustomBand;
- tmp,e : String;
- SS: TStream;
- aReaderClass : TFPCustomImageReaderClass;
- B : Byte;
- I,CD : Integer;
- begin
- aDataNode := ObjNode.FindNode('Size');
- aBand := FindBand(aPage,PixelsToMM(StrToFloatDef(GetProperty(aDataNode,'Top'),0)));
- Result := TFPReportImage.Create(aBand);
- aDataNode := ObjNode.FindNode('Picture');
- aReaderClass:=nil;
- tmp:=lowercase(GetProperty(aDataNode,'Type','Ext'));
- case tmp of
- 'jpeg','jpg': aReaderClass := TFPReaderJPEG;
- 'png': aReaderClass := TFPReaderPNG;
- 'gif': aReaderClass := TFPReaderGif;
- end;
- if Not Assigned(aReaderClass) then
- begin
- DoLog(SErrUnknownImageType,[tmp]);
- exit;
- end;
- tmp:=GetProperty(aDataNode,'Data');
- if Tmp='' then
- Exit;
- ss:=TStringStream.Create('');
- try
- for i:=1 to (system.length(tmp) div 2) do
- begin
- e:=tmp[i*2-1]+tmp[i*2];
- Val('$'+E, B, cd);
- if cd<>0 then
- DoLog(SErrWrongEncoding,[i*2-1,E]);
- ss.Write(B, 1);
- end;
- ss.Position:=0;
- Result.LoadFromStream(ss,aReaderClass);
- Result.Stretched:=True;
- Finally
- ss.Free;
- end;
- end;
- function TFPLazReport.ConvertBarcode(ObjNode: TDOMNode; APage: TFPReportCustomPage): TFPReportBarcode;
- Function StringToEncoding (s : String): TBarcodeEncoding;
- begin
- Case s of
- 'bcCode39' : Result:=be39;
- 'bcCode93' : Result:=be93;
- 'bcCodeCodabar' : Result:=beCodabar;
- 'bcCode39Extended' : Result:=be39Extended;
- 'bcCode128A' : Result:=be128A;
- 'bcCode128B' : Result:=be128B;
- 'bcCode128C' : Result:=be128C;
- 'bcCodeEAN13' : Result:=beEAN13;
- 'bcCodeEAN8' : Result:=beEAN8;
- 'bcCode_2_5_interleaved' : Result:=be2of5interleaved;
- 'bcCodeMSI' : Result:=beMSI;
- else
- DoLog(SUnknownBarcodeType,[s]);
- end;
- end;
- Var
- aDataNode : TDomNode;
- cd : integer;
- D :double;
- begin
- Result:=TFPReportBarcode.Create(Self);
- aDataNode:=ObjNode.FindNode('Size');
- Result.Parent:=FindBand(APage,PixelsToMM(StrToFloatDef(GetProperty(aDataNode,'Top'),0)));
- Result.Encoding:=StringToEncoding(GetProperty(ObjNode,'BarCode','BarType'));
- if GetProperty(ObjNode,'BarCode','Angle')<>'0' then
- DoLog(SIgnoringAngleOnBarcode);
- if GetProperty(ObjNode,'BarCode','ShowText')<>'0' then
- DoLog(SIgnoringShowTextOnBarcode);
- val(GetProperty(ObjNode,'BarCode','Zoom'),D,CD);
- if CD=0 then
- Result.Weight:=D
- else
- Result.Weight:=1;
- aDataNode:=ObjNode.FindNode('Data');
- if ADataNode<>Nil then
- Result.Expression:=GetProperty(aDataNode,'Memo');
- end;
- Procedure TFPLazReport.SizeToLayout(aDataNode : TDOMNode; aObj: TFPReportElement);
- Var
- OffsetTop: TFPReportUnits;
- OffsetLeft: TFPReportUnits;
- begin
- if Assigned(aObj.Band) then
- OffsetTop := aObj.Band.Layout.Top
- else
- OffsetTop := 0;
- OffsetLeft :=0;
- if not (aObj is TFPReportCustomBand) then
- if Assigned(aObj.Page) then
- OffsetLeft := aObj.Page.Margins.Left;
- With aObj.Layout do
- begin
- Top:=PixelsToMM(StrToFloatDef(GetProperty(aDataNode,'Top'),Top))-OffsetTop;
- Left:=PixelsToMM(StrToFloatDef(GetProperty(aDataNode,'Left'),Left))-OffsetLeft;
- Width:=PixelsToMM(StrToFloatDef(GetProperty(aDataNode,'Width'),Width));
- Height:=PixelsToMM(StrToFloatDef(GetProperty(aDataNode,'Height'),Height));
- end;
- end;
- function TFPLazReport.ConvertComponentName(const aName: UnicodeString; const AClassName: String): String;
- begin
- if IsValidIdent(aName) then
- Result:=aName
- else
- begin
- Repeat
- Inc(FCounter);
- Result:=aClassName+IntToStr(FCounter);
- Until FindComponent(Result)=Nil;
- if Assigned(FOnConvertName) then
- FOnConvertName(Self,aName,Result);
- DoLog(SWarnConvertName,[aName,Result]);
- end;
- end;
- Function TFPLazReport.ApplyFrame(aDataNode : TDOMNode; aFrame: TFPReportFrame) : Boolean;
- Var
- tmp : String;
- aColor : Integer;
- begin
- Result:=False;
- aFrame.Shape:=fsNone;
- if GetProperty(aDataNode,'FrameColor')<>'' then
- begin
- aColor := StrToIntDef(GetProperty(aDataNode,'FrameColor'),0);
- aFrame.Color:= RGBToReportColor(Red(aColor),Green(aColor),Blue(aColor));
- end;
- aFrame.Width := Round(StrToIntDef(GetProperty(aDataNode,'FrameWidth'),0)/2);
- aFrame.Lines:=[];
- tmp := GetProperty(aDataNode,'FrameBorders');
- if tmp = '' then
- exit;
- if pos('frbBottom',tmp)>0 then
- aFrame.Lines := aFrame.Lines+[flBottom];
- if pos('frbTop',tmp)>0 then
- aFrame.Lines := aFrame.Lines+[flTop];
- if pos('frbLeft',tmp)>0 then
- aFrame.Lines := aFrame.Lines+[flLeft];
- if pos('frbRight',tmp)>0 then
- aFrame.Lines := aFrame.Lines+[flRight];
- Result:=aFrame.Lines<>[];
- end;
- Procedure TFPLazReport.ApplyObjectProperties(ObjNode : TDOMNode; aObj: TFPReportElement);
- Var
- HasFrame : Boolean;
- FC: String;
- M : TFPReportMemo;
- aDataNode : TDOMNode;
- aColor : Integer;
- begin
- aObj.Name:=ConvertComponentName(GetProperty(ObjNode,'Name'),aObj.ClassName);
- aDataNode := ObjNode.FindNode('Size');
- if Assigned(aDataNode) then
- SizeToLayout(aDataNode,aObj);
- HasFrame:=False;
- aDataNode := ObjNode.FindNode('Frames');
- if Assigned(aDataNode) then
- hasFrame:=ApplyFrame(aDataNode,aObj.Frame);
- if Not (aObj is TFPReportMemo) then
- exit;
- FC:=GetProperty(ObjNode,'FillColor');
- if (FC='clNone') or (FC='') then
- exit;
- M:=TFPReportMemo(aObj);
- aColor := StrToIntDef(FC,0);
- M.Frame.Pen:=psClear;
- M.Frame.BackgroundColor:= RGBToReportColor(Red(aColor),Green(aColor),Blue(aColor));
- M.Frame.Shape:=fsRectangle;
- if not HasFrame then
- begin
- M.Frame.Color:=RGBToReportColor(Red(aColor),Green(aColor),Blue(aColor));
- M.Frame.Pen:=psClear;
- end;
- end;
- procedure TFPLazReport.ConvertPageProperties(aPage: TFPReportPage; aPageNode: TDOMNode);
- Var
- aDataNode: TDOMNode;
- begin
- aPage.PageSize.PaperName:='A4';
- aPage.Font.Name:='ArialMT';
- if GetProperty(aPageNode,'Width')<>'' then
- aPage.PageSize.Width := round(PageToMM(StrToFloatDef(GetProperty(aPageNode,'Width'),aPage.PageSize.Width)));
- if GetProperty(aPageNode,'Height')<>'' then
- aPage.PageSize.Height := round(PageToMM(StrToFloatDef(GetProperty(aPageNode,'Height'),aPage.PageSize.Width)));
- if GetProperty(aPageNode,'Orientation') = 'poLandscape' then
- aPage.Orientation:=poLandscape;
- aDataNode := aPageNode.FindNode('Margins');
- if Assigned(aDataNode) then
- begin
- aPage.Margins.Top:=PixelsToMM(StrToFloatDef(GetProperty(aDataNode,'Top'),aPage.Margins.Top));
- aPage.Margins.Left:=PixelsToMM(StrToFloatDef(GetProperty(aDataNode,'left'),aPage.Margins.Left));
- aPage.Margins.Right:=PixelsToMM(StrToFloatDef(GetProperty(aDataNode,'Right'),aPage.Margins.Right));
- aPage.Margins.Bottom:=PixelsToMM(StrToFloatDef(GetProperty(aDataNode,'Bottom'),aPage.Margins.Bottom));
- end;
- end;
- Function TFPLazReport.ConvertPage(aPageNode : TDOMNode) : TFPReportPage;
- var
- aPage: TFPReportPage;
- ObjNode : TDOMNode;
- aObj: TFPReportElement;
- J : Integer;
- NodeName,CT : String;
- begin
- FMasterData := nil;
- FDetailBand := nil;
- FDetailHeader := nil;
- FDetailFooter := nil;
- aPage := TFPReportPage.Create(Self);
- Result:=aPage;
- ConvertPageProperties(aPage,aPageNode);
- for j := 0 to aPageNode.ChildNodes.Count-1 do
- begin
- ObjNode:=aPageNode.ChildNodes.Item[j];
- NodeName:=ObjNode.NodeName;
- if (copy(NodeName,0,6)='Object') and (NodeName<>'ObjectCount') then
- begin
- CT:=GetProperty(ObjNode,'ClassName');
- case CT of
- 'TfrBandView':
- aObj:=ConvertBand(ObjNode,aPage);
- 'TfrMemoView':
- aObj:=ConvertMemo(ObjNode,aPage);
- 'TfrLineView':
- aObj:=ConvertLine(ObjNode,aPage);
- 'TfrPictureView':
- aObj:=ConvertImage(ObjNode,aPage);
- 'TfrBarCodeView':
- aObj:=ConvertBarcode(ObjNode,aPage);
- else
- DoLog(SLogUnknownClass,[NodeName,CT]);
- aObj:=Nil;
- end;
- if Assigned(aObj) then
- ApplyObjectProperties(ObjNode,aObj);
- end;
- end;
- end;
- procedure TFPLazReport.LoadFromFile(const aFileName: String);
- var
- LazReport: TXMLDocument;
- begin
- ReadXMLFile(LazReport, aFileName);
- try
- LoadFromXML(LazReport);
- finally
- LazReport.Free;
- end;
- end;
- end.
|