Reportviewer: stamparlo e\o esportarlo in un file (pdf, xls)

Ho conosciuto la classe reportviewer quando ho sentito la necessità di dover mostrare a video i dati inseriti all’interno di una applicazione da me sviluppata.

Insieme allo studio di tale classe mi sono accostato a Sql Server Reporting Services, nella sua versione in locale (DataReport nel formato .rdlc) .

Una volta creato un template, aggiungendo al progetto un nuovo elemento di tipo  “report”,

creavo un nuovo modulo/pagina  AnteprimaStampa e trascinavo al suo interno il componente report “ReportViewer”, in modo tale che da codice potevo instanziare un oggetto della classe AnteprimaStampa e potevo impostare le property del suo reportviewer per poi tramite il metodo showDialog visualizzare il tutto a video.

In questi giorni, però, mi è stato posta una domanda particolare…E se volessi creare un pdf senza visualizzare l’anteprima??? E se volessi, inoltre, stamparlo senza dover utilizzare i pulsanti  presenti nella schermata del reportviewer????

Subito ho pensato : “Potrei usare itextSharp, includere la dll al mio progetto e risolvere almeno il problema della creazione del pdf”

Qualcuno mi suggeriva di utilizzare il mailmerge con word, cioè creare un template in word e legarlo tramite questo metodo ai dati presenti sulla mia pagina/modulo, però questa soluzione risultava troppo dispendiosa (almeno con pagine aspx), in quanto richiedeva la creazione di un file xml per la sistemazione dei dati da passare al template, i dati dovevano essere trasferiti ad un file xls per poter ottenere l’origine dati da associare al file word.

Dopo un po… ecco il lampo di genio: “E se usassi DataReport ugualmente????? Ci sarà il modo per raggiungere il mio obiettivo con questa tecnologia”

E di fatti ecco a voi il codice per fare ciò che m’era stato chiesto.

Per prima cosa devo importare nella mia webForm/wimdowsForm ciò che segue:

Imports System.IO
Imports System.Text
Imports System.Drawing.Imaging
Imports System.Drawing.Printing
Imports Microsoft.Reporting.WinForms

poi dichiariamo queste variabili globali

Private path As String
Private nomeFile As String
Private warnings As Warning()
Private m_stream As IList(Of Stream)
Private WithEvents printDocument As PrintDocument
Private m_currentPageIndex As Integer
Private fileImmagine As String

E poi

metodi per la creazione del file pdf

''' <summary>
''' Esportazione di un reportviewer in un file pdf
''' </summary>
Private Sub ExportPDF()
        Dim warning As Warning() = Nothing
        Dim streamids As String()
        Dim mimeType As String
        Dim encoding As String
        Dim extesion As String
        Try
'istanzio un ogetto della classe Anteprima di stampa che contiene il ReportViewer
            Dim anteprimaStampa As New AnteprimaStampa           

           With anteprimaStampa

'definisco le property del local report e gli assegno i valori da inserire nel datSource o nei parametri

                .ReportViewer.LocalReport.ReportPath = Application.StartupPath & "\Report.rdlc"
                .ReportViewer.LocalReport.DataSources.Add(New ReportDataSource("NomeDatasourceReport", MioDatasource))


 'renderizzo il report senza mostrare l'anteprima
                .ReportViewer.RefreshReport()


'renderizzo il report creato in formato pdf in un array di byte (sostituire “PDF”  con “Excel” per ottenere la creazione di un file .xls, ovviamente rinominare il file \nomefile.xls)
                Dim bytes As Byte() = .ReportViewer.LocalReport.Render("PDF", Nothing, mimeType, encoding, extesion, streamids, warning)
                path = Application.StartupPath
                nomeFile = "\nomeFile.pdf"


'istanzio un file stream, creo il file "path + nomeFile" e gli scrivo all'interno tutti byte generati dal render precedente
                Dim fs As New FileStream(Application.StartupPath & nomeFile, FileMode.Create)
                fs.Write(bytes, 0, bytes.Length)


'forzo la scrittura
                fs.Flush()


'chiudo il fileStream
                fs.Close()

'lancio il processo di stampa
                GeneraFileImmaginePerStampa(.ReportViewer.LocalReport)

              End With
        Catch ex As Exception 
               “…….”
        End Try
    End Sub

 

metodi per la stampa del report generato

''' <summary>
''' Preparazione del report viewer alla stampa, creazione di un file image
''' </summary>

Private Sub GeneraFileImmaginePerStampa(ByVal report As LocalReport)
        Try

 

