Files
Doku/Dokumentation/PrintDGV.vb
2018-11-22 16:52:25 +01:00

293 lines
17 KiB
VB.net

Imports System.Collections.Generic
Imports Microsoft.VisualBasic.PowerPacks.Printing
Imports System.Data.Common
Public Class PrintDGV
Private Shared StrFormat As StringFormat ' Holds content of a TextBox Cell to write by DrawString
Private Shared StrFormatComboBox As StringFormat ' Holds content of a Boolean Cell to write by DrawImage
Private Shared CellButton As Button ' Holds the Contents of Button Cell
Private Shared CellCheckBox As CheckBox ' Holds the Contents of CheckBox Cell
Private Shared CellComboBox As ComboBox ' Holds the Contents of ComboBox Cell
Private Shared TotalWidth As Int16 ' Summation of Columns widths
Private Shared RowPos As Int16 ' Position of currently printing row
Private Shared NewPage As Boolean ' Indicates if a new page reached
Private Shared PageNo As Int16 ' Number of pages to print
Private Shared ColumnLefts As New ArrayList ' Left Coordinate of Columns
Private Shared ColumnWidths As New ArrayList ' Width of Columns
Private Shared ColumnTypes As New ArrayList ' DataType of Columns
Private Shared CellHeight As Int16 ' Height of DataGrid Cell
Private Shared RowsPerPage As Int16 ' Number of Rows per Page
Private Shared WithEvents PrintDoc As New System.Drawing.Printing.PrintDocument ' PrintDocumnet Object used for printing
Private Shared PrintTitle As String = "" ' Header of pages
Private Shared dgv As DataGridView ' Holds DataGrid Object to print its contents
Private Shared SelectedColumns As New List(Of String) ' The Columns Selected by user to print.
Private Shared AvailableColumns As New List(Of String) ' All Columns avaiable in DataGrid
Private Shared PrintAllRows As Boolean = True ' True = print all rows, False = print selected rows
Private Shared FitToPageWidth As Boolean = True ' True = Fits selected columns to page width , False = Print columns as showed
Private Shared HeaderHeight As Int16 = 0
Private Shared drawfont As New Font("Arial", 7) ''<-------------------------------------------------------------------8
Private Shared drawfont1 As New Font("Arial", 6, FontStyle.Bold)
Public Shared Sub Print_DataGridView(ByVal DataGridView1 As DataGridView)
Dim ppvw As PrintPreviewDialog
Try
' Getting DataGridView object to print
dgv = DataGridView1
' Getting all Coulmns Names in the DataGridView
AvailableColumns.Clear()
For Each c As DataGridViewColumn In dgv.Columns
If Not c.Visible Then Continue For
AvailableColumns.Add(c.HeaderText)
Next
' Showing the PrintOption Form
'Dim dlg As New PrintOptions(AvailableColumns)
'If dlg.ShowDialog() <> DialogResult.OK Then Exit Sub
' Saving some printing attributes
' PrintTitle = ReporTitleAsNeeded ' dlg.PrintTitle
PrintAllRows = True ' dlg.PrintAllRows
FitToPageWidth = True ' dlg.FitToPageWidth
SelectedColumns = AvailableColumns 'dlg.GetSelectedColumns
'RowsPerPage = 0
Dim psd As New PageSetupDialog()
psd.Document = PrintDoc
psd.PageSettings.Landscape = True
psd.ShowDialog()
PrintDoc.DefaultPageSettings = psd.PageSettings
PrintDoc.DefaultPageSettings.Landscape = True
ppvw = New PrintPreviewDialog
ppvw.Document = PrintDoc
' Showing the Print Preview Page
If ppvw.ShowDialog() <> DialogResult.OK Then Exit Sub
PrintDoc.Print()
Catch ex As Exception
MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error)
Finally
End Try
End Sub
Private Shared Sub PrintDoc_BeginPrint(ByVal sender As Object,
ByVal e As System.Drawing.Printing.PrintEventArgs) Handles PrintDoc.BeginPrint
Try
' Formatting the Content of Text Cells to print
StrFormat = New StringFormat
StrFormat.Alignment = StringAlignment.Near
StrFormat.LineAlignment = StringAlignment.Center
StrFormat.Trimming = StringTrimming.EllipsisCharacter
' Formatting the Content of Combo Cells to print
StrFormatComboBox = New StringFormat
StrFormatComboBox.LineAlignment = StringAlignment.Center
StrFormatComboBox.FormatFlags = StringFormatFlags.NoWrap
StrFormatComboBox.Trimming = StringTrimming.EllipsisCharacter
ColumnLefts.Clear()
ColumnWidths.Clear()
ColumnTypes.Clear()
CellHeight = 0
RowsPerPage = 0
' For various column types
CellButton = New Button
CellCheckBox = New CheckBox
CellComboBox = New ComboBox
TotalWidth = 0
For Each GridCol As DataGridViewColumn In dgv.Columns
If Not GridCol.Visible Then Continue For
If Not SelectedColumns.Contains(GridCol.HeaderText) Then Continue For
TotalWidth += GridCol.Width
Next
PageNo = 1
NewPage = True
RowPos = 0
Catch ex As Exception
MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error)
Finally
End Try
End Sub
Private Shared Sub PrintDoc_PrintPage(ByVal sender As Object,
ByVal e As System.Drawing.Printing.PrintPageEventArgs) Handles PrintDoc.PrintPage
Dim tmpWidth As Int16, i As Int16
Dim tmpTop As Int16 = e.MarginBounds.Top
Dim tmpLeft As Int16 = e.MarginBounds.Left
Try
' Before starting first page, it saves Width & Height of Headers and ColumnType
If PageNo = 1 Then
For Each GridCol As DataGridViewColumn In dgv.Columns
If Not GridCol.Visible Then Continue For
If Not SelectedColumns.Contains(GridCol.HeaderText) Then
Continue For
End If
' Detemining whether the columns are fitted to page or not.
If FitToPageWidth Then
tmpWidth = CType(Math.Floor(GridCol.Width / TotalWidth *
TotalWidth * (e.MarginBounds.Width / TotalWidth)), Int16)
Else
tmpWidth = GridCol.Width
End If
HeaderHeight = e.Graphics.MeasureString(GridCol.HeaderText,
drawfont, tmpWidth).Height + 11
ColumnLefts.Add(tmpLeft)
ColumnWidths.Add(tmpWidth)
ColumnTypes.Add(GridCol.GetType)
tmpLeft += tmpWidth
Next
End If
' Printing Current Page, Row by Row
Do While RowPos <= dgv.Rows.Count - 1
Dim GridRow As DataGridViewRow = dgv.Rows(RowPos)
If GridRow.IsNewRow OrElse (Not PrintAllRows AndAlso Not GridRow.Selected) Then
RowPos += 1 : Continue Do
End If
CellHeight = GridRow.Height ' + 10
dgv.AutoSizeRowsMode = DataGridViewAutoSizeColumnsMode.AllCells
'CellHeight = 30
If tmpTop + CellHeight >= e.MarginBounds.Height + e.MarginBounds.Top Then
DrawFooter(e, RowsPerPage)
NewPage = True
PageNo += 1
e.HasMorePages = True
Exit Sub
Else
If NewPage Then
' Draw Header
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 - 10) ''<-------------------------------------------------------------------13
Dim s As String = Now.ToLongDateString + " " + Now.ToShortTimeString
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 Columns
tmpTop = e.MarginBounds.Top
i = 0
For Each GridCol As DataGridViewColumn In dgv.Columns
If Not GridCol.Visible Then Continue For
If Not SelectedColumns.Contains(GridCol.HeaderText) Then
Continue For
End If
' Grey shading for Header Text Box
e.Graphics.FillRectangle(New SolidBrush(Drawing.Color.LightGray),
New Rectangle(ColumnLefts(i), tmpTop, ColumnWidths(i), HeaderHeight))
'Draw Header Text Box
e.Graphics.DrawRectangle(Pens.Black, New Rectangle(ColumnLefts(i),
tmpTop, ColumnWidths(i), HeaderHeight))
'Draw Header Text
e.Graphics.DrawString(GridCol.HeaderText, GridCol.InheritedStyle.Font,
New SolidBrush(GridCol.InheritedStyle.ForeColor),
New RectangleF(ColumnLefts(i), tmpTop, ColumnWidths(i),
HeaderHeight), StrFormat)
i += 1
Next
NewPage = False
tmpTop += HeaderHeight
End If
i = 0
For Each Cel As DataGridViewCell In GridRow.Cells
If Not Cel.OwningColumn.Visible Then Continue For
If Not SelectedColumns.Contains(Cel.OwningColumn.HeaderText) Then
Continue For
End If
' For the TextBox Column
If ColumnTypes(i) Is GetType(DataGridViewTextBoxColumn) OrElse
ColumnTypes(i) Is GetType(DataGridViewLinkColumn) Then
If Cel.OwningColumn.HeaderText = "A" Or Cel.OwningColumn.HeaderText = "FQDN" Then
e.Graphics.DrawString(Cel.Value.ToString, drawfont1,
New SolidBrush(Cel.InheritedStyle.ForeColor),
New RectangleF(ColumnLefts(i), tmpTop, ColumnWidths(i),
CellHeight), StrFormat)
Else
e.Graphics.DrawString(Cel.Value.ToString, drawfont,
New SolidBrush(Cel.InheritedStyle.ForeColor),
New RectangleF(ColumnLefts(i), tmpTop, ColumnWidths(i),
CellHeight), StrFormat)
End If
' For the Button Column
ElseIf ColumnTypes(i) Is GetType(DataGridViewButtonColumn) Then
CellButton.Text = Cel.Value.ToString
CellButton.Size = New Size(ColumnWidths(i), CellHeight)
Dim bmp As New Bitmap(CellButton.Width, CellButton.Height)
CellButton.DrawToBitmap(bmp, New Rectangle(0, 0,
bmp.Width, bmp.Height))
e.Graphics.DrawImage(bmp, New Point(ColumnLefts(i), tmpTop))
' For the CheckBox Column
ElseIf ColumnTypes(i) Is GetType(DataGridViewCheckBoxColumn) Then
CellCheckBox.Size = New Size(14, 14)
CellCheckBox.Checked = CType(Cel.Value, Boolean)
Dim bmp As New Bitmap(ColumnWidths(i), CellHeight)
Dim tmpGraphics As Graphics = Graphics.FromImage(bmp)
tmpGraphics.FillRectangle(Brushes.White, New Rectangle(0, 0,
bmp.Width, bmp.Height))
CellCheckBox.DrawToBitmap(bmp, New Rectangle(CType((bmp.Width -
CellCheckBox.Width) / 2, Int32), CType((bmp.Height -
CellCheckBox.Height) / 2, Int32), CellCheckBox.Width,
CellCheckBox.Height))
e.Graphics.DrawImage(bmp, New Point(ColumnLefts(i), tmpTop))
' For the ComboBox Column
ElseIf ColumnTypes(i) Is GetType(DataGridViewComboBoxColumn) Then
CellComboBox.Size = New Size(ColumnWidths(i), CellHeight)
Dim bmp As New Bitmap(CellComboBox.Width, CellComboBox.Height)
CellComboBox.DrawToBitmap(bmp, New Rectangle(0, 0,
bmp.Width, bmp.Height))
e.Graphics.DrawImage(bmp, New Point(ColumnLefts(i), tmpTop))
e.Graphics.DrawString(Cel.Value.ToString, Cel.InheritedStyle.Font,
New SolidBrush(Cel.InheritedStyle.ForeColor),
New RectangleF(ColumnLefts(i) + 1, tmpTop, ColumnWidths(i) _
- 16, CellHeight), StrFormatComboBox)
' For the Image Column
ElseIf ColumnTypes(i) Is GetType(DataGridViewImageColumn) Then
Dim CelSize As Rectangle = New Rectangle(ColumnLefts(i),
tmpTop, ColumnWidths(i), CellHeight)
Dim ImgSize As Size = CType(Cel.FormattedValue, Image).Size
e.Graphics.DrawImage(Cel.FormattedValue, New Rectangle(ColumnLefts(i) _
+ CType(((CelSize.Width - ImgSize.Width) / 2), Int32),
tmpTop + CType(((CelSize.Height - ImgSize.Height) / 2),
Int32), CType(Cel.FormattedValue, Image).Width, CType(Cel.FormattedValue,
Image).Height))
End If
' Drawing Cells Borders
e.Graphics.DrawRectangle(Pens.Black, New Rectangle(ColumnLefts(i),
tmpTop, ColumnWidths(i), CellHeight))
i += 1
Next
tmpTop += CellHeight
End If
RowPos += 1
' For the first page it calculates Rows per Page
If PageNo = 1 Then
RowsPerPage += 1
End If
Loop
If RowsPerPage = 0 Then Exit Sub
' Write Footer (Page Number)
DrawFooter(e, RowsPerPage)
e.HasMorePages = False
Catch ex As Exception
MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error)
Finally
End Try
End Sub
Private Shared Sub DrawFooter(ByVal e As System.Drawing.Printing.PrintPageEventArgs, ByVal RowsPerPage As Int32)
Dim cnt As Integer
' Detemining rows number to print
If PrintAllRows Then
If dgv.Rows(dgv.Rows.Count - 1).IsNewRow Then
' When the DataGridView doesn't allow adding rows
cnt = dgv.Rows.Count - 2
Else
' When the DataGridView allows adding rows
cnt = dgv.Rows.Count - 1
End If
Else
cnt = dgv.SelectedRows.Count
End If
' Writing the Page Number on the Bottom of Page
Dim PageNum As String = PageNo.ToString + " of " + Math.Ceiling(cnt / RowsPerPage).ToString
e.Graphics.DrawString(PageNum, drawfont, Brushes.Black, e.MarginBounds.Left + (e.MarginBounds.Width -
e.Graphics.MeasureString(PageNum, drawfont, e.MarginBounds.Width).Width) / 2, e.MarginBounds.Top +
e.MarginBounds.Height + 31)
End Sub
End Class