Click here to Skip to main content
Click here to Skip to main content

Printing Reports in .NET

By , 26 Aug 2008
 
Sample Image - SampleReport1_small.png

Introduction

Printing a document programmatically can be quite involved. Using the ReportPrinting library presented here, you'll be able to print reports with multiple sections with very little code.

The reports are comprised of plain text sections (such as the title "Birthdays", and the other paragraphs) and grids of data from a database (more specifically, from a DataView object). Lines and images (using the .NET Image class) and boxes (like the CSS box model) are also supported. The framework presented can easily be extended to handle many other primitives.

I do not plan to keep this page up-to-date with the latest code and documentation. This will just be a quick presentation of what you can do and the classes involved. For the latest version, see here. However, this project is not actively being developed, so use at your own risk. This was all written for the .NET 1.1 Framework, and I know a lot of new namespaces were added in .NET 2.0 that may make a lot of this obsolete. It solved a problem I had at the time.

Step-by-Step

This section will take you through the process of using the ReportPrinting library, step by step.

Create a DataView

The first step is to create a DataTable and DataView that serves as the source of data. The following code will create a table of some famous birthdays:

public static DataView GetDataView()
{
    DataTable dt = new DataTable("People");
    dt.Columns.Add("FirstName", typeof(string));
    dt.Columns.Add("LastName", typeof(string));
    dt.Columns.Add("Birthdate", typeof(DateTime));

    dt.Rows.Add(new Object[] {"Theodore", "Roosevelt",
        new DateTime(1858, 11, 27)});
    dt.Rows.Add(new Object[] {"Winston",  "Churchill",
        new DateTime(1874, 11, 30)});
    dt.Rows.Add(new Object[] {"Pablo",    "Picasso",
        new DateTime(1881, 10, 25)});
    dt.Rows.Add(new Object[] {"Charlie",  "Chaplin",
        new DateTime(1889,  4, 16)});
    dt.Rows.Add(new Object[] {"Steven",   "Spielberg",
        new DateTime(1946, 12, 18)});
    dt.Rows.Add(new Object[] {"Bart",     "Simpson",
        new DateTime(1987,  4, 19)});
    dt.Rows.Add(new Object[] {"Louis",    "Armstrong",
        new DateTime(1901,  8,  4)});
    dt.Rows.Add(new Object[] {"Igor",     "Stravinski",
        new DateTime(1882,  6, 17)});
    dt.Rows.Add(new Object[] {"Bill",     "Gates",
        new DateTime(1955, 10, 28)});
    dt.Rows.Add(new Object[] {"Albert",   "Einstein",
        new DateTime(1879,  3, 14)});
    dt.Rows.Add(new Object[] {"Marilyn",  "Monroe",
        new DateTime(1927,  6,  1)});
    dt.Rows.Add(new Object[] {"Mother",   "Teresa",
        new DateTime(1910,  8, 27)});

    DataView dv = dt.DefaultView;
    return dv;
}

This function will return a DataView for a table of a dozen famous individuals and their birthdays.

Create a ReportMaker

The ReportPrinting.IReportMaker interface is used to create objects that setup a ReportDocument. That is, an object that implements IReportMaker will contain all the code necessary to make a report. For this example, it is a class called SampleReportMaker1. It has one method to implement:

