Stampa di un controllo DataGridView VB.Net

Articolo conclusivo della serie riguardante la stampa di .Net 4.

il
Sviluppatore Microsoft .Net, Collaboratore di IProgrammatori

Introduzione.

Con quest’articolo si conclude la serie dedica alla gestione della stampa tramite la tecnologia .Net 4.
In quest’ultima parte vedremo come stampare un controllo datagridview  tramite il linguaggio di programmazione Visual Basic Net 2010.
Dopo aver creato un nuovo progetto di tipo Windows Application, per il liguaggio Visual Basic, aggiungiamo nella form, tre pulsanti,un controllo datagridview, un controllo printdocument, printDialog, e printPreviewdialog, il tutto come mostrato in figura 1.





Figura 1

Stesura di codice

Ora passiamo in visualizzazione codice, si deve creare una classe (da esplora soluzione, tasto destro sul nome del progetto, nuova classe) che avrà il compito di gestire il controllo datagridView e la relativa stampa.
Qui di seguito si riporta il codice completo di tale classe.


VB.Net
Imports System.Drawing.Printing
Public Class StampaDatagrid
    Private PrdPrintDocument As PrintDocument
    Private dttTAbella As DataTable
    Private dtgDatagrid As DataGridView
    Public intContaRighe As Integer = 0
    Private Const CintLineaVerticale As Integer = 10
    Public IntNumeroPagina As Integer = 1
    Public Arrlinee As ArrayList = New ArrayList()
    Public intLarghezza As Integer
    Public intAltezza As Integer
    Public intMargineSuperiore As Integer
    Public intMargineInferiore As Integer
    'costruttore della classe
    Public Sub New(ByVal dtgDatagridCostruttore As DataGridView, ByVal prdPrintDocumentCostruttore As PrintDocument, ByVal DttTAbleCostruttore As DataTable)
        'imposto i parametri dell'anteprima di stampa
        PrdPrintDocument = prdPrintDocumentCostruttore
        dttTAbella = DttTAbleCostruttore
        dtgDatagrid = dtgDatagridCostruttore
        intLarghezza = PrdPrintDocument.DefaultPageSettings.PaperSize.Width
        intAltezza = PrdPrintDocument.DefaultPageSettings.PaperSize.Height
        intMargineSuperiore = PrdPrintDocument.DefaultPageSettings.Margins.Top
        intMargineInferiore = PrdPrintDocument.DefaultPageSettings.Margins.Bottom
    End Sub
    'funzione per il disegno dell'intestazione
    Public Sub DisegnaIntestazione(ByVal g As Graphics)
        Dim ForeBrush As SolidBrush = New SolidBrush(dtgDatagrid.ColumnHeadersDefaultCellStyle.ForeColor)
        Dim BackBrush As SolidBrush = New SolidBrush(dtgDatagrid.ColumnHeadersDefaultCellStyle.BackColor)
        Dim TheLinePen As Pen = New Pen(dtgDatagrid.GridColor, 1)
        Dim FormatoCella As StringFormat = New StringFormat()
        FormatoCella.Trimming = StringTrimming.EllipsisCharacter
        FormatoCella.FormatFlags = StringFormatFlags.NoWrap Or StringFormatFlags.LineLimit
        Dim intLarghezzaColonna As Integer = intLarghezza / dttTAbella.Columns.Count
        Dim IntInizioContaRighe As Integer = intContaRighe
        'Disegno l'intestazione
        Dim IntXposizione As Single = dtgDatagrid.Location.X
        Dim nextcellbounds As RectangleF = New RectangleF(0, 0, 0, 0)
        Dim HeaderBounds As RectangleF = New RectangleF(0, 0, 0, 0)
        HeaderBounds.X = dtgDatagrid.Location.X
        HeaderBounds.Y = dtgDatagrid.Location.Y + intMargineSuperiore + (intContaRighe - IntInizioContaRighe) * (dtgDatagrid.Font.SizeInPoints + CintLineaVerticale)
        HeaderBounds.Height = dtgDatagrid.Font.SizeInPoints + CintLineaVerticale
        HeaderBounds.Width = intLarghezza
        g.FillRectangle(BackBrush, HeaderBounds)
        Dim k As Integer
        For k = 0 To dttTAbella.Columns.Count - 1 Step k + 1
            Dim nextcolumn As String = dttTAbella.Columns(k).ToString()
            Dim cellbounds As RectangleF = New RectangleF(IntXposizione, dtgDatagrid.Location.Y + intMargineSuperiore + (intContaRighe - IntInizioContaRighe) * (dtgDatagrid.Font.SizeInPoints + CintLineaVerticale), intLarghezzaColonna, dtgDatagrid.ColumnHeadersDefaultCellStyle.Font.SizeInPoints + CintLineaVerticale)
            nextcellbounds = cellbounds
            g.DrawString(nextcolumn, dtgDatagrid.ColumnHeadersDefaultCellStyle.Font, ForeBrush, cellbounds, FormatoCella)
            IntXposizione = IntXposizione + intLarghezzaColonna
        Next
        If dtgDatagrid.CellBorderStyle <> DataGridViewCellBorderStyle.None Then
            g.DrawLine(TheLinePen, dtgDatagrid.Location.X, nextcellbounds.Bottom, intLarghezza, nextcellbounds.Bottom)
        End If
    End Sub
    'funzione per disegnare le righe
    Public Function DisegnaRighe(ByVal g As Graphics) As Boolean
        Dim IntRigaSuperiore As Integer = intMargineSuperiore
        Try
            Dim ForeBrush As SolidBrush = New SolidBrush(dtgDatagrid.ForeColor)
            Dim BackBrush As SolidBrush = New SolidBrush(dtgDatagrid.BackColor)
            Dim AlternatingBackBrush As SolidBrush = New SolidBrush(dtgDatagrid.AlternatingRowsDefaultCellStyle.BackColor)
            Dim TheLinePen As Pen = New Pen(dtgDatagrid.GridColor, 1)
            Dim FormatoCella As StringFormat = New StringFormat()
            FormatoCella.Trimming = StringTrimming.EllipsisCharacter
            FormatoCella.FormatFlags = StringFormatFlags.NoWrap / StringFormatFlags.LineLimit
            Dim IntLargehzzaColonna As Integer = intLarghezza / dttTAbella.Columns.Count
            Dim IntInizioContaRighe As Integer = intContaRighe
            Dim RowBounds As RectangleF = New RectangleF(0, 0, 0, 0)
            'disegno la griglia
            Dim i As Integer
            For i = IntInizioContaRighe To dttTAbella.Rows.Count - 1 Step i + 1
                Dim dr As DataRow = dttTAbella.Rows(i)
                Dim startxposition As Integer = dtgDatagrid.Location.X
                RowBounds.X = dtgDatagrid.Location.X
                RowBounds.Y = dtgDatagrid.Location.Y + intMargineSuperiore + ((intContaRighe - IntInizioContaRighe) + 1) * (dtgDatagrid.Font.SizeInPoints + CintLineaVerticale)
                RowBounds.Height = dtgDatagrid.Font.SizeInPoints + CintLineaVerticale
                RowBounds.Width = intLarghezza
                Arrlinee.Add(RowBounds.Bottom)
                If i Mod 2 = 0 Then
                    g.FillRectangle(BackBrush, RowBounds)
                Else
                    g.FillRectangle(AlternatingBackBrush, RowBounds)
                End If
                Dim j As Integer
                For j = 0 To dttTAbella.Columns.Count - 1
                    Dim cellbounds As RectangleF = New RectangleF(startxposition, dtgDatagrid.Location.Y + intMargineSuperiore + ((intContaRighe - IntInizioContaRighe) + 1) * (dtgDatagrid.Font.SizeInPoints + CintLineaVerticale), IntLargehzzaColonna, dtgDatagrid.Font.SizeInPoints + CintLineaVerticale)
                    g.DrawString(dr(j).ToString(), dtgDatagrid.Font, ForeBrush, cellbounds, FormatoCella)
                    IntRigaSuperiore = CType(cellbounds.Bottom, Integer)
                    startxposition = startxposition + IntLargehzzaColonna
                Next
                intContaRighe = intContaRighe + 1
                If intContaRighe * (dtgDatagrid.Font.SizeInPoints + CintLineaVerticale) > (intAltezza * IntNumeroPagina) - (intMargineInferiore + intMargineSuperiore) Then
                    DisegnaLineaOrizzontale(g, Arrlinee)
                    DisegnaLineaVerticale(g, TheLinePen, intLarghezza, IntRigaSuperiore)
                    Return True
                End If
            Next
            DisegnaLineaOrizzontale(g, Arrlinee)
            DisegnaLineaVerticale(g, TheLinePen, IntLargehzzaColonna, IntRigaSuperiore)
           Return False
        Catch ex As Exception
            MessageBox.Show(ex.Message.ToString())
            Return False
        End Try
    End Function
    'funzione per disegnare la linea orizzontale
    Private Sub DisegnaLineaOrizzontale(ByVal g As Graphics, ByVal arlLinee As ArrayList)
        Dim PenDisegnaLinea As Pen = New Pen(dtgDatagrid.GridColor, 1)
        If dtgDatagrid.CellBorderStyle = DataGridViewCellBorderStyle.None Then
            Return
        End If
        Dim IntConta As Integer
        For IntConta = 0 To arlLinee.Count - 1 Step IntConta + 1
            g.DrawLine(PenDisegnaLinea, dtgDatagrid.Location.X, arlLinee(IntConta), intLarghezza, arlLinee(IntConta))
        Next
    End Sub
    'funzione per disegnare la linea verticale
    Private Sub DisegnaLineaVerticale(ByVal g As Graphics, ByVal penLinea As Pen, ByVal intLarghezzaColonna As Integer, ByVal intInferiore As Integer)
        If dtgDatagrid.CellBorderStyle = DataGridViewCellBorderStyle.None Then
            Return
        End If
        Dim intConta As Integer
        For intConta = 0 To dttTAbella.Columns.Count - 1 Step intConta + 1
            g.DrawLine(penLinea, dtgDatagrid.Location.X + intConta * intLarghezzaColonna, dtgDatagrid.Location.Y + intMargineSuperiore, dtgDatagrid.Location.X + intConta * intLarghezzaColonna, intInferiore)
        Next
    End Sub
    'funzione per disegnare un GridView
    Public Function DisegnaDatagridView(ByVal g As Graphics) As Boolean
        Try
            DisegnaIntestazione(g)
            Dim blnContinua As Boolean = DisegnaRighe(g)
            Return blnContinua
        Catch ex As Exception
            MessageBox.Show(ex.Message)
            Return False
        End Try
    End Function
