locked
datagrid print

    Question

  • dear friend,
    i am working in VB.net 2005 Expres Edition
     i would like to print my datagrid values .so i have tried  the following link

    http://www.codeproject.com/KB/printing/datagridprinter.aspx.

     here the the print page  has one herder  text called "PrintedDocuments(ALL)"  and  one table which has the datagrid  columns and values .but i need to include anothe headr text "PrintDocument1(ALL)" and  another  datagrid column values.so now in my print page i have one geader text and one table followed by some space and another header text followed by another table.because i have two dataset  which holds difference values. so in the first table my  first dataset value has to  filled and in the second table second dataset values has to filled. so please help me to design  in the print page  and help me to take print values. please show me some sample code for this to do please
    Sunday, February 24, 2008 10:17 AM

Answers

  • Not letting me do it all in one post - too long. I'll put the 2nd half next.

     

    Code Snippet

    using System;

    using System.Text;

    using System.Collections;

    using System.Collections.Generic;

    using System.Drawing;

    using System.Drawing.Printing;

    using System.Data;

    using System.Windows.Forms;

    class DataGridViewPrinter

    {

    private DataGridView[] TheDataGridViews; // The DataGridView Control which will be printed

    private DataGridView currentGrid;

    private DataGridView lastGrid;

    int intCurrentGridNo = 1;

    private bool boolDidCalculationsForCurrentGrid = false;

    private PrintDocument ThePrintDocument; // The PrintDocument to be used for printing

    private bool IsCenterOnPage; // Determine if the report will be printed in the Top-Center of the page

    private bool IsWithPageHeader; // Determine if the page contain title text

    private string ThePageHeaderText; // The title text to be printed in each page (if IsWithPageHeader is set to true)

    private Font ThePageHeaderFont; // The font to be used with the title text (if IsWithPageHeader is set to true)

    private Color ThePageHeaderColor; // The color to be used with the title text (if IsWithPageHeader is set to true)

    private bool IsWithPaging; // Determine if paging is used. If false, only the first page prints.

    private Font tableHeaderFont;

    private bool boolDrewHeaderForThisPage = false;

    private int intWhiteSpaceBetweenTables;

    static int CurrentRow; // A static parameter that keep track on which Row (in the DataGridView control) that should be printed

    static int PageNumber;

    private int PageWidth;

    private int PageHeight;

    private int LeftMargin;

    private int TopMargin;

    private int RightMargin;

    private int BottomMargin;

    private float CurrentY; // A parameter that keep track on the y coordinate of the page, so the next object to be printed will start from this y coordinate

    private float RowHeaderHeight;

    private List<float> RowsHeight;

    private List<float> ColumnsWidth;

    private float TheDataGridViewWidth;

    private List<string> TheTableHeaderTexts = new List<string>();

    // Maintain a generic list to hold start/stop points for the column printing

    // This will be used for wrapping in situations where the DataGridView will not fit on a single page

     

    public List<int[]> mColumnPoints;

    public List<float> mColumnPointsWidth;

    public int mColumnPoint;

     

     

    // The class constructor

    public DataGridViewPrinter(DataGridView[] DataGridViews, PrintDocument aPrintDocument, bool CenterOnPage, bool WithPageHeader, string PageHeader, Font PageHeaderFont, Color PageHeaderColor, bool WithPaging, Font ThetableHeaderFont, List<string> tableHeaderTexts, int WhiteSpaceBetweenTables)

    {

    TheTableHeaderTexts = tableHeaderTexts;

    intWhiteSpaceBetweenTables = WhiteSpaceBetweenTables;

    tableHeaderFont = ThetableHeaderFont;

    TheDataGridViews = DataGridViews;

    currentGrid = TheDataGridViews[0];

    lastGrid = TheDataGridViews[TheDataGridViews.Length - 1];

    ThePrintDocument = aPrintDocument;

    IsCenterOnPage = CenterOnPage;

    IsWithPageHeader = WithPageHeader;

    ThePageHeaderText = PageHeader;

    ThePageHeaderFont = PageHeaderFont;

    ThePageHeaderColor = PageHeaderColor;

    IsWithPaging = WithPaging;

    PageNumber = 0;

    RowsHeight = new List<float>();

    ColumnsWidth = new List<float>();

    mColumnPoints = new List<int[]>();

    mColumnPointsWidth = new List<float>();

    // Claculating the PageWidth and the PageHeight

    if (!ThePrintDocument.DefaultPageSettings.Landscape)

    {

    PageWidth = ThePrintDocument.DefaultPageSettings.PaperSize.Width;

    PageHeight = ThePrintDocument.DefaultPageSettings.PaperSize.Height;

    }

    else

    {

    PageHeight = ThePrintDocument.DefaultPageSettings.PaperSize.Width;

    PageWidth = ThePrintDocument.DefaultPageSettings.PaperSize.Height;

    }

    // Claculating the page margins

    LeftMargin = ThePrintDocument.DefaultPageSettings.Margins.Left;

    TopMargin = ThePrintDocument.DefaultPageSettings.Margins.Top;

    RightMargin = ThePrintDocument.DefaultPageSettings.Margins.Right;

    BottomMargin = ThePrintDocument.DefaultPageSettings.Margins.Bottom;

    CurrentY = (float)TopMargin;

    // First, the current row to be printed is the first row in the DataGridView control

    CurrentRow = 0;

    }

    // The function that calculate the height of each row (including the header row), the width of each column (according to the longest text in all its cells including the header cell), and the whole DataGridView width

    private void Calculate(Graphics g)

    {

    if (boolDidCalculationsForCurrentGrid) return;

    SizeF tmpSize = new SizeF();

    Font tmpFont;

    float tmpWidth;

    TheDataGridViewWidth = 0;

    RowsHeight = new List<float>();

    ColumnsWidth = new List<float>();

    mColumnPoints = new List<int[]>();

    mColumnPointsWidth = new List<float>();

     

    for (int i = 0; i < currentGrid.Columns.Count; i++)

    {

    tmpFont = currentGrid.ColumnHeadersDefaultCellStyle.Font;

    if (tmpFont == null) // If there is no special HeaderFont style, then use the default DataGridView font style

    tmpFont = currentGrid.DefaultCellStyle.Font;

    tmpSize = g.MeasureString(currentGrid.Columns[i].HeaderText, tmpFont);

    tmpWidth = tmpSize.Width;

    RowHeaderHeight = tmpSize.Height;

    for (int j = 0; j < currentGrid.Rows.Count; j++)

    {

    tmpFont = currentGrid.Rows[j].DefaultCellStyle.Font;

    if (tmpFont == null) // If the there is no special font style of the CurrentRow, then use the default one associated with the DataGridView control

    tmpFont = currentGrid.DefaultCellStyle.Font;

    tmpSize = g.MeasureString("Anything", tmpFont);

    RowsHeight.Add(tmpSize.Height);

    tmpSize = g.MeasureString(currentGrid.Rows[j].Cells[i].EditedFormattedValue.ToString(), tmpFont);

    if (tmpSize.Width > tmpWidth)

    tmpWidth = tmpSize.Width;

    }

    if (currentGrid.Columns[i].Visible)

    TheDataGridViewWidth += tmpWidth;

    ColumnsWidth.Add(tmpWidth);

    }

    // Define the start/stop column points based on the page width and the DataGridView Width

    // We will use this to determine the columns which are drawn on each page and how wrapping will be handled

    // By default, the wrapping will occurr such that the maximum number of columns for a page will be determine

    int k;

    int mStartPoint = 0;

    for (k = 0; k < currentGrid.Columns.Count; k++)

    if (currentGrid.Columns[k].Visible)

    {

    mStartPoint = k;

    break;

    }

    int mEndPoint = currentGrid.Columns.Count;

    for (k = currentGrid.Columns.Count - 1; k >= 0; k--)

    if (currentGrid.Columns[k].Visible)

    {

    mEndPoint = k + 1;

    break;

    }

    float mTempWidth = TheDataGridViewWidth;

    float mTempPrintArea = (float)PageWidth - (float)LeftMargin - (float)RightMargin;

    // We only care about handling where the total datagridview width is bigger then the print area

    if (TheDataGridViewWidth > mTempPrintArea)

    {

    mTempWidth = 0.0F;

    for (k = 0; k < currentGrid.Columns.Count; k++)

    {

    if (currentGrid.Columns[k].Visible)

    {

    mTempWidth += ColumnsWidth[k];

    // If the width is bigger than the page area, then define a new column print range

    if (mTempWidth > mTempPrintArea)

    {

    mTempWidth -= ColumnsWidth[k];

    mColumnPoints.Add(new int[] { mStartPoint, mEndPoint });

    mColumnPointsWidth.Add(mTempWidth);

    mStartPoint = k;

    mTempWidth = ColumnsWidth[k];

    }

    }

    // Our end point is actually one index above the current index

    mEndPoint = k + 1;

    }

    }

    // Add the last set of columns

    mColumnPoints.Add(new int[] { mStartPoint, mEndPoint });

    mColumnPointsWidth.Add(mTempWidth);

    mColumnPoint = 0;

    boolDidCalculationsForCurrentGrid = true;

    }

    private void DrawTableHeader(Graphics g, string Text, Font tableHeaderFont)

    {

    StringFormat TitleFormat = new StringFormat();

    TitleFormat.Trimming = StringTrimming.Word;

    TitleFormat.FormatFlags = StringFormatFlags.NoWrap | StringFormatFlags.LineLimit | StringFormatFlags.NoClip;

    if (IsCenterOnPage)

    TitleFormat.Alignment = StringAlignment.Center;

    else

    TitleFormat.Alignment = StringAlignment.Near;

    RectangleF TitleRectangle = new RectangleF((float)LeftMargin, CurrentY, (float)PageWidth - (float)RightMargin - (float)LeftMargin, g.MeasureString(ThePageHeaderText, tableHeaderFont).Height);

    g.DrawString(Text, tableHeaderFont, new SolidBrush(Color.Black), TitleRectangle, TitleFormat);

    CurrentY += g.MeasureString(Text, tableHeaderFont).Height;

    }

    // The funtion that print the title, page number, and the header row

    private void DrawPageHeader(Graphics g)

    {

    // Printing the page number (if isWithPaging is set to true)

    if (IsWithPaging)

    {

    PageNumber++;

    string PageString = "Page " + PageNumber.ToString();

    StringFormat PageStringFormat = new StringFormat();

    PageStringFormat.Trimming = StringTrimming.Word;

    PageStringFormat.FormatFlags = StringFormatFlags.NoWrap | StringFormatFlags.LineLimit | StringFormatFlags.NoClip;

    PageStringFormat.Alignment = StringAlignment.Far;

    //bk

    Font PageStringFont = new Font("Tahoma", 8, FontStyle.Regular, GraphicsUnit.Point);

    float yCoord = (float)TopMargin;

    RectangleF PageStringRectangle = new RectangleF((float)LeftMargin, yCoord, (float)PageWidth - (float)RightMargin - (float)LeftMargin, g.MeasureString(PageString, PageStringFont).Height);

    g.DrawString(PageString, PageStringFont, new SolidBrush(Color.Black), PageStringRectangle, PageStringFormat);

    CurrentY += g.MeasureString(PageString, PageStringFont).Height;

     

     

    }

    // Printing the title (if IsWithPageHeader is set to true)

    if (IsWithPageHeader)

    {

    StringFormat TitleFormat = new StringFormat();

    TitleFormat.Trimming = StringTrimming.Word;

    TitleFormat.FormatFlags = StringFormatFlags.NoWrap | StringFormatFlags.LineLimit | StringFormatFlags.NoClip;

    if (IsCenterOnPage)

    TitleFormat.Alignment = StringAlignment.Center;

    else

    TitleFormat.Alignment = StringAlignment.Near;

    RectangleF TitleRectangle = new RectangleF((float)LeftMargin, CurrentY, (float)PageWidth - (float)RightMargin - (float)LeftMargin, g.MeasureString(ThePageHeaderText, ThePageHeaderFont).Height);

    g.DrawString(ThePageHeaderText, ThePageHeaderFont, new SolidBrush(ThePageHeaderColor), TitleRectangle, TitleFormat);

    CurrentY += g.MeasureString(ThePageHeaderText, ThePageHeaderFont).Height;

    }

    }

    Tuesday, February 26, 2008 10:34 PM
  • Code Snippet

     

    private void calculateStartingPoints(Graphics g)

    {

    // Calculating the starting x coordinate that the printing process will start from

    float CurrentX = (float)LeftMargin;

    if (IsCenterOnPage)

    CurrentX += (((float)PageWidth - (float)RightMargin - (float)LeftMargin) - mColumnPointsWidth[mColumnPoint]) / 2.0F;

    // Setting the HeaderFore style

    Color HeaderForeColor = currentGrid.ColumnHeadersDefaultCellStyle.ForeColor;

    if (HeaderForeColor.IsEmpty) // If there is no special HeaderFore style, then use the default DataGridView style

    HeaderForeColor = currentGrid.DefaultCellStyle.ForeColor;

    SolidBrush HeaderForeBrush = new SolidBrush(HeaderForeColor);

    // Setting the HeaderBack style

    Color HeaderBackColor = currentGrid.ColumnHeadersDefaultCellStyle.BackColor;

    if (HeaderBackColor.IsEmpty) // If there is no special HeaderBack style, then use the default DataGridView style

    HeaderBackColor = currentGrid.DefaultCellStyle.BackColor;

    SolidBrush HeaderBackBrush = new SolidBrush(HeaderBackColor);

    // Setting the LinePen that will be used to draw lines and rectangles (derived from the GridColor property of the DataGridView control)

    Pen TheLinePen = new Pen(currentGrid.GridColor, 1);

    // Setting the HeaderFont style

    Font HeaderFont = currentGrid.ColumnHeadersDefaultCellStyle.Font;

    if (HeaderFont == null) // If there is no special HeaderFont style, then use the default DataGridView font style

    HeaderFont = currentGrid.DefaultCellStyle.Font;

    // Calculating and drawing the HeaderBounds

    RectangleF HeaderBounds = new RectangleF(CurrentX, CurrentY, mColumnPointsWidth[mColumnPoint], RowHeaderHeight);

    g.FillRectangle(HeaderBackBrush, HeaderBounds);

    // Setting the format that will be used to print each cell of the header row

    StringFormat CellFormat = new StringFormat();

    CellFormat.Trimming = StringTrimming.Word;

    CellFormat.FormatFlags = StringFormatFlags.NoWrap | StringFormatFlags.LineLimit | StringFormatFlags.NoClip;

    // Printing each visible cell of the header row

    RectangleF CellBounds;

    float ColumnWidth;

    for (int i = (int)mColumnPoints[mColumnPoint].GetValue(0); i < (int)mColumnPoints[mColumnPoint].GetValue(1); i++)

    {

    if (!currentGrid.Columns[i].Visible) continue; // If the column is not visible then ignore this iteration

    ColumnWidth = ColumnsWidth[i];

    // Check the CurrentCell alignment and apply it to the CellFormat

    if (currentGrid.ColumnHeadersDefaultCellStyle.Alignment.ToString().Contains("Right"))

    CellFormat.Alignment = StringAlignment.Far;

    else if (currentGrid.ColumnHeadersDefaultCellStyle.Alignment.ToString().Contains("Center"))

    CellFormat.Alignment = StringAlignment.Center;

    else

    CellFormat.Alignment = StringAlignment.Near;

    CellBounds = new RectangleF(CurrentX, CurrentY, ColumnWidth, RowHeaderHeight);

    // Printing the cell text

    g.DrawString(currentGrid.Columns[i].HeaderText, HeaderFont, HeaderForeBrush, CellBounds, CellFormat);

    // Drawing the cell bounds

    if (currentGrid.RowHeadersBorderStyle != DataGridViewHeaderBorderStyle.None) // Draw the cell border only if the HeaderBorderStyle is not None

    g.DrawRectangle(TheLinePen, CurrentX, CurrentY, ColumnWidth, RowHeaderHeight);

    CurrentX += ColumnWidth;

    }

    CurrentY += RowHeaderHeight;

    }

    // The function that print a bunch of rows that fit in one page

    // When it returns true, meaning that there are more rows still not printed, so another PagePrint action is required

    // When it returns false, meaning that all rows are printed (the CureentRow parameter reaches the last row of the DataGridView control) and no further PagePrint action is required

    private bool DrawRows(Graphics g)

    {

    // Setting the LinePen that will be used to draw lines and rectangles (derived from the GridColor property of the DataGridView control)

    Pen TheLinePen = new Pen(currentGrid.GridColor, 1);

    // The style paramters that will be used to print each cell

    Font RowFont;

    Color RowForeColor;

    Color RowBackColor;

    SolidBrush RowForeBrush;

    SolidBrush RowBackBrush;

    SolidBrush RowAlternatingBackBrush;

    // Setting the format that will be used to print each cell

    StringFormat CellFormat = new StringFormat();

    CellFormat.Trimming = StringTrimming.Word;

    CellFormat.FormatFlags = StringFormatFlags.NoWrap | StringFormatFlags.LineLimit;

    // Printing each visible cell

    RectangleF RowBounds;

    float CurrentX;

    float ColumnWidth;

    boolDrewHeaderForThisPage = false;

    CurrentY = (float)TopMargin;

    DrawPageHeader(g);

    while (true)

    {

    if (CurrentRow == 0)

    {

    boolDidCalculationsForCurrentGrid = false;

    Calculate(g);

    DrawTableHeader(g, TheTableHeaderTexts[intCurrentGridNo - 1], tableHeaderFont);

    calculateStartingPoints(g);

    }

    if (currentGrid.Rows[CurrentRow].Visible) // Print the cells of the CurrentRow only if that row is visible

    {

    // Setting the row font style

    RowFont = currentGrid.Rows[CurrentRow].DefaultCellStyle.Font;

    if (RowFont == null) // If the there is no special font style of the CurrentRow, then use the default one associated with the DataGridView control

    RowFont = currentGrid.DefaultCellStyle.Font;

    // Setting the RowFore style

    RowForeColor = currentGrid.Rows[CurrentRow].DefaultCellStyle.ForeColor;

    if (RowForeColor.IsEmpty) // If the there is no special RowFore style of the CurrentRow, then use the default one associated with the DataGridView control

    RowForeColor = currentGrid.DefaultCellStyle.ForeColor;

    RowForeBrush = new SolidBrush(RowForeColor);

    // Setting the RowBack (for even rows) and the RowAlternatingBack (for odd rows) styles

    RowBackColor = currentGrid.Rows[CurrentRow].DefaultCellStyle.BackColor;

    if (RowBackColor.IsEmpty) // If the there is no special RowBack style of the CurrentRow, then use the default one associated with the DataGridView control

    {

    RowBackBrush = new SolidBrush(currentGrid.DefaultCellStyle.BackColor);

    RowAlternatingBackBrush = new SolidBrush(currentGrid.AlternatingRowsDefaultCellStyle.BackColor);

    }

    else // If the there is a special RowBack style of the CurrentRow, then use it for both the RowBack and the RowAlternatingBack styles

    {

    RowBackBrush = new SolidBrush(RowBackColor);

    RowAlternatingBackBrush = new SolidBrush(RowBackColor);

    }

    // Calculating the starting x coordinate that the printing process will start from

    CurrentX = (float)LeftMargin;

    if (IsCenterOnPage)

    CurrentX += (((float)PageWidth - (float)RightMargin - (float)LeftMargin) - mColumnPointsWidth[mColumnPoint]) / 2.0F;

    // Calculating the entire CurrentRow bounds

    RowBounds = new RectangleF(CurrentX, CurrentY, mColumnPointsWidth[mColumnPoint], RowsHeight[CurrentRow]);

    // Filling the back of the CurrentRow

    if (CurrentRow % 2 == 0)

    g.FillRectangle(RowBackBrush, RowBounds);

    else

    g.FillRectangle(RowAlternatingBackBrush, RowBounds);

    // Printing each visible cell of the CurrentRow

    for (int CurrentCell = (int)mColumnPoints[mColumnPoint].GetValue(0); CurrentCell < (int)mColumnPoints[mColumnPoint].GetValue(1); CurrentCell++)

    {

    if (!currentGrid.Columns[CurrentCell].Visible) continue; // If the cell is belong to invisible column, then ignore this iteration

    // Check the CurrentCell alignment and apply it to the CellFormat

    if (currentGrid.Columns[CurrentCell].DefaultCellStyle.Alignment.ToString().Contains("Right"))

    CellFormat.Alignment = StringAlignment.Far;

    else if (currentGrid.Columns[CurrentCell].DefaultCellStyle.Alignment.ToString().Contains("Center"))

    CellFormat.Alignment = StringAlignment.Center;

    else

    CellFormat.Alignment = StringAlignment.Near;

    ColumnWidth = ColumnsWidth[CurrentCell];

    RectangleF CellBounds = new RectangleF(CurrentX, CurrentY, ColumnWidth, RowsHeight[CurrentRow]);

    // Printing the cell text

    g.DrawString(currentGrid.Rows[CurrentRow].Cells[CurrentCell].EditedFormattedValue.ToString(), RowFont, RowForeBrush, CellBounds, CellFormat);

    // Drawing the cell bounds

    if (currentGrid.CellBorderStyle != DataGridViewCellBorderStyle.None) // Draw the cell border only if the CellBorderStyle is not None

    g.DrawRectangle(TheLinePen, CurrentX, CurrentY, ColumnWidth, RowsHeight[CurrentRow]);

    CurrentX += ColumnWidth;

    }

    CurrentY += RowsHeight[CurrentRow];

    // Checking if the CurrentY is exceeds the page boundries

    // If so then exit the function and returning true meaning another PagePrint action is required

    if ((int)CurrentY > (PageHeight - TopMargin - BottomMargin))

    {

    CurrentRow++;

    return true;

    }

    }

    CurrentRow++;

    if (CurrentRow > currentGrid.Rows.Count - 1)

    {

    if (intCurrentGridNo < TheDataGridViews.Length)

    {

    CurrentRow = 0;

    intCurrentGridNo += 1;

    CurrentY += intWhiteSpaceBetweenTables;

    currentGrid = TheDataGridViews[intCurrentGridNo - 1];

    }

    else return false;

     

    }

    }

    CurrentRow = 0;

    mColumnPoint++; // Continue to print the next group of columns

    if (mColumnPoint == mColumnPoints.Count) // Which means all columns are printed

    {

    mColumnPoint = 0;

    return false;

    }

    else

    return true;

    }

     

    // The method that calls all other functions

    public bool DrawDataGridView(Graphics g)

    {

    bool bContinue = DrawRows(g);

    return bContinue;

    }

    }

     

     

     

    Tuesday, February 26, 2008 10:36 PM

