delphi - Performances with FastReport TFrxCrossObject and large Grids (> 1000 rows) -


i use fastreport , need preview/print grids more 1000 rows , have performances problems. typically use tfrxcrossobject prepare grid because end user may change grid presentation (used columns, column's name, size) need have dynamical print. tested simple grid (16 cols x2000 rows) , needs more 10 seconds present first preview page. idea improve performances ?

edit : said in answers, problem : how create 'dynamicaly' grid (with same columns names , sizes have on screen) in fastreport without using tfrxcrossobject seems not efficent. may admit solutions using dataset or enhancing tfrxcrossobject.

the test code :

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   := 1 16     j := 1 2000       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 tfrxcrossview   begin     cross := tfrxcrossview(c);     := 1 16       j := 1 2000         cross.addvalue([i], [j], [stringgrid1.cells[i - 1, j - 1]]);   end; end; end. 

the crosstab have many overhead. here userdataset version :

  1. just drop 1 stringgrid, 1 button, 1 frxreport, 1 frxuserdataset in form.

  2. set frxuserdataset events, form oncreate , buttom onclick below code.

  3. no need design report or set properties, set or generated @ run-time.

it seems faster cross-tab version need more coding , lost functionality of crossobject.

edit : add comments , fix paperwidth mis-calculation.

edit2 : add print-friendly version split data pages.

view friendly version show in 1 single page 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 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. conversion of mm fr component measurement   tcol := 2000; // total column   trow := 16; // total row    := 1 trow     j := 1 tcol       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   begin     if x = trow - 1       iseof := true;     inc(x);     y := 0;   end   else     inc(y); end;  end. 

print-friendly version bit more complex , separate data in different pages printing :

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 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. conversion of mm fr component measurement   tcol := 2000; // total column   trow := 16; // total row    := 1 trow     j := 1 tcol       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   begin     if y = tcol - 1       iseof := true     else     begin       frxreport1.engine.newcolumn;       inc(y);       x := colbreak - rpp;     end;   end   else if (x = colbreak - 1)   begin     if y = tcol - 1     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. 

Comments

Popular posts from this blog

delphi - How to convert bitmaps to video? -

jasper reports - Fixed header in Excel using JasperReports -

python - ('The SQL contains 0 parameter markers, but 50 parameters were supplied', 'HY000') or TypeError: 'tuple' object is not callable -