Creación de PDF desde VS.Net sin componentes de terceros

 

Fecha: 12/Ene/2006 (11-01-06)
Autor: Príapo Nicolás Rodríguez, Student Ambassador Rep.Dom. (sagara_vg@yahoo.com)

 



INTRODUCCION:

Con el paso del tiempo, las aplicaciones que desarrollamos necesitan de mayor dedicación para cumplir con los requerimientos de los usuarios. Esto provoca que en algunas ocasiones tengamos ciertos problemas para satisfacer a nuestros queridos clientes "Los Usuarios" que son la razón de ser de nuestro trabajo. Estos esfuerzos por mantenerlos contentos, se ven mermados por la imposibilidad (sea técnica o de herramientas) de mostrar una data en un formato determinado. Este es el caso de los famosos Documentos de Formato portátil (PDF) que tanto les gustan a los usuarios (Y a nosotros mismo). No hace mucho tiempo tuve el inconveniente, de que un usuario deseaba mantener los datos que le mostraba en un datagrid en un archivo. El problema comenzó cuando deseaba que como primera opción le enviara el archivo en un .PDF, cosa que no tenia idea de como lograrlo. En segundo lugar me ha propuesto que se lo envié en un documento de Word. Es decir, que la información que le mostraba en un DataGrid en una pagina, se la transformara en un documento de Word y se la enviara. Al igual que la anterior opción, no tenía dominio de tema para complacerlo. En ese caso, opté por terminar enviándole el DataGrid por correo a sugerencia de un amigo (mi colega de código, Andrés Faya) y es así como he salido de paso. Luego me he encontrado un artículo que escribió alguien para www.elguille.info para generar PDF desde .net. La idea me atrajo y me he leído el artículo y le he escrito al autor, he consultado el site que tiene como referencia para descargar el componente extra que necesito (no nativo de vs.net) y al final de cuentas no he conseguido lo que he deseado. Esta situación, gracias a vs.net ha llegado a su final, pues nuestro IDE cuenta con las herramientas necesarias para crear nuestros PDF sin tener que usar componentes ni códigos de terceros. Este artículo, no pretende volverlos unos expertos en la creación de archivos de extensión PDF, pero por lo menos les mostrará la luz para continúen por ustedes mismos explorando y de paso compartiendo los conocimientos que adquieran (que no se les olvide esa parte, pues es la única forma en que podemos crecer como comunidad .net).

Desarrollo:

Bien, lo primero que necesitamos hacer es crear un reporte con Crystal Report que nos proporcione la apariencia que deseamos en nuestro .PDF. Se preguntaran, porque un reporte con Crystal? La respuesta es sencilla, la información que vamos a cargar en nuestro PDF, es la información que le estamos mostrando a nuestros usuarios en un datagrid y por ende, quien mejor que Crystal para darle un buen formato a ese reporte que deseamos convertir a PDF. Recuerden que con crystal puedes diseñar cartas y no solo reportes como tal. El fundamento de este ejemplo está sustentado en la creación de un DataSet tipado con el esquema de los campos que vamos a mostrar en nuestro PDF. Una vez hecho esto, entonces procedemos con las funciones que nos permiten crear nuestro PDF. Cuerpo de código

Imports CrystalDecisions.CrystalReports.Engine
Imports System.Data.SqlClient
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 Button1 As System.Windows.Forms.Button
    Friend WithEvents mconn As System.Data.SqlClient.SqlConnection
    <System.Diagnostics.DebuggerStepThrough()> Private Sub InitializeComponent()
        Me.Button1 = New System.Windows.Forms.Button
        Me.mconn = New System.Data.SqlClient.SqlConnection
        Me.SuspendLayout()
        '
        'Button1
        '
        Me.Button1.Location = New System.Drawing.Point(344, 264)
        Me.Button1.Name = "Button1"
        Me.Button1.TabIndex = 1
        Me.Button1.Text = "Button1"
        '
        'mconn
        '
        Me.mconn.ConnectionString = "workstation id=U24603;packet size=4096;integrated security=SSPI;data source=U2460" & _
        "3;persist security info=False;initial catalog=TimeManager"
        '
        'Form1
        '
        Me.AutoScaleBaseSize = New System.Drawing.Size(5, 13)
        Me.ClientSize = New System.Drawing.Size(432, 318)
        Me.Controls.Add(Me.Button1)
        Me.Name = "Form1"
        Me.Text = "Form1"
        Me.ResumeLayout(False)

    End Sub