public void MakeDocument(ReportDocument reportDocument)
{

Let's take a look at the implementation of this method step-by-step. First, it is a good idea to reset the TextStyle class. TextStyle provides global styles for the formatting of text (such as heading, normal paragraphs, headers, footers, etc.) Since the scope of this class is application wide, it should be reset to a known state at the beginning of report generation.

    TextStyle.ResetStyles();

Next, setup the default margins for the document, if desired.

    // Setup default margins for the document (units of 1/100 inch)

    reportDocument.DefaultPageSettings.Margins.Top = 50;
    reportDocument.DefaultPageSettings.Margins.Bottom = 50;
    reportDocument.DefaultPageSettings.Margins.Left = 75;
    reportDocument.DefaultPageSettings.Margins.Right = 75;

As mentioned, the TextStyle class has several static, global styles that can be applied to different text blocks. These styles can each be customized. We'll change some fonts and colors just to show what's possible.

    // Setup the global TextStyles
    TextStyle.Heading1.FontFamily = new FontFamily("Comic Sans MS");
    TextStyle.Heading1.Brush = Brushes.DarkBlue;
    TextStyle.Heading1.SizeDelta = 5.0f;
    TextStyle.TableHeader.Brush = Brushes.White;
    TextStyle.TableHeader.BackgroundBrush = Brushes.DarkBlue;
    TextStyle.TableRow.BackgroundBrush = Brushes.AntiqueWhite;
    TextStyle.Normal.Size = 12.0f;

    // Add some white-space to the page.  By adding a 1/10 inch margin
    // to the bottom of every line, quite a bit of white space will be added
    TextStyle.Normal.MarginBottom = 0.1f;

Using our method defined earlier, we'll get a dataview and set the default sort based on the values setup in a GUI. (Note, this is a hack. Better encapsulation should be used to isolate the dialog, defined later, from this class.)

    // create a data table and a default view from it.
    DataView dv = GetDataView();

    // set the sort on the data view
    if (myPrintDialog.cmbOrderBy.SelectedItem != null)
    {
        string str = myPrintDialog.cmbOrderBy.SelectedItem.ToString();
        if (myPrintDialog.chkReverse.Checked)
        {
            str += " DESC";
        }
        dv.Sort = str;
    }

The next step is creating an instance of the ReportPrinting.ReportBuilder class. This object is used to simplify the task of piecing together text, data, and the container sections that they go into (these classes for text, data and sections are described in more detail later in this article).

    // create a builder to help with putting the table together.
    ReportBuilder builder = new ReportBuilder(reportDocument);

Creating a header and footer are quite easy with the builder class's five overloaded functions. The one below creates a simple header with text on the left side (Birthdays Report) and on the right side (page #). The footer has the date centered.

    // Add a simple page header and footer that is the same on all pages.
    builder.AddPageHeader("Birthdays Report", String.Empty, "page %p");
    builder.AddPageFooter(String.Empty, DateTime.Now.ToLongDateString(),

        String.Empty);

Now the real fun begins: we start a vertical, linear layout because every section from here should be added below the preceding section.

    builder.StartLinearLayout(Direction.Vertical);

Now add two text sections. The first section added will be a heading (as defined by TextStyle.Heading1). The second section is just normal text (as defined by the TextStyle.Normal).

    // Add text sections
    builder.AddTextSection("Birthdays", TextStyle.Heading1);
    builder.AddTextSection("The following are various birthdays of people " +
        "who are considered important in history."); 

Next, we add a section of a data table. The first line adds a data section with a visible header row. Then three column descriptors are added. These are added in the order that the columns are displayed. That is, LastName will be the first column, followed by FirstName, followed by Birthdate.

The first parameter passed to AddColumn is the name of the column in the underlying DataTable. The second parameter is the string as printed in the header row. The last three parameters describe the widths used. A max-width can be specified in inches. Optionally, the width can be auto-sized based on the header row and/or the data rows. In this case, with false being passed, no auto-sizing is performed.

    // Add a data section, then add columns
    builder.AddDataSection(dv, true);
    builder.AddColumn ("LastName", "Last Name", 1.5f, false, false);
    builder.AddColumn ("FirstName", "First Name", 1.5f, false, false);
    builder.AddColumn ("Birthdate", "Birthdate", 3.0f, false, false);

We set a format expression for the last column added (the date column). These format expressions are identical to those used by String.Format. This makes the date show up in long format.

    // Set the format expression to this string.
    builder.CurrentColumn.FormatExpression = "{0:D}"; 

And the very last thing is to finish the LinearLayout that was started earlier.

    builder.FinishLinearLayout();
}

Create a Form for Printing

There are only a handful of controls on the following form: a label, a combo box, a check box, and a usercontrol from ReportPrinting namespace called PrintControl. This control has the four buttons you see at the bottom of the form.

This form also has an instance of the ReportPrinting.ReportDocument class. This is a subclass of System.Drawing.Printing.PrintDocument. If you create the above form in a designer, here is the constructor required to create a new ReportDocument object.

private ReportDocument reportDocument;
public ReportPrinting.PrintControl PrintControls;
public System.Windows.Forms.ComboBox cmbOrderBy;
public System.Windows.Forms.CheckBox chkReverse;

public SamplePrintDialog1()
{
    InitializeComponent();

    this.reportDocument = new ReportDocument();
    this.PrintControls.Document = reportDocument;

    SampleReportMaker1 reportMaker = new SampleReportMaker1(this);

    this.reportDocument.ReportMaker = reportMaker;

    this.cmbOrderBy.Items.Clear();
    this.cmbOrderBy.Items.Add("FirstName");
    this.cmbOrderBy.Items.Add("LastName");
    this.cmbOrderBy.Items.Add("Birthdate");
}

In this constructor, an instance of ReportDocument is created. This instance is assigned to the PrintControls.Document property. A SampleReportMaker1 object (defined above) is then instantiated and assigned to the ReportDocument's ReportMaker property. The final bit of the constructor simply sets up the ComboBox.

You're Finished

