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 :
just drop 1 stringgrid, 1 button, 1 frxreport, 1 frxuserdataset in form.
set frxuserdataset events, form oncreate , buttom onclick below code.
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
Post a Comment