#End Region

    Private Function CrearPDF(ByVal ds As DataSet) 
        Dim strpdf As String
        'Esta es la instancia del reporte que tengo hecho con un binding del dataset tipado
        Dim cr As New Bloqueos
        cr.SetDataSource(ds)
        Try
		   'En la siguiente línea determinamos el formato final del reporte.
            cr.ExportOptions.ExportFormatType = CrystalDecisions.[Shared].ExportFormatType.PortableDocFormat
            Dim filedest As New CrystalDecisions.Shared.DiskFileDestinationOptions
            'Determinamos la ruta donde se va a crear nuestro archivo al finalizar el proceso en este caso,
            'concatenamos horas, minutos, segundos, para mantener control en caso de usar la misma ruta en otras instancias.
            Dim nombrearchivopdf As String = "C:\pdf\PDF" & Date.Now.Hour & Date.Now.Minute & Date.Now.Second & ".pdf"
            filedest.DiskFileName = nombrearchivopdf
            'Le pasamos al reporte el parámetro destino del reporte (ruta)
            cr.ExportOptions.DestinationOptions = filedest
            'Le indicamos que el reporte no es para mostrarse en pantalla, sino, que es para guardar en disco
            cr.ExportOptions.ExportDestinationType = CrystalDecisions.[Shared].ExportDestinationType.DiskFile
            'Indicamos el formato de la página del reporte
            cr.PrintOptions.PaperOrientation = CrystalDecisions.[Shared].PaperOrientation.Landscape
            'Finalmente exportamos el reporte a PDF
            cr.Export()
            'Como buenos samaritanos nos curamos en salud, y atrapamos las posibles excepciones que se pudieran presentar.
        Catch ex3 As CrystalDecisions.CrystalReports.Engine.InternalException
            MsgBox(ex3.Message & "       -----" & ex3.StackTrace)
        Catch ex2 As CrystalDecisions.CrystalReports.Engine.ExportException
            MsgBox("Se ha producido un error cargando los archivos a PDF. Error: " & ex2.Message, MsgBoxStyle.Information, "PDF Creator")
        Catch ex As System.IO.IOException
            MsgBox("Se ha producido un error cargando los archivos a PDF. Error: " & ex.Message, MsgBoxStyle.Information, "PDF Creator")
        End Try
    End Function
    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        Dim ad As New SqlDataAdapter("select * from bloqueotiempo", mconn)
        Dim ds2 As New ds
        Dim dt As New DataTable
        'Copiamos el esquema del DataSet tipado que hemos creado. "Ojo" no estamos copiando 
         'los registros que representa, solo la estructura. Pues, para copiar el contenido es con el método copy
        dt = ds2.Tables(0).Clone
        Try
            mconn.Open()
            ad.Fill(dt)
        Catch ex As Exception
            MsgBox(ex.Message, MsgBoxStyle.Information, "Prueba")
        Finally
            mconn.Close()
        End Try
        Dim i As Int32
        Dim con As Int32
        Dim dat As Date
       'Debido a que en este caso vamos a retornar un PDF por registros, entonces limpiamos
        'el DataSet tipado para que solo contenga el registro correspondiente a un pdf a la hora de llamar la función que los crea
        ds2.Tables(0).Clear()
        'Creamos un dataRow con el esquema de un row del dataset tipado para luego agregarle esta fila con datos al mismo dataset
        Dim row2 As DataRow = ds2.Tables(0).NewRow
        'Hacemos el recorrido de los registros
        For i = 0 To dt.Rows.Count - 1
        'Esta parte es fundamental que se realice de esta manera, pues en lo personal no he logrado pasar datos entre datarow directamente.
            con = dt.Rows(i)(0)
            row2(0) = con
            dat = dt.Rows(i)(1)
            row2(1) = dat
            dat = dt.Rows(i)(2)
            row2(2) = dat
            con = dt.Rows(i)(3)
            row2(3) = con
            con = dt.Rows(i)(4)
            row2(4) = con
            'Agrego la fila llena con los datos para crear el pdf al dataset tipado
            ds2.Tables(0).Rows.Add(row2)
            'Paso el dataset tipado como parámetro a la función que me genera el pdf
            CrearPDF(ds2)
            'Limpio el dataset para que la próxima iteración solo contenga el próximo registro
            ds2.Tables(0).Clear()
        Next
    End Sub
End Class

Conclusión:

Como pudieron observar, no ha sido necesaria la inclusión de ningún componente extra, para generar el PDF. Esto trae como consecuencia, que podamos crear aplicaciones Sin depender de las limitaciones que nos impongan terceros con sus componentes. Con esto y al igual que el los artículos anteriores espero que les sirva de ayuda a los que necesitan el conocimiento referente a la generación de PDF, que en honor a la verdad se que muchos son. Pues hasta hace poco era parte del conglomerado. Espero que les sirva y contribuya en su crecimientos como desarrolladores.

 


ir al índice