Link to home
Start Free TrialLog in
Avatar of VBdotnet2005
VBdotnet2005Flag for United States of America

asked on

datagrid - print

Is it possible to print what is being displayed on Datagrid?


Private Sub btnLoad_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnRefresh.Click

DataSet11.Clear()

Me.SqlDataAdapter1.Fill(DataSet11)

Me.lblTime.Text = "Last update : " & Date.Now



End Sub

ASKER CERTIFIED SOLUTION
Avatar of JRossi1
JRossi1

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of iboutchkine
iboutchkine

Prints multiple pages

Form1 - startup
Imports System.Data.OleDb

Public Class Form1
    Inherits System.Windows.Forms.Form

#Region " Windows Form Designer generated code "

    Public Sub New()
        MyBase.New()

        'This call is required by the Windows Form Designer.
        InitializeComponent()

        'Add any initialization after the InitializeComponent() call

    End Sub

    'Form overrides dispose to clean up the component list.
    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

    'Required by the Windows Form Designer
    Private components As System.ComponentModel.IContainer

    'NOTE: The following procedure is required by the Windows Form Designer
    'It can be modified using the Windows Form Designer.  
    'Do not modify it using the code editor.
    Friend WithEvents dg As System.Windows.Forms.DataGrid
    Friend WithEvents btnPrint As System.Windows.Forms.Button
    <System.Diagnostics.DebuggerStepThrough()> Private Sub InitializeComponent()
        Me.dg = New System.Windows.Forms.DataGrid
        Me.btnPrint = New System.Windows.Forms.Button
        CType(Me.dg, System.ComponentModel.ISupportInitialize).BeginInit()
        Me.SuspendLayout()
        '
        'dg
        '
        Me.dg.DataMember = ""
        Me.dg.HeaderForeColor = System.Drawing.SystemColors.ControlText
        Me.dg.Location = New System.Drawing.Point(0, 0)
        Me.dg.Name = "dg"
        Me.dg.Size = New System.Drawing.Size(292, 196)
        Me.dg.TabIndex = 0
        '
        'btnPrint
        '
        Me.btnPrint.Location = New System.Drawing.Point(8, 220)
        Me.btnPrint.Name = "btnPrint"
        Me.btnPrint.TabIndex = 1
        Me.btnPrint.Text = "Print"
        '
        'Form1
        '
        Me.AutoScaleBaseSize = New System.Drawing.Size(5, 13)
        Me.ClientSize = New System.Drawing.Size(292, 266)
        Me.Controls.Add(Me.btnPrint)
        Me.Controls.Add(Me.dg)
        Me.Name = "Form1"
        Me.Text = "Form1"
        CType(Me.dg, System.ComponentModel.ISupportInitialize).EndInit()
        Me.ResumeLayout(False)

    End Sub

#End Region
    Private dge As New DataGridEx

    Dim cn As OleDbConnection
    Dim sConn As String = _
     "Provider=Microsoft.Jet.OLEDB.4.0;" & _
     "Data Source=C:\TestDB\TestDB.mdb;"

    Dim ds As DataSet
    Dim da As OleDbDataAdapter
    Dim sSQL As String = "SELECT * FROM Test"
    Dim sSource As String = "Test"

    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        Me.CreateDS()
        dg.DataSource = ds
        dg.DataMember = "Test"
    End Sub
    Private Sub CreateDS()
        ds = New DataSet
        'Connect to database and specify sSQL
        da = New OleDbDataAdapter(sSQL, sConn)

        Try
            'using DataAdapter enter records from table to DataSet
            da.Fill(ds, sSource) 'fsSource is a table
        Catch objExc As System.Exception
            'if error happend then email or write to Log?
            Exit Sub
        End Try

    End Sub
 

    Private Sub btnPrint_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnPrint.Click
        Dim obj, obj2 As Object

        obj2 = New DataView(ds.Tables("Test"))
        dge.Print(obj2, ds.Tables("Test"), CType(Me.BindingContext(dg.DataSource), CurrencyManager))
        MsgBox("Done")
    End Sub
End Class
================================================================
Class DataGridEx

