Add FastReports & DataBases


At present it is very hard to find a company which does not use IT progress for administration and automation of production process. Different systems are able to simplify and automate a significant part of company's functions. One of the most important tasks of such systems is data systematization and creating reports on the basis of gathered information
(Reports generators).

Reports and different documents are integral part of any company, and only forms of these documents differ. But it is not always when data is flat; some tasks require hierarchy structure or tree structures. The majority of report generators work exactly with the flat data set or tables.

 Below you will find several versions of how to solve the problem of hierarchy printing by means of Fast Report reports generator.

As a very simple example we can consider the example of hierarchy of company workers, that is, there are both directors and employees (in big companies such a hierarchy can be deep). Data can be presented as a flat table one of the fields of which refers to a higher employee (director).

 An example of such a table can be seen in the figure (EmpNo the unique number of an employee, EmpOwner shows who the employee is subordinate to).

pic1

 The report creating idea is very simple. It is
necessary to sort out data in accordance with the employee's as well as director's
number. It means that at first there will be employees without owners (blank field), then employees should follow each owner and like this one by one for each record. For data set sorting you can use the list where the names of the employees will be included and sorted accordingly. For transferring to the needed data set record let us use the Locate function.

 Let us move from the description to report creation. Create a new template and set a connection to the data base, add a table or query for choosing the needed data. The example of such a table is attached to the article together with the example (HDemo.mdb). Add bands to the report such as
Report title, First level data and Page footer. Place the text object on the report title with a free text (e.g. Employees), and the object text on the page footer with the [Page] variable. In our report the data bands are decorative for making a report look good. The main processing will be connected with data bands. The report template should be just like in the figure below.

pic2

 Add necessary fields from data set (drag from data tree) to data band but do not attach the band to the data. As a result a ready template will look as
follows:

 pic3

We will use a report script for processing,
data select and shift. To do this, add the following events from listed objects (the events can be added through objects inspector):

�        
�First
level data� (MasterData1) �OnAfterPrint and OnBeforePrint events.

�        
�Report�(Report
can be chosen in the list of objects inspector), OnStopReport

     Event.

And so a template preparation is over and we can start sorting and derivation through the report script. For that, move to the code tab and start writing a script. On the very top of the script let us declare global variables:

var

 
TreeList: TStringList;// sorting list

 
ShiftList: TStringList;// sorting list

 
FDBdataSet: TfrxDBDataSet;// data set                                  

  FVal:
variant;// temporary variable for values storage

 
FPrevEmpNo: Integer;// a variable for the previous number storage

 
oldCurX: Extended; // a variable for the original position of band output storage

Now let us move on to the main script procedure (a code between begin�end), variables will be initialized in it and completion of sorting list will be called.

begin

 
{getting data set }     

 
FDBdataSet := TfrxDBDataSet(Report.GetDataset('ADOTable1'));

  {
creating sorting list }              

 
TreeList := TStringList.Create;

 
{ creating shift  list }     

 
ShiftList := TStringList.Create;                     

 
if FDBdataSet = nil then Exit;

 

  { opening
data set and move on to the first record}             

  FDBdataSet.Open;

 
FDBdataSet.First; 

  { cycle
through all data set records }             


  while
not
FDBdataSet.Eof do

  begin

    { getting
current employee's number  }               

   
FPrevEmpNo := FDBdataSet.Value('EmpNo');

    AddEmp;

   
{restore data set cursor after 
AddEmp run  }                 

    FDBdataSet.Locate('EmpNo',
FPrevEmpNo, 0);

    { moving
on to the next record }                 

    FDBdataSet.Next;                        

  end;                   

 
MasterData1.RowCount := TreeList.Count; 
                 

end.

            The Report.GetDataset function
returns data set object according to its name (If it is found). Creating
sorting list is next, as well as shifting and data set opening. Then a cycle of
all data set records is organized in which we can call a value add function
into the AddEmp list (described below). FDBdataSet.Locate function locates a
cursor in data set in a position where the specified field�s value matches with
the value sent as the second function parameter. MasterData1.RowCount sets a
number of data band repetitions (rows number).

The sort function
must be declared before the main procedure, its realization is written below:

{adding the
employee number in the corresponding  hierarchical position
}   

function AddEmp: Integer;

  var

    FEmpNo: Integer;

    RNo: Integer;

    s: String;       

  begin                          

    FVal := FDBdataSet.Value('EmpOwner');// director�s
number                                                   


    FEmpNo := FDBdataSet.Value('EmpNo');// current
employee�s number                                             

    s := IntToStr(FEmpNo);

    Result := TreeList.IndexOf(s);// searching employee
in the list,if found, then we won�t add     


    if Result <> -1 then exit;

          

    if FVal <> NULL then       

    begin

      {employee has director }

      { move to the director }                     

      FDBdataSet.DataSet.Locate('EmpNo',
FVal, 0);

      { add  employee after director }                     

      Result :=
AddEmp;

      { add employee after director }

      if Result
+ 1 >= TreeList.Count then                                     

        TreeList.Add(s)

      else                             

        TreeList.Insert(Result + 1, s);                          

    end

    else             

    begin

      {employee hasn�t got director (how lucky he
is !), simply add him to the list }                                           

      TreeList.Add(s);         

      Result := TreeList.Count;                                            

    end;       

end;

 

The function adds employees following their directors,
if the director is not in the list yet,  a
recursive  call is made until the full chain fill. If the
employee has been added already then, in the recursive call, exit from the
function is done and moves to the second record (in the main procedure).

 

In the OnStopReport event, we the deleted the
created list.

 

procedure ReportOnStopReport(Sender: TfrxComponent);

begin

   { deleteing
the list }                        

   TreeList.Free;

  
ShiftList.Free;        

end;

 

Selecting data before derivation corresponding
to band sorting and shifting has been realized in the MasterData1OnBeforePrint
event. Moving to a needed row can be done by using the function called Locate,
the value from the list is used as a key.

 

procedure MasterData1OnBeforePrint(Sender:
TfrxComponent);

var

  eOwner:
String;

  i:
Integer;                          

begin

  { pause
the addition to the page so that CurX is not made zero }     

  if
MasterData1.Height > Engine.FreeSpace then Engine.NewPage;

  FPrevEmpNo
:= <ADOTable1."EmpOwner">;                                                                                       


 {restore
the position in the data set }                       

  FDBdataSet.DataSet.Locate('EmpNo',
TreeList[<Line> - 1], 0);

  { get
the current director }

  eOwner
:= IntToStr(<ADOTable1."EmpOwner">);

  { if
the director is not found we add him }

  { Else we
get the shifting index for the employee }             

  i :=
ShiftList.IndexOf(eOwner);

  if
i = -1 then

  begin

    { for
shifting the nodes correctly , we test the previous index }                          

    i := ShiftList.IndexOf(IntToStr(FPrevEmpNo)) + 1;

   
{if the previous key is the last in the list, then we add a new shift}

}                 

   
if i >= ShiftList.Count then

   
begin               

      ShiftList.Add(eOwner); 

      i := ShiftList.Count - 1;

   
end

   
{ else we change the search key }                 

 
  else

       ShiftList[i] := eOwner;            

 
end;

 
{Remember the current band position }             

 
oldCurX := EnginE.CurX;

  { смещаем бэнд }                 

  EnginE.CurX := EnginE.CurX + 20 * i;     

end

In the
MasterData1OnAfterPrint event, we restore the position after shifting.

 

procedure
MasterData1OnAfterPrint(Sender: TfrxComponent);

begin

  { restoring the position of the band }            

  EnginE.CurX := oldCurX;

end;

Report
is ready:pic4

To conclude, need to point out that,
using Locate on a big data set can reduce the productivity of report creation,
in this case, all the needed data can be saved in a either in a list, or in a
tree structure. Without using Locate when selecting data. The general creation principal remains the same.

In the presence of the tree structure,
derivation is very simpler, since there is no need to sort the data,
and it�s possible to immediately move on the tree in the OnManualBuild event
derivates nodes via the Engine.ShowBand band, but this is a topic for a
different article.

The report examples and data applications can
be run in both �Fast Report 4 VCL�, and in �Fast Report Studio�.

 
Related Discussions
  • YOUR FAVORITE BDE ALTERNATIVE? (2001-01-13 12:44:19)
    I joined the company I am currently working for three years ago. MsAccess databases were managed with the BDE. Since we ship our application to...
  • DATAMODULE IN A DLL (2001-01-22 01:16:01)
    where is datamodule in exe or in dll. if it is in exe then most possible your dll is not able to link to that datamodule for varifying if that...
  • HOW ACCESS MS ACCESS TABLES WITH OUT TYPING THE USER ID AND PASSWORD? (2001-01-23 13:49:47)
    Drop a TDatabase component on your DataModule and set the UserID and Password, then set LoginPrompt to False. If you are using Delphi 5, do you...
  • HELP WITH ADO QUESTION PLEASE...CODE INCLUDED (2001-02-03 15:27:25)
    The FindKey only applies to TTables (BDE) and TClientDataSets (Delphi Enterprise) components. For TADOTables and TADOQueries, use the Locate...
  • NEW QUESTION ! DELPHI 5 AGAIN HELPPPPPPPPPP (2001-02-06 10:09:00)
    There are many demonstration applications included with Delphi that show how to use databases. Create your database with DataBase Desktop, it is...
  • EXPORT FROM PARADOX TO MACCESS DATABASE ? (2001-02-07 00:26:37)
    just use two datasets one linked to the source dataset and another to the target database. and then you can either use batchmove component,...
  • FINDING ANSWERS/INFORMATION (2001-02-08 22:37:00)
    Thanks :) I added http://www.tamaracka.com to my Delphi Links ! Scottg
  • INDEX PROBLEMS (2001-02-12 02:32:35)
    Are you using an autoincrement for your key fields? How many users are using the program at a time? what type of databases? Paradox?Access?
  • USE JPG IMAGES IN DATABASES (2001-02-19 20:21:46)
    Try: http://www.hoerstemeier.com/files/jpgimg.zip This includes the source for a TDBJPEGImage component which you may find useful. Good Luck!
  • HOW CAN I USE MS ACCESS TABLES (2001-02-21 08:59:35)
    The issue here is not whether you should use TTable or TADOTable; you have to choose between TDatabase (BDE), TADOConnection (ADO) or any...
Latest News
Submit News Form Past News
Latest Forum Entries