VB.Net Print Datagridview in WinForms


This article is written by Pon Saravanan  on 28-Dec-10 Last modified on :08-Feb-11





VB.Net Tutorial - Datagridview Printing

There will be situations to just print a DataGridView in a application than designing again the columns and rows in a Crystal Report. But in .Net there is no straight forward way to do this or in other words this is not supported natively. To print the Datagridview we need to draw all the objects using Graphics Object given in the PrintDocument before calling print method in the respective PrintDocument.

PrintDocument and the Graphics Object

So as I earlier said we need to actually draw all including text using the Graphics object.  The print document needs to be prepared before actual printing starts. So we can use the event PrintPage, in this event we can draw all the objects as we need.

Draw the DataGridView like a table using lines

To get a tabular data to represent the DataGridView, we need to do the following
• Draw an outer rectangle as the border to table
• Draw a line for every row
• Draw a line for every column while iterating the cell
• Draw the cell value as text
All the above said items can be drawn with the help of the DataGridView’s native properties, Left, Top, Height, Width, Row.Hieght, and Column. Width

Screen Capture in WinForms


 

Screen Capture after Print


 

Source Code

WinForms Code Behind(*.vb)

Imports System.Data.SqlClient
Imports System.Drawing.Printing
Public Class Form1
    Private Const FontAdjustmentFactor = 1.1
    Private Const ConnectionString As String = "Server=.;" & _
                   "Database=NorthWind;Trusted_Connection=True"
    Private ReadOnly Property Connection() As SqlConnection
        Get
            Dim ConnectionToFetch As New SqlConnection(ConnectionString)
            ConnectionToFetch.Open()
            Return ConnectionToFetch
        End Get
    End Property
    Public Function GetData() As DataView
        Dim SelectQry = "SELECT CategoryName,Description FROM Categories "
        'Dim SelectQry = "SELECT * FROM products "
        Dim SampleSource As New DataSet
        Dim TableView As DataView
        Try
            Dim SampleCommand As New SqlCommand()
            Dim SampleDataAdapter = New SqlDataAdapter()
            SampleCommand.CommandText = SelectQry
            SampleCommand.Connection = Connection
            SampleDataAdapter.SelectCommand = SampleCommand
            SampleDataAdapter.Fill(SampleSource)
            TableView = SampleSource.Tables(0).DefaultView
        Catch ex As Exception
            Throw ex
        End Try
        Return TableView
    End Function
    Private Sub btnLoad_Click(ByVal sender As System.Object, _
                              ByVal e As System.EventArgs) Handles btnLoad.Click
        DataGridView1.DataSource = GetData()
    End Sub
    Private Sub GridViewPrintDocument_PrintPage(ByVal sender As Object, _
                               ByVal e As PrintPageEventArgs)
        PrintGridView(e.Graphics)
    End Sub
    Private Sub btnPrint_Click(ByVal sender As Object, _
                               ByVal e As System.EventArgs) Handles btnPrint.Click
        Dim GridViewPrintDocument As New Printing.PrintDocument
        AddHandler GridViewPrintDocument.PrintPage, _
        AddressOf GridViewPrintDocument_PrintPage
        GridViewPrintDocument.Print()
    End Sub
    Private Sub PrintGridView(ByVal GxPrint As Graphics)
       
        DrawGridViewBox(GxPrint)
        DrawGridViewHeader(GxPrint)
        DrawGridViewRows(GxPrint)
    End Sub
    Private Sub DrawGridViewHeader(ByVal GxPrint As Graphics)
        Dim CellText = String.Empty
        Dim StartTop = DataGridView1.Top
        Dim PrintFont As New Font(New FontFamily("Microsoft Sans Serif"), _
                                         10, FontStyle.Bold)
        Dim StartLeft = DataGridView1.Left
        For Each PrintCol As DataGridViewColumn In DataGridView1.Columns
            CellText = PrintCol.HeaderText
            GxPrint.DrawString(CellText, PrintFont, Brushes.Gray, _
                                   StartLeft, StartTop)
            GxPrint.DrawLine(Pens.Black, StartLeft, StartTop, _
                             StartLeft, StartTop + DataGridView1.Rows(0).Height)
            StartLeft += PrintCol.Width * FontAdjustmentFactor
        Next
        GxPrint.DrawLine(Pens.Black, DataGridView1.Left, _
                         StartTop + DataGridView1.Rows(0).Height, _
                         CInt(DataGridView1.Width * FontAdjustmentFactor), _
                         StartTop + DataGridView1.Rows(0).Height)
    End Sub

    Private Sub DrawGridViewRows(ByVal GxPrint As Graphics)
        Dim RowIndex = 1 'since header is used so we start with 1
        Dim PrintFont As New Font(New FontFamily("Microsoft Sans Serif"), _
                                          10, FontStyle.Regular)
        For Each PrintRow As DataGridViewRow In DataGridView1.Rows
            Dim StartTop = DataGridView1.Top + (RowIndex * PrintRow.Height)
            Dim ColIndex = 0
            Dim StartLeft = DataGridView1.Left
            For Each PrintCell As DataGridViewCell In PrintRow.Cells

                StartLeft *= FontAdjustmentFactor
                Dim CellText = String.Empty
                If (Not IsDBNull(PrintCell.Value)) Then CellText = PrintCell.Value

                GxPrint.DrawString(CellText, PrintFont, Brushes.Gray, _
                                   StartLeft, StartTop)
                GxPrint.DrawLine(Pens.Black, StartLeft, StartTop, _
                                 StartLeft, StartTop + PrintRow.Height)
                StartLeft += DataGridView1.Columns(ColIndex).Width
                ColIndex += 1
            Next
            GxPrint.DrawLine(Pens.Black, DataGridView1.Left, _
                             StartTop + PrintRow.Height, _
                             CInt(DataGridView1.Width * FontAdjustmentFactor), _
                             StartTop + PrintRow.Height)
            RowIndex += 1
        Next
    End Sub

    Private Sub DrawGridViewBox(ByVal GxPrint As Graphics)
        Dim GridViewRect As New Rectangle( _
                    DataGridView1.Left, DataGridView1.Top, _
                    DataGridView1.Width * FontAdjustmentFactor, _
                    DataGridView1.Height * FontAdjustmentFactor)

        GxPrint.DrawRectangle(Pens.Black, GridViewRect)
    End Sub
