|
Okay, I can print page1, page2 and totals in a summary page (3pages) using multi-templates.
But can I have the summary printed on page2 or does it have to be in a separate page?
|
|
|
|
|
Just let the summary page look exactly the same as the other one (same name for the fields also), then it will look like it's printed on the second page - as opposed to a separate one.
|
|
|
|
|
I must not be using multitemplates properly:
rg.SetReportfile("InvNoTotals.rpt");
...loop thru fields and get gridsize=arr.GetSize();
...if (gridsize>24 lines)
rg.Print(); //want to print first page using InvNoTotals.rpt
rg.AddTemplate("InvWithTotals.rpt",TEMPLATE_TYPE_SUMMARY_PAGE);
...loop totals fields
rg.Print(); //want to print second page using InvWithTotals
|
|
|
|
|
The multi-report format was supposed to be a bit more automatic than that From the documentation:
"A report can be created from multiple templates. A report can have a title page, one or more sections and a summary page. The title and summary page will always be one page each. Grids can span several templates, that is, a grid with the same name can exist on the title page, a section and the summary. Data added will automatically be spread to the appropriate templates. If there is not enough data for all three types, first the section will be supressed, second the summary. To clarify, templates with a spanning grid that contains no data in this template will not be printed. Of course combinations other than title-section-summary is possible, for example title-section-section, section-summary, etc. Multi-template reports are created by calling AddTemplate for each individual template rather than SetReportfile."
That is, you are not even supposed to be switching between single- and multiple template reports; by having a section template and a summary template looking exactly the same, with the difference that the summary template will contain a totals field, you should just need to fill the grid and the totals field, print, and the report generator is supposed to take care of the rest.
|
|
|
|
|
Thank you for your patience and excuse me for being dense:
1)Do I first add the templates I will be using:
AddTemplate("InvWithTotals.rpt",TEMPLATE_TYPE_SUMMARY_PAGE)
AddTemplate("InvNoTotals.rpt",TEMPLATE_TYPE_SECTION) //identical to above but no Totals
(I don't have to use SetReportfile)
Then go through the loops to add data to either grid or fields.
But isn't it when the grid is populated that I determine the gridsize (ie when I'm in the loops)? Where or how do I switch templates?
If it is 1 page invoice then it must use InvWithTotals only,
if it is a 2 page invoice then it must first use InvNoTotals template and then InvWithTotals template.
----------
2)If I can't switch after determining the gridsize then I have to determine the detail lines before (which will = gridsize when it gets there):
if detlines<24
SetReportfile("InvWithTotals.rpt")
else
AddTemplate("InvWithTotals.rpt",TEMPLATE_TYPE_SUMMARY_PAGE)
AddTemplate("InvNoTotals.rpt",TEMPLATE_TYPE_SECTION) //identical to above but no Totals
then fill in the data
----------
Could you clarify this for me.
Thanks.
|
|
|
|
|
The thing with the section and the summary part is that the generator will populate them by itself - that is, assume you have a grid called MainGrid in both a section- and the summary report. If you load templates as per above (that is, calling AddTemplate), and then start populating MainGrid with data, the generator will, by magic (no, only kidding, it's of course programming behind...) when it comes to printing print out as many section pages as necessary and then the summary page, still filling MainGrid. If the number of lines you've added is not enough for both a section page and a summary page, only the summary page will be printed. Or, that is at least the thought.
In short, load the two templates with AddTemplate as you already have (make sure that both have a grid, and both the grids have the same name). Load your data into the grid (never mind that you have it on two templates) and the total field. Print.
|
|
|
|
|
This is basically the code I'm using:
rg.AddTemplate("GridAndTot.rpt",TEMPLATE_TYPE_SUMMARY_PAGE);//has fields (incl total) and grid
rg.AddTemplate("GridOnly.rpt",TEMPLATE_TYPE_SECTION); //identical to above less total field
int max = rg.GetTemplateSize( 0 );
for( int t = 0 ; t < max ; t++ )
{
name = rg.GetFieldName( t );
if( name.GetLength() )
{
int type = rg.GetFieldType( name );
if( type == 2)//FIELD_TYPE_FIELD
{
RgFields_Ord();//ex: if (name=="Total") data=namts;...
rg.Add( name, data );
}
else if( type == 1)//FIELD_TYPE_GRID
{
int columns = rg.GetFieldColumns( name );
if( columns > 0 )
{
arr.RemoveAll();//clears grid for next inv
RgGrid_Ord();
rg.Add( name, arr );
}
}
}
}
rg.Print();
rg.Clear();
The grid works as it should whether it is a 1 or 2 page invoice.
But on a 1 page inv I get just the grid with no header or footer fields
On a 2 page inv
page1 is correct (ie header fields and grid, looks like the Section template)
page2 I just get the grid (properly) but no header fields or footer fields (total)
Thanks.
|
|
|
|
|
I'm not surprised, really
You are getting the size of the first template (GetTemplateSize( 0 ) ), which is lacking the total field. Then, you are getting the fields, implicitly from the first template (if you look at the declaration of GetFieldName , you'll see
virtual CString GetFieldName( int field, int tplate = 0 ) const;
So, you are looping the fields of the section template only. If you change to (GetTemplateSize( 1 ) and GetFieldName( t, t ) instead, you'll operate on the summary template, of which template 1 is a subset (I assume).
As you are checking names=="Total" , you have already hardcoded a dependency to the names, and I don't really understand why you enumerate the fields. Why not just :
rg.AddTemplate("GridAndTot.rpt",TEMPLATE_TYPE_SUMMARY_PAGE
rg.AddTemplate("GridOnly.rpt",TEMPLATE_TYPE_SECTION);
rg.Add( "Total", data );
etc. etc.?
I'm also slightly baffled by the check to rg.GetFieldColumns( name ) , this would seem to be spurious. To summarize, it would seem like you are overcomplicating matters a bit (not unusual among developers, in my experience )
|
|
|
|
|
Hello Johan, great thing what you have done here...
I love it, but i have one problem, when i use it in one of my dll and i call the method GetSize(), i become allways '1' back, but in my *.rpt file are '5' fields... m_data is empty, m_fields too... what's going wrong?
i little bit from my code...
<br />
CReportGenerator m_ReportGenerator;<br />
if(m_ReportGenerator.SetReportfile(path+"test.rpt")) <br />
{<br />
m_ReportGenerator.SetReportname("test");<br />
int size = m_ReportGenerator.GetSize();
for (int p = 0; p < size; p++) <br />
{<br />
CString sName = m_ReportGenerator.GetFieldName(p); <br />
<br />
if (sName.Find("Header") != -1)<br />
{<br />
CString sText = getValueWithoutPlaceholder("%%test%%");<br />
if (! m_ReportGenerator.Add(_T(sName),_T(sText)))<br />
{<br />
AfxMessageBox("Printjob not ok!", MB_OK | MB_ICONSTOP);<br />
return;<br />
} <br />
}<br />
}<br />
m_ReportGenerator.Print();
}<br />
thanks
|
|
|
|
|
Does this happen only when you put the generator in a DLL?
|
|
|
|
|
yes, i use your Report in another project (not a dll) and there is no problem with CReportGenerator::GetSize();
*edit* No, my information ist not correct. GetSize() return allways '1'. Is this a bug by the report or what is wrong by me?
thanks for yout answer...
|
|
|
|
|
Ahhrg, I must update my own documentation every now and then... GetSize will return the number of templates in the report, not the number of fields in the template. You'll need to use GetTemplateSize to get the number of fields. The demo application contains an example on looping through the fields in OnOpenReportFile :
if( m_reportGenerator.SetReportfile( dlg.GetPathName() ) )
{
int max = m_reportGenerator.GetTemplateSize( 0 );
for( int t = 0 ; t < max ; t++ )
{
CString name = m_reportGenerator.GetFieldName( t );
if( name.GetLength() )
{
|
|
|
|
|
oh Johan, thank you very much...
you have saved my life...
|
|
|
|
|
I need to do a report that will look something like the following example…
BUT, I am unsure of how to go about the layout in the report designer, since the number of records for each weekday may vary, and is a dynamic thing…
Hope someone can give me a hint
Cheers
Alex
Monday
Record -1
Record – 2
Record – 3
Etc..
Tuesday
Record -1
Record – 2
Record – 3
Etc..
Wednesday
Record -1
Record – 2
Record – 3
Etc..
Etc…
|
|
|
|
|
Spontaneously, I would say, do a separate report for each weekday, with a grid for the records.
|
|
|
|
|
Hi Johan,
I remember seeing that there is such a concept of a Sub-report, but I can't figure out how it is done / how to insrt a sub-report into a report...
Say I have One report called Subjects.rpt, then I will have one called Monday.rpt, Tuesday.rpt etc...
BUT, how do I do that inside the report designer?
Cheers
Alex
|
|
|
|
|
The report designer is unfortunately not able to work with sub-reports. The designer is more a proof-of-concept how such an app could be built.
|
|
|
|
|
Ok, So how can I use sub-reports?
If I have a report called Courses.rpt - what will I have in the layout, so that during run time it will know when to call Monday.rpt, Tuesday.rpt etc..
Cheers
Alex
|
|
|
|
|
I was thinking more along the lines loading Monday.rpt, filtering out the data relevant for Mondays, and print it. Then load Tueday.rpt, fill it, print it, load Wednesday.rpt etc. etc. etc. Each of the reports either containing duplicates of the common fields, or (if appropriate) using multi-page templates where the first page is the common page and the second the day-specific one.
|
|
|
|
|
Hello again,
In the "CReportGenerator API" documentation there is a function which I have used before called SetReportfile(), after that there is AddTemplate() which I have not.
I thought, based on what I read that I could do the first for the report header, followed by the 2nd API for each day of the week... but I need a code sample of how this is done...
In the Template Monday.rpt, there will be a greed that will load all the monday records etc..., and Tuesday will just be a copy of the Monday RPT etc...
Is that how you mean? Can you please email me a code sample at alex.evans@iinet.net.au
Thanks again
Alex
|
|
|
|
|
Alex,
Unfortunately, I can't spare the time to write example code. The possibility to use several templates is to allow a title page, a body section and a summary (or any combination thereof). I was more thinking along the lines of loading a report for Monday, populate it, print it, load a report for Tuesday, populate, print etc. - you get the picture.
|
|
|
|
|
Hi Johan,
I didn't mean that you will write it for me, you are helping enough as is, thanks again
OK, here is what I understand I should do, please let me know if that is OK
m_reportEnvelops.SetReportfile( _T("Master.rpt") );
m_reportEnvelops.Add(_T("AddressLine1"), “My Address”);
m_reportEnvelops.Add(_T("AddressLine2"), “My Address-2”);
etc…
m_reportEnvelops.Print();
if( m_reportGenerator.AddTemplate( CString("Page1.rpt"), TEMPLATE_TYPE_TITLE_PAGE ) )
{
m_reportGenerator.Add(…);
etc…
m_reportGenerator.Print();
// Load the body page
if( m_reportGenerator.AddTemplate( CString("Page2.rpt"), TEMPLATE_TYPE_SECTION ) )
{
m_reportGenerator.Add(…);
etc…
m_reportGenerator.Print();
}
}
|
|
|
|
|
Yes, something very much like that! I can't for the life of me remember if you have to do a Clear between the prints, however
|
|
|
|
|
Thanks Johan, I'll give that a go.
ANd yes, I downloaded the current version that is on CP, I obviously has a very old version.
Cheers
Alex
|
|
|
|
|
Hello again,
When I tried the code I have just sent to you, my compiler can't find the following
m_reportCards.AddTemplate( CString("Page1.rpt"), TEMPLATE_TYPE_TITLE_PAGE );
Is this a new function? Maybe I have an older version of your program?
Cheers
Alex
|
|
|
|
|