'definisco un layout della pagina con i margini ed il formato di output del file che in seguito genererò
            Dim deviceInfo As String = "<DeviceInfo>" + "  <OutputFormat>EMF</OutputFormat>" + "  <PageWidth>8.5in</PageWidth>"
            deviceInfo += "  <PageHeight>11in</PageHeight>" + "  <MarginTop>0.25in</MarginTop>" + "  <MarginLeft>1cm</MarginLeft>" 
            deviceInfo +=+"  <MarginRight>1cm</MarginRight>" + "  <MarginBottom>0.25in</MarginBottom>" + "</DeviceInfo>"

 

'istanzio una lista di Stream
           m_streams = New List(Of (Stream)


'il report in formato immagine lo renderizzo nel file che viene creato nel metodo CreateStream passato cm parametro al metodo render
            report.Render("Image", deviceInfo, AddressOf CreaStreamImmagine, warnings)


'per ogni file che viene generato imposto il flusso corrente a 0
            For Each stream As Stream In m_streams
                stream.Position = 0
            Next

 

'imposto l'index di pagina a 0
            m_currentPageIndex = 0


'preparo la stampa dopodichè avvierò un processo di stampa
            PreparaStampaImmagine()


'chiudo i file che ho creato
            For Each stream As Stream In m_streams
                stream.Close()
            Next


        Catch ex As Exception
            “……”
        End Try
    End Sub

 

''' <summary>
''' funzione che genera uno stream per un file contenente immagini e lo inserisce nella lista di stream m_streams
''' </summary>
Private Function CreaStreamImmagine(ByVal name As String, ByVal fileNameExtension As String, ByVal encoding As Encoding, ByVal mimeType As String, ByVal willSeek As Boolean) As Stream 
    Try

'instanzio un oggetto di tipo Stream con il nome del report, il file è l'immagine da stampare e ha estenzion .emf
        Dim stream As Stream = New FileStream(name + "." + fileNameExtension, FileMode.Create)


'salvataggio del path del file di immagine, in modo da cancellarlo a fine operazione di stampa
        fileImmagine = path + "\" + name + "." + fileNameExtension


'inserimento nella lista di Stream del file di immagine
        m_streams.Add(stream)


        Return stream

    Catch ex As Exception 
      throw ex

    End Try

End Function

 

''' <summary>
''' metodo per la preparazione alla stampa
''' </summary>

    Private Sub PreparaStampaImmagine()

        Dim msg As String

Dim printDoc As PrintDocument()
       Try

'Se la lista di Stream non è instanziata o non ci sono file al suo interno visualizza un errore di stampa
            If  IsNothing(m_streams)  Or m_streams.Count = 0 Then
              msg = String.Format("File non trovato")
                Debug.WriteLine(msg)
                Exit Sub
            End If
            printDoc = New PrintDocument()


'Se le impostazioni di stampa non sono valide (es. non viene trovata la stampante predefinita) manda un messaggio di errore
            If Not printDoc.PrinterSettings.IsValid Then
                msg = String.Format("Errore nella stampa")
                Debug.WriteLine(msg)
                Exit Sub
            End If


'Associo all'evento "PrintPage" dell'oggetto PrintDoc il metodo StampaPagina
            AddHandler printDoc.PrintPage, AddressOf StampaPagina


'Scateno l'evento di stampa di printDoc, appena associato.
            printDoc.Print()


'Cancello il file immagine che ho creato per la stampa.
            IO.File.Delete(fileImmagine)


        Catch ex As Exception

               “……”
       End Try
    End Sub

''' <summary>
''' evento per la stampa di un documento
''' </summary>

   Private Sub StampaPagina(ByVal sender As Object, ByVal e As PrintPageEventArgs)
       Try

'generazione di un metafile grafico (sequenza di istruzioni grafiche da creare o visualizzare) con il file all'indice m_currentPageIndex
        Dim pageImage As New Metafile(m_streams(m_currentPageIndex))


'disegna l'ogetto immagine, e.pagebounds da le dimensioni all'immagine.
        e.Graphics.DrawImage(pageImage, e.PageBounds)


'incrementa il numero di pagina
        m_currentPageIndex += 1


'controlla se c'è qualche altra cosa da stampare, se non c'è altro da stampare chiude il processo di stampa
        e.HasMorePages = (m_currentPageIndex < m_streams.Count)

        Catch ex As Exception

               “……”
       End Try
    End Sub

 

Published 17 nov 2009 15:37 da Giorgio
Inserito sotto:
Powered by Community Server (Commercial Edition), by Telligent Systems