FastReport Master/Detail in Delphi XE2

1.4k views Asked by At

I need some help creating a Master/Detail report in Fast Reports for Delphi XE2.

I have a simple form which accepts 2 dates and 2 times from a user. I then have 2 Oracle Datasets on the form with which to retrieve my data. When the user presses the print button, the program accepts the values from the user and sends the values to the first oracle dataset, which then in turn retrieves the first value, and then sends this value along with the user accepted values to the second dataset to print the detail pertaining to the value retrieved.

For each dataset I do have a corresponding frxDBDataset component which is then assigned to the frxReport1 component. With in the report, I have created a Master Band which is assigned to dataset1, and a Detail Band assigned to datset2. When I run my report, dataset 1 brings back all the records, but dataset 2 only brings back the records for the first value and duplicates it for every record in dataset1.

Below is the code I am trying to execute:

opr_operator_ods.Close;
opr_operator_ods.SetVariable('DATEFROM', opr_datefrom_dtp.Date);
opr_operator_ods.SetVariable('DATETO', opr_dateto_dtp.Date);
opr_operator_ods.SetVariable('TIMEFROM', opr_timefrom_dtp.Text);
opr_operator_ods.SetVariable('TIMETO', opr_timeto_dtp.Text);
opr_operator_ods.Open;

if opr_operator_ods.RecordCount > 0 then
begin
while not opr_operator_ods.Eof do
begin
opr_operatorcount_ods.Close;
opr_operatorcount_ods.SetVariable('DATEFROM', opr_datefrom_dtp.Date);
opr_operatorcount_ods.SetVariable('DATETO', opr_dateto_dtp.Date);
opr_operatorcount_ods.SetVariable('TIMEFROM', opr_timefrom_dtp.Text);
opr_operatorcount_ods.SetVariable('TIMETO', opr_timeto_dtp.Text);
opr_operatorcount_ods.SetVariable('OPERATOR',
opr_operator_ods.FieldByName('opr_code').AsString);
opr_operatorcount_ods.Open;

while not opr_operatorcount_ods.Eof do
begin
frxReport1.PrepareReport(false);
opr_operatorcount_ods.Next;
end;
frxReport1.PrepareReport(true);
opr_operator_ods.Next;
end;

DecodeDate(opr_datefrom_dtp.Date, tyear, tmonth, tday);
StartDate := '''' + IntToStr(tday) + '/' + IntToStr(tmonth) + '/' + IntToStr(tyear) + '''';
DecodeDate(opr_dateto_dtp.Date, tyear, tmonth, tday);
EndDate :=  '''' + IntToStr(tday) + '/' + IntToStr(tmonth) + '/' + IntToStr(tyear) + '''';

frxReport1.Variables['StartDate'] := StartDate;
frxReport1.Variables['EndDate'] := EndDate;

//frxReport1.PrepareReport(True);
frxReport1.ShowPreparedReport;

How do I get the second dataset to move on to the next record's values?

This report used to work perfectly in Delphi 2005 with RaveReports6, but there we used code based form development which was easier to manipulate with a 'writeln' and not visual like with Fast Reports.

1

There are 1 answers

0
Val Marinov On BEST ANSWER

When creating the preview FastReport does something like this code:

while not MasterBand.DataSet.Eof do
  begin
    ...Do special FastReport's work :)
    while not DetailBand.DataSet.eof do 
      begin
        ...Do special FastReport's work :)
        DetailBand.DataSet.Next; 
      end;
    MasterBand.DataSet.Next;   
 end;

In your code:

while not opr_operatorcount_ods.Eof do
begin
 frxReport1.PrepareReport(false);
 opr_operatorcount_ods.Next; <-- here opr_operatorcount_ods is in the last position from PrepareReport 
end;  

Data bands may be a master or detail type, but they only control the positioning of data of the output page (order and number of times displayed). Data displayed by the objects in the bands depends on relationship between the two (or more) datasets. So you should made relation

Relationship can be done in several ways. If you want to use parameters you can do this as follows:

  • Place DataSource component.

  • Connect it to dataset1(opr_operator_ods) using DataSet property DataSet = opr_operator_ods;

  • in DataSource.OnDataChange event write :

      opr_operatorcount_ods.Close;
      ......
      //Set parameter(relation between opr_operator(Master) and opr_operatorcount(Detail)   
      opr_operatorcount_ods.Params.ParamByName('opr_code').asString :=   opr_operator_ods.FieldByName('opr_code').AsString);            
      opr_operatorcount_ods.Open;
    

And then prepare and print report as:

procedure Print;
begin
  //Prepare Master dataset ( parameters, close open etc.) like :
  opr_operator_ods.Close;
  opr_operator_ods.SetVariable('DATEFROM', opr_datefrom_dtp.Date); 
  opr_operator_ods.SetVariable('DATETO', opr_dateto_dtp.Date);
  opr_operator_ods.SetVariable('TIMEFROM', opr_timefrom_dtp.Text);
  opr_operator_ods.SetVariable('TIMETO', opr_timeto_dtp.Text);
  opr_operator_ods.Open;
  ... 
  frxReport1.PrepareReport;
  frxReport1.ShowPreparedReport;
end;