如何用printdocument在水平线上打印datagridview数据?

How to print datagridview data in horizontal line with printdocument?

我在 SqlServer 数据库中有一个查询,该查询的结果在 Datagridview 中播放,结果可以包含 0 到 100 个数据,如果您怀疑甚至更多。

我试图水平打印 Datagridview 的“标识”列,但没有成功。我在几个地方研究过,也没有。

screenshot of form with DataGridView

遵循表单代码:

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:

有没有人有任何想法、工具或方法来帮助我?谢谢

另一种方法是:

  1. 仅获取所需的列值。
  2. 使用分隔符(例如制表符)连接 #1 中的值。
  3. 对 #2 中的值使用 Graphics.DrawString 方法 (documentation)。

需要注意一些事项:

  1. 您需要测量 #3 中的字符串,看它是否超出打印文档的范围
  2. 如果是这样,那么您将需要打印多页,从中断的地方继续打印。

更新

根据 OP 的要求,这里有一个例子。请记住,它没有考虑上面列出的注意事项。这将需要一些调试工作来解决这些问题:

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