All replies

  • It's probably a little tricky to modify someone else's code as to make it print two reports, one after the other, on the same page, if the original programmer only had in mind one report (one datatable).


    You might want to use the ReportViewer control. Such a report offers a grid-type report called a "Table" (drop this Table from the toolbox) and I suppose (though I've never tried it) if you drop two such tables onto your report form (and note each one has its own header by default), I am guessing it will ouput the first report and then, on the same page, the second report. Here's my notes on ReportViewer (it shows you how to pass in a datatable).


                        VISUAL STUDIO 2005 REPORT VIEWER CONTROL


                            HOW TO USE IT WITH SQL SERVER REPORTING SERVICES

    The layout of those reports compatible with ReportViewer control is stored in a file with an .RDL or .RDLC file extension.  If you create and edit the layout in Visual Studio, then VS will store it in an .RDLC file ("the C means client").  But if you created the layout in SQL server, you will need to find that .RDL file and import it into your C# project.  To import a file goto Solution explorer and right-click > Add ExistingItem > Browse to the file. 


    Very important:  Next, rightclick the file you just added (the RDLC file visible in SE) and choose Properties > BuildType and change the setting from "Content" to "EmbeddedResource." This simply means that Visual Studio makes a copy of the RDLC file and embeds this copy into your C#  compiled program (your DLL).


    Then you will need code that accesses the embedded resource so that you can assign the RDLC file to the ReportViewer control dropped onto your form (see my notes below).  Actually I have never worked with RDLC files - I have only worked with RDL files.  But I will copy and paste my notes which will show you step by step how to work with ReportViewer because the steps are basically the same (except skip the steps for editing the layout since you should have already done this part in Sql server, I would imagine).

    This is a handy .Net method of using the RDL (Report Definition Language) created for Sequel Server Reporting Services. Requires very little code because it is very graphical.


    Help with this control came from (I'm happy to say Microsoft FINALLY has a decent help page for RDL reporting - see the left pane for the table of contents
        http://msdn2.microsoft.com/en-us/library/ms251671(VS.80).aspx
    It's a large table of contents. I found most of my needs in the section
        Create Client Report Definition Files > DEfining a Report layout

    ReportViewer is a Windows Forms control that ships with VS 2005 Standard Edition (whereas Crystal ships with Vs 2005 Pro Edition, which costs about $350 more).

    VS 2005 is not a database like Sql 2005. But this is what they have in common:  ReportViewer Control is a Vs 2005 tool that saves reports as .RDLC files (the "c" means Client Format). Sql Server 2005's ReportServer saves reports as .RDL files. YOU CAN CONVERT ONE FORMAT TO THE OTHER BECAUSE THEY BOTH ARE BASED ON RDL (Report Definition Language) WHICH IS AN XML TAG FILE. (However, this conversion works only if the RDL files originated in sql 2005 (versus sql 2000) or you can upgrade sql 2000 rdl files to sql 2005 rdl files). Furthermore, conversion isn't the main issue since it's easier at times to recreate the report from scratch.


       

    The ReportViewer Control usually creates reports in "local" mode (client mode) - RDLC files versus RDL files -  which means that the report engine is the local computer (the .Net runtime). You can choose <server> (from the dropdown on the microcospic arrow on the ReportViewer Control) to go into "remote" mode which activates Server-Side report-generation (and hence .RDL files rather than .RDLC files). You can convert from one format to the other as stated previously.


    Note: For some of my sample code, might need to add a reference to Microsoft.ReportViewer.winforms
    and then add the line:
        using Microsoft.Reporting.WinForms; //C#
        Imports Microsoft.Reporting.WinForms  'Vb.Net

                                    PRODUCING A BASIC REPORT


    NOTE ON DATASETS: Most of the examples given in most  tutorials call for adding a DataSet to the project. I don't like this method because .Net tends to add about 1500 lines of dataset code.   All I really need is a few column names, not 1500 lines of code, that's why I came up with the method shown here.

                                   
    What ReportViewer needs is a list of column names. ReportViewer does not distinguish between datatables and collections, so we'll pretend to use a collection of Customers just to build a list of column names but we'll actually use a datatable as the real datasource.  So start with Project > AddClass and name the class Customer. Here I can use a "fake" Customer syntax (be sure to use proper syntax if your datasource will be a real Customer collection, but again, here we will use a datatable). Here's the fake Customer class - but remember that YOU MUST HAVE THE CLASS AS A SEPARATE FILE FOR REPORTVIWER TO SEE IT. You cannot just put this class anywhere in your code - you must do a Project > AddClass to open/create a separate project file for it.

          class Customer
        {

            public string CustomerID
            {
                get { return String.Empty; }
            }
            public string City
            {
                get { return String.Empty; }
            }
     }

    This gives me two column names CustomerID and City corresponding to those two column names in my datatable. Continue adding column names until all the columns in your datable are named (or at least those columns that you intend to add to the actual report). You can also use the following sub to write the column names to a text file and then you can copy and paste the textfile into your class. The first one is for VB programs:
        Private Sub WriteColumnNamesToTextFile(ByVal dt As DataTable)
            Dim sw As New System.IO.StreamWriter("C:\ColumnNamesVB.txt", False)
            For Each dc As DataColumn In dt.Columns
                sw.WriteLine("Public ReadOnly Property " & dc.ColumnName & "() as String")
                sw.WriteLine("Get")
                sw.WriteLine("Return String.Empty")
                sw.WriteLine("End Get")
                sw.WriteLine("End Property")
                sw.WriteLine()
            Next
            sw.Close()
        End Sub
    That one's for VB.Net, now one for C#:
         private void WriteColumnNamesToTextFile(DataTable dt)
            {
                System.IO.StreamWriter sw = new System.IO.StreamWriter(@"C:\ColumnNamesC#.txt", false);
                foreach (DataColumn dc in dt.Columns)
                {
                    sw.WriteLine("public string " + dc.ColumnName);
                    sw.WriteLine("{");
                    sw.WriteLine("get {return String.Empty;}");
                    sw.WriteLine("}");
                    sw.WriteLine();
                }
                sw.Close();
            }

    NOW BUILD YOUR PROJECT SO THAT THE REPORTVIEWER CAN SEE YOUR NEW COLUMNS. Now goto Data > Add DataSource and choose Object. Look for the Customer class and add it. Then choose Data > Display DataSources. You will now see a lefthand pane called Data Source which should show a listing for Customer with all the column names, in this case the two column names CustomerID and City.

    - Goto the Toolbox and drop a ReportViewer on the form. (You MUST expand it with the mouse if it is small because otherwise it will appear to be "not working" - it won't show any data if it is small, for some reason). Or just Dock to Fill the entire form, making it as large as possible.


    - Click the upper right corner of the ReportViewr  control to expose a microsocopic arrow which you can click to see some choices, one of which is "Design a New Report." (Or simply do  Project > Add New Item > Report). Either method  will open up a a report file/form called Report1.RDLC, that is, a report designer window (let's call it the format-report window), much like a Crystal Report template or Access template, which is basically a form with a ruler at the top, and the idea is to drag column names onto the form.  In this case, the form will be labeled Report1.RDLC which is actually a file created on disk.

     Now go back to the ReportVewer's microscopic arrow and choose Report1.RDLC from the dropdown as to let the ReportViewer control  know which report file it is supposed to be using (because you could have multiple report viewers and multiple Report.RDLC files in a single app).

    The form (again, let's call it the format-report window) starts off pretty empty, it does NOT include a tabular report (a column-style report). To add a tabular report, choose View > Toolbox which opens up a special ToolBox for the ReportViewer. Choose Table because this means "tabular report." Doing so will put, on your format-report window, the following three grid-lines corresponding to the three sections of your desired report.
                HEADER section
                DETAIL - the body of the report
                FOOTER section
    On each of these three line are boxes into which you can drag column names from the left pane. (Mostly you will be using the Detail line, obviously). But since a given line only has, at the outset, 3 empty boxes, you can only add 3 column names at first. To add more columns, right-click the top-row and choose InsertNewColumnRight.  Note on dragging columns: When you drag a column from the left hand pane, such as CustomerID, a large box/rectangle forms around the cursor as you drag it(the same size as the boxes on the form). Make sure to fit the box (drop the box) precisely onto one of the boxes on the Details Line - this will ALSO add an entry to the top line (the header line), namely the column name will be added to it.


    By the way, I used the following code to generate a datatable as sample data:
             private DataTable getTheData()
            {
                string strConnection = @"Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\Northwind.mdb";
                System.Data.OleDb.OleDbDataAdapter da  = new
                   System.Data.OleDb.OleDbDataAdapter("Select * From Customers", strConnection);
                DataTable dt = new DataTable();
                da.Fill(dt);
                return dt;

            }
    Now add this code:
                    DataTable dtCustomers = getTheData(); // see the sub above.
                 this.reportViewer1.LocalReport.DataSources[0].Value = dtCustomers;
                 this.reportViewer1.RefreshReport(); //generates the report.
    And that's all there is to it.





    NOTE: IF VS ADDED A CUSTOMERSBINDINGSOURCE OBJECT into your Component Tray (underneath Form1), you may safely delete it, as far as I know.





                        CHANGE REPORT FILES AT RUN TIME

    Suppose you have a second report called Report2.RDLC. You already displayed the first report using the code above, now you want to show report2 at runtime.

    Report.RDLC files enter the project as embedded resources. I have had problems .Net prefixing an application name to the name of the embedded resource, so the first thing I do, to avoid this problem, is find the FULL name of the Report2.RDLC file (the 2nd report).

          //Loop through all embedded-resource names to get FULL name of Report2.RDLC
                string nameOfReport2 = "Report2.RDLC";
                System.Reflection.Assembly asm = System.Reflection.Assembly.GetExecutingAssembly();
                foreach (string str in asm.GetManifestResourceNames())
                    if (str.ToLower().IndexOf(nameOfReport2.ToLower()) > -1) nameOfReport2 = str;
    The fullName is now stored in nameOfReport2. Now we can load Report2 using code:
                    //Let's assume that Report2 has the same datasource name, which is usually NOT the case
                       //WARNING:This name is case senitive.
        string dataSourceName = reportViewer1.LocalReport.DataSources[0].Name; //assumes the same name, Case Senstive
               this.reportViewer1.Reset();
               this.reportViewer1.LocalReport.DataSources.Add(new ReportDataSource());
               this.reportViewer1.LocalReport.ReportEmbeddedResource = nameOfReport2;
               this.reportViewer1.LocalReport.DataSources[0].Name = dataSourceName; //WARNING:This name is case senitive
               this.reportViewer1.LocalReport.DataSources[0].Value = dtCustomers;
               this.reportViewer1.RefreshReport();

                                            MORE INFO ON DATASOURCE NAMES

    WARNING: The datasource name is intended to be a permanent part of any Report.RDLC file. Therefore if you port your RDLC file to a different project (you can do this because it is a file on disk), you will have to use the old datasource name even if that old name has the old project name as the prefix. If you don't remember the old name, play around with the options on the microscopic arrow of the ReportViewer control - hopefully the datasource name will display.

    On the other hand you can remove the old datasource name as follows.  Let's suppose you used a Customer class, as described above, as your source of columns draggable onto the report, but then you decide that you should have used the Orders table in your database (and thus an Orders class) as your source of columns. In this case you would want to dissociate the Customers datasource from the report and start over - which is a lot of work so perhaps you should just trash the first RDLC file and make a new one. Anyay, if you want to try the dissociation, then follow these steps. Make sure the format-report window is open and then  go to Report > DataSources, and there you will see your Customers DataSet (or Customer object) listed. Select it and click Remove (removes it as a datasource). To prove that it has been remvoved, hit f5 to run the project - the compiler will probably throw errors because the columns dragged onto your report have lost their source of data. You will probably have to delete any columns dragged and then redrag them onto the report.


    Another reason  you might need the Report > DataSource window is that, suppose your Customers database now has newly added columns in the Customer table. You may need to choose Refresh in this window to make these columns visible as items draggable onto your reort. Another use for this window is if you forgot the (case sensitive) name of a data source - all those names will be listed here.

    There is a "Rename" button but for renaming a datasource but it's not terribly reliable.
                   
                KEY TO FORMATTING THE REPORT

    Using the Properties window is the key to formatting the report. This makes it really easy. Always keep in mind that there are two different Property windows, namely the RDLC Properties and the regular VS Properties window (hit F4 or goto View > Properties window).  Typically it's the VS window, oddly enough, that helps you format the report.

    It is very easy to change fonts and so forth using the properties window. For example, to make a column cellular in layout (to make it gridlike/gridlines as with Excel), just select that "textbox" and then open the Properties window and set the BorderStyle to Solid.



                                EXPORT TO EXCEL  OR PDF

    There is a button on the report allowing the user to export to excel or pdf. However, if you want to force an export using code, just add this code:

            private void exportToExcel(string DestWhereExcelFileWillBe)
            {
                System.IO.FileInfo fi = new System.IO.FileInfo(DestWhereExcelFileWillBe);
                if (fi.Exists) fi.Delete();
                Warning[] warnings;
                string[] streamids;
                string mimeType,  encoding, filenameExtension;
                byte[] bytes = reportViewer1.LocalReport.Render( "Excel", null, out mimeType, out encoding, out filenameExtension,
                    out streamids, out warnings);
                System.IO.FileStream fs = System.IO.File.Create(DestWhereExcelFileWillBe);
                fs.Write(bytes, 0, bytes.Length);
                fs.Close();
            }

    and to export to PDF, just change the string literal "Excel" to "PDF".  What I didn't like was (1) it put a large empty row at the top of the Excel file even if I removed the "footer row" and "header row" from the format-report window and (2) it was not in cellular, grid form (no gridlines).





                        ADD AN IMAGE TO REPORTVIEWER CONTROL

    This allows you to add an image to a designated region of the report such as header or footer.

    With the Report1.RDLC window open (the format-report window), choose Report > Embedded Images. You should see a window that allows you to browse to the location of the image on your hard drive. Close the browse window and then Choose View > ToolBox and then drag the Image control from the toolbox onto the report.   Here's the tricky part - to get Properties, normally you would rightclick the control (in this case the Image control) and choose properties. That's NOT what you want here because it opens the RDLC properties window, and what you need here is the Vistual Studio Properties Window. So instead hit F4 or choose View Properties to open the Properties window for this image. Look for a property called Source - set it to embedded (must set this field first). THEN look for  a property called Value - it exposes a drop down allowing you to select your image.

            http://msdn2.microsoft.com/en-us/library/ms251715(VS.80).aspx

           
                ADD A BACKGROUND IMAGE TO THE REPORT

    To add an image as the background image for every page of the report (this is pretty cool), from the top of the screen goto Report > Embedded images and add the image - but you should first change the file extension to BMP (just rename the file) to insure that .Net won't ignore the image at runtime. A JPG file seemed to work OK for me if I changed the ext to BMP.


    Then choose F4 or View > Properties  and in the dropdown at the top (the list of controls) choose BODY.  Now look for the Background Image property and choose Embedded image, and in the Value field select your image from the dropdown. You can choose Repeat (the default) to have the image duplicated multiple times on the page (as many times as it will fit). If you want a single instance of the image to fill the page, you should have scaled the image to the page size before adding it to the project.



        `                Adding a Chart

    After you drop a chart control onto the form, use Properties to set what type of chart you are adding. You can choose any of the following chart types: bar, pie, line, stock, area, and bubble.
        http://msdn2.microsoft.com/en-us/library/ms252128(VS.80).aspx

                   




    Sunday, February 24, 2008 8:24 PM
  • dear  friend  ,
     i will  draw some example  here. like that my print page should be like that


    example: 

    Employee Details:
    _____________________________________________________________________________________
     name         age                salary                   designation
    _____________________________________________________________________________________
    sdads        12                  232322                   dasdsada
    asads         34                543443543                 sdfdfs



    Manager Details:
    _____________________________________________________________________________________
     name         age                salary                  rights
    _____________________________________________________________________________________
    sdads        12                  232322                   dasdsada
    asads         34                543443543                 sdfdfs

    i need to create two report  in a same page .becos i have two dataset. so i need to populate the dataset values based on the details. so please show me some sample code to print two reports in the same page. please
    Monday, February 25, 2008 12:41 PM
  •  Born2Achieve wrote:
    dear  friend  ,
     i will  draw some example  here. like that my print page should be like that


    example: 

    Employee Details:
    _____________________________________________________________________________________
     name         age                salary                   designation
    _____________________________________________________________________________________
    sdads        12                  232322                   dasdsada
    asads         34                543443543                 sdfdfs



    Manager Details:
    _____________________________________________________________________________________
     name         age                salary                  rights
    _____________________________________________________________________________________
    sdads        12                  232322                   dasdsada
    asads         34                543443543                 sdfdfs

    i need to create two report  in a same page .becos i have two dataset. so i need to populate the dataset values based on the details. so please show me some sample code to print two reports in the same page. please


    I just tested  ReportViwer on this - it does the above.  Use the notes I gave you to figure out how to get the first table.  And then, for adding the second table,  here's a new section of my notes that I created based on my experience just now doing what you asked:


    SHOW TWO DATATABLES/ REPORTS ON THE SAME PAGE


    You want to display the first datatable at the top of the page, the second datatable at the bottom of the page. Drop two Tables onto your RDLC report. One at the top, the other at the bottom.

     This situation creates a conflict if both datatable are pulling from the same databae, beccause if you drag columns from a single class
        Public Class Customers
    onto the report, ReportViewer is only expecting a single datatable.
               this.reportViewer1.LocalReport.DataSources[0].Value = dtCustomers;
    You will need, therefore,
         Public Class Customers2
    and then drag columns from this second class onto the second table. And in this case you'll need two set two datasoruces:
        ReportViewer1.LocalReport.DataSources(0).Value = datatable1
        ReportViewer1.LocalReport.DataSources(1).Value = datatable2
    But I ran into a  problem. ReportViewer should, but does not alwys, automatically add the second datasource! You can test for this using this code:
         MessageBox.Show(ReportViewer1.LocalReport.DataSources.Count)  ' should be 2 sources in this case
    I don't know how to fix it, I played around with it, and got it working, not sure how. One of the things I played around with was deleting from the Form1 tray, in the Designer, the CustomrBindingSource and Customers2BindingSource icons. Maybe that did the trick. You may also have to click the microscop icon on ReportViwer controla and choose RebindDataSources.        
    - Also I got the following error: "Report item expressions can only refer to fields within the current data set scope". Not sure how I fixed this one either - it was only occurring in my second table. What I did to fix it was, I removed all the columns I had dragged onto this table, and then redragged them on.
    - If you want to put a heading over each of the two reports, drop a textbox above each of them and use F4 to open the Properties window as to set the Value property (the actual heading).





    Tuesday, February 26, 2008 1:55 AM
  • dear jal2,

    i have mentioned that i am using vb.net express edition.so there is no report viewer control.  what shal i do?please
    Tuesday, February 26, 2008 2:48 AM
  • Sorry, didn't realize unavailable for express edition.


    By the way, do you know C#?
    Tuesday, February 26, 2008 11:01 AM
  • Code project has a c# class for printing datagrids on a form.  I figured out  how to make it due two datagrids on one page (took several hours to figure this out).  You can compile it to a DLL using C# express.  The sample code for using it is in C# as well, but it shouldn't be too hard to convert to vb.Net.  First, here's the sample code for using it(drop 2 datagrids on a form).  Includes table headers - and page  headers. It's not perfect, but best I could do on short notice.

     System.Drawing.Printing.PrintDocument printDoc = new System.Drawing.Printing.PrintDocument();
            DataGridViewPrinter gridPrinter;

            private void Form1_Load(object sender, EventArgs e)
            {
                OleDbConnection cn = new OleDbConnection(@"Provider = Microsoft.Jet.OLEDB.4.0; Data Source =C:\Northwind.mdb");
                OleDbDataAdapter da = new OleDbDataAdapter("SELECT  TOP 2   CustomerID  FROM Customers", cn);
                DataTable dt1 = new DataTable("Customers");
                da.Fill(dt1);
                dataGridView1.DataSource = dt1;
                DataTable dt2 = new DataTable();
                da = new OleDbDataAdapter("SELECT  TOP 100  CustomerID,  CompanyName  FROM Customers", cn);
                da.Fill(dt2);
                dataGridView2.DataSource = dt2;
                DataGridView[] grids = new DataGridView[] { dataGridView1, dataGridView2 };
                List<string> tableheaders = new List<string>(new string[] { "Table header 1", "tableHeader 2" });

                //add row numbers for testing purposes only
                foreach (DataTable dt in new DataTable[] { dt1, dt2 })
                {
                    int i = 1;
                    dt.Columns.Add("#");
                    foreach (DataRow row in dt.Rows) row["#"] = Convert.ToString(i++);
                }
                PageSetupDialog dlg = new PageSetupDialog();
                dlg.Document = printDoc;
                dlg.PageSettings.Landscape = false; //you can set this to true.
                printDoc.PrintPage += new System.Drawing.Printing.PrintPageEventHandler(doc_PrintPage);
                Font tableHeaderFont = new Font("New Times Roman", 24, FontStyle.Bold);
                Font pagehederFont = new Font("New Times Roman", 24, FontStyle.Bold);
                gridPrinter = new DataGridViewPrinter(grids, printDoc, true, true, "Here is the Page Header", pagehederFont, Color.Black, true, tableHeaderFont, tableheaders, 50);
                printDoc.Print(); //fires the PrintPage handler below.
            }

            void doc_PrintPage(object sender, System.Drawing.Printing.PrintPageEventArgs e)
            {
                e.HasMorePages = gridPrinter.DrawDataGridView(e.Graphics); //reexecutes each time e.HasMorePages has remained true.
            }
        }

    Tuesday, February 26, 2008 4:13 PM

  • Now here's the class :







    using System;
    using System.Text;
    using System.Collections;
    using System.Collections.Generic;
    using System.Drawing;
    using System.Drawing.Printing;
    using System.Data;
    using System.Windows.Forms;

    class DataGridViewPrinter
    {
        private DataGridView[] TheDataGridViews; // The DataGridView Control which will be printed
        private DataGridView currentGrid;
         private DataGridView lastGrid;
         int intCurrentGridNo  = 1;
        private bool boolDidCalculationsForCurrentGrid = false;
        private PrintDocument ThePrintDocument; // The PrintDocument to be used for printing
        private bool IsCenterOnPage; // Determine if the report will be printed in the Top-Center of the page
        private bool IsWithPageHeader; // Determine if the page contain title text
        private string ThePageHeaderText; // The title text to be printed in each page (if IsWithPageHeader is set to true)
        private Font ThePageHeaderFont; // The font to be used with the title text (if IsWithPageHeader is set to true)
        private Color ThePageHeaderColor; // The color to be used with the title text (if IsWithPageHeader is set to true)
        private bool IsWithPaging; // Determine if paging is used. If false, only the first page prints.
        private Font tableHeaderFont;
        private bool boolDrewHeaderForThisPage = false;
        private int intWhiteSpaceBetweenTables;
        static int CurrentRow; // A static parameter that keep track on which Row (in the DataGridView control) that should be printed

        static int PageNumber;

        private int PageWidth;
        private int PageHeight;
        private int LeftMargin;
        private int TopMargin;
        private int RightMargin;
        private int BottomMargin;

        private float CurrentY; // A parameter that keep track on the y coordinate of the page, so the next object to be printed will start from this y coordinate

        private float RowHeaderHeight;
        private List<float> RowsHeight;
        private List<float> ColumnsWidth;
        private float TheDataGridViewWidth;
        private List<string> TheTableHeaderTexts = new List<string>(); 

        // Maintain a generic list to hold start/stop points for the column printing
        // This will be used for wrapping in situations where the DataGridView will not fit on a single page
       
      
        public List<int[]> mColumnPoints;
        public List<float> mColumnPointsWidth;
        public int mColumnPoint;



        // The class constructor
        public DataGridViewPrinter(DataGridView[] DataGridViews, PrintDocument aPrintDocument, bool CenterOnPage, bool WithPageHeader, string PageHeader, Font PageHeaderFont, Color PageHeaderColor, bool WithPaging, Font ThetableHeaderFont,  List<string> tableHeaderTexts, int WhiteSpaceBetweenTables)
        {
            TheTableHeaderTexts = tableHeaderTexts;
            intWhiteSpaceBetweenTables = WhiteSpaceBetweenTables;
            tableHeaderFont = ThetableHeaderFont ;
            TheDataGridViews = DataGridViews;
            currentGrid = TheDataGridViews[0];
            lastGrid = TheDataGridViews[TheDataGridViews.Length - 1];
            ThePrintDocument = aPrintDocument;
            IsCenterOnPage = CenterOnPage;
            IsWithPageHeader = WithPageHeader;
            ThePageHeaderText = PageHeader;
            ThePageHeaderFont = PageHeaderFont;
            ThePageHeaderColor= PageHeaderColor;
            IsWithPaging = WithPaging;

            PageNumber = 0;

            RowsHeight = new List<float>();
            ColumnsWidth = new List<float>();

            mColumnPoints = new List<int[]>();
            mColumnPointsWidth = new List<float>();

            // Claculating the PageWidth and the PageHeight
            if (!ThePrintDocument.DefaultPageSettings.Landscape)
            {
                PageWidth = ThePrintDocument.DefaultPageSettings.PaperSize.Width;
                PageHeight = ThePrintDocument.DefaultPageSettings.PaperSize.Height;
            }
            else
            {
                PageHeight = ThePrintDocument.DefaultPageSettings.PaperSize.Width;
                PageWidth = ThePrintDocument.DefaultPageSettings.PaperSize.Height;
            }

            // Claculating the page margins
            LeftMargin = ThePrintDocument.DefaultPageSettings.Margins.Left;
            TopMargin = ThePrintDocument.DefaultPageSettings.Margins.Top;
            RightMargin = ThePrintDocument.DefaultPageSettings.Margins.Right;
            BottomMargin = ThePrintDocument.DefaultPageSettings.Margins.Bottom;
            CurrentY = (float)TopMargin;

            // First, the current row to be printed is the first row in the DataGridView control
            CurrentRow = 0;
        }

        // The function that calculate the height of each row (including the header row), the width of each column (according to the longest text in all its cells including the header cell), and the whole DataGridView width
        private void Calculate(Graphics g)
        {
          if (boolDidCalculationsForCurrentGrid) return;
                  SizeF tmpSize = new SizeF();
                Font tmpFont;
                float tmpWidth;

                TheDataGridViewWidth = 0;
                RowsHeight = new List<float>();
                ColumnsWidth = new List<float>();
                mColumnPoints = new List<int[]>();
                mColumnPointsWidth = new List<float>();


                for (int i = 0; i < currentGrid.Columns.Count; i++)
                {
                    tmpFont = currentGrid.ColumnHeadersDefaultCellStyle.Font;
                    if (tmpFont == null) // If there is no special HeaderFont style, then use the default DataGridView font style
                        tmpFont = currentGrid.DefaultCellStyle.Font;

                    tmpSize = g.MeasureString(currentGrid.ColumnsIdea.HeaderText, tmpFont);
                    tmpWidth = tmpSize.Width;
                    RowHeaderHeight = tmpSize.Height;

                    for (int j = 0; j < currentGrid.Rows.Count; j++)
                    {
                        tmpFont = currentGrid.Rows[j].DefaultCellStyle.Font;
                        if (tmpFont == null) // If the there is no special font style of the CurrentRow, then use the default one associated with the DataGridView control
                            tmpFont = currentGrid.DefaultCellStyle.Font;

                        tmpSize = g.MeasureString("Anything", tmpFont);
                        RowsHeight.Add(tmpSize.Height);

                        tmpSize = g.MeasureString(currentGrid.Rows[j].CellsIdea.EditedFormattedValue.ToString(), tmpFont);
                        if (tmpSize.Width > tmpWidth)
                            tmpWidth = tmpSize.Width;
                    }
                    if (currentGrid.ColumnsIdea.Visible)
                        TheDataGridViewWidth += tmpWidth;
                    ColumnsWidth.Add(tmpWidth);
                }

                // Define the start/stop column points based on the page width and the DataGridView Width
                // We will use this to determine the columns which are drawn on each page and how wrapping will be handled
                // By default, the wrapping will occurr such that the maximum number of columns for a page will be determine
                int k;

                int mStartPoint = 0;
                for (k = 0; k < currentGrid.Columns.Count; k++)
                    if (currentGrid.Columns[k].Visible)
                    {
                        mStartPoint = k;
                        break;
                    }

                int mEndPoint = currentGrid.Columns.Count;
                for (k = currentGrid.Columns.Count - 1; k >= 0; k--)
                    if (currentGrid.Columns[k].Visible)
                    {
                        mEndPoint = k + 1;
                        break;
                    }

                float mTempWidth = TheDataGridViewWidth;
                float mTempPrintArea = (float)PageWidth - (float)LeftMargin - (float)RightMargin;

                // We only care about handling where the total datagridview width is bigger then the print area
                if (TheDataGridViewWidth > mTempPrintArea)
                {
                    mTempWidth = 0.0F;
                    for (k = 0; k < currentGrid.Columns.Count; k++)
                    {
                        if (currentGrid.Columns[k].Visible)
                        {
                            mTempWidth += ColumnsWidth[k];
                            // If the width is bigger than the page area, then define a new column print range
                            if (mTempWidth > mTempPrintArea)
                            {
                                mTempWidth -= ColumnsWidth[k];
                                mColumnPoints.Add(new int[] { mStartPoint, mEndPoint });
                                mColumnPointsWidth.Add(mTempWidth);
                                mStartPoint = k;
                                mTempWidth = ColumnsWidth[k];
                            }
                        }
                        // Our end point is actually one index above the current index
                        mEndPoint = k + 1;
                    }
                }
                // Add the last set of columns
                mColumnPoints.Add(new int[] { mStartPoint, mEndPoint });
                mColumnPointsWidth.Add(mTempWidth);
                mColumnPoint = 0;
                boolDidCalculationsForCurrentGrid = true;
            }

        private void DrawTableHeader(Graphics g, string Text, Font tableHeaderFont)
        {
       
                StringFormat TitleFormat = new StringFormat();
                TitleFormat.Trimming = StringTrimming.Word;
                TitleFormat.FormatFlags = StringFormatFlags.NoWrap | StringFormatFlags.LineLimit | StringFormatFlags.NoClip;
               
                if (IsCenterOnPage)
                    TitleFormat.Alignment = StringAlignment.Center;
                else
                    TitleFormat.Alignment = StringAlignment.Near;
                RectangleF TitleRectangle = new RectangleF((float)LeftMargin, CurrentY, (float)PageWidth - (float)RightMargin - (float)LeftMargin, g.MeasureString(ThePageHeaderText, tableHeaderFont ).Height);
                g.DrawString(Text, tableHeaderFont, new SolidBrush(Color.Black), TitleRectangle, TitleFormat);
                CurrentY += g.MeasureString(Text,  tableHeaderFont).Height;
       
        }

        // The funtion that print the title, page number, and the header row
        private void DrawPageHeader(Graphics g)
        {
      
            // Printing the page number (if isWithPaging is set to true)
            if (IsWithPaging)
            {
                PageNumber++;
                string PageString = "Page " + PageNumber.ToString();
                StringFormat PageStringFormat = new StringFormat();
                PageStringFormat.Trimming = StringTrimming.Word;
                PageStringFormat.FormatFlags = StringFormatFlags.NoWrap | StringFormatFlags.LineLimit | StringFormatFlags.NoClip;
                PageStringFormat.Alignment = StringAlignment.Far;
                //bk
                Font PageStringFont = new Font("Tahoma", 8, FontStyle.Regular, GraphicsUnit.Point);
                float yCoord = (float)TopMargin;
                RectangleF PageStringRectangle = new RectangleF((float)LeftMargin, yCoord, (float)PageWidth - (float)RightMargin - (float)LeftMargin, g.MeasureString(PageString, PageStringFont).Height);
                g.DrawString(PageString, PageStringFont, new SolidBrush(Color.Black), PageStringRectangle, PageStringFormat);
                CurrentY += g.MeasureString(PageString, PageStringFont).Height;
              


            }

            // Printing the title (if IsWithPageHeader is set to true)
            if (IsWithPageHeader)
            {
                StringFormat TitleFormat = new StringFormat();
                TitleFormat.Trimming = StringTrimming.Word;
                TitleFormat.FormatFlags = StringFormatFlags.NoWrap | StringFormatFlags.LineLimit | StringFormatFlags.NoClip;
                if (IsCenterOnPage)
                    TitleFormat.Alignment = StringAlignment.Center;
                else
                    TitleFormat.Alignment = StringAlignment.Near;

                RectangleF TitleRectangle = new RectangleF((float)LeftMargin, CurrentY, (float)PageWidth - (float)RightMargin - (float)LeftMargin, g.MeasureString(ThePageHeaderText, ThePageHeaderFont).Height);

                g.DrawString(ThePageHeaderText, ThePageHeaderFont, new SolidBrush(ThePageHeaderColor), TitleRectangle, TitleFormat);

                CurrentY += g.MeasureString(ThePageHeaderText, ThePageHeaderFont).Height;
            }

        }
        private void calculateStartingPoints(Graphics g)
        {
            // Calculating the starting x coordinate that the printing process will start from
            float CurrentX = (float)LeftMargin;
            if (IsCenterOnPage)
                CurrentX += (((float)PageWidth - (float)RightMargin - (float)LeftMargin) - mColumnPointsWidth[mColumnPoint]) / 2.0F;

            // Setting the HeaderFore style
            Color HeaderForeColor = currentGrid.ColumnHeadersDefaultCellStyle.ForeColor;
            if (HeaderForeColor.IsEmpty) // If there is no special HeaderFore style, then use the default DataGridView style
                HeaderForeColor = currentGrid.DefaultCellStyle.ForeColor;
            SolidBrush HeaderForeBrush = new SolidBrush(HeaderForeColor);

            // Setting the HeaderBack style
            Color HeaderBackColor = currentGrid.ColumnHeadersDefaultCellStyle.BackColor;
            if (HeaderBackColor.IsEmpty) // If there is no special HeaderBack style, then use the default DataGridView style
                HeaderBackColor = currentGrid.DefaultCellStyle.BackColor;
            SolidBrush HeaderBackBrush = new SolidBrush(HeaderBackColor);

            // Setting the LinePen that will be used to draw lines and rectangles (derived from the GridColor property of the DataGridView control)
            Pen TheLinePen = new Pen(currentGrid.GridColor, 1);

            // Setting the HeaderFont style
            Font HeaderFont = currentGrid.ColumnHeadersDefaultCellStyle.Font;
            if (HeaderFont == null) // If there is no special HeaderFont style, then use the default DataGridView font style
                HeaderFont = currentGrid.DefaultCellStyle.Font;

            // Calculating and drawing the HeaderBounds       
            RectangleF HeaderBounds = new RectangleF(CurrentX, CurrentY, mColumnPointsWidth[mColumnPoint], RowHeaderHeight);
            g.FillRectangle(HeaderBackBrush, HeaderBounds);

            // Setting the format that will be used to print each cell of the header row
            StringFormat CellFormat = new StringFormat();
            CellFormat.Trimming = StringTrimming.Word;
            CellFormat.FormatFlags = StringFormatFlags.NoWrap | StringFormatFlags.LineLimit | StringFormatFlags.NoClip;

            // Printing each visible cell of the header row
            RectangleF CellBounds;
            float ColumnWidth;
            for (int i = (int)mColumnPoints[mColumnPoint].GetValue(0); i < (int)mColumnPoints[mColumnPoint].GetValue(1); i++)
            {
                if (!currentGrid.ColumnsIdea.Visible) continue; // If the column is not visible then ignore this iteration

                ColumnWidth = ColumnsWidthIdea;

                // Check the CurrentCell alignment and apply it to the CellFormat
                if (currentGrid.ColumnHeadersDefaultCellStyle.Alignment.ToString().Contains("Right"))
                    CellFormat.Alignment = StringAlignment.Far;
                else if (currentGrid.ColumnHeadersDefaultCellStyle.Alignment.ToString().Contains("Center"))
                    CellFormat.Alignment = StringAlignment.Center;
                else
                    CellFormat.Alignment = StringAlignment.Near;

                CellBounds = new RectangleF(CurrentX, CurrentY, ColumnWidth, RowHeaderHeight);

                // Printing the cell text
                g.DrawString(currentGrid.ColumnsIdea.HeaderText, HeaderFont, HeaderForeBrush, CellBounds, CellFormat);

                // Drawing the cell bounds
                if (currentGrid.RowHeadersBorderStyle != DataGridViewHeaderBorderStyle.None) // Draw the cell border only if the HeaderBorderStyle is not None
                    g.DrawRectangle(TheLinePen, CurrentX, CurrentY, ColumnWidth, RowHeaderHeight);

                CurrentX += ColumnWidth;
            }

            CurrentY += RowHeaderHeight;
        }

        // The function that print a bunch of rows that fit in one page
        // When it returns true, meaning that there are more rows still not printed, so another PagePrint action is required
        // When it returns false, meaning that all rows are printed (the CureentRow parameter reaches the last row of the DataGridView control) and no further PagePrint action is required
        private bool DrawRows(Graphics g)
        {
            // Setting the LinePen that will be used to draw lines and rectangles (derived from the GridColor property of the DataGridView control)
            Pen TheLinePen = new Pen(currentGrid.GridColor, 1);

            // The style paramters that will be used to print each cell
            Font RowFont;
            Color RowForeColor;
            Color RowBackColor;
            SolidBrush RowForeBrush;
            SolidBrush RowBackBrush;
            SolidBrush RowAlternatingBackBrush;

            // Setting the format that will be used to print each cell
            StringFormat CellFormat = new StringFormat();
            CellFormat.Trimming = StringTrimming.Word;
            CellFormat.FormatFlags = StringFormatFlags.NoWrap | StringFormatFlags.LineLimit;

            // Printing each visible cell
            RectangleF RowBounds;
            float CurrentX;
            float ColumnWidth;
            boolDrewHeaderForThisPage = false;
            CurrentY = (float)TopMargin;
            DrawPageHeader(g);
            while (true)
            {
                if (CurrentRow == 0)
                {
                    boolDidCalculationsForCurrentGrid = false;
                    Calculate(g);
                    DrawTableHeader(g, TheTableHeaderTexts[intCurrentGridNo -1], tableHeaderFont);
                    calculateStartingPoints(g);
                }
                if (currentGrid.Rows[CurrentRow].Visible) // Print the cells of the CurrentRow only if that row is visible
                {
                    // Setting the row font style
                    RowFont = currentGrid.Rows[CurrentRow].DefaultCellStyle.Font;
                    if (RowFont == null) // If the there is no special font style of the CurrentRow, then use the default one associated with the DataGridView control
                        RowFont = currentGrid.DefaultCellStyle.Font;

                    // Setting the RowFore style
                    RowForeColor = currentGrid.Rows[CurrentRow].DefaultCellStyle.ForeColor;
                    if (RowForeColor.IsEmpty) // If the there is no special RowFore style of the CurrentRow, then use the default one associated with the DataGridView control
                        RowForeColor = currentGrid.DefaultCellStyle.ForeColor;
                    RowForeBrush = new SolidBrush(RowForeColor);

                    // Setting the RowBack (for even rows) and the RowAlternatingBack (for odd rows) styles
                    RowBackColor = currentGrid.Rows[CurrentRow].DefaultCellStyle.BackColor;
                    if (RowBackColor.IsEmpty) // If the there is no special RowBack style of the CurrentRow, then use the default one associated with the DataGridView control
                    {
                        RowBackBrush = new SolidBrush(currentGrid.DefaultCellStyle.BackColor);
                        RowAlternatingBackBrush = new SolidBrush(currentGrid.AlternatingRowsDefaultCellStyle.BackColor);
                    }
                    else // If the there is a special RowBack style of the CurrentRow, then use it for both the RowBack and the RowAlternatingBack styles
                    {
                        RowBackBrush = new SolidBrush(RowBackColor);
                        RowAlternatingBackBrush = new SolidBrush(RowBackColor);
                    }

                    // Calculating the starting x coordinate that the printing process will start from
                    CurrentX = (float)LeftMargin;
                    if (IsCenterOnPage)
                        CurrentX += (((float)PageWidth - (float)RightMargin - (float)LeftMargin) - mColumnPointsWidth[mColumnPoint]) / 2.0F;

                    // Calculating the entire CurrentRow bounds               
                    RowBounds = new RectangleF(CurrentX, CurrentY, mColumnPointsWidth[mColumnPoint], RowsHeight[CurrentRow]);

                    // Filling the back of the CurrentRow
                    if (CurrentRow % 2 == 0)
                        g.FillRectangle(RowBackBrush, RowBounds);
                    else
                        g.FillRectangle(RowAlternatingBackBrush, RowBounds);

                    // Printing each visible cell of the CurrentRow               
                    for (int CurrentCell = (int)mColumnPoints[mColumnPoint].GetValue(0); CurrentCell < (int)mColumnPoints[mColumnPoint].GetValue(1); CurrentCell++)
                    {
                        if (!currentGrid.Columns[CurrentCell].Visible) continue; // If the cell is belong to invisible column, then ignore this iteration

                        // Check the CurrentCell alignment and apply it to the CellFormat
                        if (currentGrid.Columns[CurrentCell].DefaultCellStyle.Alignment.ToString().Contains("Right"))
                            CellFormat.Alignment = StringAlignment.Far;
                        else if (currentGrid.Columns[CurrentCell].DefaultCellStyle.Alignment.ToString().Contains("Center"))
                            CellFormat.Alignment = StringAlignment.Center;
                        else
                            CellFormat.Alignment = StringAlignment.Near;

                        ColumnWidth = ColumnsWidth[CurrentCell];
                        RectangleF CellBounds = new RectangleF(CurrentX, CurrentY, ColumnWidth, RowsHeight[CurrentRow]);

                        // Printing the cell text
                        g.DrawString(currentGrid.Rows[CurrentRow].Cells[CurrentCell].EditedFormattedValue.ToString(), RowFont, RowForeBrush, CellBounds, CellFormat);

                        // Drawing the cell bounds
                        if (currentGrid.CellBorderStyle != DataGridViewCellBorderStyle.None) // Draw the cell border only if the CellBorderStyle is not None
                            g.DrawRectangle(TheLinePen, CurrentX, CurrentY, ColumnWidth, RowsHeight[CurrentRow]);

                        CurrentX += ColumnWidth;
                    }
                    CurrentY += RowsHeight[CurrentRow];

                    // Checking if the CurrentY is exceeds the page boundries
                    // If so then exit the function and returning true meaning another PagePrint action is required
                       if ((int)CurrentY > (PageHeight - TopMargin - BottomMargin))
                    {
                        CurrentRow++;
                        return true;
                    }
                }

                CurrentRow++;
                if (CurrentRow > currentGrid.Rows.Count - 1)
                {
                   
                    if (intCurrentGridNo < TheDataGridViews.Length)
                    {
                        CurrentRow = 0;
                        intCurrentGridNo += 1;
                        CurrentY += intWhiteSpaceBetweenTables;
                        currentGrid = TheDataGridViews[intCurrentGridNo - 1];
                    }
                    else return false;
                      
                   
                }
            }
       
            CurrentRow = 0;
            mColumnPoint++; // Continue to print the next group of columns

            if (mColumnPoint == mColumnPoints.Count) // Which means all columns are printed
            {
                mColumnPoint = 0;
                return false;
            }
            else
                return true;
        }
       

        // The method that calls all other functions
        public bool DrawDataGridView(Graphics g)
        {
         
              
                   
                    bool bContinue = DrawRows(g);
                     return bContinue;
              

      
           

        }
    }



    Tuesday, February 26, 2008 4:17 PM
  • dear jal2,

    thanks for reply  friend . i tried your code. but it shows error in the followinfg systax:

    ColumnWidth = ColumnsWidthIdea;
    tmpSize = g.MeasureString(currentGrid.Rows[j].CellsIdea.EditedFormattedValue.ToString(), tmpFont);

    g.DrawString(currentGrid.ColumnsIdea.HeaderText, HeaderFont, HeaderForeBrush, CellBounds, CellFormat);

    so please send your class file to the following mail id please.  so that that would be very helpful for me friend please. how t orectify the error  please help me

    talk2karthik@hotmail.com
    Tuesday, February 26, 2008 4:55 PM
  • Not letting me do it all in one post - too long. I'll put the 2nd half next.

     

    Code Snippet

    using System;

    using System.Text;

    using System.Collections;

    using System.Collections.Generic;

    using System.Drawing;

    using System.Drawing.Printing;

    using System.Data;

    using System.Windows.Forms;

    class DataGridViewPrinter

    {

    private DataGridView[] TheDataGridViews; // The DataGridView Control which will be printed

    private DataGridView currentGrid;

    private DataGridView lastGrid;

    int intCurrentGridNo = 1;

    private bool boolDidCalculationsForCurrentGrid = false;

    private PrintDocument ThePrintDocument; // The PrintDocument to be used for printing

    private bool IsCenterOnPage; // Determine if the report will be printed in the Top-Center of the page

    private bool IsWithPageHeader; // Determine if the page contain title text

    private string ThePageHeaderText; // The title text to be printed in each page (if IsWithPageHeader is set to true)

    private Font ThePageHeaderFont; // The font to be used with the title text (if IsWithPageHeader is set to true)

    private Color ThePageHeaderColor; // The color to be used with the title text (if IsWithPageHeader is set to true)

    private bool IsWithPaging; // Determine if paging is used. If false, only the first page prints.

    private Font tableHeaderFont;

    private bool boolDrewHeaderForThisPage = false;

    private int intWhiteSpaceBetweenTables;

    static int CurrentRow; // A static parameter that keep track on which Row (in the DataGridView control) that should be printed

    static int PageNumber;

    private int PageWidth;

    private int PageHeight;

    private int LeftMargin;

    private int TopMargin;

    private int RightMargin;

    private int BottomMargin;

    private float CurrentY; // A parameter that keep track on the y coordinate of the page, so the next object to be printed will start from this y coordinate

    private float RowHeaderHeight;

    private List<float> RowsHeight;

    private List<float> ColumnsWidth;

    private float TheDataGridViewWidth;

    private List<string> TheTableHeaderTexts = new List<string>();

    // Maintain a generic list to hold start/stop points for the column printing

    // This will be used for wrapping in situations where the DataGridView will not fit on a single page

     

    public List<int[]> mColumnPoints;

    public List<float> mColumnPointsWidth;

    public int mColumnPoint;

     

     

    // The class constructor

    public DataGridViewPrinter(DataGridView[] DataGridViews, PrintDocument aPrintDocument, bool CenterOnPage, bool WithPageHeader, string PageHeader, Font PageHeaderFont, Color PageHeaderColor, bool WithPaging, Font ThetableHeaderFont, List<string> tableHeaderTexts, int WhiteSpaceBetweenTables)

    {

    TheTableHeaderTexts = tableHeaderTexts;

    intWhiteSpaceBetweenTables = WhiteSpaceBetweenTables;

    tableHeaderFont = ThetableHeaderFont;

    TheDataGridViews = DataGridViews;

    currentGrid = TheDataGridViews[0];

    lastGrid = TheDataGridViews[TheDataGridViews.Length - 1];

    ThePrintDocument = aPrintDocument;

    IsCenterOnPage = CenterOnPage;

    IsWithPageHeader = WithPageHeader;

    ThePageHeaderText = PageHeader;

    ThePageHeaderFont = PageHeaderFont;

    ThePageHeaderColor = PageHeaderColor;

    IsWithPaging = WithPaging;

    PageNumber = 0;

    RowsHeight = new List<float>();

    ColumnsWidth = new List<float>();

    mColumnPoints = new List<int[]>();

    mColumnPointsWidth = new List<float>();

    // Claculating the PageWidth and the PageHeight

    if (!ThePrintDocument.DefaultPageSettings.Landscape)

    {

    PageWidth = ThePrintDocument.DefaultPageSettings.PaperSize.Width;

    PageHeight = ThePrintDocument.DefaultPageSettings.PaperSize.Height;

    }

    else

    {

    PageHeight = ThePrintDocument.DefaultPageSettings.PaperSize.Width;

    PageWidth = ThePrintDocument.DefaultPageSettings.PaperSize.Height;

    }

    // Claculating the page margins

    LeftMargin = ThePrintDocument.DefaultPageSettings.Margins.Left;

    TopMargin = ThePrintDocument.DefaultPageSettings.Margins.Top;

    RightMargin = ThePrintDocument.DefaultPageSettings.Margins.Right;

    BottomMargin = ThePrintDocument.DefaultPageSettings.Margins.Bottom;

    CurrentY = (float)TopMargin;

    // First, the current row to be printed is the first row in the DataGridView control

    CurrentRow = 0;

    }

    // The function that calculate the height of each row (including the header row), the width of each column (according to the longest text in all its cells including the header cell), and the whole DataGridView width

    private void Calculate(Graphics g)

    {

    if (boolDidCalculationsForCurrentGrid) return;

    SizeF tmpSize = new SizeF();

    Font tmpFont;

    float tmpWidth;

    TheDataGridViewWidth = 0;

    RowsHeight = new List<float>();

    ColumnsWidth = new List<float>();

    mColumnPoints = new List<int[]>();

    mColumnPointsWidth = new List<float>();

     

    for (int i = 0; i < currentGrid.Columns.Count; i++)

    {

    tmpFont = currentGrid.ColumnHeadersDefaultCellStyle.Font;

    if (tmpFont == null) // If there is no special HeaderFont style, then use the default DataGridView font style

    tmpFont = currentGrid.DefaultCellStyle.Font;

    tmpSize = g.MeasureString(currentGrid.Columns[i].HeaderText, tmpFont);

    tmpWidth = tmpSize.Width;

    RowHeaderHeight = tmpSize.Height;

    for (int j = 0; j < currentGrid.Rows.Count; j++)

    {

    tmpFont = currentGrid.Rows[j].DefaultCellStyle.Font;

    if (tmpFont == null) // If the there is no special font style of the CurrentRow, then use the default one associated with the DataGridView control

    tmpFont = currentGrid.DefaultCellStyle.Font;

    tmpSize = g.MeasureString("Anything", tmpFont);

    RowsHeight.Add(tmpSize.Height);

    tmpSize = g.MeasureString(currentGrid.Rows[j].Cells[i].EditedFormattedValue.ToString(), tmpFont);

    if (tmpSize.Width > tmpWidth)

    tmpWidth = tmpSize.Width;

    }

    if (currentGrid.Columns[i].Visible)

    TheDataGridViewWidth += tmpWidth;

    ColumnsWidth.Add(tmpWidth);

    }

    // Define the start/stop column points based on the page width and the DataGridView Width

    // We will use this to determine the columns which are drawn on each page and how wrapping will be handled

    // By default, the wrapping will occurr such that the maximum number of columns for a page will be determine

    int k;

    int mStartPoint = 0;

    for (k = 0; k < currentGrid.Columns.Count; k++)

    if (currentGrid.Columns[k].Visible)

    {

    mStartPoint = k;

    break;

    }

    int mEndPoint = currentGrid.Columns.Count;

    for (k = currentGrid.Columns.Count - 1; k >= 0; k--)

    if (currentGrid.Columns[k].Visible)

    {

    mEndPoint = k + 1;

    break;

    }

    float mTempWidth = TheDataGridViewWidth;

    float mTempPrintArea = (float)PageWidth - (float)LeftMargin - (float)RightMargin;

    // We only care about handling where the total datagridview width is bigger then the print area

    if (TheDataGridViewWidth > mTempPrintArea)

    {

    mTempWidth = 0.0F;

    for (k = 0; k < currentGrid.Columns.Count; k++)

    {

    if (currentGrid.Columns[k].Visible)

    {

    mTempWidth += ColumnsWidth[k];

    // If the width is bigger than the page area, then define a new column print range

    if (mTempWidth > mTempPrintArea)

    {

    mTempWidth -= ColumnsWidth[k];

    mColumnPoints.Add(new int[] { mStartPoint, mEndPoint });

    mColumnPointsWidth.Add(mTempWidth);

    mStartPoint = k;

    mTempWidth = ColumnsWidth[k];

    }

    }

    // Our end point is actually one index above the current index

    mEndPoint = k + 1;

    }

    }

    // Add the last set of columns

    mColumnPoints.Add(new int[] { mStartPoint, mEndPoint });

    mColumnPointsWidth.Add(mTempWidth);

    mColumnPoint = 0;

    boolDidCalculationsForCurrentGrid = true;

    }

    private void DrawTableHeader(Graphics g, string Text, Font tableHeaderFont)

    {

    StringFormat TitleFormat = new StringFormat();

    TitleFormat.Trimming = StringTrimming.Word;

    TitleFormat.FormatFlags = StringFormatFlags.NoWrap | StringFormatFlags.LineLimit | StringFormatFlags.NoClip;

    if (IsCenterOnPage)

    TitleFormat.Alignment = StringAlignment.Center;

    else

    TitleFormat.Alignment = StringAlignment.Near;

    RectangleF TitleRectangle = new RectangleF((float)LeftMargin, CurrentY, (float)PageWidth - (float)RightMargin - (float)LeftMargin, g.MeasureString(ThePageHeaderText, tableHeaderFont).Height);

    g.DrawString(Text, tableHeaderFont, new SolidBrush(Color.Black), TitleRectangle, TitleFormat);

    CurrentY += g.MeasureString(Text, tableHeaderFont).Height;

    }

    // The funtion that print the title, page number, and the header row

    private void DrawPageHeader(Graphics g)

    {

    // Printing the page number (if isWithPaging is set to true)

    if (IsWithPaging)

    {

    PageNumber++;

    string PageString = "Page " + PageNumber.ToString();

    StringFormat PageStringFormat = new StringFormat();

    PageStringFormat.Trimming = StringTrimming.Word;

    PageStringFormat.FormatFlags = StringFormatFlags.NoWrap | StringFormatFlags.LineLimit | StringFormatFlags.NoClip;

    PageStringFormat.Alignment = StringAlignment.Far;

    //bk

    Font PageStringFont = new Font("Tahoma", 8, FontStyle.Regular, GraphicsUnit.Point);

    float yCoord = (float)TopMargin;

    RectangleF PageStringRectangle = new RectangleF((float)LeftMargin, yCoord, (float)PageWidth - (float)RightMargin - (float)LeftMargin, g.MeasureString(PageString, PageStringFont).Height);

    g.DrawString(PageString, PageStringFont, new SolidBrush(Color.Black), PageStringRectangle, PageStringFormat);

    CurrentY += g.MeasureString(PageString, PageStringFont).Height;

     

     

    }

    // Printing the title (if IsWithPageHeader is set to true)

    if (IsWithPageHeader)

    {

    StringFormat TitleFormat = new StringFormat();

    TitleFormat.Trimming = StringTrimming.Word;

    TitleFormat.FormatFlags = StringFormatFlags.NoWrap | StringFormatFlags.LineLimit | StringFormatFlags.NoClip;

    if (IsCenterOnPage)

    TitleFormat.Alignment = StringAlignment.Center;

    else

    TitleFormat.Alignment = StringAlignment.Near;

    RectangleF TitleRectangle = new RectangleF((float)LeftMargin, CurrentY, (float)PageWidth - (float)RightMargin - (float)LeftMargin, g.MeasureString(ThePageHeaderText, ThePageHeaderFont).Height);

    g.DrawString(ThePageHeaderText, ThePageHeaderFont, new SolidBrush(ThePageHeaderColor), TitleRectangle, TitleFormat);

    CurrentY += g.MeasureString(ThePageHeaderText, ThePageHeaderFont).Height;

    }

    }

    Tuesday, February 26, 2008 10:34 PM
  • Code Snippet

     

    private void calculateStartingPoints(Graphics g)

    {

    // Calculating the starting x coordinate that the printing process will start from

    float CurrentX = (float)LeftMargin;

    if (IsCenterOnPage)

    CurrentX += (((float)PageWidth - (float)RightMargin - (float)LeftMargin) - mColumnPointsWidth[mColumnPoint]) / 2.0F;

    // Setting the HeaderFore style

    Color HeaderForeColor = currentGrid.ColumnHeadersDefaultCellStyle.ForeColor;

    if (HeaderForeColor.IsEmpty) // If there is no special HeaderFore style, then use the default DataGridView style

    HeaderForeColor = currentGrid.DefaultCellStyle.ForeColor;

    SolidBrush HeaderForeBrush = new SolidBrush(HeaderForeColor);

    // Setting the HeaderBack style

    Color HeaderBackColor = currentGrid.ColumnHeadersDefaultCellStyle.BackColor;

    if (HeaderBackColor.IsEmpty) // If there is no special HeaderBack style, then use the default DataGridView style

    HeaderBackColor = currentGrid.DefaultCellStyle.BackColor;

    SolidBrush HeaderBackBrush = new SolidBrush(HeaderBackColor);

    // Setting the LinePen that will be used to draw lines and rectangles (derived from the GridColor property of the DataGridView control)

    Pen TheLinePen = new Pen(currentGrid.GridColor, 1);

    // Setting the HeaderFont style

    Font HeaderFont = currentGrid.ColumnHeadersDefaultCellStyle.Font;

    if (HeaderFont == null) // If there is no special HeaderFont style, then use the default DataGridView font style

    HeaderFont = currentGrid.DefaultCellStyle.Font;

    // Calculating and drawing the HeaderBounds

    RectangleF HeaderBounds = new RectangleF(CurrentX, CurrentY, mColumnPointsWidth[mColumnPoint], RowHeaderHeight);

    g.FillRectangle(HeaderBackBrush, HeaderBounds);

    // Setting the format that will be used to print each cell of the header row

    StringFormat CellFormat = new StringFormat();

    CellFormat.Trimming = StringTrimming.Word;

    CellFormat.FormatFlags = StringFormatFlags.NoWrap | StringFormatFlags.LineLimit | StringFormatFlags.NoClip;

    // Printing each visible cell of the header row

    RectangleF CellBounds;

    float ColumnWidth;

    for (int i = (int)mColumnPoints[mColumnPoint].GetValue(0); i < (int)mColumnPoints[mColumnPoint].GetValue(1); i++)

    {

    if (!currentGrid.Columns[i].Visible) continue; // If the column is not visible then ignore this iteration

    ColumnWidth = ColumnsWidth[i];

    // Check the CurrentCell alignment and apply it to the CellFormat

    if (currentGrid.ColumnHeadersDefaultCellStyle.Alignment.ToString().Contains("Right"))

    CellFormat.Alignment = StringAlignment.Far;

    else if (currentGrid.ColumnHeadersDefaultCellStyle.Alignment.ToString().Contains("Center"))

    CellFormat.Alignment = StringAlignment.Center;

    else

    CellFormat.Alignment = StringAlignment.Near;

    CellBounds = new RectangleF(CurrentX, CurrentY, ColumnWidth, RowHeaderHeight);

    // Printing the cell text

    g.DrawString(currentGrid.Columns[i].HeaderText, HeaderFont, HeaderForeBrush, CellBounds, CellFormat);

    // Drawing the cell bounds

    if (currentGrid.RowHeadersBorderStyle != DataGridViewHeaderBorderStyle.None) // Draw the cell border only if the HeaderBorderStyle is not None

    g.DrawRectangle(TheLinePen, CurrentX, CurrentY, ColumnWidth, RowHeaderHeight);

    CurrentX += ColumnWidth;

    }

    CurrentY += RowHeaderHeight;

    }

    // The function that print a bunch of rows that fit in one page

    // When it returns true, meaning that there are more rows still not printed, so another PagePrint action is required

    // When it returns false, meaning that all rows are printed (the CureentRow parameter reaches the last row of the DataGridView control) and no further PagePrint action is required

    private bool DrawRows(Graphics g)

    {

    // Setting the LinePen that will be used to draw lines and rectangles (derived from the GridColor property of the DataGridView control)

    Pen TheLinePen = new Pen(currentGrid.GridColor, 1);

    // The style paramters that will be used to print each cell

    Font RowFont;

    Color RowForeColor;

    Color RowBackColor;

    SolidBrush RowForeBrush;

    SolidBrush RowBackBrush;

    SolidBrush RowAlternatingBackBrush;

    // Setting the format that will be used to print each cell

    StringFormat CellFormat = new StringFormat();

    CellFormat.Trimming = StringTrimming.Word;

    CellFormat.FormatFlags = StringFormatFlags.NoWrap | StringFormatFlags.LineLimit;

    // Printing each visible cell

    RectangleF RowBounds;

    float CurrentX;

    float ColumnWidth;

    boolDrewHeaderForThisPage = false;

    CurrentY = (float)TopMargin;

    DrawPageHeader(g);

    while (true)

    {

    if (CurrentRow == 0)

    {

    boolDidCalculationsForCurrentGrid = false;

    Calculate(g);

    DrawTableHeader(g, TheTableHeaderTexts[intCurrentGridNo - 1], tableHeaderFont);

    calculateStartingPoints(g);

    }

    if (currentGrid.Rows[CurrentRow].Visible) // Print the cells of the CurrentRow only if that row is visible

    {

    // Setting the row font style

    RowFont = currentGrid.Rows[CurrentRow].DefaultCellStyle.Font;

    if (RowFont == null) // If the there is no special font style of the CurrentRow, then use the default one associated with the DataGridView control

    RowFont = currentGrid.DefaultCellStyle.Font;

    // Setting the RowFore style

    RowForeColor = currentGrid.Rows[CurrentRow].DefaultCellStyle.ForeColor;

    if (RowForeColor.IsEmpty) // If the there is no special RowFore style of the CurrentRow, then use the default one associated with the DataGridView control

    RowForeColor = currentGrid.DefaultCellStyle.ForeColor;

    RowForeBrush = new SolidBrush(RowForeColor);

    // Setting the RowBack (for even rows) and the RowAlternatingBack (for odd rows) styles

    RowBackColor = currentGrid.Rows[CurrentRow].DefaultCellStyle.BackColor;

    if (RowBackColor.IsEmpty) // If the there is no special RowBack style of the CurrentRow, then use the default one associated with the DataGridView control

    {

    RowBackBrush = new SolidBrush(currentGrid.DefaultCellStyle.BackColor);

    RowAlternatingBackBrush = new SolidBrush(currentGrid.AlternatingRowsDefaultCellStyle.BackColor);

    }

    else // If the there is a special RowBack style of the CurrentRow, then use it for both the RowBack and the RowAlternatingBack styles

    {

    RowBackBrush = new SolidBrush(RowBackColor);

    RowAlternatingBackBrush = new SolidBrush(RowBackColor);

    }

    // Calculating the starting x coordinate that the printing process will start from

    CurrentX = (float)LeftMargin;

    if (IsCenterOnPage)

    CurrentX += (((float)PageWidth - (float)RightMargin - (float)LeftMargin) - mColumnPointsWidth[mColumnPoint]) / 2.0F;

    // Calculating the entire CurrentRow bounds

    RowBounds = new RectangleF(CurrentX, CurrentY, mColumnPointsWidth[mColumnPoint], RowsHeight[CurrentRow]);

    // Filling the back of the CurrentRow

    if (CurrentRow % 2 == 0)

    g.FillRectangle(RowBackBrush, RowBounds);

    else

    g.FillRectangle(RowAlternatingBackBrush, RowBounds);

    // Printing each visible cell of the CurrentRow

    for (int CurrentCell = (int)mColumnPoints[mColumnPoint].GetValue(0); CurrentCell < (int)mColumnPoints[mColumnPoint].GetValue(1); CurrentCell++)

    {

    if (!currentGrid.Columns[CurrentCell].Visible) continue; // If the cell is belong to invisible column, then ignore this iteration

    // Check the CurrentCell alignment and apply it to the CellFormat

    if (currentGrid.Columns[CurrentCell].DefaultCellStyle.Alignment.ToString().Contains("Right"))

    CellFormat.Alignment = StringAlignment.Far;

    else if (currentGrid.Columns[CurrentCell].DefaultCellStyle.Alignment.ToString().Contains("Center"))

    CellFormat.Alignment = StringAlignment.Center;

    else

    CellFormat.Alignment = StringAlignment.Near;

    ColumnWidth = ColumnsWidth[CurrentCell];

    RectangleF CellBounds = new RectangleF(CurrentX, CurrentY, ColumnWidth, RowsHeight[CurrentRow]);

    // Printing the cell text

    g.DrawString(currentGrid.Rows[CurrentRow].Cells[CurrentCell].EditedFormattedValue.ToString(), RowFont, RowForeBrush, CellBounds, CellFormat);

    // Drawing the cell bounds

    if (currentGrid.CellBorderStyle != DataGridViewCellBorderStyle.None) // Draw the cell border only if the CellBorderStyle is not None

    g.DrawRectangle(TheLinePen, CurrentX, CurrentY, ColumnWidth, RowsHeight[CurrentRow]);

    CurrentX += ColumnWidth;

    }

    CurrentY += RowsHeight[CurrentRow];

    // Checking if the CurrentY is exceeds the page boundries

    // If so then exit the function and returning true meaning another PagePrint action is required

    if ((int)CurrentY > (PageHeight - TopMargin - BottomMargin))

    {

    CurrentRow++;

    return true;

    }

    }

    CurrentRow++;

    if (CurrentRow > currentGrid.Rows.Count - 1)

    {

    if (intCurrentGridNo < TheDataGridViews.Length)

    {

    CurrentRow = 0;

    intCurrentGridNo += 1;

    CurrentY += intWhiteSpaceBetweenTables;

    currentGrid = TheDataGridViews[intCurrentGridNo - 1];

    }

    else return false;

     

    }

    }

    CurrentRow = 0;

    mColumnPoint++; // Continue to print the next group of columns

    if (mColumnPoint == mColumnPoints.Count) // Which means all columns are printed

    {

    mColumnPoint = 0;

    return false;

    }

    else

    return true;

    }

     

    // The method that calls all other functions

    public bool DrawDataGridView(Graphics g)

    {

    bool bContinue = DrawRows(g);

    return bContinue;

    }

    }

     

     

     

    Tuesday, February 26, 2008 10:36 PM
  • dear jal2,

     thanks a lot for the reply. really very very thank u for spending time for me friend.i started  to work your code. so if i face any problem i will get back to you
    Wednesday, February 27, 2008 4:46 AM
  • Hi

    That looks like a really great bit of code.  I have converted it to VB.NET, to use in a project I'm doing, but I have a problem when I try to initialize a variable "g" as the Graphics value for the DrawDataGrid Method.  It says that System.Drawing.Graphics has no constructors.

    What do I need to do?

    Thanks
    Guy Joseph - Intel Quad Q9450, 4Gb Ram, 1Tb Hard Drive, NVidia 8800GT, Marian Marc 8, VB Express 2008
    Friday, June 19, 2009 9:36 AM
  • Hello jal2, You seem like you know what you're doing.. i've got a slight problem... if you could help me that would be awesome thank you....

    I'm using 3 tables, Primary, Secondary and Tertiary,
    how do i get all three datagridview's to show for print preview and print on one form?? Any idea what the code may be as i have no idea because I have never done a print procedure for datagridview's on a form before.. but i want to show all three datagrids of the stock items that values have been changed from each datagrid on the one form...

    Sorry if this doesn't make sense. if it doesn't, please get back to me and i will try and make it a bit more clearer..

    Thanks in advanced

    Harvey
    Friday, January 08, 2010 4:46 PM