End Class











Comments
  • GUEST
    How to integrate page break (multiple page) in this logic? 7/26/2011 2:12:42 PM

  • GUEST
    9/9/2011 6:55:29 AM

  • GUEST
    Use below code for multiple pages

    Dim pointedIndex As Integer
    Dim rowInPage As Integer
    Dim printPending As Boolean = True
    Dim gridViewDoc As New Printing.PrintDocument
    AddHandler gridViewDoc.PrintPage, AddressOf GridView_Print
    gridViewDoc.PrinterSettings.Copies = 2
    gridViewDoc.Print()
    panWMSTotals.Cursor = System.Windows.Forms.Cursors.Default

    Private Sub GridView_Print(ByVal sender As Object, ByVal e As PrintPageEventArgs)
    PrintGridView(e.Graphics)
    If printPending = True Then
    e.HasMorePages = True
    Else
    e.HasMorePages = False
    End If
    End Sub
    Private Sub PrintGridView(ByVal print As Graphics)
    FillHeaders(print)
    DataGridViewHeader(print)
    DataGridViewRow(print)
    DataGridViewBox(print)
    End Sub

    Private Sub FillHeaders(ByVal print As Graphics)
    Dim rectangle As New Rectangle(CInt(12.5), dgPlans.Top, CInt(dgPlans.Width * 1.367), CInt(dgPlans.Rows(0).Height - 4.3))
    Dim brush As New SolidBrush(Color.LightGray)
    print.FillRectangle(brush, rectangle)

    End Sub


    Private Sub DataGridViewHeader(ByVal print As Graphics)
    Dim cellText As String = String.Empty
    Dim startTop As Integer = dgPlans.Top
    Dim title As String = String.Empty
    Dim printfont As New Font(New FontFamily("Arial"), 7, FontStyle.Bold)
    Dim titlefont As New Font(New FontFamily("Arial"), 12, FontStyle.Bold)
    Dim colIndex As Integer = 0
    Dim startLeft As Integer = 12
    Dim center As Integer
    Dim size As SizeF
    Dim headerWidth As Integer
    title = "List Of Subscribers"
    print.DrawString(title, titlefont, Brushes.Black, 310, 8)
    For Each printcolumn As DataGridViewColumn In dgPlans.Columns
    Using measure As System.Drawing.Graphics = System.Drawing.Graphics.FromImage(New Bitmap(1, 1))
    size = measure.MeasureString(dgPlans.Columns(colIndex).HeaderText, New Font("Arial", 10, FontStyle.Regular, GraphicsUnit.Point))
    End Using
    headerWidth = CInt(Math.Floor(Convert.ToDecimal(CType(size.Width, String), CultureInfo.CurrentCulture)))
    For calculate As Integer = 0 To dgPlans.Columns(colIndex).Width
    Dim firsthalf As Integer = calculate
    Dim secondhalf As Integer = dgPlans.Columns(colIndex).Width - (calculate + headerWidth)
    If firsthalf = secondhalf Then
    center = calculate
    Exit For
    ElseIf (firsthalf = secondhalf - 1) Then
    center = calculate
    Exit For
    End If
    Next
    startLeft = CInt(startLeft * 1.1)
    cellText = printcolumn.HeaderText
    print.DrawString(cellText, printfont, Brushes.Black, startLeft + center, startTop + 5)
    print.DrawLine(Pens.Black, startLeft, startTop, startLeft, startTop + CInt(dgPlans.Rows(0).Height - 4.3))
    startLeft += dgPlans.Columns(colIndex).Width - 20
    colIndex += 1
    Next
    print.DrawLine(Pens.Black, 13, startTop + CInt(dgPlans.Rows(0).Height - 4.3), CInt(dgPlans.Width * 1.4), CInt(startTop + dgPlans.Rows(0).Height - 4.3))
    End Sub

    Private Sub DataGridViewRow(ByVal print As Graphics)
    Dim rowIndex As Integer = 1
    Dim printFont As New Font(New FontFamily("Arial"), 7, FontStyle.Bold)
    While printPending = True
    For pointedIndex = pointedIndex To dgPlans.Rows.Count - 1
    Dim starttop As Integer = dgPlans.Top + CInt(rowIndex * (dgPlans.Rows(pointedIndex).Height - 4.3))
    Dim colIndex As Integer = 0
    Dim startLeft As Integer = 12

    For Each printCell As DataGridViewCell In dgPlans.Rows(pointedIndex).Cells
    startLeft = CInt(startLeft * 1.1)
    Dim cellText As String = String.Empty
    If (Not IsDBNull(printCell.Value)) Then cellText = CStr(printCell.Value)
    print.DrawString(cellText, printFont, Brushes.Black, startLeft, starttop + 5)
    print.DrawLine(Pens.Black, startLeft, starttop, startLeft, starttop + CInt(dgPlans.Rows(pointedIndex).Height - 4.3))
    startLeft += dgPlans.Columns(colIndex).Width - 20
    colIndex += 1
    Next
    print.DrawLine(Pens.Black, 12, starttop + CInt(dgPlans.Rows(pointedIndex).Height - 4.3), CInt(dgPlans.Width * 1.4), starttop + CInt(dgPlans.Rows(pointedIndex).Height - 4.3))
    rowIndex += 1
    rowInPage = rowIndex
    If rowIndex = 45 Then
    pointedIndex = pointedIndex + 1
    Exit While
    End If
    If pointedIndex = dgPlans.Rows.Count - 1 Then
    printPending = False
    End If
    Next
    End While
    End Sub


    Private Sub DataGridViewBox(ByVal print As Graphics)
    Dim gridviewRect As New Rectangle(CInt(12.5), dgPlans.Top, CInt(dgPlans.Width * 1.368), CInt((dgPlans.Rows(0).Height - 4.3) * rowInPage))
    print.DrawRectangle(Pens.Black, gridviewRect)
    End Sub

    Regards
    Ramkumar. V
    1/10/2012 4:25:40 AM

  • GUEST
    how to print in landscape using this code 5/4/2012 6:35:26 AM

  • GUEST
    gridviewDoc.DefaultSetting.LandScape= true

    do this before calling gridViewDoc.Print()

    Regards
    Ramkumar.V
    6/4/2012 8:20:56 AM

  • GUEST
    7/27/2012 3:18:39 PM

  • GUEST
    Hi,
    any body knows how to remove some columns from print preview.i need your help urgent.
    Thanks
    8/11/2012 3:59:18 PM

  • GUEST
    hi rajkumar,
    Am Mahadevan. i have tried for print grid in multiple page, but i was supposed to meet error in "dgPlans" as dgplans is not diclared. and f i diclared t as integer, den it shows error in dgplans.width, dgplans.rows, dgplans.columns.....
    could u explain t in detail...
    4/5/2013 6:17:26 AM

  • GUEST
    dgPlans is the gridview,, instead of dgplans give the name of your gridview in design page.

    Regards
    Ramkumar V
    4/8/2013 11:47:48 PM

  • GUEST
    http://ramcreatus.blogspot.in/2013/05/print-datagridview-in-winforms.html

    Check this I explained it in detail

    Regards
    Ramkumar V
    5/3/2013 6:32:09 AM


Comments
   
Captcha Image
For you specially:  
Captcha Text Enter the text in the image.(Not Case sensitive)