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

用于打印和打印预览 DataGrid 或 DataGridView 控件的类

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.76/5 (34投票s)

2005 年 8 月 22 日

CPOL

2分钟阅读

viewsIcon

501344

downloadIcon

9942

一个可以添加到应用程序中的类,用于从 DataGrid 生成格式精美的打印件。

引言

System.Windows.Forms.DataGrid 控件是 .NET 工具库中最强大且最常用的控件之一,而这个类 (DataGridPrinter) 增加了功能,允许您从数据网格中生成打印件和打印预览,采用整洁且可自定义的布局。

要绘制网格,首先绘制一个正方形

绘制 datagrid 时的基本操作是绘制一个矩形并在其中填充文本。 为此,我有一个名为 DrawCellString 的单个子程序,它根据传入的对齐方式和格式参数在单元格内绘制一个 string

Public Function DrawCellString(ByVal s As String, _
      ByVal HorizontalAlignment As CellTextHorizontalAlignment, _
      ByVal VerticalAlignment As CellTextVerticalAlignment, _
      ByVal BoundingRect As Rectangle, _
      ByVal DrawRectangle As Boolean, _
      ByVal Target As Graphics, _
      ByVal PrintFont As Font)


        Dim x As Single, y As Single

        If DrawRectangle Then
            Target.DrawRectangle(_GridPen, BoundingRect)
        End If

        '\\ Set the text alignment
        If HorizontalAlignment = 
              CellTextHorizontalAlignment.LeftAlign Then
            _Textlayout.Alignment = StringAlignment.Near
        ElseIf HorizontalAlignment = 
                   CellTextHorizontalAlignment.RightAlign _
        Then
             _Textlayout.Alignment = StringAlignment.Far
        Else
             _Textlayout.Alignment = StringAlignment.Center
        End If

        Dim BoundingRectF As New RectangleF(BoundingRect.X + _CellGutter, _ 
                                BoundingRect.Y + _CellGutter,  _ 
                                BoundingRect.Width - (2 * _CellGutter),  _ 
                                BoundingRect.Height - (2 * _CellGutter))

        Target.DrawString(s, PrintFont, System.Drawing.Brushes.Black, _ 
                          BoundingRectF, _Textlayout)

End Function

有两个类级别变量用于定义如何绘制单元格:CellGutter 指定 string 边界框边缘与 GridPen 之间的边距(以像素为单位),而 GridPen 是用于绘制框的笔。

现在你可以画一个盒子,你可以画一行

为了打印网格,您需要打印两种类型的行:列标题行和数据行。 此类始终以一列列标题开始每个新页面。

    Private Sub PrintGridHeaderLine(ByVal e As _
              System.Drawing.Printing.PrintPageEventArgs)

        Dim Top As Double = _PageContentRectangle.Top
        Dim Bottom As Double = Top + _Rowheight + (2 * _CellGutter)

        Top = RoundTo(Top, 2)
        Bottom = RoundTo(Bottom, 2)

        Dim nColumn As Integer

        For nColumn = 0 To GridColumnCount() - 1
            Dim rcCell As New Rectangle(_ColumnBounds(nColumn).Left, Top, _
                                 _ColumnBounds(nColumn).Width, Bottom - Top)
            Call DrawCellString(GetColumnHeadingText(nColumn),  _ 
                                CellTextHorizontalAlignment.CentreAlign, _
                                CellTextVerticalAlignment.MiddleAlign, _ 
                                rcCell, True, e.Graphics, _PrintFont)
        Next
    End Sub

这非常简单。 唯一棘手的部分是从 datagrid 获取列的标题,方法如下:

    Private Function GetColumnHeadingText(ByVal Column As Integer) As String

        If TypeOf _DataGrid.DataSource Is DataTable Then
            Return CType(_DataGrid.DataSource, _
                        DataTable).Columns(Column).ToString
        ElseIf TypeOf _DataGrid.DataSource Is DataSet Then
            Return CType(_DataGrid.DataSource, DataSet).Tables( _
                      _DataGrid.DataMember).Columns(Column).ToString
        ElseIf TypeOf _DataGrid.DataSource Is DataView Then
            Return CType(_DataGrid.DataSource, _
                    DataView).Table.Columns(Column).ToString
        Else
            'TODO : Get the column caption....
        End If
    End Function

