{ RxDBGridPrintGrid unit Copyright (C) 2005-2017 Lagunov Aleksey alexs@yandex.ru 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 RxDBGridPrintGrid; {$I rx.inc} interface uses Classes, SysUtils, DB, rxdbgrid, LR_Class, LR_DSet, LR_DBSet, contnrs, Graphics, Printers, rxlclutils; type TRxDBGridPrintOption = (rxpoShowTitle, rxpoShowFooter, rxpoShowGridColor, rxpoShowFooterColor, rxpoShowReportTitle, rxpoHideZeroValues, rxpoColSpanning ); TRxDBGridPrintOptions = set of TRxDBGridPrintOption; { TRxColInfo } TRxColInfo = class Col:TRxColumn; ColWidth:integer; ColTitles:TStringList; constructor Create; destructor Destroy; override; end; { TRxDBGridPrint } TRxDBGridPrint = class(TRxDBGridAbstractTools) private FModifyPrepared: boolean; FOptions: TRxDBGridPrintOptions; FOrientation: TPrinterOrientation; FPageMargin: TRxPageMargin; FReport : TfrReport; FReportDataSet : TfrDBDataSet; FColumnDataSet : TfrUserDataSet; FDataSet : TDataset; FPage : TfrPage; FReportTitle: string; FShowColumnHeaderOnAllPage: boolean; FShowProgress : Boolean; FTitleRowCount : integer; FRxColInfoList : TObjectList; FYPos: Integer; FXPos: Integer; procedure DoCreateReport; procedure DoShowReportTitle; procedure DoSetupColumns; procedure DoShowColumnsTitle; procedure DoShowFooter; procedure OnPrintColumn(ColNo: Integer; var Width: Integer); procedure OnEnterRect(Memo: TStringList; View: TfrView); procedure SetPageMargin(AValue: TRxPageMargin); protected function DoExecTools:boolean;override; function DoSetupTools:boolean; override; public constructor Create(AOwner: TComponent); override; destructor Destroy; override; procedure PreviewReport; published property Orientation: TPrinterOrientation read FOrientation write FOrientation default poPortrait; property Options:TRxDBGridPrintOptions read FOptions write FOptions; property ShowProgress : Boolean read FShowProgress write FShowProgress default false; property PageMargin:TRxPageMargin read FPageMargin write SetPageMargin; property ReportTitle:string read FReportTitle write FReportTitle; property ShowColumnHeaderOnAllPage:boolean read FShowColumnHeaderOnAllPage write FShowColumnHeaderOnAllPage default false; property ModifyPrepared:boolean read FModifyPrepared write FModifyPrepared default false; end; procedure Register; implementation uses math, RxDBGridPrintGrid_SetupUnit, Forms, Controls, rxdconst, LCLIntf; {$R rxdbgridprintgrid.res} procedure Register; begin RegisterComponents('RX DBAware',[TRxDBGridPrint]); end; { TRxColInfo } Type THackRxDBGrid = class(TRxDBGrid); constructor TRxColInfo.Create; begin inherited Create; ColTitles:=TStringList.Create; end; destructor TRxColInfo.Destroy; begin ColTitles.Clear; FreeAndNil(ColTitles); inherited Destroy; end; { TRxDBGridPrint } procedure TRxDBGridPrint.DoShowReportTitle; var FBand: TfrBandView; FView: TfrMemoView; begin FBand := TfrBandView(frCreateObject(gtBand, '', FPage)); FBand.SetBounds(10, FYPos, 1000, 25); FBand.BandType := btReportTitle; // FPage.Objects.Add(FBand); FView := frCreateObject(gtMemo, '', FPage) as TfrMemoView; FView.SetBounds(FXPos, FYPos, FPage.PrnInfo.PgW - 40, 25); FView.Alignment:=taCenter; FView.Font.Size:=12; // FView.Font.Assign(FTitleFont); FView.Memo.Add(FReportTitle); // FPage.Objects.Add(FView); Inc(FYPos, 27) end; procedure TRxDBGridPrint.DoCreateReport; var FBand: TfrBandView; FView: TfrMemoView; begin if FReport.Pages.Count=0 then FReport.Pages.add; FPage := FReport.Pages[FReport.Pages.Count-1]; FPage.ChangePaper(FPage.pgSize, FPage.Width, FPage.Height, FOrientation); FPage.Margins.Top:=FPageMargin.Top; FPage.Margins.Left:=FPageMargin.Left; FPage.Margins.Bottom:=FPageMargin.Bottom; FPage.Margins.Right:=FPageMargin.Right; FYPos:=FPageMargin.Top; FXPos:=FPageMargin.Left; if rxpoShowReportTitle in FOptions then DoShowReportTitle; if rxpoShowTitle in FOptions then DoShowColumnsTitle; FBand := TfrBandView(frCreateObject(gtBand, '', FPage)); FBand.BandType := btMasterData; FBand.Dataset := FReportDataSet.Name; FBand.SetBounds(0, FYPos, 1000, 18); FBand.Flags:=FBand.Flags or flStretched; // FPage.Objects.Add(FBand); FBand := TfrBandView(frCreateObject(gtBand, '', FPage)); FBand.BandType := btCrossData; FBand.Dataset := FColumnDataSet.Name; FBand.SetBounds(FXPos, 0, 20, 1000); // FPage.Objects.Add(FBand); FView := frCreateObject(gtMemo, '', FPage) as TfrMemoView; FView.SetBounds(FXPos, FYPos, 20, 18); FView.Memo.Add('[Cell]'); FView.Flags:=FView.Flags or flStretched; FView.Font.Size:=10; // FView.Font.Assign(FFont); FView.Frames:=frAllFrames; FView.Layout:=tlTop; // FPage.Objects.Add(FView); FYPos := FYPos + 22; if (RxDBGrid.FooterOptions.Active) and (RxDBGrid.FooterOptions.RowCount>0) then DoShowFooter; end; procedure TRxDBGridPrint.DoSetupColumns; var P:TRxColInfo; i: Integer; j: Integer; begin FTitleRowCount:=1; FRxColInfoList.Clear; for i:=0 to RxDBGrid.Columns.Count-1 do begin if RxDBGrid.Columns[i].Visible then begin P:=TRxColInfo.Create; FRxColInfoList.Add(P); P.Col:=RxDBGrid.Columns[i] as TRxColumn; P.ColWidth:=RxDBGrid.Columns[i].Width; for j:=0 to TRxColumnTitle(RxDBGrid.Columns[i].Title).CaptionLinesCount-1 do P.ColTitles.Add(TRxColumnTitle(RxDBGrid.Columns[i].Title).CaptionLine(j).Caption); FTitleRowCount:=Max(FTitleRowCount, P.ColTitles.Count) end; end; end; procedure TRxDBGridPrint.DoShowColumnsTitle; var FBand: TfrBandView; FView: TfrMemoView; i: Integer; begin FBand := TfrBandView(frCreateObject(gtBand, '', FPage)); FBand.BandType := btMasterHeader; FBand.SetBounds(0, FYPos, 1000, 20 * FTitleRowCount); FBand.Flags:=FBand.Flags or flStretched; // FPage.Objects.Add(FBand); if FShowColumnHeaderOnAllPage then FBand.Flags:=FBand.Flags + flBandRepeatHeader; for i:=0 to FTitleRowCount-1 do begin FView := frCreateObject(gtMemo, '', FPage) as TfrMemoView; FView.SetBounds(FXPos, FYPos, 20, 20); FView.Alignment:=taCenter; FView.FillColor := clSilver; // FView.Font.Assign(FTitleFont); FView.Font.Size:=12; FView.Frames:=frAllFrames; FView.Layout:=tlTop; FView.Memo.Add(Format('Header_%d', [i])); // FPage.Objects.Add(FView); FYPos:=FYPos + 20 end; FYPos := FYPos + 2; end; procedure TRxDBGridPrint.DoShowFooter; var FBand: TfrBandView; FView: TfrMemoView; begin FBand := TfrBandView(frCreateObject(gtBand, '', FPage)); FBand.BandType := btMasterFooter; FBand.SetBounds(FXPos, FYPos, 1000, 20); FBand.Flags:=FBand.Flags or flStretched; FView := frCreateObject(gtMemo, '', FPage) as TfrMemoView; FView.SetBounds(FXPos, FYPos, 20, 20); if rxpoShowFooterColor in FOptions then FView.FillColor := RxDBGrid.FooterOptions.Color; FView.Font.Size:=12; FView.Frames:=frAllFrames; FView.Layout:=tlTop; FView.Memo.Add('Footer'); FYPos := FYPos + 22; end; procedure TRxDBGridPrint.OnPrintColumn(ColNo: Integer; var Width: Integer); begin if (ColNo > 0) and (ColNo <= FRxColInfoList.Count) then Width := TRxColInfo(FRxColInfoList[ColNo-1]).ColWidth; end; procedure TRxDBGridPrint.OnEnterRect(Memo: TStringList; View: TfrView); var i, k: Integer; F:TRxColInfo; FDataField:TField; FDataCollumn:TRxColumn; S: String; C:TColor; J, L, R: Integer; begin i := FColumnDataset.RecNo; View.Visible:=true; FDataField:=nil; FDataCollumn:=nil; if (i >= 0) and (i < FRxColInfoList.Count) then begin F:=TRxColInfo(FRxColInfoList[i]); if Assigned(F) then FDataCollumn:=F.Col; if Assigned(FDataCollumn) then FDataField:=FDataCollumn.Field; View.dx := F.ColWidth; if Assigned(F.Col) and (Memo.Count>0) then begin S:=Memo[0]; if (S='[Cell]') and Assigned(F.Col.Field) then begin if (rdgColSpanning in RxDBGrid.OptionsRx) and (rxpoColSpanning in Options) then begin if RxDBGrid.IsMerged(I + 1, L, R, FDataCollumn) then begin if I + 1 = L then begin if Assigned(FDataCollumn) then FDataField:=FDataCollumn.Field else begin if Assigned(F) then FDataCollumn:=F.Col; if Assigned(FDataCollumn) then FDataField:=FDataCollumn.Field; end; for j:=L + 1 to R do if FRxColInfoList.Count > j - 1 then View.dx := View.dx + TRxColInfo(FRxColInfoList[j - 1]).ColWidth; end else begin View.Visible:=false; Memo[0] := ''; exit; end; end else begin if Assigned(F) then FDataCollumn:=F.Col; if Assigned(FDataCollumn) then FDataField:=FDataCollumn.Field; end end; if not Assigned(FDataCollumn) then begin C:=0; end; if rxpoShowGridColor in FOptions then begin C:=FDataCollumn.Color; if Assigned(RxDBGrid.OnGetCellProps) then RxDBGrid.OnGetCellProps(RxDBGrid, FDataField, TfrMemoView(View).Font, C); if C = clWindow then C := clNone; TfrMemoView(View).FillColor:=C; end; { S:= FDataField.DisplayText; //F.Col.Field.DisplayText; if Assigned(FDataCollumn) and (FDataCollumn.KeyList.Count > 0) and (FDataCollumn.PickList.Count > 0) then begin J := FDataCollumn.KeyList.IndexOf(S); if (J >= 0) and (J < FDataCollumn.PickList.Count) then S := FDataCollumn.PickList[j]; end else} if (rxpoHideZeroValues in FOptions) and Assigned(FDataField) and (FDataField.DataType in [ftSmallint, ftInteger, ftWord, ftFloat, ftCurrency, ftLargeint]) and (FDataField.AsFloat = 0) then S:='' else S:=THackRxDBGrid(RxDBGrid).GetFieldDisplayText(FDataField, FDataCollumn); Memo[0] := S; TfrMemoView(View).Alignment:=FDataCollumn.Alignment; end else if Copy(S, 1, 7) = 'Header_' then begin TfrMemoView(View).Alignment:=F.Col.Title.Alignment; K:=StrToIntDef(Copy(S, 8, Length(S)), 0); if TRxColumnTitle(F.Col.Title).CaptionLinesCount = 0 then begin S:=TRxColumnTitle(F.Col.Title).Caption; if K = 0 then Memo[0] := TRxColumnTitle(F.Col.Title).Caption else Memo[0] := ''; end else if K