Datagridview打印

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;
using System.IO;
using Languages;

class DataGridViewPrinter
{
private DataGridView TheDataGridView; // The DataGridView Control which will be printed
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 IsWithTitle; // Determine if the page contain title text
private string TheTitleText; // The title text to be printed in each page (if IsWithTitle is set to true)
private Font TheTitleFont; // The font to be used with the title text (if IsWithTitle is set to true)
private Color TheTitleColor; // The color to be used with the title text (if IsWithTitle is set to true)
private bool IsWithPaging; // Determine if paging is used

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;
    
// 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
private List<int[]> mColumnPoints;
private List<float> mColumnPointsWidth;
private int mColumnPoint;
    
// The class constructor
public DataGridViewPrinter(DataGridView aDataGridView, PrintDocument aPrintDocument, bool CenterOnPage, bool WithTitle, string aTitleText, Font aTitleFont, Color aTitleColor, bool WithPaging)
{
    TheDataGridView = aDataGridView;
    ThePrintDocument = aPrintDocument;
    IsCenterOnPage = CenterOnPage;
    IsWithTitle = WithTitle;
    TheTitleText = aTitleText;
    TheTitleFont = aTitleFont;
    TheTitleColor = aTitleColor;
    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;

    // 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 (PageNumber == 0) // Just calculate once
    {
        SizeF tmpSize = new SizeF();
        Font tmpFont;
        float tmpWidth;


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

            tmpSize = g.MeasureString(TheDataGridView.Columns[i].HeaderText, tmpFont);
            tmpWidth = tmpSize.Width;
            RowHeaderHeight = tmpSize.Height;

            for (int j = 0; j < TheDataGridView.Rows.Count; j++)
            {
                tmpFont = TheDataGridView.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 = TheDataGridView.DefaultCellStyle.Font;

                tmpSize = g.MeasureString("Anything", tmpFont);
                RowsHeight.Add(TheDataGridView.Rows[j].Height);

                tmpSize = g.MeasureString(TheDataGridView.Rows[j].Cells[i].EditedFormattedValue.ToString(), tmpFont);
                if (tmpSize.Width > tmpWidth)
                    tmpWidth = tmpSize.Width;
            }
            if (TheDataGridView.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 < TheDataGridView.Columns.Count; k++)
            if (TheDataGridView.Columns[k].Visible)
            {
                mStartPoint = k;
                break;
            }

        int mEndPoint = TheDataGridView.Columns.Count;
        for (k = TheDataGridView.Columns.Count - 1; k >= 0; k--)
            if (TheDataGridView.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 < TheDataGridView.Columns.Count; k++)
            {
                if (TheDataGridView.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;
    }
}

// The funtion that print the title, page number, and the header row
private void DrawHeader(Graphics g)
{
    CurrentY = (float)TopMargin;

    // 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;

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

        RectangleF PageStringRectangle = new RectangleF((float)LeftMargin, CurrentY, (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 IsWithTitle is set to true)
    if (IsWithTitle)
    {
        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(TheTitleText, TheTitleFont).Height);

        g.DrawString(TheTitleText, TheTitleFont, new SolidBrush(TheTitleColor), TitleRectangle, TitleFormat);

        CurrentY += g.MeasureString(TheTitleText, TheTitleFont).Height;
    }

    // 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 = TheDataGridView.ColumnHeadersDefaultCellStyle.ForeColor;
    if (HeaderForeColor.IsEmpty) // If there is no special HeaderFore style, then use the default DataGridView style
        HeaderForeColor = TheDataGridView.DefaultCellStyle.ForeColor;
    SolidBrush HeaderForeBrush = new SolidBrush(HeaderForeColor);

    // Setting the HeaderBack style
    Color HeaderBackColor = TheDataGridView.ColumnHeadersDefaultCellStyle.BackColor;
    if (HeaderBackColor.IsEmpty) // If there is no special HeaderBack style, then use the default DataGridView style
        HeaderBackColor = TheDataGridView.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(TheDataGridView.GridColor, 1);

    // Setting the HeaderFont style
    Font HeaderFont = TheDataGridView.ColumnHeadersDefaultCellStyle.Font;
    if (HeaderFont == null) // If there is no special HeaderFont style, then use the default DataGridView font style
        HeaderFont = TheDataGridView.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 (!TheDataGridView.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 (TheDataGridView.ColumnHeadersDefaultCellStyle.Alignment.ToString().Contains("Right"))
            CellFormat.Alignment = StringAlignment.Far;
        else if (TheDataGridView.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(TheDataGridView.Columns[i].HeaderText, HeaderFont, HeaderForeBrush, CellBounds, CellFormat);

        // Drawing the cell bounds
        if (TheDataGridView.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(TheDataGridView.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;
    while (CurrentRow < TheDataGridView.Rows.Count)
    {
        if (TheDataGridView.Rows[CurrentRow].Visible) // Print the cells of the CurrentRow only if that row is visible
        {
            // Setting the row font style
            RowFont = TheDataGridView.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 = TheDataGridView.DefaultCellStyle.Font;

            // Setting the RowFore style
            RowForeColor = TheDataGridView.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 = TheDataGridView.DefaultCellStyle.ForeColor;
            RowForeBrush = new SolidBrush(RowForeColor);

            // Setting the RowBack (for even rows) and the RowAlternatingBack (for odd rows) styles
            RowBackColor = TheDataGridView.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(TheDataGridView.DefaultCellStyle.BackColor);
                RowAlternatingBackBrush = new SolidBrush(TheDataGridView.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 (!TheDataGridView.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 (TheDataGridView.Columns[CurrentCell].DefaultCellStyle.Alignment.ToString().Contains("Right"))
                    CellFormat.Alignment = StringAlignment.Far;
                else if (TheDataGridView.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]);

                if (TheDataGridView.Rows[CurrentRow].Cells[CurrentCell].Value == null)
                {

                }
                else if (TheDataGridView.Rows[CurrentRow].Cells[CurrentCell].Value is Image)
                {
                    Image img = TheDataGridView.Rows[CurrentRow].Cells[CurrentCell].Value as Image;
                    if (img != null)
                    {
                        RectangleF CellBound = new RectangleF(CurrentX, CurrentY, img.Width, img.Height);
                        g.DrawImage(img, CellBound);
                    }
                }
                else
                {
                    // Printing the cell text
                    g.DrawString(TheDataGridView.Rows[CurrentRow].Cells[CurrentCell].Value.ToString(), RowFont, RowForeBrush, CellBounds, CellFormat);
                }
                
                // Drawing the cell bounds
                if (TheDataGridView.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++;
    }

    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)
{
    try
    {
        Calculate(g);
        DrawHeader(g);
        bool bContinue = DrawRows(g);
        return bContinue;
    }
    catch (Exception ex)
    {
        MessageBox.Show("Operation failed: " + ex.Message.ToString(), Application.ProductName + " - Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
        return false;
    }
}

}

class DataTablePrinter
{
private DataTable TheDataGridView; // The DataGridView Control which will be printed
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 IsWithTitle; // Determine if the page contain title text
private string TheTitleText; // The title text to be printed in each page (if IsWithTitle is set to true)
private Font TheTitleFont; // The font to be used with the title text (if IsWithTitle is set to true)
private Color TheTitleColor; // The color to be used with the title text (if IsWithTitle is set to true)
private bool IsWithPaging; // Determine if paging is used

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;

// 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
private List<int[]> mColumnPoints;
private List<float> mColumnPointsWidth;
private int mColumnPoint;

// The class constructor
public DataTablePrinter(DataTable aDataGridView, PrintDocument aPrintDocument, bool CenterOnPage, bool WithTitle, string aTitleText, Font aTitleFont, Color aTitleColor, bool WithPaging)
{
    TheDataGridView = aDataGridView;
    ThePrintDocument = aPrintDocument;
    IsCenterOnPage = CenterOnPage;
    IsWithTitle = WithTitle;
    TheTitleText = aTitleText;
    TheTitleFont = aTitleFont;
    TheTitleColor = aTitleColor;
    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;

    // 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 (PageNumber == 0) // Just calculate once
    {
        SizeF tmpSize = new SizeF();
        Font tmpFont;
        float tmpWidth = 0;
        int rowHeight = 30;

        TheDataGridViewWidth = 0;
        for (int i = 0; i < TheDataGridView.Columns.Count; i++)
        {
            tmpFont = new Font("Tahoma", 8, FontStyle.Regular, GraphicsUnit.Point);               

            tmpSize = g.MeasureString(TheDataGridView.Columns[i].ColumnName, tmpFont);
            tmpWidth = tmpSize.Width;
            RowHeaderHeight = tmpSize.Height;

            for (int j = 0; j < TheDataGridView.Rows.Count; j++)
            {
                tmpSize = g.MeasureString("Anything", tmpFont);
                RowsHeight.Add(rowHeight);
                if (tmpSize.Width > tmpWidth)
                    tmpWidth = tmpSize.Width;
            }
        }

        for (int colIndex = 0; colIndex < TheDataGridView.Columns.Count; colIndex++ )
        {
            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;
        int mEndPoint = TheDataGridView.Columns.Count;

        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 < TheDataGridView.Columns.Count; k++)
            {
                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;
    }
}

// The funtion that print the title, page number, and the header row
private void DrawHeader(Graphics g)
{
    CurrentY = (float)TopMargin;

    // 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;

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

        RectangleF PageStringRectangle = new RectangleF((float)LeftMargin, CurrentY, (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 IsWithTitle is set to true)
    if (IsWithTitle)
    {
        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(TheTitleText, TheTitleFont).Height);

        g.DrawString(TheTitleText, TheTitleFont, new SolidBrush(TheTitleColor), TitleRectangle, TitleFormat);

        CurrentY += g.MeasureString(TheTitleText, TheTitleFont).Height;
    }

    // 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 = Color.Black;      
    SolidBrush HeaderForeBrush = new SolidBrush(HeaderForeColor);

    // Setting the HeaderBack style
    Color HeaderBackColor = Color.White;
    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(Color.Blue, 1);

    // Setting the HeaderFont style
    Font HeaderFont = new Font("Tahoma", 8, FontStyle.Regular, GraphicsUnit.Point);       

    // 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++)
    {
        ColumnWidth = ColumnsWidth[i];
        CellFormat.Alignment = StringAlignment.Center;
        CellBounds = new RectangleF(CurrentX, CurrentY, ColumnWidth, RowHeaderHeight);

        // Printing the cell text
        g.DrawString(TheDataGridView.Columns[i].ColumnName, HeaderFont, HeaderForeBrush, CellBounds, CellFormat);

        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(Color.Blue, 1);

    // The style paramters that will be used to print each cell
    Font RowFont = new Font("Tahoma", 8, FontStyle.Regular, GraphicsUnit.Point); ;
    Color RowForeColor = Color.Black;
    Color RowBackColor = Color.White;
    SolidBrush RowForeBrush = new SolidBrush(RowForeColor);
    SolidBrush RowBackBrush = new SolidBrush(RowBackColor); ;
    SolidBrush RowAlternatingBackBrush = new SolidBrush(RowBackColor); ;

    // 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;
    while (CurrentRow < TheDataGridView.Rows.Count)
    {

        // 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++)
        {
            CellFormat.Alignment = StringAlignment.Center;

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

            if (TheDataGridView.Rows[CurrentRow][CurrentCell] == null)
            {

            }
            else if (TheDataGridView.Rows[CurrentRow][CurrentCell].ToString().Contains(".jpg"))
            {
                string fileName = TheDataGridView.Rows[CurrentRow][CurrentCell].ToString();
                Image img = Helper.GetImgFromPath(fileName);
                if (img != null)
                {
                    RectangleF CellBound = new RectangleF(CurrentX, CurrentY, img.Width, img.Height);
                    g.DrawImage(img, CellBound);
                }
            }
            else
            {
                // Printing the cell text
                string tempValue = TheDataGridView.Rows[CurrentRow][CurrentCell].ToString();
                g.DrawString(tempValue, RowFont, RowForeBrush, CellBounds, CellFormat);
            }

            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++;
    }

    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)
{
    try
    {
        Calculate(g);
        DrawHeader(g);
        bool bContinue = DrawRows(g);
        return bContinue;
    }
    catch (Exception ex)
    {
        MessageBox.Show("Operation failed: " + ex.Message.ToString(), Application.ProductName + " - Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
        return false;
    }
}

}
/*调用方式
print.PrintGridView(dvBoardList,
false, true, MultiLanguage.GetString(“SPC_Record”), new Font(“Tahoma”, 18,
FontStyle.Bold, GraphicsUnit.Point), Color.Black, true);
*/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
注意:本3.0版控件过于老旧,该控件最新版本为4.7版,您可以到http://myyouping.download.csdn.net/免费下载,也是完全免费的,没有任何功能及使用时间限制,0积分下载。我将3.0版控件的下载分提为10分,是希望大家使用最新版的控件。 控件特色: 1、超强大的DataGridView打印功能,不光可以以多种形式(普通打印、分栏打印、跨页打印、工资条打印打印DataGridView表格,基本上能完全按DataGridView控件本身设置的格式如字体、字号、背景颜色、前景颜色、单元格对齐方式等打印出来,文字图像都可以打印,而且是完全根据表格当前的显示顺序进行打印的,如果您在使用时调整了列的顺序,刷新打印后就会按调整后的列显示顺序进行打印(这是网上很多DataGridView打印控件没有实现的),基本上做到了所见即所得的打印。 2、强大的文本打印输出功能,打印文本时,如果需要,控件会自动换行或换页打印输出。 3、支持同一文档多种版面格式打印(类似于Word中的节的功能):对同一份文档,不同的页面可以设置不同的格式(纸张大小、纸张方向、页边距),只需要在新增一页时在NewPage方法中指定要使用的页面格式即可,使用非常简单。 4、报表功能。本控件允许将当前打印预览的内容保存为报表文件,以后使用本控件重新打开该报表文件即可重现原来保存报表时的打印内容。 5、打印方案保存与读取功能。可以将当前打印参数保存为打印方案文件,或都从保存的打印方案文件中读取打印参数。 6、水印功能。根据需要,可以在页面中打印或不打印以半透明空心文字打印水印。 7、特殊文字效果功能。本版控件具有打印浮雕文字、阴影文字、空心文字、块文字的功能,效果非常不错。 8、页眉页脚中既可打印文字,也可打印图像,或者即打印图像又打印输出文字。 9、图像打印输出功能。 本控件包括两个打印组件:DGVprint打印组件与VB2008print打印组件。VB2008Print为通用打印控件(为可视化组件),可以混合打印一个或多个DataGridView表格、DataGrid表格与文字、图片等内容;而DGVprint是以VB2008Print为基础开发的(为非可视化组件),为专用的表格打印控件,可以很方便打印单个DatatGridview、DataGrid、DataTable表格的内容,并提供打印时的可视化设置界面,可设置表格打印方式(普通打印、分栏打印、跨页打印、工资条打印)、标题内容及字体、页眉页脚、选择要打印的表格列、列顺序调整及列格式设置、更改列标题名称等,使用非常方便,功能非常强大。 与本控件的上一个版本2.1版相比,本版控件新增功能如下: VB2008Print打印组件新增功能: 1、多种特效文字打印输出功能,能打印的特效文字有 空心文字、浮雕文字、块文字、阴影文字等。 2、水印打印功能。可以在面页中以半透明空心文字的形式打印背景水印,只需要简单设置控件的WaterMarkText等几个以WaterMark开头的属性即可,程序会自动打印水印。 3、PrintDGV函数可直接使用DGVPrint组件保存的打印方案文件打印输出DataGridView表格, 4、在页眉页脚中不光可以打印文本,还可以打印图像,文本与图像可同时打印(即在图像上显示文本)。此外,页眉页脚文字可以换行打印了,页面的左边也右边距也可以打印内容了(调用相应的函数PrintLeft与PrintRight实现)。 5、改进DrawText函数输出文本的功能,现在,即便调用没有指定打印区域或打印宽度的DrawText函数输出文本,打印输出时控件也会智能换行和换页(原版本是需要指定打印宽度才能自动换行换页打印的) 6、改进DrawImage与DrawCellImage输出图像功能,如果图像比较小(小于打印区域大小),可以不进行放大打印。(但如果图像大于打印区域的话,还是采用整体缩小打印,而不是区域剪裁打印)。 7、增加IsShowPrintStatusDialog属性,指示在发送到打印打印时,是否显示一个指示正在打印的状态窗口(可以取消打印),为TRUE表示要显示,为False表示不显示。 8、改进页眉页脚事件,将原来的HeaderOut与FooterOut统一为HeaderFooterOut事件,在该事件中,您可以调用PrintFooter、PrintHeader、PrintLeft、PrintRight函数分别打印上下左右的页眉。(PrintLeft与PrintRight函数为新增加的,用于在左边与右边页边距处输出内容) DGVPrint打印组件新增功能: 1、打印方案保存与读取功能。本版控件可以将您的可视化设置(包括列格式设置等)全部保存为打印方案文件(文本文件,您可以用记事本打开并修改),并有读取方案文件的功能,不再需要每次都进行打印格式设置了,一劳永逸! 2、直接调用打印方案文件打印功能。您不光可以设计DGVPrint打印组件的属性来进行打印,还可以直接调用DGVPrint组件中保存的打印方案文件,直接利用保存的方案文件的参数进行打印预览输出。 3、新增在可视化打印参数设置界面的列标题重命名功能,可能修改列标题要打印的名字。 4、水印打印功能。如果水印文本设置为空,则不打印水印。 5、导出数据成Excel功能。暂未提供该功能的函数接口,只在打印参数设置窗口中增加了一个数据导出的按钮,可以将当前要打印DataGridView的内容导出成Excel文件。该功能以后会进一步完善。 6、在进行页眉页脚文本设置时,可以用 [页码] 代表要输出的当前页码,用 [总页数] 代表要输出总页数,控件在进行输出时,会自动将其转换为对应的页码与文档总页数。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值