Public Class DataGridEx
    Inherits DataGrid

    Protected protCustomColumnsHeaders As Boolean
    Protected protOldHeaderFont As Font
    Protected protNRowsInCaption As Integer
    Protected protRowHeaderWidth As Integer

    Private components As System.ComponentModel.IContainer

    Public Function CreateTableStyle(ByVal Table As DataTable) As DataGridTableStyle
        Dim ts1 As New DataGridTableStyle
        ts1.MappingName = Table.TableName
        Dim i As Integer
        For i = 0 To Table.Columns.Count - 1
            If Table.Columns(i).DataType Is GetType(Boolean) Then
                Dim boolCol As New DataGridBoolColumn '       DataGridBoolColumnEx
                boolCol.MappingName = Table.Columns(i).ColumnName
                boolCol.HeaderText = Table.Columns(i).ColumnName
                ts1.GridColumnStyles.Add(boolCol)
            Else
                Dim TextCol As New DataGridTextBoxColumn '   DataGridTextBoxColumnEx
                TextCol.MappingName = Table.Columns(i).ColumnName
                TextCol.HeaderText = Table.Columns(i).ColumnName
                ts1.GridColumnStyles.Add(TextCol)
            End If
        Next
        Me.TableStyles.Add(ts1)
        Return ts1
    End Function

    Private storedPageSettings As System.Drawing.Printing.PageSettings
    Public Property PageSettings() As System.Drawing.Printing.PageSettings
        Get
            Return storedPageSettings
        End Get
        Set(ByVal Value As System.Drawing.Printing.PageSettings)
            storedPageSettings = Value
        End Set
    End Property

    Public Sub PageSetup()
        Try
            Dim psDlg As New PageSetupDialog

            If (storedPageSettings Is Nothing) Then
                storedPageSettings = New System.Drawing.Printing.PageSettings
            End If

            psDlg.PageSettings = storedPageSettings
            psDlg.ShowDialog()
        Catch ex As Exception
            'msgbox('error")
        End Try

    End Sub

    Public Sub Print(ByVal objView As DataView, ByVal objTable As DataTable, ByVal cm As CurrencyManager)
        Try
            'Assumes the default printer
            Dim pd As DataGridPrintDocument = New DataGridPrintDocument(Me, objView, objTable, cm, -1, Nothing)

            If Not (storedPageSettings Is Nothing) Then
                pd.DefaultPageSettings = storedPageSettings
            End If

'if we want to set default Landscape then
'pd.DefaultPageSettings.Landscape = True


            Dim dlg As New PrintDialog
            dlg.Document = pd
            Dim result As DialogResult = dlg.ShowDialog()

            If (result = DialogResult.OK) Then
                pd.Print()
            End If

        Catch ex As Exception
            'InformationMessageModule.InformationMessage("An error occurred printing the DataGrid - " & ex.Message)
        End Try

    End Sub

    Public Property CustomColumnHeaders() As Boolean
        Get
            Return protCustomColumnsHeaders
        End Get
        Set(ByVal Value As Boolean)
            If Value Then
                If protCustomColumnsHeaders = False Then
                    protOldHeaderFont = Me.HeaderFont
                    Dim g As Graphics = Me.CreateGraphics()
                    Me.HeaderFont = New Font(System.Drawing.FontFamily.GenericSerif, (protNRowsInCaption) * Me.HeaderFont.GetHeight(g) - 8, FontStyle.Regular, GraphicsUnit.Point)
                    g.Dispose()
                    protRowHeaderWidth = Me.RowHeaderWidth
                End If
                Me.CaptionVisible = False
                Me.ColumnHeadersVisible = True
            Else
                If Not Me.HeaderFont Is Nothing Then Me.HeaderFont.Dispose()
                Me.HeaderFont = Me.protOldHeaderFont
                Me.protOldHeaderFont = Nothing
                Me.CaptionVisible = True
                Me.ColumnHeadersVisible = True
            End If
            protCustomColumnsHeaders = Value
        End Set
    End Property

    Public ReadOnly Property CustomColumnHeaderHeight() As Integer
        Get
            Return Me.HeaderFont.Height
        End Get
    End Property

    Public ReadOnly Property CustomColumnHeaderFont() As Font
        Get
            If protCustomColumnsHeaders Then
                Return Me.protOldHeaderFont
            End If
            Return Me.HeaderFont
        End Get
    End Property

    Public Sub PaintHeaderCell(ByVal g As Graphics, ByVal Sentence As String, ByVal F As Font, ByVal br As Brush, ByVal Bounds As Rectangle, ByVal offsetx As Integer, ByVal offsety As Integer)
        Dim strs(protNRowsInCaption - 1), tt() As String
        tt = Sentence.Split(" "c)
        Dim i, j, n As Integer
        j = 0
        Dim s As String = ""
        Dim os As String
        os = s
        For i = 0 To protNRowsInCaption - 1
            strs(i) = ""
        Next
        For i = 0 To tt.Length - 1
            If s <> "" Then
                s &= " " & tt(i)
            Else
                s = tt(i)
                os = s
            End If
            Dim w As Integer = CInt(g.MeasureString(s, F).Width)
            If w >= Bounds.Width Then
                strs(j) = os
                If s <> tt(i) Then
                    s = tt(i)
                    os = tt(i)
                Else
                    s = ""
                    os = ""
                End If
                If j = protNRowsInCaption - 1 And i <= tt.Length - 1 Then
                    strs(j) = "..."
                    Exit For
                End If
                j += 1
            Else
                os = s
            End If
            If i = tt.Length - 1 And j <> protNRowsInCaption Then
                strs(j) = s
            End If
        Next
        n = Me.protNRowsInCaption - 1
        Dim h As Integer = (Bounds.Height Mod F.Height) \ 2
        For i = 0 To n
            Dim w As Integer = CInt(g.MeasureString(strs(i), F).Width)
            If w < Bounds.Width Then
                w = (Bounds.Width - w) \ 2
            Else
                If Bounds.Width > 0 Then
                    While w >= Bounds.Width
                        strs(i) = strs(i).Substring(0, strs(i).Length - 1)
                        w = CInt(g.MeasureString(strs(i), F).Width)
                    End While
                Else
                    Return
                End If
                w = 0
            End If
            g.DrawString(strs(i), F, br, Bounds.X + w + offsetx, Bounds.Y + h + offsety)
            h += F.Height
        Next
    End Sub

    Public Function GetHeaderWidth(ByVal g As Graphics, ByVal Text As String) As Integer
        Dim strs() As String
        strs = Text.Split(" "c)
        Dim ws(strs.Length - 1) As Integer
        Dim i, n As Integer
        n = Math.Min(ws.Length - 1, Me.protNRowsInCaption - 1)
        Dim f As Font
        If protCustomColumnsHeaders Then
            f = protOldHeaderFont
        Else
            f = Me.HeaderFont
        End If
        For i = 0 To n
            ws(i) = CInt(g.MeasureString(strs(i), f).Width)
            GetHeaderWidth = Math.Max(GetHeaderWidth, ws(i))
        Next
    End Function