The above code prints a fairly simple document. Just to note, you can use the standard PrintDialog, PrintPreview, and PageSettings dialogs (without using the PrintControls usercontrol).

This entire sample can be found in the download of the ReportPrinting library, along with many other tests that I have created (most are boring to look at, but test various random settings).

Report Document Classes

There are several classes introduced into the ReportPrinting namespace. They work together for the printing of the above report (in addition to all the .NET Framework base classes that are used). Here is a quasi-UML diagram that shows the relationship between these classes. An open triangle is generalization (i.e. it points to the super-class in the inheritance chain). The black diamonds are composite (i.e. show that one class instantiates members of another class). The dashed-lines are dependency (i.e. it uses the class).

ReportDocument

ReportDocument extends from PrintDocument and is customized for printing reports from one or more tables of data. A ReportDocument object is the top-level container for all the sections that make up the report. (This consists of a header, body, and footer.)

The ReportDocument's main job is printing, which occurs when the Print() method is called of the base class. The Print() method iterates through all the ReportSections making up the document, printing each one.

The strategy design pattern is employed for formatting the report. An object implementing IReportMaker may be associated with the ReportDocument. This IReportMaker object is application specific and knows how to create a report based on application state and user settings. This object would be responsible for creating sections, associating DataViews, and applying any required styles through use of the TextStyle class. It will generally use the ReportBuilder class to assist with the complexity of building a report.

ReportSection

ReportSection is an abstract class that represents a printable section of a report. There are several subclasses of ReportSection, including ReportSectionText (which represents a string of text) and ReportSectionData (which represents a printable DataView). There are also container sections (which derive from SectionContainer class, which in turn derives from ReportSection). These containers hold child ReportSection objects (also known as subsections) to be printed. Let’s take a quick look at how this might work with an example.

