Search code examples
vb.netvisual-studio-2017

How to print datagridview data in horizontal line with printdocument?


I have a query in the SqlServer database, the result of that query is played inside a Datagridview, the result can contain from 0 to 100 data or even more if you doubt it.

I'm trying to print the "Identification" column of Datagridview horizontally, but without success. I have researched in several places and nothing too.

screenshot of form with DataGridView

Follow the form code:

Imports System.ComponentModel
Imports System.Data.SqlClient
Imports System.Drawing.Printing
Public Class frm_relatorio_entregas

    ' Variables used in the module
    Dim RelatorioTitulo As String ' Report title
    Dim paginaatual As Integer ' Page number being printed
    Dim LinhaAtual As Integer  ' Current line number being printed
    Dim LinhasporPagina As Integer ' Number of lines per page
    Dim PosicaoDaLinha As Single  ' Position of the line being printed
    Dim registro As Integer  ' Record being printed


    Private Sub Imprimir()
    RelatorioTitulo = "Delivery Report"
    Dim doc As PrintDocument = New PrintDocument
    AddHandler doc.PrintPage, New Printing.PrintPageEventHandler(AddressOf Me.pdRelatorios_Printpage)
    AddHandler doc.BeginPrint, New Printing.PrintEventHandler(AddressOf Me.Begin_Print)
    Dim dialogo As PrintDialog = New PrintDialog
    'dialogo.Document = doc
    '   If (dialogo.ShowDialog = DialogResult.OK) Then
    Dim preview As PrintPreviewDialog = New PrintPreviewDialog()
    preview.Document = doc
    preview.WindowState = FormWindowState.Maximized
    preview.PrintPreviewControl.Zoom = 1.0
    preview.ShowDialog()
    'End If
    End Sub

    Private Sub Begin_Print(ByVal sender As Object, ByVal e As Printing.PrintEventArgs)
    ' Assigning values ​​to variables at the start of printing
    LinhaAtual = 0
    paginaatual = 1
    PosicaoDaLinha = 0
    registro = 0
    End Sub

    Private Sub pdRelatorios_Printpage(ByVal sender As System.Object, ByVal e As System.Drawing.Printing.PrintPageEventArgs)

    ' Margin variables (e.MarginBounds obtain the rectangular area that represents the part of the page within the margins.)
    Dim MargemEsquerda As Single = e.MarginBounds.Left
    Dim MargemDireita As Single = e.MarginBounds.Right
    Dim MargemSuperior As Single = e.MarginBounds.Top
    Dim MargemInferios As Single = e.MarginBounds.Bottom

    'Pen class defines an object used to define lines and curves
    Dim CanetaDaImpressora As Pen = New Pen(Color.Black, 1)

    'Variables of the fonts used (the font class defines a specific format for text, including font face, size and style attributes.
    Dim FonteNegrito As Font
    Dim FonteTitulo As Font
    Dim FonteSubTitulo As Font
    Dim FonteRodape As Font
    Dim FonteNormal As Font
    Dim font1 As Font

    'Define effects on fonts used
    FonteNegrito = New Font("Arial", 9, FontStyle.Bold)
    FonteTitulo = New Font("Arial", 13, FontStyle.Bold)
    FonteSubTitulo = New Font("Arial", 9, FontStyle.Bold)
    FonteRodape = New Font("Arial", 8)
    FonteNormal = New Font("Calibri", 9)
    font1 = New Font("Segoe UI", 8, FontStyle.Bold)

    'Print the title of the report
    e.Graphics.DrawString(RelatorioTitulo, FonteTitulo, Brushes.Black, MargemEsquerda + 200, 30, New StringFormat)

    If DateTimePicker1.Value = DateTimePicker1.Value Then
        e.Graphics.DrawString(DateTimePicker1.Value, FonteSubTitulo, Brushes.Black, MargemEsquerda + 900, 30, New StringFormat)

    Else

        e.Graphics.DrawString(DateTimePicker1.Value & "  -  " & DateTimePicker1.Value, FonteSubTitulo, Brushes.Black, MargemEsquerda + 900, 30, New StringFormat)

    End If

    'Define the number of lines per page
    LinhasporPagina = CInt(e.MarginBounds.Height / New Font("Calibri", 18).GetHeight(e.Graphics) - 2)


    While (LinhaAtual <= LinhasporPagina AndAlso registro <= DataGridView1.Rows.Count - 1)

        PosicaoDaLinha = MargemSuperior + (LinhaAtual * New Font("Calibri", 18).GetHeight(e.Graphics) + 30)


        e.Graphics.DrawString(DataGridView1.Rows(registro).Cells(0).Value.ToString, New Font("Calibri", 8, FontStyle.Bold), Brushes.Black, 30, PosicaoDaLinha, New StringFormat())

        'Increment record
        registro += 1
        'increment line
        LinhaAtual += 1

    End While


    'baseboard
    e.Graphics.DrawLine(CanetaDaImpressora, 20, MargemInferios + 15, 1150, MargemInferios + 15)
    e.Graphics.DrawString(System.DateTime.Now.ToString(), FonteRodape, Brushes.Black, 30, MargemInferios + 15, New StringFormat())
    e.Graphics.DrawString("Página : " & paginaatual, FonteRodape, Brushes.Black, 1070, MargemInferios + 15, New StringFormat)

    'Increase the page number
    paginaatual += 1

    'Here check if you are going to open a new page
    If (LinhaAtual > LinhasporPagina) Then
        ' When you open a new page, you have to reset LlinhaAtual
        e.HasMorePages = True
        LinhaAtual = 0
    Else
        e.HasMorePages = False
    End If
    End Sub

    Private Sub frm_relatorio_entregas_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    txtcod.Clear()
    txtrazao.Clear()
    TextBox1.Clear()
    TextBox2.Clear()
    TextBox3.Clear()
    DateTimePicker1.ResetText()
    DateTimePicker2.ResetText()
    ComboBox1.SelectedIndex = 0
    txtcod.Select()
    End Sub

    Private Sub txtcod_KeyUp(sender As Object, e As KeyEventArgs) Handles txtcod.KeyUp
    If e.KeyCode = Keys.F2 Then

        frm_consulta_cliente_cadastro.ShowDialog()
    End If
    End Sub

    Private Sub consulta()
    DataGridView1.Rows.Clear()
    Cursor.Current = Cursors.WaitCursor
    Dim consultando As New frm_aguarde_consultando
    consultando.Show()
    ' Set cursor as hourglass
    Application.DoEvents()

    Dim ano, mes, dia As Integer
    Dim var1data, var2data As Date
    Dim dinicio, dfim As String

    var1data = DateTimePicker1.Value '.ToString.Substring(0, 10)
    dia = var1data.Day
    mes = var1data.Month
    ano = var1data.Year
    dinicio = ano & "-" & mes & "-" & dia

    var2data = DateTimePicker2.Value
    dia = var2data.Day
    mes = var2data.Month
    ano = var2data.Year
    dfim = ano & "-" & mes & "-" & dia

    Using sqlcoon As SqlConnection = GetConnectionsql()
        Dim READER As SqlDataReader
        Try
            sqlcoon.Open()
            Dim Query As String
            Query = "select MOV_IDENTIFICACAO,MOV_PROTOCOLO,MOV_DATADOC,MOV_SITUACAO,MOV_DATAENTREGA,MOV_HORAENTREGA,MOV_SITEND_CODIGO
                    from movimento where MOV_DATADOC = '" & dinicio & "' 
                    AND MOV_CLI_CODIGO = '" & txtcod.Text & "' AND MOV_SITUACAO = '" & "E" & "'
                    AND CAST(MOV_DATAENTREGA AS DATE) = '" & dfim & "' "


            Dim COMMAND As SqlCommand = New SqlCommand(Query, sqlcoon)

            READER = COMMAND.ExecuteReader

            While READER.Read
                Dim MOV_IDENTIFICACAO = READER("MOV_IDENTIFICACAO")
                Dim MOV_DATADOC = READER("MOV_DATADOC")
                Dim MOV_DATAENTREGA = READER("MOV_DATAENTREGA")
                Dim MOV_PROTOCOLO = READER("MOV_PROTOCOLO")
                Dim MOV_SITUACAO = READER("MOV_SITUACAO")
                Dim MOV_SITEND_CODIGO = READER("MOV_SITEND_CODIGO")
                DataGridView1.Rows.Add(MOV_IDENTIFICACAO, MOV_PROTOCOLO, MOV_DATADOC, MOV_SITUACAO, MOV_DATAENTREGA, MOV_SITEND_CODIGO)

            End While
            READER.Close()
            sqlcoon.Close()
            ''--------------'''''''''

            Label9.Text = DataGridView1.Rows.Count


            For Each linha In DataGridView1.Rows
                Dim altura As Integer = 17
                linha.height = altura

            Next

            If DataGridView1.Rows.Count >= 0 Then
                ' Set cursor as default arrow
                Cursor.Current = Cursors.Default

                ' Hide the please wait form
                consultando.Hide()

            End If
        Catch ex As SqlException
            MessageBox.Show(ex.Message)
        Finally
            ' sqlcoon.Dispose()


        End Try

        sqlcoon.Open()

        Try


            For r As Integer = 0 To DataGridView1.Rows.Count - 1
                Dim COMMAND3 As SqlCommand
                Dim READER3 As SqlDataReader
                Dim Query_3 As String

                Query_3 = "select IMOV_CODIGORECBTO from imovimento where IMOV_MOV_IDENTIFICACAO ='" & DataGridView1.Rows(r).Cells(0).Value.ToString & "'"

                COMMAND3 = New SqlCommand(Query_3, sqlcoon)
                READER3 = COMMAND3.ExecuteReader

                While READER3.Read
                    Dim IMOV_CODIGORECBTO = READER3("IMOV_CODIGORECBTO")
                    'DataGridView1.Columns(6).HeaderCell.Value = "ID"
                    DataGridView1.Rows(r).Cells(6).Value = IMOV_CODIGORECBTO
                End While
                READER3.Close()

            Next
            DataGridView1.Sort(DataGridView1.Columns(6), ListSortDirection.Ascending)
            sqlcoon.Close()
        Catch ex As SqlException
            MsgBox(ex.Message)
        End Try

    End Using

    End Sub


    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    consulta()

    End Sub

    Private Sub Button4_Click(sender As Object, e As EventArgs) Handles Button4.Click
    Imprimir()
    End Sub
End Class

screenshot of what is currently being printed

screenshot of I would like the result to be:

Would anyone have any ideas, tools or means to help me? I thank.


Solution

  • An alternative would be to:

    1. Get just the column values that you want.
    2. Join the values from #1 using a delimiter, such as a tab.
    3. Use the Graphics.DrawString method (documentation) for the value from #2.

    There will need to be some considerations:

    1. You will need to measure the string from #3 to see if it exceeds the bounds of your print document
    2. If so, then you will need to print multiple pages, picking up where you left off.

    Update

    Per the OP's request, here is an example. Keep in mind that it doesn't account for the considerations listed above. That will take a bit of effort in debugging to account for those points:

    Private Sub pdRelatorios_PrintPage(sender As Object, e As PrintPageEventArgs) Handles pdRelatorios.PrintPage
        Dim title = "Relatorio de Entregas"
        Dim titleFont = New Font(Font.FontFamily, Convert.ToSingle(Font.Size * 1.5), FontStyle.Bold)
        Dim titlePosition = New PointF(Convert.ToSingle(e.MarginBounds.X * 2 - e.PageBounds.Width / 2), e.MarginBounds.Y)
        Dim titleSize = e.Graphics.MeasureString(title, titleFont)
    
        e.Graphics.DrawString(title, titleFont, SystemBrushes.ControlText, titlePosition)
    
        Dim cellValues = DataGridView1.Rows.Cast(Of DataGridViewRow).Select(Function(row) row.Cells(0)?.Value?.ToString())
        Dim joinedCellValues = String.Join(Constants.vbTab, cellValues)
        Dim bodyBounds = New RectangleF(e.MarginBounds.X, Convert.ToSingle(titleSize.Height + e.MarginBounds.Y), e.PageBounds.Width - e.MarginBounds.X * 2, e.PageBounds.Height - e.MarginBounds.Y * 2)
    
        e.Graphics.DrawString(joinedCellValues, Font, SystemBrushes.ControlText, bodyBounds)
    End Sub