2012-03-10 7 views
6

के साथ प्रदर्शन मैं फास्ट रिपोर्ट का उपयोग करता हूं और मुझे 1000 से अधिक पंक्तियों के साथ ग्रिड का पूर्वावलोकन/प्रिंट करने की आवश्यकता है और मेरे पास कुछ प्रदर्शन समस्याएं हैं। आमतौर पर मैं अपने ग्रिड को तैयार करने के लिए TfrxCrossObject का उपयोग करता हूं क्योंकि अंतिम उपयोगकर्ता ग्रिड प्रस्तुति (कॉलम, कॉलम का नाम, आकार) का उपयोग कर सकता है, इसलिए मुझे गतिशील प्रिंट होना चाहिए। मैंने एक साधारण ग्रिड (16 कोल्स x2000 पंक्तियों) का परीक्षण किया और इसे पहले पूर्वावलोकन पृष्ठ को प्रस्तुत करने के लिए 10 सेकंड से अधिक की आवश्यकता है। प्रदर्शन में सुधार करने के लिए कोई विचार?FastReport TFrxCrossObject और बड़े ग्रिड (> 1000 पंक्तियां)

संपादित करें: के रूप में कुछ जवाब में कहा, समस्या यह है: 'dynamicaly' TFrxCrossObject का उपयोग किए बिना एक ग्रिड FastReport में (एक ही कॉलम नाम और आकार मैं स्क्रीन पर है के साथ) जो नहीं हो रहा है बनाने के लिए कैसे बहुत प्रभावशाली मैं डेटासेट का उपयोग करने या TfrxCrossObject को बढ़ाने जैसे सभी समाधान स्वीकार कर सकता हूं।

परीक्षण कोड:

unit Unit1; 

interface 

uses 
    Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, 
    frxClass, StdCtrls, Grids, frxCross; 

type 
    TForm1 = class(TForm) 
    Button1: TButton; 
    StringGrid1: TStringGrid; 
    frxCrossObject1: TfrxCrossObject; 
    frxReport1: TfrxReport; 
    procedure Button1Click(Sender: TObject); 
    procedure FormCreate(Sender: TObject); 
    procedure frxReport1BeforePrint(c: TfrxReportComponent); 
    end; 

var 
    Form1: TForm1; 

implementation 
{$R *.DFM} 

procedure TForm1.FormCreate(Sender: TObject); 
var 
    i, j: Integer; 
begin 
    for i := 1 to 16 do 
    for j := 1 to 2000 do 
     StringGrid1.Cells[i - 1, j - 1] := IntToStr(i * j); 
end; 

procedure TForm1.Button1Click(Sender: TObject); 
begin 
    frxReport1.ShowReport; 
end; 

procedure TForm1.frxReport1BeforePrint(c: TfrxReportComponent); 
var 
    Cross: TfrxCrossView; 
    i, j: Integer; 
begin 
    if c is TfrxCrossView then 
    begin 
    Cross := TfrxCrossView(c); 
    for i := 1 to 16 do 
     for j := 1 to 2000 do 
     Cross.AddValue([i], [j], [StringGrid1.Cells[i - 1, j - 1]]); 
    end; 
end; 
end. 
+1

मैं इस प्रश्न को फास्ट रीपॉर्ट्स मंचों पर पोस्ट करने की अनुशंसा करता हूं। यदि आप AQTime का उपयोग कर रहे हैं, तो आप इसका उपयोग अपने आवेदन को प्रोफाइल करने के लिए कर सकते हैं और कम से कम देख सकते हैं कि उस समय का अधिकांश समय क्या चल रहा है। एल्टाइम डेल्फी एक्सई और एक्सई 2 के कुछ संस्करणों में शामिल है ताकि आपके पास पहले से ही हो। –

+3

'क्रॉसव्यू' के बजाय क्लाइंटडेटासेट का उपयोग करने का प्रयास करें। – teran

+1

कोड प्रदर्शन का परीक्षण करने का सबसे आसान तरीका कोड के कुछ हिस्सों के पहले और बाद में 'GetTickCount' का उपयोग करना और मूल्यों की तुलना करना है। लेकिन सबसे पहले, स्ट्रिंगग्रिड भरते समय 'BeginUpdate' /' EndUpdate' का उपयोग करने का प्रयास करें। – LightBulb

उत्तर

4

क्रॉसटैब कई भूमि के ऊपर है। यहाँ एक UserDataSet संस्करण है:

  1. बस 1 stringgrid, 1 बटन, 1 frxReport, 1 frxUserDataSet ड्रॉप के रूप में।

  2. नीचे दिए गए कोड के रूप में frxUserDataSet ईवेंट, फॉर्म ऑनक्रेट और बटम ऑनक्लिक सेट करें।

  3. कोई भी डिज़ाइन रिपोर्ट करने या सेट करने की आवश्यकता नहीं है, सभी रन-टाइम पर सेट या जेनरेट किए जाएंगे।