End Class
 


Terminato ciò, passiamo in visualizzazione codice della form.
Scriviamo una variabile a livello di classe, dopo la dichiarazione di form, scriviamo un oggetto di tipo della classe precedentemente creata.
Qui di seguito si riporta tale esempio
Private stampaGriglia As StampaDatagrid

A questo punto, dobbiamo creare una funzione che permetta il caricamento dei dati del controllo datagridview e che inizializzi l’oggetto della classe StampaDatagrid.
Qui di seguito riportiamo il frammento di codice di tali operazioni.
Private Sub CaricaGriglia()
        Dim dttDati As New DataTable()
        Dim dtcNome As New DataColumn("Nome")
        Dim dtcCognome As New DataColumn("Cognome")
        dttDati.Columns.Add(dtcCognome)
        dttDati.Columns.Add(dtcNome)
        Dim dtrRiga As DataRow
        dtrRiga = dttDati.NewRow()
        dtrRiga("Nome") = "Emanuele"
        dtrRiga("Cognome") = "Mattei"
        dttDati.Rows.Add(dtrRiga)
        dtrRiga = dttDati.NewRow()
        dtrRiga("Nome") = "Emanuele2"
        dtrRiga("Cognome") = "Mattei2"
        dttDati.Rows.Add(dtrRiga)
        dtrRiga = dttDati.NewRow()
        dtrRiga("Nome") = "Emanuele3"
        dtrRiga("Cognome") = "Mattei3"
        dttDati.Rows.Add(dtrRiga)
        dgvDati.DataSource = dttDati
        stampaGriglia = New StampaDatagrid(dgvDati, PrintDocument1, dttDati)
    End Sub


