크로스 탭은 많은 오버 헤드를 가지고있다. 여기 UserDataSet 버전은 다음과 같습니다
이
단지 형태로 1 stringgrid, 1 개 버튼 1 frxReport, 1 frxUserDataSet 놓습니다.
아래 코드와 같이 frxUserDataSet 이벤트, Form OnCreate 및 Buttom OnClick을 설정하십시오.
보고서를 디자인하거나 속성을 설정할 필요가 없습니다. 모두 런타임에 설정되거나 생성됩니다.
크로스 탭 버전보다 빠르지 만 CrossObject의 코딩 및 손실 된 기능이 더 필요합니다.
편집 : 일부 의견을 추가하고 PaperWidth 잘못 계산을 수정하십시오.
편집 2 : 페이지로 데이터를 분할하는 인쇄용 버전을 추가하십시오.
stringgrid로 한 하나의 페이지에서
보기 친절한 버전 쇼 :
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, frxClass, Grids, StdCtrls;
type
TForm1 = class(TForm)
Button1: TButton;
StringGrid1: TStringGrid;
frxReport1: TfrxReport;
frxUserDataSet1: TfrxUserDataSet;
procedure Button1Click(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure frxUserDataSet1Next(Sender: TObject);
procedure frxUserDataSet1GetValue(const VarName: string; var Value: Variant);
procedure frxUserDataSet1CheckEOF(Sender: TObject; var Eof: Boolean);
procedure frxUserDataSet1First(Sender: TObject);
private
X, Y, TCol, TRow : Integer;
IsEof : Boolean;
CW, CH, PF : Double;
Page : TfrxReportPage;
MDB : TfrxMasterData;
Memo : TfrxMemoView;
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.Button1Click(Sender: TObject);
var
BW : Double;
begin
IsEof := False;
Page.PaperWidth := CW * TCol + 20; // EndlessWidth seems not work with band column
MDB.SetBounds(0,0, CW * PF * TCol, CH * PF);
MDB.Columns := TCol;
MDB.ColumnWidth := CW * PF;
frxReport1.ShowReport;
end;
procedure TForm1.FormCreate(Sender: TObject);
var
i, j : Integer;
begin
CW := 12; // Cell Width in mm
CH := 5; // Cell Height in mm
PF := 3.7794; // Pixie Factor i.e. the conversion of mm to FR component measurement
TCol := 2000; // Total Column
TRow := 16; // Total Row
for i := 1 to TRow do
for j := 1 to TCol do
StringGrid1.Cells[i - 1, j - 1] := IntToStr(i * j);
frxUserDataSet1.Fields.Text := 'Data';
frxReport1.Clear;
frxReport1.DataSets.Add(frxUserDataSet1);
Page := TfrxReportPage.Create(frxReport1);
Page.CreateUniqueName;
Page.TopMargin := 10;
Page.BottomMargin := 10;
Page.LeftMargin := 10;
Page.RightMargin := 10;
Page.EndlessHeight := True;
Page.EndlessWidth := True;
MDB := TfrxMasterData.Create(Page);
MDB.DataSet := frxUserDataSet1;
Memo := TfrxMemoView.Create(MDB);
Memo.SetBounds(0,0,CW * PF,CH * PF);
Memo.Memo.Text := '[frxUserDataSet1."Data"]';
Memo.Frame.Typ := [ftLeft, ftRight, ftTop, ftBottom];
end;
procedure TForm1.frxUserDataSet1CheckEOF(Sender: TObject; var Eof: Boolean);
begin
Eof := IsEof;
end;
procedure TForm1.frxUserDataSet1First(Sender: TObject);
begin
X := 0;
Y := 0;
end;
procedure TForm1.frxUserDataSet1GetValue(const VarName: string; var Value: Variant);
begin
Value := StringGrid1.Cells[X,Y];
end;
procedure TForm1.frxUserDataSet1Next(Sender: TObject);
begin
If Y = TCol - 1 then
begin
if X = TRow - 1 then
IsEof := True;
Inc(X);
Y := 0;
end
else
Inc(Y);
end;
end.
인쇄용 버전 조금 더 복잡한 인쇄 및 다른 페이지에 별도의 데이터입니다 :
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, frxClass, Grids, StdCtrls;
type
TForm1 = class(TForm)
Button1: TButton;
StringGrid1: TStringGrid;
frxReport1: TfrxReport;
frxUserDataSet1: TfrxUserDataSet;
procedure Button1Click(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure frxUserDataSet1Next(Sender: TObject);
procedure frxUserDataSet1GetValue(const VarName: string; var Value: Variant);
procedure frxUserDataSet1CheckEOF(Sender: TObject; var Eof: Boolean);
procedure frxUserDataSet1First(Sender: TObject);
private
X, Y, TCol, TRow, RPP, ColBreak : Integer;
IsEof : Boolean;
CW, CH, PF : Double;
Page : TfrxReportPage;
MDB : TfrxMasterData;
Memo : TfrxMemoView;
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
uses Math;
{$R *.dfm}
procedure TForm1.Button1Click(Sender: TObject);
var
BW : Double;
begin
IsEof := False;
RPP := Ceil((Page.PaperHeight - Page.TopMargin - Page.BottomMargin)/CH) - 1; // Row per page
ColBreak := RPP; // break to next column
frxReport1.ShowReport;
end;
procedure TForm1.FormCreate(Sender: TObject);
var
i, j : Integer;
begin
CW := 12; // Cell Width in mm
CH := 5; // Cell Height in mm
PF := 3.7794; // Pixil Factor i.e. the conversion of mm to FR component measurement
TCol := 2000; // Total Column
TRow := 16; // Total Row
for i := 1 to TRow do
for j := 1 to TCol do
StringGrid1.Cells[i - 1, j - 1] := IntToStr(i * j);
frxUserDataSet1.Fields.Text := 'Data';
frxReport1.Clear;
frxReport1.DataSets.Add(frxUserDataSet1);
Page := TfrxReportPage.Create(frxReport1);
Page.CreateUniqueName;
Page.TopMargin := 10;
Page.BottomMargin := 10;
Page.LeftMargin := 10;
Page.RightMargin := 10;
Page.Columns := Ceil(Page.PaperWidth/CW);
MDB := TfrxMasterData.Create(Page);
MDB.DataSet := frxUserDataSet1;
MDB.SetBounds(0,0, CW * PF, CH * PF);
Memo := TfrxMemoView.Create(MDB);
Memo.Align := baClient;
Memo.Memo.Text := '[frxUserDataSet1."Data"]';
Memo.Frame.Typ := [ftLeft, ftRight, ftTop, ftBottom];
end;
procedure TForm1.frxUserDataSet1CheckEOF(Sender: TObject; var Eof: Boolean);
begin
Eof := IsEof;
end;
procedure TForm1.frxUserDataSet1First(Sender: TObject);
begin
X := 0;
Y := 0;
end;
procedure TForm1.frxUserDataSet1GetValue(const VarName: string; var Value: Variant);
begin
Value := StringGrid1.Cells[X,Y];
end;
procedure TForm1.frxUserDataSet1Next(Sender: TObject);
begin
If X = TRow - 1 then
begin
if Y = TCol - 1 then
IsEof := True
else
begin
frxReport1.Engine.NewColumn;
Inc(Y);
X := ColBreak - RPP;
end;
end
else if (X = ColBreak - 1) then
begin
if Y = TCol - 1 then
begin
frxReport1.Engine.NewPage;
ColBreak := ColBreak + RPP;
Y := 0;
end
else
Inc(Y);
frxReport1.Engine.NewColumn;
X := ColBreak - RPP;
end
else
Inc(X);
end;
end.
이 질문은 FastReports 포럼에 게시하는 것이 좋습니다. AQTime을 사용하는 경우 응용 프로그램을 프로파일 링하고 적어도 대부분의 시간을 볼 수 있습니다. AQtime은 Delphi XE 및 XE2의 일부 에디션에 포함되어 있으므로 이미 가지고있을 수 있습니다. –
'crossview' 대신 ClientDataSet을 사용하십시오. – teran
코드 성능을 테스트하는 가장 간단한 방법은 코드의 일부와 전후에'GetTickCount'를 사용하여 값을 비교하는 것입니다. 하지만 먼저 StringGrid를 채울 때'BeginUpdate' /'EndUpdate'를 사용하십시오. – LightBulb