ऐसा लगता है यह पार टैब संस्करण की तुलना में तेजी है, लेकिन आप अधिक कोडिंग और CrossObject की खो कार्यक्षमता की जरूरत है।

संपादित करें: कुछ टिप्पणियां जोड़ें और पेपरविड्थ गलत गणना को ठीक करें।

संपादित 2: एक प्रिंट-अनुकूल संस्करण जोड़ें जो पृष्ठों को डेटा में विभाजित करता है।

stringgrid के रूप में 1 ही पृष्ठ में

देखें अनुकूल संस्करण शो:

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. 
+0

मेरे नोटबुक कंप्यूटर (i5 2.4GHz, 4GRam) में, मूल संस्करण 2.5 सेकंड पर पहला पृष्ठ दिखाता है और तैयार (सभी पृष्ठ लोड) 9 सेकंड पर। मेरा प्रदर्शन संस्करण (1 बड़ा पृष्ठ) 2.5 सेकंड पर तैयार है। मेरा प्रिंट संस्करण 1.5 सेकंड पर तत्काल और तैयार (112 पेज) पहले पृष्ठ दिखाता है। 2000 कर्नल एक्स 200 पंक्ति पहले पृष्ठ को तत्काल और तैयार (448 पेज) 10.5 सेकेंड पर दिखाएं। 2000 कर्नल एक्स 2000 पंक्ति 104 सेकंड पर तत्काल और तैयार (4144 पृष्ठ) पहला पृष्ठ दिखाएं। – Justmade

+0

एक सही तरीका लगता है। मैं आज इसका परीक्षण करूंगा। – philnext

+0

@philnext यदि आप डीबीजीड/डेटासेट का उपयोग कर रहे हैं, तो वाई फील्ड इंडेक्स और इंक (एक्स) में डेटासेट में बदल सकते हैं। अगला और आपको कॉलम ब्रेक के लिए बुकमार्क की आवश्यकता हो सकती है। तो Getvalue घटना में आप DataSet.Fields [वाई] प्रदान कर सकते हैं। Value। – Justmade

2

आपका कोड का टुकड़ा फास्ट रिपोर्ट के PrintStringGrid डेमो से थोड़ा संशोधित है (16 के बजाय RowCount = 2000)।

एक कंटेनर के रूप में TStringGrid का उपयोग करना एक अच्छा विचार नहीं है यदि आपको बड़े डेटा से निपटना है: इसे केवल प्रस्तुति चिंता के लिए उपयोग किया जाना चाहिए।

एक इन-मेमोरी डेटासेट का उपयोग करें (उदा। प्रश्न डेटा थ्रेड में सुझाए गए टेरन के रूप में क्लाइंटडेटसेट), यदि आप इसका उपयोग करते हुए अपने बड़े डेटा को टीस्ट्रिंगग्रिड में अभी भी अनिवार्य कर सकते हैं लेकिन टीडीबीजीड अधिक उपयुक्त है।

एक बड़े TDataset को इटरेट करना केवल TStringGrid के साथ ऐसा करने से तेज़ है।

FastReport की PrintTable डेमो एक प्रारंभिक बिंदु के रूप में काम कर सकता है, जानते हुए भी कि यह PrintStringGrid डेमो के रूप में एक ही घटकों का उपयोग करता अनुकूल एक व्यायाम के रूप में यह आप के लिए छोड़ दिया जाता है:

  • एक TfrxReport और
  • एक TfrxCrossObject जहां पुनरावृत्ति होती है।
+1

क्या मैं पूछ सकता हूं कि क्लाइंटडेटसेट (ग्रिड) में डेटा के साथ वर्तमान में 100 पंक्ति * 100 कॉल है और उपयोगकर्ता क्लाइंटडेटसेट में कॉलम जोड़ने के लिए 1 और कॉलम जोड़ना चाहते हैं? साथ ही, उस कॉलम को रिपोर्ट में कैसे जोड़ना है? यदि DBCrossTab का उपयोग करते हैं, तो मुझे यकीन है कि क्रॉसटाब की गणना और सॉर्टिंग ओवरहेड की वजह से कोई प्रदर्शन सुधार नहीं होगा। – Justmade

+0

हां आईआरएल, मैं टीडीबी ग्रिड का उपयोग करता हूं लेकिन मेरी समस्या को समझाने के लिए टीस्ट्रिंगग्रिड आसान था और जवाब देने वालों के लिए इसका परीक्षण करना आसान था। मुझे एक ही पेफ है। टीडीबीजीड के साथ समस्याएं – philnext

संबंधित मुद्दे