Masterdata over two *different* pages
Hi all, former Rave Reports user now having to learn a new system. So far it's been not too painful, but I seem to have a problem I haven't seen addressed in the manual or in this forum.
I am printing a pretty specific form for the government. For argument's sake, let's call it an invoice. There can be multiple invoices associated with what I'll call a "Transaction".
As it's currently set, My Report has a Page 1 with a GroupHeader, Masterdata, and PageFooter.
I have 3 datasets: InvoiceHeader, InvoiceDetail, and InvoiceOther.
I also have a second page to this invoice.
The problem is that the 2nd page background and formatting is *different* than the 1st page.
First Page is:
GroupHeader (contains the information contained in InvoiceHeader - GroupHeader repeats when I hit a new invoice)
As much Invoice detail as will fit in the space provided (uses InvoiceDetail)
PageFooter (some summary data, mostly uses InvoiceOther, only prints on 1st page)
Second Page is:
Greatly reduced Header (only a few data fields, takes much less real estate)
Tons of Invoice Detail (the data should continue from where the first page left off)
No Footer at all.
When I try to print this, what happens is that the 1st page looks perfect, but if the detail is larger than the space provided, a second Page 1 prints, with the extra detail at the top (where the GroupHeader was on the 1st page). Then, assuming all the rest of my detail fit on that page, it prints Page 2 with all the masterdata again.
What I *want* to happen is for Page 1 to print as it is, but for the *rest* of the MasterData, use Page 2 and the formatting/background defined therein until I hit the end of the MasterData.
Is there any way to do this?
Thanks, I really appreciate your help in teaching me how to use this.
I am printing a pretty specific form for the government. For argument's sake, let's call it an invoice. There can be multiple invoices associated with what I'll call a "Transaction".
As it's currently set, My Report has a Page 1 with a GroupHeader, Masterdata, and PageFooter.
I have 3 datasets: InvoiceHeader, InvoiceDetail, and InvoiceOther.
I also have a second page to this invoice.
The problem is that the 2nd page background and formatting is *different* than the 1st page.
First Page is:
GroupHeader (contains the information contained in InvoiceHeader - GroupHeader repeats when I hit a new invoice)
As much Invoice detail as will fit in the space provided (uses InvoiceDetail)
PageFooter (some summary data, mostly uses InvoiceOther, only prints on 1st page)
Second Page is:
Greatly reduced Header (only a few data fields, takes much less real estate)
Tons of Invoice Detail (the data should continue from where the first page left off)
No Footer at all.
When I try to print this, what happens is that the 1st page looks perfect, but if the detail is larger than the space provided, a second Page 1 prints, with the extra detail at the top (where the GroupHeader was on the 1st page). Then, assuming all the rest of my detail fit on that page, it prints Page 2 with all the masterdata again.
What I *want* to happen is for Page 1 to print as it is, but for the *rest* of the MasterData, use Page 2 and the formatting/background defined therein until I hit the end of the MasterData.
Is there any way to do this?
Thanks, I really appreciate your help in teaching me how to use this.
Comments
are you talking about design pages or output pages?
gov forms are usually 1 set design page of many fields on a pre printed forms with a number of copies required.
or are you trying to control a multi design page report?
like invoice,packing slip,billing copy.
multi designpage reports require a datset be connected to the tfrxreportcomponent itself and
controls the number of times the report is run (it cannot be the same dataset as any masterband)
The issue is this: I am *replicating* the form for a canada customs invoice. This form's first page is different from every other page that follows.
All the invoice header/footer information goes on the first page, as well as whatever detail will fit between them.
The second and subsequent pages are called "continuation sheets", and consist of a very small header (an abbreviated version of the first page) and a huge amount of detail (no footer).
I'm using background images for the form(s), and have positioned my fields/bands on each page appropriately.
However, it appears that page one wants to iterate through *all* the masterdata before it goes to page 2, at which point all the masterdata prints again on as many page 2s as are required. I want to iterate through whatever masterdata will fit on page 1, and then have it print the rest on page 2.
Does that make more sense? Thanks very much for your reply.
Edit: I should point out that page 1 and page 2 have *different* backgrounds.
I am not sure how the different backgrounds could be achieved. Loading background image at run-time?
Can your software determine how much detail can be printed on page 1? If yes and assuming it is 15 items, a SELECT FIRST 15 * FROM TABLE (Firebird syntax) with one query, printing page 1 (report 1), then a SELECT SKIP 15 * FROM TABLE with another query for page 2+ (report 2).
Then use the composite report feature to merge report 1 and 2 into a single report.
Ah, I see. That's really unfortunate - it was great feature of Rave to be able to print a different first page from subsequent pages, and carry over the existing dataset cursor to the second page. There's really no other way of doing it?
Do you think I could load the new background from a script in a OnBeforePrint script, say?
This is a real problem. Need to think more on this. Thanks very much for your help.
what is the form number and i'll dl and take a look
better yet zip and send the images you are using for positioning.
Regards
Gord K
gord@fast-report.com
do not use groupheaders footers. and do not connect the databand on design page 1 to a dataset.
control the dataset from code and set the rowcount property of the databand.
use tables or queries in a master data relationship.
the master dataset will be the dataset for the tfrxreport component. it will actually control the
number of times the report is run as well as providing masterdata for the
areas above and below the record detail area on design page 1, even though this is detail data
use a master databand and set its rowcount property to the num of recs it can contain.
code page
var
ds: TfrxDataSet;
begin // at bottom of code page assuming record area can handle 12 recs
ds := Report.GetDataset('frxDBDataSet2'); //the user name of the detaildataset
// now set props for masterdata on design pages 1 and 2
begin
if ds.recordcount >12 then
begin
page2 .visible := true; //set designpage 2 visible
masterdata1.rowcount := 12;
masterdata1.dataset :='';
masterdata2.dataset := 'frxDBDataSet2';
end
else
begin
page2 .visible := false// not enough records so dont need
masterdata1.dataset := 'frxDBDataSet2';
masterdata2.dataset :='';
masterdata1.rowcount := 0;
end;
ds.first;// make sure on first record
end;
end.
write code for the oap event of masterdata1
if masterdata1.rowcount > 0 then ds.next;
dont confuse the name of bands with data relationships bands are really just place holders on a design page
Is there a feature-request section on the website? I'd be a big fan of building "second page different from the first" into the engine itself.
Thanks again, I'll let you know how it goes.
Cheers,
Ian
design page 1
probably
page header for fixed position memos large height
masterdataband1 set for fixed num of rows
page footer for fixed position memos below area used by x num of masterdataband records
design page 2
probably known as the overrun page
page header for fixed position memos smaller height
masterdataband we connect to data set and let it control num of pages produced due to num recs
page footer for fixed position memos below area used by masterdataband records.
what most miss is that masterdataband, detaildataband do not have a masterdata relation to data only to each other as to which band comes first in processing, the data source properties of those bands then supply info as to which datasets are involved and their datarelationship.
the best way to think of databand names in fr is datalevel1(masterdataband),
datalevel2(detaildataband1) and so on
what i suggest is to use a query to supply masterdata for the fixed memos,
this will be the tfrxreport components dataset also (controls num times report is run)
and is also the master for the query that supplies the detail records.
BTW there is a demo in the binaries news group on multi design page reports
and you never did tell me what form you were using.
Sorry about that.
The first page looks like this: http://www.noglobalborders.com/cusdocs/customs_invoice.pdf
The second page looks like this: http://www.noglobalborders.com/cusdocs/cus...invoice_pg2.pdf
I'm really sorry for being so obtuse, but I'm still not really certain I understand your instructions. I'll look for the demo in the binaries.
Your description of Page 1 is how I have it set out now, with the page footer sized such that 4 records of the dataset are printed on Page 1.
I use an invoice_header query for the data in the page_header, which is (as you suggest), also the master for the invoice_detail query.
I use a third query (invoice_adjustments) for the data in the page_footer, which also uses the invoice_header query as the master.
All of the queries are MySQL components that are on the same window that the frxReport is on. I am not using the data page of the fast-report.
While I understand your script, I'm not sure what event I should attach it to (it has no declaration in your example).
Clearly I am missing some fundamental understanding of how fast-report works. Perhaps the shift from the RAVE paradigm is beyond me.
I do very much appreciate your patience.
begin
end.
block of the code page as was stated.
it is the first script to be processed.
Depending on page number within a group (select ... from customers group by state) I choose which of two Childs should be visible. It work correctly, but as report is double pass I had to do something about the last State (TX), which tried to appear on THE FIRST page (with companies of AL). This script is not perfect, but it shows the location of the problem.
The code at PageHeader1OnBeforePrint does its duty to change pagefooter on the Page1
but it causes a critical error to FR engine. Be carefull as IT DESTROYS this report [img]style_emoticons/<#EMO_DIR#>/sad.gif" style="vertical-align:middle" emoid=":(" border="0" alt="sad.gif" /> The problem is to avoid bad pointer operations, which is black magic for me[/img][img]style_emoticons/<#EMO_DIR#>/sad.gif" style="vertical-align:middle" emoid=":(" border="0" alt="sad.gif" /> I do not use Delphi. My area is pure script of FR and SQL database - that's why I couldn't solve pointer operation error. Below there's PDF file to show what I got, and fr3 to how I did it. Mick PS. I'll be gratefull to know how to manage those Page1.Objects[/img]
Besides which, If I understand correctly, the main procedure checks to see if my detail set contains more than 4 records. If it does, then I'm going to be using page 2, so I should make it visible. I set the maximum number of rows to be printed on Page 1 to 4 (which is how many fit in there), but I set the dataset for the Page 1 databand to nothing? How does that work? I still need page 1 to print with 4 records, before continuing on to print the rest of them on page 2.
I'm not even trying to create a true master/child relationship in the databases. I have two queries for the header and footer (each which return only 1 record), and a third for the data (which can contain many, all which relate to the one header record), and still can't make it work.
Man, I've been programming successfully for 26 years in 5 different languages, so I don't think I'm stupid, but this really seems kluge-y.
What am I missing, please?
Here's what my code looks like:
void MasterData1OnAfterPrint(TfrxComponent Sender)
{
TfrxDataSet ds;
ds = Report.GetDataSet("InvoiceDetail");
if (MasterData1.RowCount > 0)
ds.Next();
}
{
TfrxDataSet ds;
ds = Report.GetDataSet("InvoiceDetail");
if (ds.RecordCount > 4)
{
Page2.Visible = true;
MasterData1.RowCount = 4;
MasterData1.DataSet = NULL;
MasterData2.DataSet = ds;
}
else
{
Page2.Visible = false;
MasterData1.RowCount = 0;
MasterData1.DataSet = ds;
MasterData2.DataSet = NULL;
}
ds.First();
}
If you find a minute of spare time then have a look at PDF file I enclosed here yesterday.
Is it the result that you are looking for?
I've spent over 2 hours testing that, please do not make think it was my lost time ;-)
Mick
here are the mods to the code. this is all in the report code page.
var
ds: TfrxDataSet;
procedure Page1OnBeforePrint(Sender: TfrxComponent);
begin
if ds.recordcount > 4 then
begin
ds.first;
masterdata1.rowcount := 4;
masterdata2.rowcount := ds.recordcount - 4;
page2.visible := true;
end
else
begin
page2.visible := false;
masterdata1.rowcount := ds.recordcount;
masterdata2.rowcount:= 0;
end;
end;
procedure MasterData1OnAfterPrint(Sender: TfrxComponent);
begin
ds.next;
end;
procedure Page2OnBeforePrint(Sender: TfrxComponent);
begin
// not used was just here for testing
end;
procedure MasterData2OnAfterPrint(Sender: TfrxComponent);
begin
ds.next;
end;
begin
ds := Report.GetDataset('Items'); //the user name of the detaildataset
end.
I've joined this forum just few days ago and maybe that's why I don't know enough about standards of comunication over here. But I do NOT understand why do you both keep on complicating this by writing more and more code and forcing DataSets to do some work :-(
On Feb 2 2011, 09:46 PM I gave here my proposition how to solve the problem with 2 different PageHeader and PageFooter - I did attach PDF file to show the result of my succesfull tests. After all - I used less then 30 lines of pure FR script working ONLY with PageHeaderOnBeforePrint.
Below is my solution, which needs only small corrects (pointer operation). I use ADOQuery2 (select * from Customers) to show better how PageHeader & PageFooter do work for me for different number of companies in each state.
var LState :string;
procedure PageHeader1OnBeforePrint(Sender: TfrxComponent);
var PF :TfrxPageFooter;
i :int;
begin
if Engine.FinalPass then begin
Child1.Visible := <Page> = 1;
Child2.Visible := not Child1.Visible;
end;
if Engine.FinalPass
then if (<Page#> = 1)
then begin
Memo12.Memo.Text := LState;
Memo13.Memo.Text := LState;
end
else begin
Memo12.Memo.Text := <ADOQuery2."State">;
Memo13.Memo.Text := <ADOQuery2."State">;
end
else if LState = ''
then LState := <ADOQuery2."State">;
// code below needs to be corrected due to bad pointer operations
if Engine.FinalPass then with Page1 do for i:=0 to Objects.Count -1 do
if Objects is TfrxPageFooter
then if Child1.Visible
then Page1.Objects.Items := Page2.Objects.Items[0]
else Page1.Objects.Items := Page3.Objects.Items[0];
end;
Full report definition is within my post on Feb 2 2011, 09:46 PM.
Is my solution really so bad that it is not worth to exchange any comments on it ?
Mick
i retrieved the code of gordk, but i have a problem.
I need to show 2 lines on the first page (masterdata1) and i want the rest of my lines (masterdata2) on the second page.
For example:
If i have 4 lines in total, my problem, on the second page, i have the first and the third lines, not the third and fourth.
Hereis my code:
var
ds: TfrxDataSet;
procedure Page1OnBeforePrint(Sender: TfrxComponent);
begin
if ds.recordcount > 2 then
begin
ds.first;
MasterData1.rowcount := 2;
MasterData2.rowcount := ds.recordcount - 2;
//showmessage(MasterData1.rowcount) ;
//showmessage(MasterData2.rowcount) ;
page3.visible := true;
page1.visible := true;
end
else
begin
page3.visible := false;
page1.visible := true;
MasterData1.rowcount := ds.recordcount;
MasterData2.rowcount:= 0;
end;
end;
procedure MasterData1OnAfterPrint(Sender: TfrxComponent);
begin
ds.next;
//showmessage(ds.next);
end;
procedure MasterData2OnAfterPrint(Sender: TfrxComponent);
begin
ds.next;
//masterData2.rowcount := ds.recordcount - 2;
end;
begin
ds := Report.GetDataset('PERSO01'); //the user name of the detaildataset
end.