In the sample report shown at the top of this article, there is a paragraph of text followed by a table of data. (There are actually two paragraphs of text, one of which is a heading. Plus there is a page header, but we'll ignore all that for now.) We would create a ReportSectionText object to print the paragraph of text and a ReportSectionData object to print the table of data. To add both of these ReportSections to the ReportDocument, we must create a container. We would create a LinearSections container to hold these two sections. This container is then made the body of the ReportDocument. When the document is printed, the section container will first print the ReportSectionText, and then below that, it will print the ReportSectionData. Simply printing each section below the preceding one will result in the finished report. But there are many other ways to set up these classes.

SectionContainer

This abstract class defines a container of sections. There are two types provided with the framework: LinearSections and LayeredSections.

LinearSections

The LinearSections class is a subclass of SectionContainer, which is a subclass of ReportSection. Therefore, the LinearSections can be thought of as "a printable section of a report." However, it is also a container of one or more sections.

As its name implies, it lays sections out linearly -- that is, in a row or in a column. A property named Direction specifies if this container will layout sections going down the page (typical) or across the page (not as typical).

LayeredSections

The LayeredSections class is also a subclass of SectionContainer, which is a subclass of ReportSection. Therefore, the LayeredSections can be thought of as "a printable section of a report." It is also a container of one or more sections.

The child sections of a LayeredSections object are all painted on top of one another (creating layers). The first section added to a LayeredSections object is the bottom layer. Subsequent ReportSection objects added to the LayeredSections object will be shown on top of each other.

ReportSectionText

The ReportSectionText prints a string to the page. Two public properties are used to setup this section. Text is used to specify the string to print. TextStyle, described later, sets the font, color, alignment and other properties for how the text is printed.

It is interesting to note that the string specified for this section can be just one word, or many paragraphs of text.

ReportSectionData

The ReportSectionData prints a table of data. It uses a DataView object (from the .NET System.Data namespace) as the source of data. It then uses a series of ReportDataColumns to provide the formatting details. These ReportDataColumns are similar to the DataGridColumnStyle class.

ReportDataColumn

The ReportDataColumn provides the necessary information for formatting data for a column of a report. For every column to be presented within a section of data, a new ReportDataColumn object is instantiated and added to the ReportSection. At a minimum, each column describes a source field from the DataSource (that is, a column name from the DataView) and a maximum width on the page.

The ReportDataColumn can be setup with its own unique TextStyle for both header and normal rows. Therefore, each column's data can be formatted differently (e.g. an important column could be bold and red). The TextStyle is also used to set the horizontal alignment (justification).

TextStyle

The TextStyle class allows styles and fonts to be added to text selectively, allowing default styles to be used when not explicitly set. All styles (except for the static TextStyle.Normal) have another style as their "default" style. Until a property is set (like bold, underline, size, font family, etc), a TextStyle object always uses the corresponding value from its default (or parent) style.

For example, a new style can be defined using Normal as its default, but setting bold.

TextStyle paragraphStyle = new TextStyle(TextStyle.Normal);
paragraphStyle.Bold = true;

It will have all the same properties as TextStyle.Normal, except it will be bold. A later change to Normal (such as below) will have the effect of increasing the size of both styles (Normal and paragraphStyle).

TextStyle.Normal.Size += 1.0f

ReportBuilder

ReportBuilder assists with the building of a report. This class is the main interface between your code and the ReportPrinting library. In many cases, you will never explicitly create any of the above objects. Instead, the ReportBuilder will create them for you.

To instantiate a ReportBuilder, you must provide the ReportDocument to be built. Then you can call its various Add… methods to sequentially add pieces to a report document.

We've already seen an example of using ReportBuilder above.

IReportMaker

IReportMaker is an interface used to implement the strategy design pattern. An object that implements IReportMaker can be added to a ReportDocument. When the document is about to be printed, it automatically calls the single method MakeDocument(). The above example shows an implementation of that method to print a one-page report.

For example, you could have an application that can print either detailed reports or a shorter overview. The logic to make each of these reports would be located in separate classes. Each class would implement the IReportMaker interface. Your print dialog could have a "Print What" combo box to allow the user to select the type of report, and use the selection in the combo box to associate the correct implementation of IReportMaker with the ReportDocument.

Conclusion

That summarizes the ReportPrinting library.

Revision History

  • 06-Sep-2003
    • Initial version of article posted with version 0.32 of the ReportPrinting library
  • 01-Sep-2003
    • An updated version of code
  • 24-Aug-2008
    • Removed two dead links
    • Updated code to the latest known good code from Sourceforge
    • Added a little bit of text that this is no longer being actively worked on
    • Ran through Visual Studio's reformat document to clean up some HTML

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

Mike Mayer
United States United States
Member
No Biography provided

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
QuestionAdding image at the header sectionmemberkhairulmm11 Nov '12 - 17:07 
How to add image such as logo in the top header?
BugCrystal Report error in Client PCmemberrehanparvez9 Sep '12 - 20:21 
i have error when going to Open Crystal Report Page Mad | :mad: from Client PC
 
I include all the Dll file that they want but still error Sleepy | :zzz:
QuestionlayoutmembermohAli09825 Jun '12 - 3:17 
please i want to know how to change the layout
QuestionBlank pages with direct printingmemberAlas24 May '12 - 4:59 
We are using last release of Citrix and we can only print directly to printer because a system are crashing. But when we use a caching (pooling) it shows a pages but if I don't cache it shows only blank pages.
Suggestions?
QuestionPass Date to print Document..memberParesh Kacha22 May '12 - 1:17 
Hi.. !
 
This is very helpful for me,,
but I have only one problem ..
 
I use sql database in SampleReportMaker1 for get data,,
but in sqlquery I have to pass date from MainForm.cs .
 
but I cant get textbox or datepicker value in ReportTes11.cs by create property or function ,what is sloution?
 
public static DataView GetDataViewCreditLubeSaleDetail()
{
SqlDataAdapter adapter = new SqlDataAdapter("SELECT Item_Name,Quantity,Unit_Rate,Item_Final_Amount FROM FuelPump.dbo.Frm_FAS_Sale_Detail", strsql);
DataSet ds1 = new DataSet();
adapter.Fill(ds1, "Frm_FAS_Sale_Detail");
 
DataTable dt = new DataTable();
DataTable dt22 = new DataTable();
dt22 = ds1.Tables[0];
 
DataRow row = dt22.Rows[0];
 
DataView dv = dt22.DefaultView;
return dv;
 
}
GeneralMy vote of 5memberJack_32112 May '12 - 11:24 
thank you for this artical. Smile | :)
GeneralAdd Image to Reportmember_rush_1 Jan '11 - 23:56 
Hi,
 
great stuff.
 
Does anybody know how can i add a picture or image to the report?
 
thanks in advance
Thomas
GeneralMy vote of 5memberHeaven20203 Nov '10 - 10:47 
very Cool
Questionhow to apply row span, and column span at Report printing?memberRocky Fan Pengxin11 Oct '10 - 4:52 
Hello,
 
I am working on a project to print report and find Report printing is very useful. But I've got a problem to work it out because the report layout requires row span and column span, and can't find how to do it with Report printing. Can anyone help?
 
Thanks,
 
Rocky
GeneralSo where does it do the actual printingmemberstapes5 Feb '09 - 6:02 
Hi
 
I spent the afternoon incorporating all this stuff into my project. The result - NOTHING!
 
What bit does the actual printing?
 
