0
votes

I am working with Delphi 16 and Fast Reports 4.1. Embarcadero Edidion.

Roughly, my question is : Is there a way to force frxReport (connected to a Data Base) to skip some of the table entries during report generation?

What I mean can be illustrated as follows:

Assume that we have a large table from the database, one with 1000 entries, and assume that we want to generate a report filled with data from this table, with one page per entry. Naturally, 1000 pages report will be a bit too much to handle, so we need a way to tell Fast Report which entries of the table to use while preparing the report.

To select only a subset of all entries of the table, I use DBGrid where I set the DBGrid.Options.dgMultiselect := True and select the desired rows with mouse clicks. Then I copy the selected rows into a seperate TClientDataSet(named TempDataSet) component, after which I set the current report's data set to the newly created TempDataSet ( 'frxDataSet1.DataSet := TempDataSet' ) and launch prepare report.

This seems to be ok, but in the context of the application I am programming, is unacceptable. So going back to the original question: Is there a way to control which entries in 'frxDBDataset1.DataSet' must be visited when 'frxReport1.PrepareReport();' is called ?

Thank you

2
All filter and sort procedures should take place before passing data to report. You can use a TClientDataSet for storing the filtered and sorted rows (like you already do) :o)Sir Rufo
As an alternative you can try TfrxUserDatasetSir Rufo
The thing is, half of my application assumes that frxReport's data set is of type TADOTable. Bad application design, I guess. That is why I am looking for an alternative. is it possible then to create and fill with data a TADOTable object without associating it with a concrete database table? I mean kind of in-memory TADOTable...kenny

2 Answers

1
votes

You can resort to any of this methods:

Filter

Your original DataSet (if the DataSet is capable of filtering). You usually write a a la SQL filter, like this:

MyDataSet.Filter := 'MYCOLUMN in (''a'', ''b'', ''c'')';
MyDataSet.Filtered := True;

Or write a OnFilterRecord event to exclude/include the records you want to show in the report.

procedure TMyForm.MyDataSetFilterRecord(DataSet: TDataSet; var Accept: Boolean);
begin
  Accept := (DataSet.FieldByName('MYFIELD').AsInteger mod 7 = 0) or 
            (DataSet.FieldByName('MYOTHERFIELD').AsInteger in MySetOfValues);
end;

TFrxDBDataSet events

You can also resort to the events of the TfrxDBDataSet component you usually use to bind your report to the data. Write a OnOpen, OnFirst, OnNext, OnCheckEOF event handlers to prevent the report to include all the records by "stoping" only on the records of your interest.

For example, if you want to print each second row, you could write this:

procedure TMyForm.fdsEstPagosNext(Sender: TObject);
begin
  MyDataSet.Next; 
  MyDataSet.Next; //advance not one, but two records.
end;
1
votes

My answer is a little off topic, refering to your last comment, it is possible to use Adodatasets as Memorytables

var
 I:Integer;
begin
  for I := 0 to AdoDataset1.FieldCount - 1 do
    begin
      Adodataset2.FieldDefs.Add(AdoDataset1.Fields[i].FieldName
                               ,AdoDataset1.Fields[i].Datatype
                               ,AdoDataset1.Fields[i].Size);
    end;
      Adodataset2.CreateDataSet;
                                // just as example     
  While not AdoDataset1.Eof do  // here would be you code for inserting selected Rows
    begin
     AdoDataset2.Append;
    for I := 0 to AdoDataset1.FieldCount - 1 do
      begin
        Adodataset2.Fields[i].Assign(Adodataset1.Fields[i]);
      end;
    AdoDataset2.Post;
    AdoDataset1.Next;
    end;

end;