|
Only my sunny disposition stops me from reporting this as spam
|
|
|
|
|
>>Only my sunny disposition stops me from reporting this as spam
Well Sir I don't blame you if you did, but thanks
It is really legitimate work and truly coming product. I thought of dropping a note at your nice article, but I am planning to do the advertising the proper way
|
|
|
|
|
Hello Johan,
Hope all is well in “Sunny” Sweden and all is well at your end.
So, I have a few problem(s) that puzzles me…
1) Using the Report-Creator, when I save the file into the RPT, it creates one long line – I then have to go through and break the lines using Notepad, I had that in the past, and now it comes up again…
2) When I do a Print-Preview in the report creator, it looks all good, but when I try to print to the printer from the “View” it is NOT printing a bitmap that I have placed on the page.
3) When however I print from my own program, it prints the bitmap OK, but where I have a doted line across the page, it prints a whole number of small icons that look like a small Mail-Box with the flag raised up, to say, there is mail…, AND it is missing on printing the doted line…
So, what should I make of that?
Cheers
Alex
|
|
|
|
|
I'll answer here as well, for the benefit of others that might have the same problems:
1) This was solved by statically linking MFC to the application. The application uses CArchive, but is writing strings rather than streaming the data. This obviously works differently depending on the MFC-version (in this case VS 2003 was used).
I'll set the projects to link MFC statically when updating the article.
2) The generator uses the function CDrawPicture::Draw to draw images, while the creator uses CReportEntityPicture::Draw . The main difference between those two is that CDrawPicture converts the image to a DIB (device independent bitmap) internally, while CReportEntityPicture does not. I can see that I need to update CReportEntityPicture - if you want, you can update the class yourself by doing this conversion - The funcation you need to call is DDBToDIB in StringHelpers.cpp and you can see how it is used in DrawPicture.cpp after the call to ::LoadImage .
I'll correct this in the next update.
3) This sounds like the application is using Wingdings as the style for the
dotted line. This could happen, for example, if you use a novelty font of
some kind to design the line, and try to print it on a computer that does
not have the font in question (it will then select another decorative font).
It could also be due to a downright bug in the code, of course. If it is a
label, you can put a breakpoint in CDrawLabel::Draw , and see the information the application tries to assemble into a font, that might give a clue to what is happening.
This was never resolved.
|
|
|
|
|
Hi,
How would I have the Totals showing only on the last page of a 2 or 3 page invoice. Currently, the Totals print on all the pages. The Details are in a grid and there are header and footer fields (eg.Totals). I am using the Print() function as I have to print a range of invoices and need to print them right away.
Thanks.
|
|
|
|
|
You will have to add a template of the type TEMPLATE_TYPE_SUMMARY_PAGE containing your totals field.
|
|
|
|
|
I am using the previous version, is it the same as far as this is concerned?
|
|
|
|
|
This was added in the 28/5 2005-version.
|
|
|
|
|
Can these totals be on the same page, ie a 1-page invoice, or will they be on a page of their own? If the latter is the case then it would not be a solution for me. Do you know of anyway I could accomplish this, perhaps a separate totals grid?
|
|
|
|
|
You can have a separate "normal" text field as a totals field. That is, you create a report with a grid for the individual items in the invoice, as well as a separate text field for the total (and VAT etc). If your problem is that you don't know if it will be a single- or multiple page invoice, you'll have to do two reports, one single page report as described above and one multi-template report where the summary page is the same as the above and the first (or all except the summary, in case you are lucky enough to have very big invoices ).
As you know the max number of lines for the grid, you'll then have to select the correct template(s) when printing.
|
|
|
|
|
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.
|
|
|
|
|