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
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
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
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
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
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
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
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
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
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
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
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
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
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
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