[VB.NET] - 打印DataGridView类
Imports System.Drawing.Printing
Public Class PrintDataGridView
Private WithEvents PrintDocument1 As New Printing.PrintDocument
Private WithEvents PageSetupDialog1 As New System.Windows.Forms.PageSetupDialog
Private WithEvents FontDialog1 As New System.Windows.Forms.FontDialog
Private WithEvents PrintPreviewDialog1 As New System.Windows.Forms.PrintPreviewDialog
Private DGV As DataGridView
Private strTitle As String
Private tsiDisplayStyle As ToolStripItemDisplayStyle = ToolStripItemDisplayStyle.Image
Private tirTextImageRelation As TextImageRelation = Windows.Forms.TextImageRelation.ImageAboveText
Private wInc As Single = 5 'wInc 为单元格宽增量
Private hInc As Single = 5 'hInc 为单元格竖增量
Private MainStartHeigth As Single 'MainStartHeigth 为主体表格起始的高度
Shared pNo As Integer = 1 'pNo 为页码
Private StartHeigth As Single
Private StartPos As Single
Shared hi As Integer = 0
Public PrintFont As Font = New Font("Arial", 16)
Private ColumnsWidth() As Single '数组 ColumnsWidth 为计算后的列宽
Private orgColumnsWidth() As Single '数组 orgColumnsWidth 为原始的最大列宽
Private RowHeigth As Single 'RowHeigth 为计算后的行高
Sub New()
AddHandler PrintDocument1.PrintPage, AddressOf Me.pd_PrintMain
End Sub
'按钮显示方式
'遍历整个表格,得到每列的最大宽度
Private Sub GetLargestWidthOfColumn(ByVal g As System.Drawing.Graphics)
ReDim ColumnsWidth(DGV.Columns.Count - 1) '定义列宽数组的长度
ReDim orgColumnsWidth(DGV.Columns.Count - 1)
For i As Integer = 0 To DGV.Columns.Count - 1
If DGV.Columns(i).Visible = False Then Continue For '如果列为隐藏,不打印
ColumnsWidth(i) = DGV.Columns(i).Width
Next
Dim iC, iR As Integer
For iC = 0 To DGV.Columns.Count - 1
If DGV.Columns(iC).Visible = False Then Continue For '如果列为隐藏,不打印
Dim dc As DataGridViewColumn = DGV.Columns(iC)
'计算列头文字需要的宽
Dim sizeFHeader As Drawing.SizeF
sizeFHeader = g.MeasureString(dc.HeaderText, PrintFont)
If sizeFHeader.Width > ColumnsWidth(iC) Then
orgColumnsWidth(iC) = sizeFHeader.Width
Else
If orgColumnsWidth(iC) > ColumnsWidth(iC) * 3 Then
orgColumnsWidth(iC) = ColumnsWidth(iC) * 3
Else
orgColumnsWidth(iC) = ColumnsWidth(iC)
End If
End If
RowHeigth = sizeFHeader.Height
dc.Dispose()
'计算值的宽
For iR = 0 To DGV.Rows.Count - 1
Dim dr As DataGridViewRow = DGV.Rows(iR)
If dr.Cells(iC).Value IsNot Nothing AndAlso Not IsDBNull(dr.Cells(iC).Value) Then
sizeFHeader = g.MeasureString(dr.Cells(iC).Value.ToString, PrintFont)
If orgColumnsWidth(iC) < sizeFHeader.Width Then
orgColumnsWidth(iC) = sizeFHeader.Width
End If
End If
dr.Dispose()
Next
Next
End Sub
'根据纸张宽度,计算出合适的列宽,返回缩小的比例
Private Function GetFitWidthOfColumn(ByVal pWidth As Single) As Integer
'每列按原始宽度的1%递减,直到适合纸张宽度(pWidth)
Dim l, i, k As Integer
l = orgColumnsWidth.Length
For k = 100 To 1 Step -1
Dim WidthSum As Single = 0
'按比例求宽度
For i = 0 To l - 1
ColumnsWidth(i) = orgColumnsWidth(i) * k / 100
WidthSum += orgColumnsWidth(i) * k / 100 + wInc
Next
If Not WidthSum > pWidth Then
Exit For
End If
Next
Return (k)
End Function
'根据合适的列宽和列宽缩小的比例,计算出合适的行高
Private Sub GetFitHeightOfRow(ByVal pScale As Integer)
RowHeigth = RowHeigth * Fix((100 / pScale) + 1) + hInc
End Sub
'打印主体
Private Sub pd_PrintMain(ByVal sender As Object, ByVal e As System.Drawing.Printing.PrintPageEventArgs)
Dim g As Graphics = e.Graphics
'如果是第一页,计算长宽
If pNo = 1 Then
GetLargestWidthOfColumn(g)
GetFitHeightOfRow(GetFitWidthOfColumn(e.MarginBounds.Width))
End If
'添加DataGridView主体
'计算标题的高度,预留空间
Dim sizeFTitle As Drawing.SizeF
sizeFTitle = e.Graphics.MeasureString(Title, New Font("宋体", 30, FontStyle.Bold))
MainStartHeigth = sizeFTitle.Height + e.MarginBounds.Top
StartHeigth = MainStartHeigth
'-------------------再来开始------------------------
'添加列头,按已经求出的最长宽度
'起始位置为纸张可打印边框的左边
StartPos = e.MarginBounds.Left
Dim i As Integer
For i = 0 To DGV.Columns.Count - 1
'如果列为隐藏,不打印
If DGV.Columns(i).Visible = False Then
Continue For
End If
Dim dc As DataGridViewColumn
dc = DGV.Columns(i)
Dim sizeFHeader As New Drawing.SizeF
sizeFHeader = e.Graphics.MeasureString(dc.HeaderText, PrintFont, ColumnsWidth(i)) '写表头
g.DrawString(dc.HeaderText, PrintFont, Drawing.Brushes.Black, New RectangleF(StartPos + wInc, StartHeigth + hInc, ColumnsWidth(i) - wInc, RowHeigth - hInc)) '添加外边框
g.DrawLine(Pens.Black, StartPos, StartHeigth, StartPos + ColumnsWidth(i), StartHeigth) '上
g.DrawLine(Pens.Black, StartPos, StartHeigth, StartPos, StartHeigth + RowHeigth) '左
StartPos += ColumnsWidth(i)
Next '添加主体
StartHeigth += RowHeigth
While hi < DGV.Rows.Count And StartHeigth < e.MarginBounds.Height
StartPos = e.MarginBounds.Left
Dim obj As New Object
Dim wi As Integer = 0
For wi = 0 To DGV.Columns.Count - 1
If DGV.Columns(wi).Visible = False Then Continue For '如果列为隐藏,不打印
Dim dcWidth As Single
dcWidth = ColumnsWidth(wi)
g.DrawLine(Pens.Black, StartPos, StartHeigth, StartPos + dcWidth, StartHeigth) '上
g.DrawLine(Pens.Black, StartPos, StartHeigth, StartPos, StartHeigth + RowHeigth) '左
StartPos += dcWidth
Try
If Not IsDBNull(DGV.Rows(hi).Cells(wi).Value) Then
g.DrawString(DGV.Rows(hi).Cells(wi).Value.ToString(), PrintFont, Drawing.Brushes.Black, New RectangleF(StartPos - dcWidth + 2, StartHeigth + 3, dcWidth + 2, RowHeigth))
End If
Catch ex As Exception
MessageBox.Show(ex.Message, "Error!", MessageBoxButtons.OK, MessageBoxIcon.Error)
End Try
Next
StartHeigth += RowHeigth
hi += 1
End While
'如果是第一页,添加表头
'根据绘制表格的宽度添加标题()
If pNo = 1 Then
If StartPos - e.MarginBounds.Left < sizeFTitle.Width Then
'如果标题的宽度大于表格的宽度,则缩小标题字号
For i = 30 To 1 Step -1
sizeFTitle = e.Graphics.MeasureString(Title, New Font("宋体", i, FontStyle.Bold))
If sizeFTitle.Width < StartPos - e.MarginBounds.Left Then
g.DrawString(Title, New Font("宋体", i, FontStyle.Bold), Brushes.Black, (StartPos - e.MarginBounds.Left - sizeFTitle.Width) / 2 + e.MarginBounds.Left, (MainStartHeigth - sizeFTitle.Height) / 2)
Exit For
End If
Next
Else
g.DrawString(Title, New Font("宋体", 30, FontStyle.Bold), Brushes.Black, (StartPos - e.MarginBounds.Left - sizeFTitle.Width) / 2 + e.MarginBounds.Left, (MainStartHeigth - sizeFTitle.Height) / 2)
End If
End If
g.DrawLine(Pens.Black, e.MarginBounds.Left, StartHeigth, StartPos, StartHeigth) '封底
g.DrawLine(Pens.Black, StartPos, MainStartHeigth, StartPos, StartHeigth) '封右边
If StartHeigth + RowHeigth > e.MarginBounds.Height And hi < DGV.Rows.Count Then
e.HasMorePages = True
pNo += 1 '页码加1
StartPos = e.MarginBounds.Left
StartHeigth = e.MarginBounds.Top
Else
e.HasMorePages = False
End If '结尾标志
'If hi.Equals(dgv.Rows.Count) Then 'And e.HasMorePages.Equals(False) Then
If hi >= DGV.Rows.Count Then 'And e.HasMorePages.Equals(False) Then
hi = 0
pNo = 1
Exit Sub
End If
End Sub
'数据源,输入DataGridView
Public Property MyDataGridView() As DataGridView
Set(ByVal value As DataGridView)
DGV = value
End Set
Get
Return DGV
End Get
End Property
'报表标题
Public Property Title() As String
Set(ByVal value As String)
strTitle = value
End Set
Get
Return strTitle
End Get
End Property
'页面设置
Public Sub PageSetup()
Me.PageSetupDialog1.Document = Me.PrintDocument1
Me.PageSetupDialog1.ShowDialog()
Me.PrintDocument1.DefaultPageSettings = Me.PageSetupDialog1.PageSettings
End Sub
'打印预览
Public Sub PrintPreview()
Me.PrintPreviewDialog1.Document = Me.PrintDocument1
Me.PrintPreviewDialog1.ShowDialog()
End Sub
'设置字体
Public Sub PrintPreviewFont()
Me.FontDialog1.ShowDialog()
PrintFont = Me.FontDialog1.Font
End Sub
'打印
Public Sub Print()
Me.PrintDocument1.Print()
End Sub
End Class
个性签名:做要做好,做到不三不四不如不做。