Report construction with the help of a code
The FastReport engine usually is responsible for report’s constructing. It shows report’s bands in a particular order as many times, as the datasource to which it is connected requires, thus forming a finished report. Sometimes it is necessary to create a report of a non-standard form, which FastReport’s engine is unable to produce. In this case, one can use the ability of constructing a report manually, with the help of the TfrxReport.OnManualBuild
event. If to define a handler of this event, the FastReport engine sends management to it. At the same time, allocation of responsibilities for forming a report is changed in the following way:
FastReport engine:
report’s preparation (script, data sources initialization, bands’ tree forming)
all calculations (aggregate functions, event handlers)
new pages/columns’ forming (automatic showing a page/column header/footer, report title/summary)
other routine work
Handler:
- bands’ presentation in a certain order
The OnManualBuild handler’s essence is to issue commands concerning presenting certain bands to the FastReport’s engine. The engine itself will do the rest: a new page will be created, as soon as there is no place in the current one; execution of scripts will be performed, etc.
The engine is represented with the TfrxCustomEngine
class. A link to the instance of this class is located in the TfrxReport.Engine
property.
Property or method | Description |
---|---|
procedure NewColumn | Creates a new column. If a column is the last one, it creates a new page. |
procedure NewPage | Creates a new page. |
procedure ShowBand(Band: TfrxBand) | Shows a band. |
procedure ShowBand(Band: TfrxBandClass) | Shows a band of the given type. |
function FreeSpace: Extended | Returns the amount of free space on the page (in pixels). After the next band is presented, this value descends. |
property CurColumn: Integer | Returns/sets the current column’s number |
property CurX: Extended | Returns/sets the current X position. |
property CurY: Extended | Returns/sets the current Y position. After the next band is presented, this value ascends. |
property DoublePass: Boolean | Defines whether a report is a two-pass one. |
property FinalPass: Boolean | Defines whether the current pass is the last one. |
property FooterHeight: Extended | Returns the page footer height. |
property HeaderHeight: Extended | Returns the page header height. |
property PageHeight: Extended | Returns the height of the page’s printable region. |
property PageWidth: Extended | Returns the width of the page’s printable region. |
property TotalPages: Integer | Returns the number of pages in a finished report (only on the second pass of the two-pass report). |
Let us give an example of a simple handler. There is two «Master Data» bands in a report, which are not connected to data. The handler presents these bands in an interlaced order, six times each one. After six bands, a small gap is made.
Pascal:
var
i: Integer;
Band1, Band2: TfrxMasterData;
{ find required bands }
Band1 := frxReport1.FindObject('MasterData1') as TfrxMasterData;
Band2 := frxReport1.FindObject('MasterData2') as TfrxMasterData;
for i := 1 to 6 do
begin
{ lead/deduce bands one after another }
frxReport1.Engine.ShowBand(Band1);
frxReport1.Engine.ShowBand(Band2);
{ make a small gap }
if i = 3 then
frxReport1.Engine.CurY := frxReport1.Engine.CurY + 10;
end;
C++:
int i;
TfrxMasterData * Band1;
TfrxMasterData * Band2;
// find required bands
Band1 := dynamic_cast <TfrxMasterData *> (frxReport1->FindObject("MasterData1"));
Band2 := dynamic_cast <TfrxMasterData *> (frxReport1->FindObject("MasterData2"));
for(i = 1; i <= 6; i++)
{
// lead/deduce bands one after another
frxReport1->Engine->ShowBand(Band1);
frxReport1->Engine->ShowBand(Band2);
// make a small gap
if(i == 3)
frxReport1->Engine->CurY += 10;
}
The next example shows two groups of bands alongside each other.
Pascal:
var
i, j: Integer;
Band1, Band2: TfrxMasterData;
SaveY: Extended;
Band1 := frxReport1.FindObject('MasterData1') as TfrxMasterData;
Band2 := frxReport1.FindObject('MasterData2') as TfrxMasterData;
SaveY := frxReport1.Engine.CurY;
for j := 1 to 2 do
begin
for i := 1 to 6 do
begin
frxReport1.Engine.ShowBand(Band1);
frxReport1.Engine.ShowBand(Band2);
if i = 3 then
frxReport1.Engine.CurY := frxReport1.Engine.CurY + 10;
end;
frxReport1.Engine.CurY := SaveY;
frxReport1.Engine.CurX := frxReport1.Engine.CurX + 200;
end;
C++:
int i, j;
TfrxMasterData * Band1;
TfrxMasterData * Band2;
Extended SaveY;
Band1 = dynamic_cast <TfrxMasterData *> (frxReport1->FindObject("MasterData1"));
Band2 = dynamic_cast <TfrxMasterData *> (frxReport1->FindObject("MasterData2"));
SaveY = frxReport1->Engine->CurY;
for(j = 1; j <= 2; j++)
{
for(i = 1; i <= 6; i++)
{
frxReport1->Engine->ShowBand(Band1);
frxReport1->Engine->ShowBand(Band2);
if(i == 3)
frxReport1->Engine->CurY += 10;
}
frxReport1->Engine->CurY = SaveY;
frxReport1->Engine->CurX += 200;
}