Printing a DataGridView in Vb.Net

  • Thread starter Thread starter mdruk
  • Start date Start date
M

mdruk

Guest
I have written a vb.net 2008 Express Edition application that pulls transaction history for customers from an iSeries. Everything appears to work as planned, except when you select to print Datagridview it prints the Date column as a DateTime instead of Date. When you are viewing the Datagridview in the VB.Net application it looks like it should.

On the iSeries the field with the date data is a decimal field with length of 7,0 with the following format CYYMMDD. In the VB.Net application the date portion is correct the time portion always is 12:00:00 AM due to i guess that it is picking up zeros somehow for time. Following is the code for the application. Any help would be appreciated.

Imports IBM.Data.DB2.iSeries
Public Class Transactions
Inherits System.Windows.Forms.Form
Private WithEvents dgv1 As New DataGridView()
Private bindingSource1 As New BindingSource()
Private Sub Transactions_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
Me.dgv1.Location = New Point(5, 25)
Me.dgv1.Size = New Size(940, 360)
Me.dgv1.Anchor = AnchorStyles.Top Or AnchorStyles.Left Or AnchorStyles.Bottom Or AnchorStyles.Right
Me.dgv1.ScrollBars = ScrollBars.Both
Me.Controls.Add(Me.dgv1)
Try
Set up the datagridview
With Me.dgv1
.AutoGenerateColumns = True
bindingSource1.DataSource = GetData("SELECT ""MTD.QRY"".AACCT, DATE(INT(MOD(""MTD.QRY"".ADATE,10000)/100) || / || MOD(""MTD.QRY"".ADATE,100) || / || INT((19000000 + ""MTD.QRY"".ADATE)/10000)), ""MTD.QRY"".AKEY, ""MTD.QRY"".ABATCH, ""MTD.QRY"".ATC, ""UBA.TC"".TDESC, ""MTD.QRY"".AAMT, ""UBA.TC"".TDC, ""MTD.QRY"".UBCHG, ""MTD.QRY"".ATIME1 FROM ""MTD.QRY"" INNER JOIN ""UBA.TC"" ON ""MTD.QRY"".ATC = ""UBA.TC"".TTC WHERE (AACCT=@aact)")
.DataSource = bindingSource1
.AutoSizeRowsMode = DataGridViewAutoSizeRowsMode.DisplayedCellsExceptHeaders
.BorderStyle = BorderStyle.Fixed3D
.SelectionMode = DataGridViewSelectionMode.FullRowSelect
.MultiSelect = True
.AllowUserToAddRows = False
.ShowCellToolTips = False
.Columns("AACCT").HeaderText = "Acct. No."
.Columns(1).HeaderText = "Date"
.Columns("AKEY").HeaderText = "Receipt"
.Columns("ABATCH").HeaderText = "Batch"
.Columns("ATC").HeaderText = "Trans Code"
.Columns("TDESC").HeaderText = "Trans Desc"
.Columns("AAMT").HeaderText = "Debit"
.Columns("TDC").HeaderText = "Debit/Credit"
.Columns("UBCHG").HeaderText = "Balance"
End With
Catch ex As Exception
MessageBox.Show(ex.Message)
System.Threading.Thread.CurrentThread.Abort()
End Try
For x = 0 To dgv1.Rows.Count - 1
If dgv1.Rows(x).Cells(7).Value = "C" Then
dgv1.Rows(x).Cells(8).Value = CDbl(dgv1.Rows(x).Cells(6).Value)
dgv1.Rows(x).Cells(6).Value = 0
End If
Next
Me.dgv1.Columns("TDC").Visible = False
Me.dgv1.Columns("ATIME1").Visible = False
End Sub
Private Shared Function GetData(ByVal iDB2Command As String) As DataTable
Dim thisConnectionString As String = "DataSource=sub; Naming=System; LibraryList=QS36F"
Dim thisConnection As iDB2Connection = New iDB2Connection(thisConnectionString)
thisConnection.Open()
Dim thisCommand As New iDB2Command(iDB2Command, thisConnection)
thisCommand.DeriveParameters()
thisCommand.Parameters("@aact").Value = CustInfo.txtAcct.Text
Dim thisReader As iDB2DataAdapter = New iDB2DataAdapter()
thisReader.SelectCommand = thisCommand
Dim table As New DataTable
table.Locale = System.Globalization.CultureInfo.InvariantCulture
thisReader.Fill(table)
table.Columns.Add("Credit", Type.GetType("System.Double")).SetOrdinal(8)
table.DefaultView.Sort = """00002"" DESC, ATIME1 DESC"
thisConnection.Close()
Return table
End Function
<STAThreadAttribute()> Public Shared Sub main()
Application.Run(New Transactions)
End Sub
Private Sub ExitToolStripMenuItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ExitToolStripMenuItem.Click
Me.Close()
End Sub
Private Sub PrintToolStripMenuItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles PrintToolStripMenuItem.Click
PrintDGV.Print_DataGridView(dgv1)
End Sub
End Class

The print code, which i copied and adapted from one of these forums:

Imports System.Collections.Generic
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", 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 = dlg.PrintTitle
PrintAllRows = dlg.PrintAllRows
FitToPageWidth = dlg.FitToPageWidth
SelectedColumns = dlg.GetSelectedColumns
RowsPerPage = 0
Dim psd As New PageSetupDialog()
psd.Document = PrintDoc
psd.ShowDialog()
PrintDoc.DefaultPageSettings = psd.PageSettings
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
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 - 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 = "Name" Or Cel.OwningColumn.HeaderText = "Address" 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 doesnt 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

Continue reading...
 
Back
Top