End Class

================================================================
Class DataGridPrintDocument

Imports System.Drawing.Printing

Public Class DataGridPrintDocument
    Inherits PrintDocument

    Private printFont As Font
    Private headerFont As Font
    Private dataGridToPrint As DataGridEx
    Private objTable As DataTable
    Private objView As DataView
    Private privCM As CurrencyManager
    Private privNP As Integer
    Private privStrQuestion As String

    Public Sub New(ByVal dataGridToPrint As DataGridEx, ByVal objView As DataView, ByVal objTable As DataTable, ByVal privCM As CurrencyManager, _
    ByVal NP As Integer, ByVal Question As String)
        MyBase.New()
        Me.dataGridToPrint = dataGridToPrint
        If objView Is Nothing Then
            Me.objView = objTable.DefaultView
        Else
            Me.objView = objView
        End If
        Me.objTable = objTable
        Me.privCM = privCM
        privNP = NP
        privStrQuestion = Question
    End Sub

    Private npp As Integer
    'Override OnBeginPrint to set up the font we are going to use
    Protected Overrides Sub OnBeginPrint(ByVal ev As PrintEventArgs)
        MyBase.OnBeginPrint(ev)
        CurRow = 0
        CurCol = 0
        NextFirstCol = 0
        npp = 0
        headerFont = dataGridToPrint.HeaderFont
        printFont = dataGridToPrint.DefaultFont
    End Sub

    Dim CurRow, CurCol As Integer
    Dim NextFirstCol As Integer
    'Override the OnPrintPage to provide the printing logic for the document
    Protected Overrides Sub OnPrintPage(ByVal ev As PrintPageEventArgs)

        MyBase.OnPrintPage(ev)

        NextFirstCol = 0
        npp += 1

        Dim lpp As Single = 0
        Dim yPos As Single = 0
        Dim count As Integer = 0
        Dim leftMargin As Single = ev.MarginBounds.Left
        Dim topMargin As Single = ev.MarginBounds.Top
        Dim line As String

        'Work out the number of lines per page
        'Use the MarginBounds on the event to do this
        lpp = ev.MarginBounds.Height / printFont.GetHeight(ev.Graphics)

        'Now iterate over the file printing out each line
        'NOTE WELL: This assumes that a single line is not wider than the page width
        'Check count first so that we don't read line that we won't print
        Dim tblStyle As DataGridTableStyle = dataGridToPrint.TableStyles(objTable.TableName)
        If tblStyle Is Nothing Then
            tblStyle = dataGridToPrint.CreateTableStyle(objTable)
        End If
        Dim rh As Integer = tblStyle.PreferredRowHeight
        Dim headerHeight As Integer
        If dataGridToPrint.CustomColumnHeaders = False Then
            headerHeight = rh
        Else
            headerHeight = dataGridToPrint.CustomColumnHeaderHeight
        End If
        Dim nrperpage As Integer = (ev.MarginBounds.Height \ rh) - (headerHeight \ rh)
        Dim i, j, w, l As Integer
        l = CInt(topMargin)
        w = CInt(leftMargin)
        Dim divPen As New Pen(dataGridToPrint.GridLineColor)
        Dim hfpen As New Pen(dataGridToPrint.HeaderForeColor)
        Dim hbBrush As New SolidBrush(dataGridToPrint.HeaderBackColor)
        Dim hfBrush As New SolidBrush(dataGridToPrint.HeaderForeColor)
        For j = CurCol To tblStyle.GridColumnStyles.Count - 1
            If w + tblStyle.GridColumnStyles(j).Width >= ev.MarginBounds.Right And j <> CurCol Then
                NextFirstCol = j
                Exit For
            End If
            If tblStyle.GridColumnStyles(j).Width = 0 Then GoTo continuefor
            Dim r As New Rectangle(w, l, tblStyle.GridColumnStyles(j).Width, headerHeight)
            Dim rf As New Drawing.RectangleF(w, l, r.Width, r.Height)
            ev.Graphics.FillRectangle(hbBrush, r)
            'ev.Graphics.DrawRectangle(Pens.Black, r)

            If dataGridToPrint.CustomColumnHeaders = False Then
                ev.Graphics.DrawString(tblStyle.GridColumnStyles(j).HeaderText, headerFont, hfBrush, rf)
            Else
                dataGridToPrint.PaintHeaderCell(ev.Graphics, tblStyle.GridColumnStyles(j).HeaderText, _
                    dataGridToPrint.CustomColumnHeaderFont, hfBrush, r, 0, 0)
            End If
            w += tblStyle.GridColumnStyles(j).Width
