65.9K
CodeProject 正在变化。 阅读更多。
Home

通过选择列和行打印DataGridView

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.85/5 (99投票s)

2006年12月6日

CPOL

3分钟阅读

viewsIcon

945886

downloadIcon

46142

一篇关于 DataGrdView 打印的文章。

引言

有时,用户需要打印 DataGridView 中的特定列和行(或全部)。一些情况可能如下所示:

  • DataGridView 中有太多行,没有必要打印所有行。
  • 列宽总和可能大于页面宽度,最好在打印时删除一列或多列。

因此,实现了一个名为 PrintDGV 的类,可以在任何 .NET2.0 应用程序中使用。我已经在 C# 和 VB.NET 中 为 DataGridDataGridView 实现了它。

描述

代码的主要部分是 PrintDGV 类和 PrintOptions 窗体。

PrintDGV 中,我们有:

  • SelectedColumnsAvailableColumns 列表,用于保存列名。
  • 一个名为 PrintDocPrintDocument 对象(具有 BeginPrintPrintPage 事件处理程序)
  • 四个函数:
    • Print_DataGridView:可以从类外部调用的主函数。
    • PrintDoc_BeginPrint:初始化一些变量以开始打印。
    • PrintDoc_PrintPage:执行打印工作。
    • DrawFooter:写入页码。

该代码具有以下特点:

  • 支持 TextBoxLinkButtonComboBoxCheckBoxImage 列。
  • 绘制列以适应页面宽度,或按照显示的列进行绘制。
  • 如果单元格宽度小于其内容,则换行单元格文本。
  • 在页面上绘制页脚、日期、时间和标题。

使用代码

要在应用程序中使用该代码,必须将 PrintDGV 类和 PrintOptions 窗体添加到其中,然后调用函数 Print_DataGridView。在我们的示例中,示例项目有一个名为 MainFormForm

MainForm 中,DataGridView 填充了 'Persongs.mdb' 的 'Persons' 表。

PrintOption 窗体中,用户可以选择 DataGridView 列、适应页面和标题。

PrintDoc_PrintPage 事件处理程序执行以下任务:

  • 计算列宽。
  • 打印当前页面,逐行打印 - 循环遍历 DataGridView 中的所有行。
  • 在“打印选定行”模式下,如果未选择当前行,则跳过它。
  • 如果到达页面末尾,则写入页码并转到下一页。如果未到达页面末尾,则:
  • 如果在新页面中,则绘制标题、日期-时间、页眉和列(检查是否已由用户选择每个列,如果未选择,则跳过它)。
  • 绘制 TextBoxLinkButtonCheckBoxComboBoxImage 单元格的列内容(检查是否已由用户选择每个列,如果未选择,则跳过它)。
  • 绘制边框。
  • 计算第一页的“每页行数”。
  • 写入页脚(页码)。
