CompositeReport problem

I use this code to show detail report (detail = for 1 record from db):

frReport.LoadFromFile('report.frf');
frVariables := ARowId;
frReport.ShowReport;

Inside a report I have dialog form with a query component with SQL with 1 parameter, and it is set through params editor (ID = [RecId]). It works without problem.

In my app i have ListForm with DBGrid with list of bills and I allow users to select multiple records and then print selected. Here is the code:

for i := 0 to High(ARowIds) do begin
fr := TfrReport.Create(self);
fr.LoadFromFile('report.frf');
frVariables := ARowIds;
frCompositeReport.Reports.Add(fr);
end;//for i
frCompositeReport.ShowReport;
for i := 0 to frCompositeReport.Reports.Count - 1 do
TfrReport(frCompositeReport.Reports).Free;

And I always get x reports with same data i know this is because frVariables is global object and after setting a [RecId] variable with values in loop overwrite its value.

How can I do this, so every report in composite report gets different value?
Maybe I should set query param directly without using frVariables, but how to do this?

Best regards
misiak

Comments

  • gordkgordk St.Catherines On. Canada.
    edited 6:58AM
    Hi
    you'll probably have to modify your loop
    and create each reportobject with its own identity
    normal with reportcomponents on a form, requires 1 reportcomponent for each report to be loaded then added to the composite.

    frReport1.LoadFromFile(WPath + '1.frf');
    frReport2.LoadFromFile(WPath + '3.frf');
    this is required for composite
    frCompositeReport1.DoublePass := True;
    frCompositeReport1.Reports.Clear;
    frCompositeReport1.Reports.Add(frReport1);
    frCompositeReport1.Reports.Add(frReport2);

    another way is to use 2 report objects and concantenate the output
    concantenate reports
    code to load...
    frReport1.PrepareReport;
    code to load....
    frReport2.PrepareReport;
    frReport2.EMFPages.AddFrom(frReport1);

    regards ;)
  • edited January 2004
    Thanks Gord, I think the 2nd method will work for me.

    Is it possible to change SQL property of Query placed on frReport's DialogForm from Delphi code? Something like this:

    obj := frReport.FindObjectByName('MyQuery1');
    obj.Sql.Text := 'select * ...';

    or

    frReport.DialogForms[0].Objects[0].Sql.Text := 'select ...'

    Thanks again Gord!

    Best regards
    misiak
  • edited 6:58AM
    For 2nd method I wrote this code:

    frReport.Clear;
    fr := TfrReport.Create(self);
    try
    for i := 0 to High(ARowIds) do begin // ARowIds := [100, 101, 102]
    fr.Clear;
    fr.LoadFromFile('report.frf');
    frVariables := ARowIds;//this is RECORD_ID
    fr.PrepareReport; //prepare report for given RECORD_ID
    frReport.EMFPages.AddFrom(fr);
    end;//for i
    finally
    fr.Free;
    end;//try f
    frReport.ShowPreparedReport;

    This code doesnt work also. It creates a report where 1st report (for 1st RECORD_ID) is repeated 3 times.

    Maybe I missed something obvious? Maybe it shoul be done in another way?
    Is there any help for me?

    Best regards
    misiak
  • edited 6:58AM
    Ok I found a way!
    frReport (the one to which I add prepared reports) canot have loaded .frf file.
    frReport.Clear;
    frReport.EMFPages.AddFrom(fr);

    This works!

    Best regards
    misiak
  • gordkgordk St.Catherines On. Canada.
    edited 6:58AM
    misiak wrote:
    Is it possible to change SQL property of Query placed on frReport's DialogForm from Delphi code? Something like this:
    yes you can you must change the whole statement or create a report with parameterized query and point the parameter to a variable then modify the variable as needed.
    typically
    var
    v: tfrview;
    begin
    ........//code to load report
    v:= frreport1.findobject('Query1');
    v.prop:= 'your statement'
    becarefull when forming the statement don't for get delphi strips ' when passing strings
    regards ;)
  • edited January 2004
    I can change SQL property of queries on frReport's DialogForm but then my reports are empty. It looks like queries have no records, but if i check SQL its ok,
    its different for every report (diffrent = every report has different RECORD_ID).

    I think the easiest way is with setting frVariables but unfortunately its global object.
    If I remember right, You have access to FR3 Alpha. Can You tell me if this is going to change? Will every frReport have its own frVariables?

    frReport1.Variables := 13;
    frReport2.Variables := 15;


    Thanks again.

    --
    Best regard
    misiak
  • gordkgordk St.Catherines On. Canada.
    edited 6:58AM
    Hi
    There is no sense commenting on fr3 as it is still in alpha testing.
    You have to be very carefull when changing query statements and names you use for variables.
    first consider an .frf file with a query on the dialog form and variables in data dictionary containing expressions refereing to the fields of the query
    if you change the sql statement at runtime you may not be pointing to the correct field with the variable,probably because the index of the field list is changed.
    second don't make variable names the same as a field names or you will get unexpected results, when the parser/interpreter strips the unwanted characters it ends up with the same "name" and can't determine which one to pick.
    It's like having a field name Date and trying to use Date variable in same report.
    it will not work.
    your comment about not being able to have a .frf loaded into the report you are trying to concantenate tells me that you haven't called prepare method for that report before trying to concantenate.
    IMHO i expect your also having a problem in the loop where you are creating the report components, each pass through the loop the variable fr is pointing to a different object, so it cannot refrence a previously created object.
    regards ;)
  • edited 6:58AM
    Ad 1)
    Actually I dont change SQL much ;) :
    before:
    'select * from bill where bill_id = :RID'
    after:
    'select * from bill where bill_id = 15'
    Ad 2)
    I do not define anything in data dictionary (no expressions)
    Ad 3)
    I dont make variables names same as filed names (BILL_ID, :RID, RecId)
    Ad 4)
    Concantenateing report works ok (frRepor.EMFPages.AddFrom(fr)), but for every added report i need to call frReport.Prepare and it shows progress dialog. If there are 10 reports it will show progree dialog 10 times. I would like to have 1 progress dialog for preparing all reports (like frCompositeReport with 10 reports)
    Ad 5)
    There is no problem in the loop. In each pass of the loop I have fr := TfrReport.Create and frCompositeReport.Reports.Add(fr), so I dont need fr. If I want to access previously created fr object, I can do frCompositeReport.Reports[i-1]. This way I destroy created frs:
    for i := 0 to frCompositeReport.Reports.Count - 1 do
    TfrReport(frCompositeReport.Reports).Free;


    Ad 4 <- this works but I think if every frReport could have its own frVariables it would be more kosher/elegant way.
    frReport1.Variables := 11;
    frReport2.Variables := 13;
    I'm going to ask FR team about it.

    Gord, thank You very much. I appreciate Your help.
    Thanks to You I've found my way out ;)

    --
    Best regards
    misiak
  • gordkgordk St.Catherines On. Canada.
    edited 6:58AM
    Hi
    What i was attempting to tell you was to separate your component creation from your component use.
    Ie since we are going to concantenate 2 reports into 1
    we need only 2 report objects, 1 to hold finished pages 1 to empty clear and reload, modify and prepare again and add produced pages to the first, in the loop
    My own prefrence would be to create the 2 report objects and set their properties
    to what I want ie turn progress form off etc.
    set screen cursor to crhand
    now load and prepare first reportobject with rec id value from first record id in array.

    now you work with the loop, starting at second record, and using the second report object clearing, loading,setting var values. preparing and concantenating to the first, as you iterate through the loop, when you exit the loop
    set your cursor back to crdefault
    call showpreparedreport,for first report object.
    after you have returned from the preview window then free up your created report objects.
    goodluck
    gord ;)
  • gordkgordk St.Catherines On. Canada.
    edited 6:58AM
    Hi Mis
    here is a follow up code sample tested and works fine
    procedure TForm1.Button1Click(Sender: TObject);
    var
    rep1,rep2:Tfrreport;
    begin
    screen.Cursor := crhourglass;
    // report has a variable recid created in the dictionary
    // on dialog form of report sql parm name oid set to type float value set to
    // [recid] note if run under ide you will get error that query1 already exists
    //create repobjects and set properties and event methods if needed
    rep1 := tfrreport.Create(self);
    rep2 := tfrreport.create(self);
    rep2.ShowProgress := false;
    //load into rep1 set dictionary variable recid to a value
    rep1.LoadFromFile(wpath+'mytest.frf');
    //rep1.Pages[0].pgSize:=
    Rep1.Dictionary.Variables := 1221;
    // hardcoded value too lazy to load array
    rep1.PrepareReport;// obvious
    //*****
    rep2.clear;
    rep2.LoadFromFile(wpath+'mytest.frf');
    Rep2.Dictionary.Variables := 1269;
    rep2.PrepareReport;
    rep1.EMFPages.AddFrom(Rep2);
    //***** above could be run in loop to pick up recid value from array
    screen.Cursor:= crdefault;
    rep1.ShowPreparedReport;
    rep1.Free;
    rep2.free;
    end;

    regards
    gord ;)
  • edited 6:58AM
    gordk wrote:
    // report has a variable recid created in the dictionary
    // on dialog form of report sql parm name oid set to type float value set to
    // [recid]
    Hi Gord,

    One more question:
    How to change name of variable ([recid] -> [recid1]) which will be used to set a value of query param from Delphi code?

    --
    Best regards
    misiak
  • gordkgordk St.Catherines On. Canada.
    edited 6:58AM
    Hi Misiak
    found problem in loop
    the variable value is changing ok
    the query is not deactivating so it just keeps repeating with value it gets in first pass in the loop and thats why the pages that are added apear to be duplicates.
    ill try to find out how to turn it off.
    gord ;)
  • gordkgordk St.Catherines On. Canada.
    edited 6:58AM
    Hi Misiak
    sorry this took so long and it was so simple
    the key is the first report after preparing save it to a .frp,clear the report object,and reload the .frp and the second report will run fin in the loop.

    rep1.PrepareReport;// obvious

    rep1.SavePreparedReport(wpath+'ordtemp.frp'); //save as .frp
    rep1.Clear; // clear it
    rep1.LoadPreparedReport(wpath+'ordtemp.frp'); reload the frp.

    some times it's so simple it's painful
    all the best
    gord ;)

Leave a Comment

Rich Text Editor. To edit a paragraph's style, hit tab to get to the paragraph menu. From there you will be able to pick one style. Nothing defaults to paragraph. An inline formatting menu will show up when you select text. Hit tab to get into that menu. Some elements, such as rich link embeds, images, loading indicators, and error messages may get inserted into the editor. You may navigate to these using the arrow keys inside of the editor and delete them with the delete or backspace key.