continuefor:
        Next
        l += headerHeight
        For i = CurRow To nrperpage + CurRow - 1
            If i >= objView.Count Then Exit For
            w = CInt(leftMargin)
            For j = CurCol To tblStyle.GridColumnStyles.Count - 1
                If w + tblStyle.GridColumnStyles(j).Width >= ev.MarginBounds.Right And j <> CurCol Then Exit For
                If tblStyle.GridColumnStyles(j).Width = 0 Then GoTo continuefor2
                Dim r As New Rectangle(w, l, tblStyle.GridColumnStyles(j).Width, rh)
                Dim rf As New Drawing.RectangleF(w, l, r.Width, r.Height)
                ev.Graphics.DrawRectangle(divPen, r)
                ev.Graphics.DrawString(objView.Item(i).Item(j).ToString(), printFont, Drawing.Brushes.Black, rf)
                w += tblStyle.GridColumnStyles(j).Width
continuefor2:
            Next
            l += rh
        Next

        l = CInt(topMargin)
        w = CInt(leftMargin)
        For j = CurCol To tblStyle.GridColumnStyles.Count - 1
            If w + tblStyle.GridColumnStyles(j).Width >= ev.MarginBounds.Right And j <> CurCol Then
                Exit For
            End If
            If tblStyle.GridColumnStyles(j).Width = 0 Then GoTo continuefor3
            Dim r As New Rectangle(w, l, tblStyle.GridColumnStyles(j).Width, headerHeight)
            ev.Graphics.DrawRectangle(Pens.Black, r)

            w += tblStyle.GridColumnStyles(j).Width
continuefor3:
        Next

        CurRow = i
        'If we have more lines then print another page
        If (CurRow < objView.Count) Then
            ev.HasMorePages = True
        Else
            If NextFirstCol = 0 Then
                ev.HasMorePages = False
            Else
                CurRow = 0
                CurCol = NextFirstCol
                ev.HasMorePages = True
            End If
        End If
        divPen.Dispose()
        hfpen.Dispose()
        hbBrush.Dispose()
        hfBrush.Dispose()
    End Sub
End Class