Stapes
GeneralRe: So where does it do the actual printingmemberMike Mayer5 Feb '09 - 12:01 
Take a look at the Print() method on ReportDocument, or else using the PrintDialog (it's been years since I've looked at this code, but I believe you assign your report document to the Document property on PrintDialog and then call ShowDialog().
GeneralOK - got that working - can I export this report as a pdf?memberstapes6 Feb '09 - 0:55 
Hi
 
Thank you - got that working, after adding a .print() command.
 
Now, how can I export this report to a pdf?
 
Stapes
AnswerRe: OK - got that working - can I export this report as a pdf?memberintrepid_is29 Jun '10 - 23:10 
Use BullZip PDF printer
Find the simplest proof and you have the ultimate truth.

GeneralPrinting in landscape bugmemberMember 357639612 Nov '08 - 4:58 
Hi, i've tried the following use case:
 
1. launch ReportDocumentTesting application
2. click on Setup button on Toolbar and select horizontal page orientation
3. print or preview Test 6 (or any other example)
 
The bug is that the print output doesn't fit the page width fully.
 
Have someone ever encountered this strange behavior?
GeneralRe: Printing in landscape bugmemberGrafne8 Sep '09 - 1:23 
Hi,
I am having a similar problem. Did this ever get resolved?
 
G
GeneralRe: Printing in landscape bugmembergamexs24 Nov '09 - 16:28 
Bug solved in version 0.50. http://www.developerfusion.com/resource/download/content/4585/download/ Smile | :)
QuestionUnicode processing and right to left layoutmemberMember 297968926 May '08 - 6:18 
How Can I set the text layout as rtl to print correct Arabic sentences. Please note that the sentence may contain numbers and english letters. Is there a way to use USP10.dll in this library.
Quick help is very much approciated.
 
Thanks,
Ahmad.
AnswerRe: Unicode processing and right to left layoutmemberxoox27 Aug '08 - 2:38 
You might want to check sourceforge 'Now on SourceForge'
GeneralRe: Unicode processing and right to left layoutmemberMember 29796896 Sep '08 - 9:58 
Sorry, I could not find anything about using USP10.DLL in ReportPrinting Lib. Would you please clarify?
Thanks,
Ahmad.
GeneralLandscape from page 1memberBertil de Groot19 May '08 - 23:09 
I started using this ReportPrinting recently. I want to set the PageOrientation of my report to Landscape. I can do that from page 2 with this code:
_builder = new ReportBuilder(reportDocument);
_builder.StartLinearLayout(Direction.Vertical);
SectionBreak _break = new SectionBreak();
_break.NewPageOrientation = PageOrientation.Landscape;
_builder.AddSection(_break);
But the first page still will be portrait.
 
Does anybody know how to make the orientation Landscape from the start of the document?
 
With Regards,
Bertil de Groot
GeneralRe: Landscape from page 1memberGrafne8 Sep '09 - 1:25 
Hi Bertil,
I am having a similar problem!! did you ever find a solution to this issue?
 
G
GeneralRe: Landscape from page 1memberAjayBritto5 Feb '10 - 22:04 
Hi Guys,
I have a fix for this. Contact me for details.
GeneralRe: Landscape from page 1memberWahbiii21 Jan '11 - 9:35 
Hi,
 
Would you please share with me your idea about the reportPrinting landscape bug?
 
Thanks,
 
Wahbi
GeneralRe: Landscape from page 1 [modified]memberOsman Kalache23 Jun '12 - 21:39 
i've been messing arround to find a quick fix for this tricky bug and here's what i found:
you can set the page orientation with the 'ReportDocument' Object's property 'DefaultPageSettings.Landscape'
so if you set it for example like this :
// 
// reportDocument3
// 
this.reportDocument3.Body = null;
this.reportDocument3.PageFooter = null;
this.reportDocument3.PageHeader = null;
            
this.reportDocument3.DefaultPageSettings.Landscape = true;
 
The the printing layout bug for the Landscape mode is fixed in the newer version of the framework (v0.50) http://www.developerfusion.com/resource/download/content/4585/download/

modified 24 Jun '12 - 3:54.

Questionvb.net print form problemmemberraniranjith14 May '08 - 4:35 
Hi friend,
my problem is,
 
I have one form which contains so many textboxes.
And one datagrid also.
Datagrid is using for listing the size,color etc. of item code.
Iam not created the report,
Instead I want to print like that form itself.
I am using formprint to print the form.But datagrid was connected to the
table so that it is not displaying.
Is there any method to print datagid along with the contents of the form.
 

I used this code,it will give print as an image.Not like report
 
e.Graphics.DrawImage(formImage, 100, 100)
also I used
Dim fp As New FormPrinting.FormPrinting(Me)
fp.Print()
 
but still problem.Datagrid not printing along with form

by rani
Frown | :(
 
rani

GeneralCountPages bug.memberI Fahdah25 May '07 - 10:49 
If you have a table run on more than one page and set reportDocument.CountPages = true; the printing goes to infinite loop.
 
Anyway to sort this out.
 
Many thanks
 

GeneralRe: CountPages bug.memberV# Guy3 Sep '07 - 15:07 
I've got this bug too.
Anyway it is great code 5 globe from me.
 
Dream it, Do it.

QuestionPrint Preview Control - SpeedUp the generation of pagesmemberumaramiya11 Dec '06 - 21:59 
Hi,
 
I am working windows .Net 2.0 application involving generation of dynamic reports. I use PrintPreview Control for previewing/printing the document. Unsure | :~ My problem is when the reports are bulky the User has to wait till all the pages are populated for the Preview and then only click on print icon. Is there any way to speedup the process or Preview Pages are displayed upon generation of each page.
 
Thanks,
Uma Ramiya
GeneralNow Released on SourceForgememberMark Farmiloe27 Nov '06 - 7:55 
As well as being on CVS on SF, I have just released the source as a zip file as version 0.7.
There's a new test called 'Table Test', which demonstrates some of the extensions I've added to the printing of tabular data.
Please try it out.

GeneralNow on SourceForgememberMark Farmiloe22 Oct '06 - 4:17 
So that this project can move on, I've now created this on SF with a project name of net-rep-printer. Due to the fact Mike Mayer cannot be contacted, I've taken the admin post. The SF version includes a few bug fixes and a few enhancements. I hope it helps. Wink | ;)
GeneralRe: Now on SourceForgememberKlaasjanMors29 Oct '06 - 23:20 
Hi,
 
Good thing.
I went to sourceforge, but there is no code. I'm interested in the new version.
 
Thanks
Klaasjan
GeneralRe: Now on SourceForgememberBalazs Zoltan30 Oct '06 - 6:53 
I'm glad to see that this project is not dead Smile | :)
If you need to download the code you can use the CVS. But a zip file would be more
conveniable.
 
I did some modification to the code myself, and downloaded the latest from the CVS.
Hovever now in the first page there appear a 0 and a 1 in the same time at the page number.
There is a bug somewhere in the code checked-in the CVS.
 

 

 
Visit me at www.netis.ro
GeneralRe: Now on SourceForgememberMark Farmiloe31 Oct '06 - 10:02 
Mea culpa, I'm afraid.
In my rush to put the changes onto SF, I appear to have introduced some errors. Frown | :(
The original upload to SF is exactly as Mike Mayer supplied here, so the diffs should point to my errors.
I'll review and fix asap, so please be patient.
In the meantime if anyone has fixes or modifications to contribute, please let me know.
GeneralRe: Now on SourceForgememberBalazs Zoltan31 Oct '06 - 10:48 
I wrote a comment on the SF bugtracker and posted the bugfix there. I wasn't sure you are reading this Smile | :)
 
Do you have any plans to further develop and add new functionalities to this library? Columnheaders that span on multiple column would be a great thing Smile | :) maybe I look it into as time permits.
 
Regards,
 
Visit me at www.netis.ro

GeneralRe: Now on SourceForgememberMark Farmiloe27 Nov '06 - 7:50 
Thanks Balazs
 
I think SF bugtracker is the best route from now on.
I also 'think' that your bug is fixed now, as it doesn't appear on my system and I've just updated a load of minor changes to SF. I've also released it as version 0.7 (see new message).
 
Yes I/we do plan to futher develop it, (or I wouldn't have put it on SF). I'd like to allow the data to come from any IList-compatible source, not just a dataview. Your suggestion sounds fun too - please feel free to request membership of the developer's group on the project.

GeneralRe: Now on SourceForgememberBalazs Zoltan28 Nov '06 - 20:26 
Ok, i'll do that.
 
company, work and everything else www.netis.ro

QuestionVersion 0.5 Update....?memberKentuckyEnglishman28 Oct '05 - 8:03 
Okay, from the European web site specified in another response in this section, someone found and posted where we can go get version 0.50 of this package. For those interested, I can say I've been through it and found it to be even better than this one, so you might want to check it out. In the meantime, does anyone know if we can post the update to it here? I would be glad to arrange the updated package source for the above, if there is a way to do it...
AnswerRe: Version 0.5 Update....?memberKentuckyEnglishman28 Oct '05 - 8:05 
Oh, BTW - the location for the V0.50 package is repeated here:
 
http://www.developerfusion.co.uk/show/4585
[^]
 
-- modified at 15:39 Friday 28th October, 2005
GeneralRe: Version 0.5 Update....?memberMark Farmiloe20 Mar '06 - 6:16 
Thanks for the link.
Does anyone know what has happened to Mike Mayer - his website's not responding and I can't find any trace of him?
Failing finding MM, is there any way we can pool any fixes/enhancements to this great library. I've added the 'Page x of x' and 'print a range' features mentioned in earlier posts and possibly fixed the overlapping text problem also mentioned earlier.
I'd also be interested whether anyone has tried to add subtotals - my attempts so far are tying me up in knots.
GeneralRe: Version 0.5 Update....?memberKentuckyEnglishman21 Mar '06 - 2:50 
As I am a Visual Basic .Net programmer, I have not disected and/or performed any updates to the source - although I have seriously been thinking about converting it to Visual Basic just so I CAN do updates and whatnot! So ANY updates would be welcome - especially the two features you mentioned above!
 
Last but not least, I was hoping to get the multi-column/multi-page feature to work. Most of my printing requirements center around phonebook-type reporting, and as stated earlier, there is a serious hangup in this code that prevents it from printing beyond page one.
 
Tell you what I'll do by the end of the week if I can: I'll contact this sites administrator and explain the situation about your updates you implemented, and see what options might be available for us to re-incorporate all revisions todate with a complete history so that the individuals involved get the appropriate credit. Maybe we can get this great library re-established for people to use. Smile | :) Heck, maybe someday I'll actually egt all of it converted into Visual Basic for other users as well!
Cool | :cool:
 
-- Steve
GeneralRe: Version 0.5 Update....?memberbalazs zoltan18 Jul '06 - 3:21 

Mark Farmiloe wrote:
Failing finding MM, is there any way we can pool any fixes/enhancements to this great library. I've added the 'Page x of x' and 'print a range' features mentioned in earlier posts and possibly fixed the overlapping text problem also mentioned earlier.

 
Hello, could you post here some of what you did for
the 'Page x of x' problem ?
I think it would be very usefull for others as well.
Thanks.
GeneralRe: Version 0.5 Update....?memberMark Farmiloe18 Jul '06 - 4:54 
I may, with the help of KentuckyEnglishman, eventually post a version 0.6, which has a few extras on top of the Page x of y feature, but work has kept getting in the way. Frown | :( br /> 
In the meantime the changes I made to enable the 'page x of y' feature were:
In RepeatableTextSection.cs I added -
After line 31:
/// <item><term>%tp</term><description>Total Pages - this requires the 'CountPages' flag to be set</description></item>  
After line 97:
text = text.Replace("%tp", reportDocument.TotalPages.ToString());
 
In ReportDocument.cs -
Uncommented the following lines:
     bool pagesWereCounted;   // line 114 & 115
     bool countPages;
 
     this.pagesWereCounted = false;   // line 336
 
     if (this.countPages && !this.pagesWereCounted)   // lines 483 - 492
     {                                             // slight amendments in here too !!!  
          this.totalPages = 1;
          while (PrintAPage(e, true))
          {
               this.totalPages++;
          }
          this.pagesWereCounted = true;
          e.Graphics.Clear(Color.White);
          this.reset();
     }
 
Added: after line 178.
/// <summary>
/// Gets or sets the flag
/// indicating that a first pass should be done to count the pages. /// This allows 'Page # of #' using the TotalPages property. /// </summary> [DefaultValue(false)] public bool CountPages {
     get { return this.countPages; }
     set { this.countPages = value; }
}
 
That should be all you need.
IF we get 0.6 sorted, we'll be posting it here too.
GeneralRe: Version 0.5 Update....?memberbalazs zoltan18 Jul '06 - 5:47 
Great !
 
I find this library very usefull and easy to use.
Maybe it is possible to post this project to Sourceforge. This way the
download link would be solved and other developers may add new features
to this library.
You newer know Big Grin | :-D
GeneralRe: Version 0.5 Update....? [modified]memberPatrick Sears16 Oct '06 - 12:34 
This section of code:
 
if (this.countPages && !this.pagesWereCounted)   // lines 483 - 492
    {                              // slight amendments in here too !!!  
        this.totalPages = 1;
        while (PrintAPage(e, true))
        {
            this.totalPages++;
        }
        this.pagesWereCounted = true;
        e.Graphics.Clear(Color.White);
        this.reset();
    }
 
Needs a slight adjustment to account for Landscape pages whose content won't fit on a Portrait page. This results in a situation where the "Fits" bool is always false and the "Continued" bool is always true, resulting in an infinite loop.
 
Here is the corrected snippet:
 
            if (this.countPages && !this.pagesWereCounted)
            {
                this.totalPages = 1;
                this.currentPage++; // preincrement, so the first page is page 1
                while (PrintAPage(e, false))
                {
                    this.totalPages++;
 
                    this.currentPage++; // increment for SetOrientation call

                    // Call SetOrientation to properly orient the next page
                    SetOrientation(e, this.currentPage + 1);
                }
                this.pagesWereCounted = true;
                e.Graphics.Clear(Color.White);
 
                this.reset();
            }
 
This may necessitate an edit to the SetOrientation method, so that it will always reset the orientation to Portrait, if Landscape wasn't specified (since SetOrientation only looks at a table of provided values). I haven't looked into this in depth, so if you use the above code and your page orientations are going wonky, edit SetOrientation to be the following:
 
        protected virtual void SetOrientation (PrintPageEventArgs e, int page)
        {
            // Setup pageSettings for next page
            if (this.pageOrientations.ContainsKey(page))
            {
                PageOrientation orient = (PageOrientation)this.pageOrientations[page];
                switch (orient)
                {
                    case PageOrientation.Portrait:
                        e.PageSettings.Landscape = false;
                        break;
                    case PageOrientation.Landscape:
                        e.PageSettings.Landscape = true;
                        break;
                    default:
                        e.PageSettings.Landscape = false;
                        break;
                }
            }
        }
 
Finally, if you're doing anything where you use DateTime.Now in any way, the duplicate calls to MakeDocument will result in the time being printed out twice.. and different. I know, the call to e.Graphics.Clear(Color.White); should prevent that from happening but it doesn't seem to, least not in my testing.
 
So just change the reset() method on or about ReportDocument.cs line 353 to do this:
 

        void reset()
        {
            this.pageOrientations = new Hashtable();
            if (this.ReportMaker != null && (this.countPages && !this.pagesWereCounted)) //Different!
            {
                this.ReportMaker.MakeDocument(this);
            }
            if (this.Body != null)
            {
                this.Body.Reset();
            }
            if (this.PageFooter != null)
            {
                this.PageFooter.Reset();
            }
            if (this.PageHeader != null)
            {
                this.PageHeader.Reset();
            }
 
            this.currentPage = 0;
            //this.bodyBeginPrintCalled = false;
        }
 
Hope this helps. I've spent the better part of 6 hours hunting this down D'Oh! | :doh:
 

 
-- modified at 12:40 Tuesday 17th October, 2006
General2-Column Multi-Page Fails...memberKentuckyEnglishman28 Oct '05 - 7:59 
I have a type of price-list report where I want to print a part number, description and price. As a single column table, it does just fine - except it takes 47 pages to generate. As soon as I try to put it in a 2-column report, however, the first page does great, but then ... it stops. There is no more than one page to the report in the preview window. Anyone have any ideas... at all... ? Frown | :(
GeneralRe: 2-Column Multi-Page Fails...memberMark Farmiloe21 Mar '06 - 8:05 
I've not been using the 2-column option, so I amended test 9 to have ten times the data and no text other than the header and footer - and it works Confused | :confused: (apart from a spurious line at the right margin which isn't quite vertical).
Maybe I fixed the problem while adding the features?
Can you send me some code/data?

QuestionPrinting lots of text in a tablesussAnonymous26 Oct '05 - 10:14 
When I attempt to print a table where a cell contains more text that can be contained on the page, the code goes into an infinite loop, rather than wrap to the next page. I have set AllowMultiPageWidth to true for the table, but this only allows columns to span multiple pages, not the contents of a column on 1 row to span across pages. Any ideas?
QuestionPrint From PrintpreviewmemberProgressive Support6 Oct '05 - 2:28 
Hi All.
 
Is there a way to print the document through printpreview? It display all lekka and shows it very pretty but when I click the print button it just pulls a blank page through the printer. Is there anyway to print with the preview except for calling the print method on the ReportDocument from inside the code.D'Oh! | :doh:

AnswerRe: Print From Printpreviewmemberbreakpoint20 Oct '05 - 19:10 
Hello,
 
I got the same problem too. It looks great in the print preview but it comes out blank when i print it. Frown | :(
GeneralRe: Print From PrintpreviewmemberKlaasjanMors22 Oct '05 - 1:36 
It's a bug in the sourcecode.
A collegue of mine found the bug. Somewhere in de code the printdocument will be cleared.
When I find the bug i will notify you.
 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Permalink | Advertise | Privacy | Mobile
Web03 | 2.6.130516.1 | Last Updated 27 Aug 2008
Article Copyright 2003 by Mike Mayer
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid