Topic: How to add Variables to Report DataSEt by Script

Hello MVD , fans - experts ,  I know that you can choose 'Report' from the action menu to attach to a button if you want to display data on a report, this allows you to choose the database table you want to query.   In this instance, it allows you to even choose calculated fields that are contained in the table, which is great.   My question is, how do you do the same thing with the action 'Report SQL' to allow you to include calculated fields and different tables in the same report?  Or is there a way to do it by a script?   HELP PLEASE!!!

P.S.  A sample would be nice if anybody has done it before

Re: How to add Variables to Report DataSEt by Script

Hello gonpublic2k,


You are right, sometimes, the simple "Report" button is not enough and you need more flexibility on the data you send to the report.
You have to more options at your disposal to do so.


1 - The first one you already known : it's the "Report SQL" button.
With this option, you can write the query you want and add all the joints and calculated fields you need, cases and so on.
The main problem with this approach being that a complex query will narrow down the data you get in return.

Look at the query bellow :

SELECT DISTINCT
asset.asset_sku,
asset.asset_name,
asset.asset_price,
asset.asset_status,
keyword.kw_text
FROM
asset
INNER JOIN asset_kw ON asset_kw.id_asset = asset.id
INNER JOIN keyword ON asset_kw.id_keyword = keyword.id
ORDER BY keyword.kw_text,
CAST(asset_sku AS INTEGER) ASC  

This query returns every asset in my database as long as they are linked with a keyword (or more) and prints out a report.
(I have 3 tables : a table called asset, a table called keywords and a joining table called asset_kw in between)


The INNER JOIN instruction does filter a lot the result of the query because it's result is exclusive. All my assets that are not linked with a keyword will not show up in the report. If I want them all, I need to replace the INNER JOIN with LEFT JOIN. This way, all assets are reported, and those having an assigned a keyword will show this extra information.


As for calculated fields, they are added the same way as you did them in you database except the come directly in the query. If I add

(SELECT COUNT(id_keyword) FROM asset_kw WHERE asset_kw.id_asset = asset.id) AS NBK    

in my query, I have one more result column in my report counting how many keyword has been assigned to each asset.


But sometimes, one query for too many tables is too complicated to write and you can not link all needed tables with JOIN and so on.


2 - Then you can simply write you queries in script and send them to the report.
Add an Onclick event to a button and use datasets.

You will need two different kind of datasets, the regular one you probably already use, and the ones for the reports.


Here is an example on how you could send the results of 3 different queries to a single report :

procedure Form2_Button1_OnClick (Sender: string; var Cancel: boolean);
var
    frxDBDataSet1, frxDBDataSet2, frxDBDataSet3 : TfrxDBDataset;
    Results1, Results2, Results3 : TDataSet;
    asset_id : Integer;
begin
    //the variable I need to trigger the queries
    asset_id := mark_list.TableGrid1.dbItemID;
      
      //qyery one stored in dataset1
      SQLQuery('SELECT '+
                'asset_sku,'+
                'asset_old_sku,'+
                'asset_name,'+
                'asset_url,'+
                'asset_price,'+
                'vendor_name,'+
                'asset_status,'+
                'asset_detail '+
                'FROM '+
                'asset '+
                'INNER JOIN vendor ON asset.id_vendor = vendor.id '+
                'WHERE asset.id = "'+IntToStr(asset_id)+'"', Results1);

        //query two stored in dataset 2
        SQLQuery('SELECT '+
                 'asset.asset_sku,'+
                 'asset.asset_name,'+
                 'asset.asset_status '+
                 'FROM '+
                 'asset '+
                 'INNER JOIN asset_req ON asset_req.id_asset1 = asset.id '+
                 'WHERE asset_req.id_asset = "'+IntToStr(asset_id)+'" ORDER BY CAST(asset_sku AS INTEGER) ASC ', Results2);

      //query three stored in dataset 3
      SQLQuery('SELECT '+
                'artist.artist_name '+
                'FROM '+
                'asset '+
                'INNER JOIN artist_asset ON artist_asset.id_asset = asset.id '+
                'INNER JOIN artist ON artist_asset.id_artist = artist.id '+
                'WHERE artist_asset.id_asset = "'+IntToStr(asset_id)+'"', Results3);

      
    //transfer standard datasets results to report datasets
    frxDBDataSet1 := TfrxDBDataset.Create(Form2);
    frxDBDataSet1.UserName := 'Asset';
    frxDBDataSet1.CloseDataSource := True;
    frxDBDataSet1.OpenDataSource := True;
    frxDBDataSet1.DataSet := Results1;

    frxDBDataset2 := TfrxDBDataset.Create(Form2);
    frxDBDataset2.UserName := 'Reqs';
    frxDBDataset2.CloseDataSource := True;
    frxDBDataset2.OpenDataSource := True;
    frxDBDataset2.DataSet := Results2;

    frxDBDataset3 := TfrxDBDataset.Create(Form2);
    frxDBDataset3.UserName := 'Artists';
    frxDBDataset3.CloseDataSource := True;
    frxDBDataset3.OpenDataSource := True;
    frxDBDataset3.DataSet := Results3;


    //assign the three report datasets to the same report
    Form1.frxReport.Clear;
    Form1.frxReport.DataSets.Clear;
    Form1.frxReport.DataSets.Add(frxDBDataSet1);
    Form1.frxReport.DataSets.Add(frxDBDataset2);
    Form1.frxReport.DataSets.Add(frxDBDataset3);

    //DESIGN MODE - comment the following two lines and uncomment the preview mode lines to preview report

    Form1.frxReport.LoadFromFile('.\Report\full_asset_report-backup.fr3');
    Form1.frxReport.DesignReport;


    //PREVIEW MODE - comment the following four lines and uncomment the above design mode lines to design report

    //frxDBDataset1.DataSet.Close;
    //frxDBDataset2.DataSet.Close;
    //Form1.frxReport.LoadFromFile(ExtractFilePath(Application.ExeName)+'Report\MyReport.fr3'); //this is my path and my report name, you need to use yours
    //Form1.frxReport.ShowReport;

    Results1.Free;
    frxDBDataSet1.Free;
    Results2.Free;
    frxDBDataset2.Free;
    Results3.Free;
    frxDBDataset3.Free;
    
    Form1.frxReport.Clear;
    Form1.frxReport.DataSets.Clear;
end;

NOTE : the customized report is called from Form2, but you will see calls to Form1 (the main application form). This is because the report handling is done by the main form of your application. Don't forget that smile

This example is built with 3 queries, but you can use as many as you want. The datasets produced will appear in design mode in your report under the names you'll have given them (here Asset, Reqs and Artists).


I can not send you this example because it is part of a very large project that is more than 200 Mo once compressed but if things are unclear, I'll arrange something to give you an example.


Hope this helped a little and was not too long to read.


have a good day


Cheers



Mathias

I'm a very good housekeeper !
Each time I get a divorce, I keep the house

Zaza Gabor

3 (edited by gonpublic2k 2018-06-20 12:23:52)

Re: How to add Variables to Report DataSEt by Script

Excellent explanation Mathias, you should consider writing tutorials for MVD!   Now I understand better the insides of reporting with these
highlights.  I've been playing around with charts and reporting tyring different things to manipulate data but the calculated fields were giving
me a headache.  I will apply what you explained here and see how it goes.  Again, thanks a million!!!

4 (edited by gonpublic2k 2018-06-20 12:54:31)

Re: How to add Variables to Report DataSEt by Script

Also, if it's not too much to ask, I'd like to see a small example using the datasets that contain at least one calculated field to be done by script.  Nothing fancy, just so I can see it clearly from an application approach.  smile

Re: How to add Variables to Report DataSEt by Script

I need an example!!!!!   pleaseeeee !   Anyone sad

Re: How to add Variables to Report DataSEt by Script

Anyone?    sad

Re: How to add Variables to Report DataSEt by Script

You should just insert content of calculate field to SQL query, example:


We have calculate field like this

(SELECT group.groupname FROM group WHERE group.id=person.id_group)

To use this calculate field, you must insert to SQL query not just name of calculate filed, but its content, example:

SELECT 
person.name,
(SELECT group.groupname FROM group WHERE group.id=person.id_group) as "calc_fieldname",
person.dateofbirth
FROM person
Dmitry.

Re: How to add Variables to Report DataSEt by Script

DriveSoft wrote:

You should just insert content of calculate field to SQL query, example:


We have calculate field like this

(SELECT group.groupname FROM group WHERE group.id=person.id_group)

To use this calculate field, you must insert to SQL query not just name of calculate filed, but its content, example:

SELECT 
person.name,
(SELECT group.groupname FROM group WHERE group.id=person.id_group) as "calc_fieldname",
person.dateofbirth
FROM person

Ahh ok, perfect.  Thanks Dimitry!!

Re: How to add Variables to Report DataSEt by Script

Dimitry, 

On that same subject,  what if I had two different tables, each one with a calculated field how do I select both of these tables to display their values on the same report do I need to use datasets for that?   How would I go about it?

Re: How to add Variables to Report DataSEt by Script

gonpublic2k wrote:

Dimitry, 

On that same subject,  what if I had two different tables, each one with a calculated field how do I select both of these tables to display their values on the same report do I need to use datasets for that?   How would I go about it?

You can attach some test project and describe, what exactly report you need.

Dmitry.

11 (edited by gonpublic2k 2018-06-22 16:46:13)

Re: How to add Variables to Report DataSEt by Script

DriveSoft wrote:
gonpublic2k wrote:

Dimitry, 

On that same subject,  what if I had two different tables, each one with a calculated field how do I select both of these tables to display their values on the same report do I need to use datasets for that?   How would I go about it?

You can attach some test project and describe, what exactly report you need.

Following Mathias' suggestion and parting from what you showed Dimitry, I actually figured it out, I solved it by sending an action script with the print button:

procedure Main_btnChart_OnClick (Sender: TObject; var Cancel: boolean);
var
    frxDBDataSet1, frxDBDataSet2 : TfrxDBDataset;
    Results1, Results2 : TDataSet;
begin
        // Query 1 stored in DataSet 1

        SQLQuery ('SELECT ' +
                  'provinc.provinc,' +
                  '(SELECT count(*) from prov where provinc.id = prov.id_provinc) AS "cfproname"'+
                  'FROM provinc', Results1);

       // Query 2 stored in DataSet 2

           SQLQuery ('SELECT ' +
                     'sexo.sexo,' +
                     '(SELECT count(*) from prov where sexo.id = prov.id_sexo) AS "cfsexname"'+
                     'FROM sexo', Results2);

     // Transfer standard datasets results to report datasets

     // DATASET 1

     frxDBDataSet1 := TfrxDBDataSet.Create(Main);
     frxDBDataSet1.Username := 'cfproname';
     frxDBDataSet1.CloseDataSource := TRUE;
     frxDBDataSet1.OpenDataSource := TRUE;
     frxDBDataSet1.DataSet := Results1;

     // DATASET 2

     frxDBDataSet2 := TfrxDBDataSet.Create(Main);
     frxDBDataSet2.Username := 'cfsexname';
     frxDBDataSet2.CloseDataSource := TRUE;
     frxDBDataSet2.OpenDataSource := TRUE;
     frxDBDataSet2.DataSet := Results2;

     // ASSIGN THE REPORTS DATASETS TO SAME REPORT

     Main.frxReport.Clear;
     Main.frxReport.DataSets.Clear;
     Main.frxReport.DataSets.Add(frxDBDataSet1);
     Main.frxReport.DataSets.Add(frxDBDataSet2);

     // DESIGN MODE - COMMENT THE FOLLOWING TWO LINES AND UNCOMMENT THE PREVIEW MODE LINES TO PREVIEW REPORT

     //Main.frxReport.LoadFromFile('.\Report\report.fr3');
     //Main.frxReport.DesignReport;

     // PREVIEW MODE - COMMENT THE FOLLOWING FOUR LINES AND UNCOMMENT THE ABOVE DESIGN MODE LINES TO DESIGN REPORT

     frxDBDataSet1.DataSet.Close;
     frxDBDataSet2.DataSet.Close;
     Main.frxReport.LoadFromFile(ExtractFilePath(Application.ExeName)+'Report\report.fr3');
     Main.frxReport.ShowReport;


     // CLEAR MEMORY & RESET DATASETS

     Results1.Free;
     frxDBDataSet1.Free;
     Results2.Free;
     frxDBDataSet2.Free;

     Main.frxReport.Clear;
     Main.frxReport.DataSets.Clear;
 end;

Here, I have two tables -  PROVINC  and SEXO  , the first one contains names of states and the second one gender information (male, female) I have two calculated fields to count the number of states and the number of gender by region, since they're on different tables I needed the calculated fields from both to be on the same report.  By using DataSets and declaring the calc fields directly in the script as you suggested     I was able to display a pie chart and a bar chart on the same report with these values!   I'm learning!! 

Thanks!!