private static void PrintDoc_PrintPage(object sender, 
        System.Drawing.Printing.PrintPageEventArgs e) 
{
    int tmpWidth, i;
    int tmpTop = e.MarginBounds.Top;
    int tmpLeft = e.MarginBounds.Left;
    int HeaderHeight=0;

    try 
    {            
        // Before starting first page, it saves
        // Width & Height of Headers and CoulmnType
        if (PageNo == 1) 
        {
            foreach (DataGridViewColumn GridCol in dgv.Columns)
            {
                if (!GridCol.Visible) continue;
                // Skip if the current column not selected
                if (!PrintDGV.SelectedColumns.Contains(
                     GridCol.HeaderText)) continue;

                // Detemining whether the columns
                // are fitted to the page or not.
                if (FitToPageWidth) 
                    tmpWidth = (int)(Math.Floor((double)(
                               (double)GridCol.Width / 
                               (double)TotalWidth * (double)TotalWidth * 
                               ((double)e.MarginBounds.Width / 
                                (double)TotalWidth))));
                else
                    tmpWidth = GridCol.Width;

                HeaderHeight = 
                   (int)(e.Graphics.MeasureString(GridCol.HeaderText,
                    GridCol.InheritedStyle.Font, tmpWidth).Height) + 11;

                // Save width & height of headres and ColumnType
                ColumnLefts.Add(tmpLeft);
                ColumnWidths.Add(tmpWidth);
                ColumnTypes.Add(GridCol.GetType());
                tmpLeft += tmpWidth;
            }
        }

        // Printing Current Page, Row by Row
        while (RowPos <= dgv.Rows.Count - 1)
        {
            DataGridViewRow GridRow = dgv.Rows[RowPos];
            if (GridRow.IsNewRow || (!PrintAllRows && !GridRow.Selected))
            {
                RowPos++;
                continue;
            }

            CellHeight = GridRow.Height;

            if (tmpTop + CellHeight >= 
                 e.MarginBounds.Height + e.MarginBounds.Top)
            {
                DrawFooter(e, RowsPerPage);
                NewPage = true;
                PageNo++;
                e.HasMorePages = true;
                return;
            }
            else
            {
                if (NewPage)
                {
                    // Draw Print Title
                    e.Graphics.DrawString(PrintTitle, 
                           new Font(dgv.Font, FontStyle.Bold), 
                            Brushes.Black, e.MarginBounds.Left, 
                            e.MarginBounds.Top -
                            e.Graphics.MeasureString(PrintTitle, 
                            new Font(dgv.Font, 
                            FontStyle.Bold), 
                            e.MarginBounds.Width).Height - 13);

                    String s = DateTime.Now.ToLongDateString() + " " + 
                               DateTime.Now.ToShortTimeString();
                    // Draw Time and Date    
                    e.Graphics.DrawString(s, 
                            new Font(dgv.Font, FontStyle.Bold), 
                            Brushes.Black, e.MarginBounds.Left + 
                            (e.MarginBounds.Width - 
                            e.Graphics.MeasureString(s, new Font(dgv.Font, 
                            FontStyle.Bold), e.MarginBounds.Width).Width), 
                            e.MarginBounds.Top - 
                            e.Graphics.MeasureString(PrintTitle, 
                            new Font(new Font(dgv.Font, 
                            FontStyle.Bold), FontStyle.Bold), 
                            e.MarginBounds.Width).Height - 13);

                    // Draw Headers
                    tmpTop = e.MarginBounds.Top;
                    i = 0;
                    foreach (DataGridViewColumn GridCol in dgv.Columns)
                    {
                        if (!GridCol.Visible) continue;
                        if (!PrintDGV.SelectedColumns.Contains(
                                            GridCol.HeaderText)) 
                            continue;

                        e.Graphics.FillRectangle(new 
                            SolidBrush(Color.LightGray), 
                            new Rectangle((int) ColumnLefts[i], tmpTop,
                            (int)ColumnWidths[i], HeaderHeight));

                        e.Graphics.DrawRectangle(Pens.Black, 
                            new Rectangle((int) ColumnLefts[i], tmpTop,
                            (int)ColumnWidths[i], HeaderHeight));

                        e.Graphics.DrawString(GridCol.HeaderText, 
                            GridCol.InheritedStyle.Font, 
                            new SolidBrush(GridCol.InheritedStyle.ForeColor),
                            new RectangleF((int)ColumnLefts[i], tmpTop, 
                            (int)ColumnWidths[i], HeaderHeight), StrFormat);
                        i++;
                    }
                    NewPage = false;
                    tmpTop += HeaderHeight;
                }

                // Draw Columns Contents
                i = 0;
                foreach (DataGridViewCell Cel in GridRow.Cells)
                {
                    if (!Cel.OwningColumn.Visible) continue;
                    if (!SelectedColumns.Contains(
                            Cel.OwningColumn.HeaderText))
                        continue;

                    // For the TextBox Column
                    if (((Type) ColumnTypes[i]).Name == 
                         "DataGridViewTextBoxColumn" || 
                        ((Type) ColumnTypes[i]).Name == 
                         "DataGridViewLinkColumn")
                    {
                        e.Graphics.DrawString(Cel.Value.ToString(), 
                                Cel.InheritedStyle.Font, 
                                new SolidBrush(Cel.InheritedStyle.ForeColor),
                                new RectangleF((int)ColumnLefts[i], 
                                (float)tmpTop,
                                (int)ColumnWidths[i], 
                                (float)CellHeight), StrFormat);
                    }
                    // For the Button Column
                    else if (((Type) ColumnTypes[i]).Name == 
                                     "DataGridViewButtonColumn")
                    {
                        CellButton.Text = Cel.Value.ToString();
                        CellButton.Size = new Size((int)ColumnWidths[i], 
                                                    CellHeight);
                        Bitmap bmp = new Bitmap(CellButton.Width, 
                                                CellButton.Height);
                        CellButton.DrawToBitmap(bmp, new Rectangle(0, 0, 
                                bmp.Width, bmp.Height));
                        e.Graphics.DrawImage(bmp, 
                          new Point((int)ColumnLefts[i], tmpTop));
                    }
                    // For the CheckBox Column
                    else if (((Type) ColumnTypes[i]).Name == 
                              "DataGridViewCheckBoxColumn")
                    {
                        CellCheckBox.Size = new Size(14, 14);
                        CellCheckBox.Checked = (bool)Cel.Value;
                        Bitmap bmp = new Bitmap((int)ColumnWidths[i], 
                                                 CellHeight);
                        Graphics tmpGraphics = Graphics.FromImage(bmp);
                        tmpGraphics.FillRectangle(Brushes.White, 
                                new Rectangle(0, 0, 
                                bmp.Width, bmp.Height));
                        CellCheckBox.DrawToBitmap(bmp, 
                                new Rectangle((int)((bmp.Width - 
                                CellCheckBox.Width) / 2), 
                                (int)((bmp.Height - CellCheckBox.Height) / 2), 
                                CellCheckBox.Width, CellCheckBox.Height));
                        e.Graphics.DrawImage(bmp, 
                                new Point((int)ColumnLefts[i], tmpTop));
                    }
                    // For the ComboBox Column
                    else if (((Type) ColumnTypes[i]).Name == 
                              "DataGridViewComboBoxColumn")
                    {
                        CellComboBox.Size = new Size((int)ColumnWidths[i], 
                                                CellHeight);
                        Bitmap bmp = new Bitmap(CellComboBox.Width, 
                                                CellComboBox.Height);
                        CellComboBox.DrawToBitmap(bmp, new Rectangle(0, 0, 
                                bmp.Width, bmp.Height));
                        e.Graphics.DrawImage(bmp, 
                                new Point((int)ColumnLefts[i], tmpTop));
                        e.Graphics.DrawString(Cel.Value.ToString(), 
                                Cel.InheritedStyle.Font, 
                                new SolidBrush(Cel.InheritedStyle.ForeColor), 
                                new RectangleF((int)ColumnLefts[i] + 1, 
                                tmpTop, (int)ColumnWidths[i]
                                - 16, CellHeight), StrFormatComboBox);
                    }
                    // For the Image Column
                    else if (((Type) ColumnTypes[i]).Name == 
                              "DataGridViewImageColumn")
                    {
                        Rectangle CelSize = new Rectangle((int)ColumnLefts[i], 
                                tmpTop, (int)ColumnWidths[i], CellHeight);
                        Size ImgSize = ((Image)(Cel.FormattedValue)).Size;
                        e.Graphics.DrawImage((Image)Cel.FormattedValue, 
                                new Rectangle((int)ColumnLefts[i] + 
                                (int)((CelSize.Width - ImgSize.Width) / 2), 
                                tmpTop + (int)((CelSize.Height - 
                                ImgSize.Height) / 2), 
                                ((Image)(Cel.FormattedValue)).Width, 
                                ((Image)(Cel.FormattedValue)).Height));

                    }

                    // Drawing Cells Borders 
                    e.Graphics.DrawRectangle(Pens.Black, 
                            new Rectangle((int)ColumnLefts[i], 
                            tmpTop, (int)ColumnWidths[i], CellHeight));

                    i++;

                }
                tmpTop += CellHeight;
            }

            RowPos++;
            // For the first page it calculates Rows per Page
            if (PageNo == 1) RowsPerPage++;
        }

        if (RowsPerPage == 0) return;

        // Write Footer (Page Number)
        DrawFooter(e, RowsPerPage);

        e.HasMorePages = false;
    }
    catch (Exception ex)
    {
        MessageBox.Show(ex.Message, "Error", 
                        MessageBoxButtons.OK, 
                        MessageBoxIcon.Error);
    }
}

历史

修复了两个错误 (2007 年 2 月 22 日)

  • C# 代码中的页数是错误的。
  • 对于第一页之后的页面,列标题覆盖了第一行(C# 代码和 VB 代码中都是如此)。
© . All rights reserved.