为了打印一行数据,我们使用当前行的行内容执行相同的操作

Private Sub PrintGridLine(ByVal e As _
         System.Drawing.Printing.PrintPageEventArgs, _ 
              ByVal RowNumber As Integer)

        Dim RowFromTop As Integer = RowNumber + 1 - _CurrentPrintGridLine
        Dim Top As Double = _PageContentRectangle.Top + (RowFromTop * _
                                         ((_CellGutter * 2) + _Rowheight))
        Dim Bottom As Double = Top + _Rowheight + (2 * _CellGutter)

        Top = RoundTo(Top, 2)
        Bottom = RoundTo(Bottom, 2)

        Dim Items() As Object

            If TypeOf _DataGrid.DataSource Is DataTable Then
                Items = CType(_DataGrid.DataSource, _
                        System.Data.DataTable).DefaultView.Item(_
                                         RowNumber - 1).Row.ItemArray
            ElseIf TypeOf _DataGrid.DataSource Is DataSet Then
                Items = CType(_DataGrid.DataSource, _
                              System.Data.DataSet).Tables(     _
                                _DataGrid.DataMember).DefaultView.Item(_
                                             RowNumber - 1).Row.ItemArray
            ElseIf TypeOf _DataGrid.DataSource Is DataView Then
                Items = CType(_DataGrid.DataSource, _
                         System.Data.DataView).Table.DefaultView.Item( _
                                             RowNumber - 1).Row.ItemArray
            Else
                'TODO : Get the content for the current row from the data 
                '       source ....
            End If

            Dim nColumn As Integer
            For nColumn = 0 To Items.Length - 1
                Dim rcCell As New Rectangle(_ColumnBounds(nColumn).Left, Top,_
                       _ColumnBounds(nColumn).Width, Bottom - Top)
                Call DrawCellString(Items(nColumn).ToString, _ 
                               CellTextHorizontalAlignment.CentreAlign, _ 
                               CellTextVerticalAlignment.MiddleAlign,  _ 
                               rcCell, True, e.Graphics, _PrintFont)
            Next
End Sub

将所有内容放到一个页面上

打印页面分为三个区域:页眉、正文和页脚。 还有一个 InterSectionSpacing 属性,用于指定各部分之间的间隙。 这些都表示为页面高度的百分比,将任何一个设置为零将省略该部分。

正文部分是从页面高度的剩余部分计算出来的,当页眉、页脚和部分间距相加后,这用于计算每个页面上可能容纳的行数

    Private Function RowsPerPage(ByVal GridLineFont As Font, _
                                ByVal e As Graphics) As Integer

        Return (_PageContentRectangle.Height / _ 
                ((_CellGutter * 2) + _Rowheight)) - 2

    End Function

更改网格外观的设置

可以使用 HeaderPenFooterPenGridPen 属性分别设置各部分周围线条的颜色和宽度。

可以使用 HeaderFontFooterFontPrintFont 属性分别设置每个部分的字体。

使用该类预览和打印 DataGrid

如果您在窗体上有一个 datagrid,并且想要使用此类预览和选择性地打印它,您可以将 System.Windows.Forms.PrintPreviewDialog 添加到您的窗体和一个打印菜单,并添加以下代码

    Private GridPrinter As DataGridPrinter

    Private Sub MenuItem_File_print_Click(ByVal sender As Object, _ 
                                   ByVal e As System.EventArgs) _ 
                                   Handles MenuItem_File_print.Click

        If GridPrinter Is Nothing Then
            GridPrinter = New DataGridPrinter(Me.DataGrid1)
        End If

        With GridPrinter
            .HeaderText = "Some text"
            .HeaderHeightPercent = 10
            .FooterHeightPercent = 5
            .InterSectionSpacingPercent = 2
            '\\ Set any other properties to 
            'affect the look of the grid...
        End With

        With Me.PrintPreviewDialog1
            .Document = GridPrinter.PrintDocument
            If .ShowDialog = DialogResult.OK Then
                GridPrinter.Print()
            End If
        End With
    End Sub

如果您希望使用更新的 DataGridView 控件而不是 DataGrid 控件,则有一个构造函数可以将它作为参数。 其他一切都以相同的方式工作。

历史

  • 2006-04-06:创建
  • 2016-01-24:添加了构造函数/代码以使用 DataGridView 类作为网格数据源
© . All rights reserved.