经过两天的学习,终于写出来了,通用的datagrid打印程序,但是有一个要求,必须要有datagrid的格式设置,源代码如下:
Imports System.ComponentModel
Imports System.Drawing
Imports System.Windows.Forms
Public Class DataGridPrint
Inherits System.Drawing.Printing.PrintDocument
#Region " 组件设计器生成的代码 "
Public Sub New()
MyBase.New()
' 该调用是组件设计器所必需的。
InitializeComponent()
'在 InitializeComponent() 调用之后添加任何初始化
End Sub
'Control 重写 dispose 以清理组件列表。
Protected Overloads Overrides Sub Dispose(ByVal disposing As Boolean)
If disposing Then
If Not (components Is Nothing) Then
components.Dispose()
End If
End If
MyBase.Dispose(disposing)
End Sub
'控件设计器所必需的
Private components As System.ComponentModel.IContainer
'注意: 以下过程是组件设计器所必需的
' 可以使用组件设计器修改此过程。不要使用
' 代码编辑器修改它。
<System.Diagnostics.DebuggerStepThrough()> Private Sub InitializeComponent()
components = New System.ComponentModel.Container
End Sub
#End Region
Dim _table As DataTable
<Description("传入的表变量")> Public WriteOnly Property Table() As DataTable
Set(ByVal Value As DataTable)
_table = Value
End Set
End Property
Dim _ds As DataGridTableStyle
<Description("传入的表风格的变量")> Public WriteOnly Property DataGridTableStyle() As DataGridTableStyle
Set(ByVal Value As DataGridTableStyle)
_ds = Value
End Set
End Property
Dim _htext As String = ""
<Description("表头文件")> Public WriteOnly Property HeaderText() As String
Set(ByVal Value As String)
_htext = Value
End Set
End Property
Dim _hfont As New Font("Arial", 11)
<Description("表头字体")> Public WriteOnly Property HeaderFont() As Font
Set(ByVal Value As Font)
_hfont = Value
End Set
End Property
Dim _rfont As New Font("Arial", 9)
<Description("行字体")> Public WriteOnly Property RowFont() As Font
Set(ByVal Value As Font)
_rfont = Value
End Set
End Property
Dim _isLine As Boolean = False
<Description("是否需要打印线条")> Public WriteOnly Property IsPaintLine() As Boolean
Set(ByVal Value As Boolean)
IsPaintLine = False
End Set
End Property
<Description("是否具有可以打印的页")> Public ReadOnly Property PagesCount() As Int16 '这个函数可以不用
Get
Return GetTotalPage()
End Get
End Property
Dim _totalColumns As Int16 = 0
Dim _totalPage As Int16 = 0 '总页数
Dim _curPage As Int16 = 1 '当前页数
Dim _curRow As Int32 = 0 '当前行数
Dim _curColumn As Int32 = 0 '当前列数
Function GetTotalPage() As Int16
Dim dcs As DataGridColumnStyle
For Each dcs In _ds.GridColumnStyles
_totalColumns += 1
Next
'先计算列占页,因为这个计算有点小问题
'有可能造成的问题是单列会超出页宽,这种情况下将不进行打印,_totalPage=0
Dim _width As Int16 = 0 '用来保存每一次计算的总宽度
Dim i As Int16 = 0 '进行循环计算的条件
If _table.Columns.Count = 0 Then '没有列
Return 0
End If
If _table.Rows.Count = 0 Then '没有行
Return 0
End If
While i < _totalColumns
If _ds.GridColumnStyles(i).Width > Me.DefaultPageSettings.Bounds.Width Then '假如单列的宽度大于页面设置的宽度,则不打印
Return 0
End If
_width += _ds.GridColumnStyles(i).Width
If _width > Me.DefaultPageSettings.Bounds.Width Then
i -= 1 '退回一列,将此列计算到下一页中
_totalPage += 1 '页数增加
_width = 0 '宽度和置0
End If
i += 1
End While
_totalPage += 1 '全部通过了还有最后一页
i = 0 '用来计算行所占页
Dim j As Int16 = 0 '每页行数
j = (Me.DefaultPageSettings.Bounds.Height - _hfont.Height - 2 - (_rfont.Height - 2) * 2) / (_rfont.Height + 2) '每行保留2的间距,页尾也必须得加上
i = _table.Rows.Count / j
_totalPage *= i
Return (_totalPage) '是返回,顺便也解决了_totalPage
End Function
Function GetTotalPage(ByVal width As Int16, ByVal height As Int16)
Dim dcs As DataGridColumnStyle
_totalColumns = 0
_totalPage = 0
For Each dcs In _ds.GridColumnStyles
_totalColumns += 1
Next
'先计算列占页,因为这个计算有点小问题
'有可能造成的问题是单列会超出页宽,这种情况下将不进行打印,_totalPage=0
Dim _width As Int16 = 0 '用来保存每一次计算的总宽度
Dim i As Int16 = 0 '进行循环计算的条件
If _table.Columns.Count = 0 Then '没有列
Return 0
End If
If _table.Rows.Count = 0 Then '没有行
Return 0
End If
While i < _totalColumns
If _ds.GridColumnStyles(i).Width > width Then '假如单列的宽度大于页面设置的宽度,则不打印
Return 0
End If
_width += _ds.GridColumnStyles(i).Width
If _width > width Then
i -= 1 '退回一列,将此列计算到下一页中
_totalPage += 1 '页数增加
_width = 0 '宽度和置0
End If
i += 1
End While
_totalPage += 1 '全部通过了还有最后一页
i = 0 '用来计算行所占页
Dim j As Int16 = 0 '每页行数
j = Math.Floor((height - _hfont.Height - 2 - (_rfont.Height - 2) * 2) / (_rfont.Height + 2)) '每行保留2的间距,页尾也必须得加上
i = Math.Ceiling(_table.Rows.Count / j)
_totalPage *= i
Return (_totalPage) '是返回,顺便也解决了_totalPage
End Function
Protected Overrides Sub OnPrintPage(ByVal e As System.Drawing.Printing.PrintPageEventArgs)
If _curPage = 1 Then '第一次运行,先运行计算总页数的程序,以前的都是错的
GetTotalPage(e.MarginBounds.Width, e.MarginBounds.Height)
End If
Dim rPerPage As Int16 = (e.MarginBounds.Height - _hfont.Height - 2 - (_rfont.Height - 2) * 2) / (_rfont.Height + 2)
Dim cPerPage As Int16 = 0 '每页能打印的列数
Dim i As Int16 = _curRow '计算行数 需要打印到第几行
Dim j As Int16 = _curColumn '列数的计算 ‘需要本页需要打印到第几列
Dim xPos As Int16 = 0 '纵横点的坐标
Dim yPos As Int16 = e.MarginBounds.Top
Dim _width As Int16 = 0 '用来计算能用多少列的玩意,同时用于计算当前的宽度
While _curColumn + cPerPage < _totalColumns
cPerPage += 1
_width += _ds.GridColumnStyles(j + cPerPage - 1).Width
If _width > e.MarginBounds.Width Then
cPerPage -= 1 '由于最大化后需要回退一列,所以每页打印的列数需要减1
Exit While
End If
End While
Dim o As Int16 = 1 '用于行数计数
Dim p As Int16 = 1 '用于列数计数
'''打印列头
'''如何将文字居中:
xPos = (e.MarginBounds.Width - _htext.Length * _hfont.Size) / 2
e.Graphics.DrawString(_htext, _hfont, Brushes.Black, xPos, yPos)
xPos = e.MarginBounds.Left
yPos += _hfont.Height + 2
''打印表的列头
While p <= cPerPage
e.Graphics.DrawString(_ds.GridColumnStyles(p + _curColumn - 1).HeaderText, _rfont, Brushes.Black, xPos, yPos)
xPos += _ds.GridColumnStyles(p + _curColumn - 1).Width
p += 1
End While
xPos = e.MarginBounds.Left
yPos += _rfont.Height + 1
''打完表头画根线,总比不画要强多了
e.Graphics.DrawLine((New Pen(Color.Black)), xPos, yPos, xPos + e.MarginBounds.Width, yPos)
xPos = e.MarginBounds.Left
yPos += 2
p = 1
'进入表格内容打印阶断
While o < rPerPage
If _curRow + 1 > _table.Rows.Count Then
Exit While
End If
While p <= cPerPage
e.Graphics.DrawString(_table.Rows(i + o - 1)(_ds.GridColumnStyles(_curColumn + p - 1).MappingName) & "", _rfont, Brushes.Black, xPos, yPos)
xPos += _ds.GridColumnStyles(_curColumn + p - 1).Width
p += 1
End While
_curRow += 1
p = 1 '列次减1
yPos += _rfont.Height + 2
xPos = e.MarginBounds.Left
o += 1 '行次增加
End While
'打印主体后还得加一点后续
e.Graphics.DrawString("打印日期:" & Date.Now.ToString("yyyy-MM-dd"), _rfont, Brushes.Black, xPos, yPos)
'打印完后当前列需要增加
If _curRow + 1 > _table.Rows.Count Then
_curColumn += cPerPage
_curRow = 0
End If
'打印完后当前页增加1
_curPage += 1
If _curPage > _totalPage Then
_totalPage = 0 '由于预览完后需要打印的话就完了,因为变量已经超出了范围
_totalColumns = 0
_curPage = 1
_curRow = 0
_curColumn = 0
e.HasMorePages = False
Else
e.HasMorePages = True
End If
End Sub
End Class
调用实例之一:
dim pd as new datagridprint
pd.table=ptable
pd.datagridtablestyle=datagrid1.tablestyles(0)
...
pd.print