Dopo il caricamento della griglia, si inizializza l’oggetto di tipo StampaDatagrid, impostando i parametri del costruttore con il controllo griglia, il controllo di tipo printdocument e l’oggetto di tipo datatable contenente i dati.
Questa funzione, viene richiamata dall’evento load della form, come riportato qui di seguito.
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        CaricaGriglia()
    End Sub

 

Scriviamo il codice, riguardante l’evento printpage, in cui si utilizzerà il metodo DisegnaDataGridView, per impostare l’area di
stampa.
Private Sub PrintDocument1_PrintPage(ByVal sender As System.Object, ByVal e As System.Drawing.Printing.PrintPageEventArgs) Handles PrintDocument1.PrintPage
        Dim g As Graphics = e.Graphics     
        Dim more As Boolean = stampaGriglia.DisegnaDatagridView(g)      
    End Sub
 


Ora non resta che scrivere il codice , riguardante il controllo PrintPreviewDialog, qui di seguito si riporta il frammento di codice.
Private Sub PrintPreviewDialog1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles PrintPreviewDialog1.Load
        PrintPreviewDialog1.Bounds = ClientRectangle
    End Sub

 

Siamo giunti quasi alla fine della stesura di codice, dobbiamo impostare gli eventi click del pulsante anteprima e stampa.
Nel primo caso utilizziamo il controllo printprewiewdialog, mentre nel secondo caso il controllo printdocument.
Si riporta il frammento di codice di tali operazioni.
Per il pulsante di anteprima, qui di seguito il codice dell’evento click
Private Sub BtnAnteprima_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles BtnAnteprima.Click
        stampaGriglia.IntNumeroPagina = 1
        stampaGriglia.intContaRighe = 0
        If Me.PrintPreviewDialog1.ShowDialog() = DialogResult.OK Then
        End If
 
 
Mentre qui di seguito, si riporta il codice, riguardante l’evento click del pulsante di stampa.
Private Sub BtnStampa_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles BtnStampa.Click
        stampaGriglia.IntNumeroPagina = 1
        stampaGriglia.intContaRighe = 0
        If PrintDialog1.ShowDialog() = DialogResult.OK Then
            'toglie la popup
            Me.PrintDocument1.PrintController = New System.Drawing.Printing.StandardPrintController()
            PrintDocument1.Print()
        End If
    End Sub
 


Conclusione

In questa serie di articoli, il lettore avrà acquisito le conoscenze per la stampa in ambito delle Windows Application, tramite la tecnologia .Net 4. La stampa è un elemento fondamentale, nel caso si sviluppano applicazioni gestionali, come software per la contabilità, buste paga, ed altro ancora. Le tecniche per la stampa di un controllo Datagridview, sono diverse, in questa guida è stata illustrata una delle tante tecniche.

Tramite la parola download si può scaricare il file d’esempio utilizzato in questo articolo.

Download