• 打印datagridview内容 实现横向纵向分页(转)


    网上找了很多打印的,只发现这个比较好,实现了横向纵向分页。

    代码如下:

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

    //打印类  

     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(tmpSize.Height);
                            RowsHeight.Add(tmpSize.Height+3);//修改+3
                            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]);

                            // Printing the cell text
                            g.DrawString(TheDataGridView.Rows[CurrentRow].Cells[CurrentCell].EditedFormattedValue.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;
                }
            }
        } 

    //实现打印和打印预览

    全局对象: 

    DataGridViewPrinter MyDataGridViewPrinter;

    //PrintPage事件

     private void MyPrintDocument_PrintPage_1(object sender, PrintPageEventArgs e)
            {
                bool more = MyDataGridViewPrinter.DrawDataGridView(e.Graphics);
                if (more == true)
                    e.HasMorePages = true;
            }

    //设置打印
            private bool SetupThePrinting()
            {           

                PrintDialog MyPrintDialog = new PrintDialog();
                MyPrintDialog.AllowCurrentPage = false;
                MyPrintDialog.AllowPrintToFile = false;
                MyPrintDialog.AllowSelection = false;
                MyPrintDialog.AllowSomePages = false;
                MyPrintDialog.PrintToFile = false;
                MyPrintDialog.ShowHelp = false;
                MyPrintDialog.ShowNetwork = false;      

                if (MyPrintDialog.ShowDialog() != DialogResult.OK)
                    return false;

                MyPrintDocument.DocumentName = "XX统计";
                MyPrintDocument.PrinterSettings = MyPrintDialog.PrinterSettings;
                MyPrintDocument.DefaultPageSettings = MyPrintDialog.PrinterSettings.DefaultPageSettings;
                MyPrintDocument.DefaultPageSettings.Margins = new Margins(40, 40, 40, 40);

    //是否居中
               if (MessageBox.Show("Do you want the report to be centered on the page", "InvoiceManager - Center on Page", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes)
               MyDataGridViewPrinter = new DataGridViewPrinter(this.dgvSensRate, MyPrintDocument, true, true, "XXX统计", new Font("Tahoma", 18, FontStyle.Regular, GraphicsUnit.Point), Color.Black, true);
                else
                MyDataGridViewPrinter = new DataGridViewPrinter(this.dgvSensRate, MyPrintDocument, false, true, "XXX统计", new Font("Tahoma", 18, FontStyle.Regular, GraphicsUnit.Point), Color.Black, true);

                return true;
            }

    //打印预览

     private void btnPreview_Click(object sender, EventArgs e)
            {

                    if (SetupThePrinting())
                    {
                        PrintPreviewDialog MyPrintPreviewDialog = new PrintPreviewDialog();
                        MyPrintPreviewDialog.Document = MyPrintDocument;
                        MyPrintPreviewDialog.ShowDialog();
                    }

                }

    //打印

      private void cmdPrint_Click(object sender, EventArgs e)
            {
          
                    if (SetupThePrinting())
                        MyPrintDocument.Print();
                    return;
                }

    另外的----------------------------------

     //打印格式設置頁面
                PageSetupDialog dlgPageSetup = new PageSetupDialog();
                dlgPageSetup.Document = MyPrintDocument;
                dlgPageSetup.ShowDialog();
    //

  • 相关阅读:
    架构师养成记--19.netty
    架构师养成记--18.NIO
    架构师养成记--17.disrunptor 多生产者多消费者
    JS计算字符长度、字节数 -- 转
    BootStrap Modal 点击空白时自动关闭
    架构师养成记--16.disruptor并发框架中RingBuffer的使用
    架构师养成记--15.Disruptor并发框架
    架构师养成记--14.重入锁ReentrantLock 和 读写锁 ReentrantReadWriteLock
    049、Java中使用switch判断,不加入break时的操作
    048、Java中使用switch判断
  • 原文地址:https://www.cnblogs.com/china-guoch/p/3282076.html
Copyright © 2020-2023  润新知