Archivo de la Categoría 'Crystal Reports'

Report in .NET using Crystal Reports and MySQL database.

This is just the first of some English posts that I’ll publish by translating most popular posts in this blog. Original version (in Spanish) is here.

First of all, I must asume that creating reports is one of that things I like worst in programming. But it’s quite obvious that few serious applications don’t need them, and the one I’m developing now isn’t an exception to this rule. So I’ve been creating some reports recently and I’ve discovered a new way to do it. And that’s what I explain in this post.

As I’ve said sometimes before in previous posts, I develop with VisualBasic.NET and MySQL database. And I use Crystal Reports to create reports, as this tool is integrated in VisualStudio.NET. Since now, I used to use an ODBC connection configured in each PC to connect to MySQL server. But I didn’t like this system much, because actually I’m not working just with one database but with some with different names. They have the same structure, tables and data, but just one is the good one, as the rest are just for developing purposes. It’s really easy to use one or other connection string to make the application connect with one or other database, but with reports it isn’t so easy as they take data using that ODBC connection (and it just can connect with one database).

But now I’ve discovered how to create reports with just a DataTable and an XML schema, needing nothing else. Actually it’s possible to use a DataSet instead of a DataTable as well. So I’m going to explain it with an easy example and some images.

I’ll work with two tables in my MySQL database where I’ll keep information about bills. First table is the one with information about headers and has this data:

+---------+------------+-------------------------+
| blh_num | blh_dat    | blh_cus                 |
+---------+------------+-------------------------+
|       1 | 2008-07-30 | CERAMICAS PEPE, S.A.    |
|       2 | 2008-07-30 | TALLERES GOMEZ, S.L.    |
|       3 | 2008-07-31 | DEPORTES DAMIAN, S.L.   |
|       4 | 2008-07-31 | SOFTWARE ALBERTMATA.NET |
+---------+------------+-------------------------+

Second table is the one with information about positions and has this rows:

+---------+---------+------------------------+---------+---------+
| blp_num | blp_pos | blp_art                | blp_pri | blp_qty |
+---------+---------+------------------------+---------+---------+
|       1 |       1 | RATON LOGITECH         |   15.95 |       1 |
|       2 |       1 | MONITOR LG 19 PULGADAS |   210.5 |       1 |
|       3 |       1 | ROUTER DLINK           |      56 |       1 |
|       4 |       1 | RATON LOGITECH         |   15.95 |       2 |
|       4 |       2 | TECLADO LOGITECH       |   12.95 |       1 |
|       4 |       3 | RECEPTOR GPS ZAPPA     |   59.95 |       1 |
|       4 |       4 | PAQUETE 500 FOLIOS     |     3.7 |       4 |
+---------+---------+------------------------+---------+---------+

It’s something really simple and not normalized, but will be enough for this example, as we’re going to create a report that will be the inovice for purchase number 4 (the one with customer SOFTWARE ALBERTMATA.NET). Obviously, we’ll need information about both tables but I just want to work with one DataTable, so first of all I’m going to create a MySQL view with this sentence:

CREATE VIEW zbl_bill2print AS 
(
SELECT
    blh_num AS BILL_NUMBER,
    blh_dat AS BILL_DATE,
    blh_cus AS BILL_CUSTOMER,
    blp_pos AS LINE_NUMBER,
    blp_art AS LINE_ARTICLE,
    blp_pri AS LINE_UNITPRICE,
    blp_qty AS LINE_UNITS,
    blp_pri * blp_qty AS LINE_TOTALPRICE
FROM
    blh_billheader LEFT JOIN blp_billposits ON blh_num = blp_num
WHERE
    blh_num = 4
);

So, from now on the report will be created using this zbl_bill2print view. Let’s go with the .NET part.

Step 1. Creating XML file containing table/view structure.

Along this post we’ll work with these three things:

1) a Windows form (frmMain) where we’ll have the report viewer object.
2) a class (clsReportCreator) we’re going to create right now.
3) a report (rptBill) that will be the invoice we want to print.

So let’s start creating clsReportCreator class. It’ll have only one attribute (the name of the table or view), one constructor method, one method to load DataTable object and one last method to generate the XML file. Here is the full code for this class:

'--------------------------------------------------------------------
' Author:      Albert Mata (www.albertmata.net)
' Date:        20080731
' Needs:       MySQL.Data reference.
' Description: Class to create a report using just an XML file. 
'--------------------------------------------------------------------
Imports MySql.Data.MySqlClient

Public Class clsReportCreator

    '----------------------------------------------------------------
    ' Attributes.
    '----------------------------------------------------------------
    Private TableOrView As String

    '----------------------------------------------------------------
    ' Constructor method.
    '----------------------------------------------------------------
    Public Sub New(ByVal TableOrView As String)
        Me.TableOrView = TableOrView
    End Sub

    '----------------------------------------------------------------
    ' Returns DataTable corresponding to TableOrView.
    '----------------------------------------------------------------
    Public Function GetDataTable() As DataTable
        Dim DA As MySqlDataAdapter
        Dim DS As New DataSet
        Dim DT As DataTable
        Dim ConnectionString As String
        Dim SQL As String

        'Setting connection string to connect to MySQL database.
        ConnectionString = "Database = blog; " _
                         & "Data Source = localhost; " _
                         & "User ID = root; " _
                         & "Password = mypassword"

        'Setting SQL string.
        SQL = "SELECT * FROM " & Me.TableOrView

        'Getting data and filling DataSet and DataTable.
        DA = New MySqlDataAdapter(SQL, ConnectionString)
        DA.Fill(DS, Me.TableOrView)
        DT = DS.Tables(Me.TableOrView)

        'Returning DataTable.
        Return DT
    End Function

    '----------------------------------------------------------------
    ' Creates XML file in desired path.
    '----------------------------------------------------------------
    Public Sub CreateXMLFile(ByVal FilePath As String)
        Dim DT As DataTable

        'Creating DataTable.
        DT = Me.GetDataTable()

        'Writting XML file in desired path.
        DT.WriteXmlSchema(FilePath & Me.TableOrView & ".xml")
    End Sub

End Class

And we also create frmMain form, which only code by the moment will be this:

'--------------------------------------------------------------------
' Author:      Albert Mata (www.albertmata.net)
' Date:        20080731
' Description: Form to show how to create a report using just an XML
'              file. 
'--------------------------------------------------------------------
Public Class frmMain

    '----------------------------------------------------------------
    ' As a first step, creates XML file.
    '----------------------------------------------------------------
    Private Sub frmMain_Load(ByVal sender As System.Object, _
    ByVal e As System.EventArgs) Handles MyBase.Load
       'Creating XML file.
        Dim RC As New clsReportCreator("zbl_bill2print")
        RC.CreateXMLFile("C:\")
    End Sub

End Class

Right now we have a first application. If we execute it we’ll get C:\zbl_bill2print.xml file with the structure of zbl_bill2print view. So we run it and get that file.

Step 2. Creating report and loading data source.

First, we add a report to our project and give it a name like rptBill.rpt. We create it choosing empty report option, so desestimating any templates.

Now we go to Fields explorer menu and right-click the first option (Database fields). In new contextual menu we click on Database assistant option.

After this we get the Available data source menu, where we choose Create new connection and after that ADO.NET option.

Making this, we’ll see a new form where we’ll be asked about File’s path. In this point we have to find XML file we’ve created before (in my example C:\zbl_bill2print.xml) and then press Finish. We have NewDataSet option including our just added zbl_bill2print in Available data source menu now.

So we select it and press button to move it to Selected tables menu. Done this, it’s time to click on Accept.

With all this stuff we’ve gotten that zbl_bill2print structure available in Fields explorer menu with all its fields, as shown in image below:

Step 3. Designing report.

Nothing special to say here. Just adding fields from Fields explorer menu, inserting text objects where needed, sums, text formats, images and so on…

I’ve just created a very simple design like this:

Step 4. Last actions to get the invoice.

Finally we’re going to create the bill. To do that, we add a CrystalReportViewer object in frmMain form. I call it crvBill. After that it’s necessary to modify frmMain source code to make it look like this:

'--------------------------------------------------------------------
' Author:      Albert Mata (www.albertmata.net)
' Date:        20080731
' Description: Form to show how to create a report using just an XML
'              file. 
'--------------------------------------------------------------------
Imports CrystalDecisions.CrystalReports.Engine

Public Class frmMain

    '----------------------------------------------------------------
    ' Creates XML file (just once) and creates and loads a report.
    '----------------------------------------------------------------
    Private Sub frmMain_Load(ByVal sender As System.Object, _
    ByVal e As System.EventArgs) Handles MyBase.Load
        'Creating XML file.
        Dim RC As New clsReportCreator("zbl_bill2print")
        'RC.CreateXMLFile("C:\")

        'Creating report.
        Dim RD As ReportDocument = New rptBill()

        'Setting data source for report.
        Dim DT As DataTable = RC.GetDataTable()
        RD.SetDataSource(DT)

        'Setting data source for possible subreports.
        For Each SR As ReportDocument In RD.Subreports
            If SR.Database.Tables.Count > 0 Then
                SR.SetDataSource(DT)
            End If
        Next

        'Setting recently created report must be shown in viewer.
        Me.crvBill.ReportSource = RD
    End Sub

End Class

It’s important to note that the line where the XML file is created is commented now, as we just need to create this file once to use it to create the source data, but from now on we don’t need to generate it every time.

What we’re mainly doing in this code is:

1) creating a report object same kind we’ve designed in step 3,
2) getting a DataTable with data we want to show (in this example and according to the way we’ve defined MySQL view, we want to show invoice number 4),
3) setting this DataTable as the report’s source data,
4) asking CrystalReportViewer to show this report.

We execute the application again and get desired invoice:

Of course there should be quite more information, images and legal texts in a real invoice, but this is just an easy example of how to do the report itself.

So we’ve seen how to create a report in VisualBasic.NET just using an XML file. Of course there are plenty of things to improve, as optimizing how database connection is done, or avoiding WHERE condition directly in MySQL view and so on… but what I was looking for with this example was just a very minimum guide to show the process.

PS. Some menu and option names can be different as I develope in VisualStudio Spanish version and I’ve just translated them as I’ve thought they could appear in English version. Sorry about that!

Update.

There is a second part for this post explaining how to pass parameters from form to report, but it’s still only in Spanish.

Pasando parámetros al informe en .NET con Crystal Reports.

Hace unas semanas publiqué el post Informe en .NET con Crystal Reports y base de datos MySQL, que se convirtió rápidamente en el post más visitado de este blog. También en el que más comentarios ha recibido, y precisamente de uno de ellos ha surgido este apéndice a dicho post.

Recordemos que en él enseñábamos cómo crear un informe con Crystal Reports utilizando un archivo XML y un DataTable (también servía un DataSet). En éste vamos a ver cómo podemos pasar parámetros al informe creado, por ejemplo para enviar el valor de un TextBox (aunque en mi ejemplo utilizaré una constante) y mostrarlo en el informe o bien utilizarlo para filtrar qué registros se tienen que mostrar y cuáles no.

Vamos a meternos pues en faena.

Paso 1. Recopilatorio de lo que teníamos.

Partíamos de un par de tablas de MySQL y una vista que se había establecido así:

CREATE VIEW zbl_bill2print AS 
(
SELECT
    blh_num AS BILL_NUMBER,
    blh_dat AS BILL_DATE,
    blh_cus AS BILL_CUSTOMER,
    blp_pos AS LINE_NUMBER,
    blp_art AS LINE_ARTICLE,
    blp_pri AS LINE_UNITPRICE,
    blp_qty AS LINE_UNITS,
    blp_pri * blp_qty AS LINE_TOTALPRICE
FROM
    blh_billheader LEFT JOIN blp_billposits ON blh_num = blp_num
WHERE
    blh_num = 4
);

En la que por tanto filtrábamos los valores para obtener sólo los registros correspondientes a la factura número 4. Bien, vamos a cambiar eso para que ahora nuestro DataTable contenga todos los registros correspondientes a todas las facturas. La vista quedará pues ahora así:

CREATE VIEW zbl_bill2print AS 
(
SELECT
    blh_num AS BILL_NUMBER,
    blh_dat AS BILL_DATE,
    blh_cus AS BILL_CUSTOMER,
    blp_pos AS LINE_NUMBER,
    blp_art AS LINE_ARTICLE,
    blp_pri AS LINE_UNITPRICE,
    blp_qty AS LINE_UNITS,
    blp_pri * blp_qty AS LINE_TOTALPRICE
FROM
    blh_billheader LEFT JOIN blp_billposits ON blh_num = blp_num
);

El resto de objetos siguen de momento igual. Esto es, el formulario frmMain y el reporte rptBill. No es preciso volver a generar el archivo XML para los cambios que vamos a hacer.

Paso 2. Añadir parámetro en el informe rptBill.

En el Explorador de campos hacemos click derecho en la opción Campos de parámetro para crear un nuevo parámetro. Lo creamos dándole un nombre (BillNumber) y un tipo de valor (Número) y aceptamos.

Si y sólo si tenemos algún interés en que este parámetro que posteriormente le enviaremos al informe aparezca en algún sitio de este informe, lo añadiremos a su área de impresión. En mi caso y sólo para que todo quede más claro, lo añado tal como se muestra en la imagen siguiente (el parámetro es el campo ?BillNumber):

Pero insisto en que lo importante ha sido crearlo. Arrastrarlo hasta el área de impresión del informe es absolutamente opcional.

Paso 3. Establecer el filtro para el informe.

En este ejemplo partimos de un DataTable con varios registros pertenecientes a distintas facturas y desearemos filtrar el reporte para que nos muestre sólo un determinado número de factura. Para ello tenemos pues que establecer este filtro.

Para ello, hacemos click derecho en cualquier punto del área de impresión del report y seleccionamos la opción Report - Fórmula de selección - Registro. En el editor que nos aparece seleccionamos los campos correspondientes para terminar creando la siguiente fórmula:

{zbl_bill2print.BILL_NUMBER} = {?BillNumber}

Guardamos el filtro y cerramos el editor.

Paso 4. Enviar el valor del parámetro desde el formulario.

Ya hemos creado un parámetro en el informe y hemos definido también un filtro basado en ese parámetro. Lo último que nos queda es pues informar el valor que deseamos que coja ese parámetro. En este caso lo haremos enviándoselo desde el formulario a través de una constante, pero como he dicho antes podríamos hacerlo tomando el valor, por ejemplo, de un TextBox o un DataGridView.

Para enviar el valor simplemente debemos añadir esta línea al código del formulario:

RD.SetParameterValue(”BillNumber”, BILL_NUMBER)

Con lo cual el código íntegro del formulario queda como sigue:

'--------------------------------------------------------------------
' Author:      Albert Mata (www.albertmata.net)
' Date:        20081001
' Description: Form to show how to create a report using just an XML
'              file, and how to send parameters to it.
'--------------------------------------------------------------------
Imports CrystalDecisions.CrystalReports.Engine

Public Class frmMain

    '----------------------------------------------------------------
    ' Constants.
    '----------------------------------------------------------------
    Const BILL_NUMBER As Integer = 4

    '----------------------------------------------------------------
    ' Creates XML file (just once) and creates and loads a report.
    '----------------------------------------------------------------
    Private Sub frmMain_Load(ByVal sender As System.Object, _
    ByVal e As System.EventArgs) Handles MyBase.Load
        'Creating XML file.
        Dim RC As New clsReportCreator("zbl_bill2print")
        'RC.CreateXMLFile("C:\")

        'Creating report.
        Dim RD As ReportDocument = New rptBill()

        'Setting data source for report.
        Dim DT As DataTable = RC.GetDataTable()
        RD.SetDataSource(DT)

        'Setting data source for possible subreports.
        For Each SR As ReportDocument In RD.Subreports
            If SR.Database.Tables.Count > 0 Then
                SR.SetDataSource(DT)
            End If
        Next

        'Setting recently created report must be shown in viewer.
        Me.crvBill.ReportSource = RD

        'Sending parameter to the report.
        RD.SetParameterValue("BillNumber", BILL_NUMBER)

    End Sub

End Class

Y esto es todo. A partir de aquí si ejecutamos la aplicación obtendremos el informe correspondiente.

Concretamente tal como está el código obtendremos lo siguiente:

Es decir, la factura número 4 porque hemos establecido el valor de la constante BILL_NUMBER a 4. Si cambiamos ese valor por un 3 y volvemos a ejecutar, obtendremos esto otro:

O sea, la factura número 3.

Vemos además que tanto en una como en la otra aparecen esos 4,00 y 3,00 fruto de que en el paso opcional de añadir el parámetro al área de impresión del informe, yo sí lo hice.

Informe en .NET con Crystal Reports y base de datos MySQL.

Vaya por delante que el tema de la creación de informes (o reports) siempre ha sido una de las partes de la programación que me ha dado más pereza. Pero está claro que pocas aplicaciones se salvan de requerirlos en mayor o menor grado, y la que actualmente tengo entre manos no es, en absoluto, una excepción. Así pues, estos últimos días he tenido que preparar un nuevo report y de paso he aprovechado para investigar un poco y descubrir una nueva manera de realizarlos. Paso a explicarme.

Como ya he comentado en ocasiones, mi entorno de desarrollo es VisualBasic.NET y una base de datos MySQL. Y los informes los hago con el propio Crystal Reports que incorpora el VisualStudio.NET. El tema está en que hasta ahora los hacía a través de una conexión ODBC que tenía que instalar en cada máquina apuntando hacia el servidor MySQL, pero este sistema no me gustaba demasiado. Y no me gustaba porque en realidad de bases de datos tengo distintas con distintos nombres pero con las mismas estructuras de tablas y datos parecidos, ya que una es la productiva (la real, la buena) y las otras son para desarrollo, para que los usuarios hagan pruebas sin que afecte a los datos reales, etc. Controlar la cadena de conexión en la aplicación para que ataque a una u otra base de datos no me supone el más mínimo problema, pero los informes cogen sus datos a través de una conexión ODBC concreta y ésta en cada máquina ataca a una única base de datos. Así que no me convence este sistema.

Y ahora he descubierto cómo puede crear informes a través de un DataTable y de una estructura en un archivo XML, sin necesidad de nada más. De hecho en lugar de un DataTable se puede utilizar perfectamente un DataSet y funciona sin ningún tipo de problemas ni apenas modificaciones (dejo en manos del lector probarlo si le interesa). Voy a pasar a explicar mediante un ejemplo y algunas imágenes cómo realizarlo desde cero.

Partiré de dos tables en mi base de datos MySQL en las que guardaré información de facturas. La primera tabla es de cabeceras de esas facturas y tiene estos datos:

+---------+------------+-------------------------+
| blh_num | blh_dat    | blh_cus                 |
+---------+------------+-------------------------+
|       1 | 2008-07-30 | CERAMICAS PEPE, S.A.    |
|       2 | 2008-07-30 | TALLERES GOMEZ, S.L.    |
|       3 | 2008-07-31 | DEPORTES DAMIAN, S.L.   |
|       4 | 2008-07-31 | SOFTWARE ALBERTMATA.NET |
+---------+------------+-------------------------+

La segunda tabla son las posiciones de cada factura y tiene estos otros datos:

+---------+---------+------------------------+---------+---------+
| blp_num | blp_pos | blp_art                | blp_pri | blp_qty |
+---------+---------+------------------------+---------+---------+
|       1 |       1 | RATON LOGITECH         |   15.95 |       1 |
|       2 |       1 | MONITOR LG 19 PULGADAS |   210.5 |       1 |
|       3 |       1 | ROUTER DLINK           |      56 |       1 |
|       4 |       1 | RATON LOGITECH         |   15.95 |       2 |
|       4 |       2 | TECLADO LOGITECH       |   12.95 |       1 |
|       4 |       3 | RECEPTOR GPS ZAPPA     |   59.95 |       1 |
|       4 |       4 | PAQUETE 500 FOLIOS     |     3.7 |       4 |
+---------+---------+------------------------+---------+---------+

Es algo muy sencillo y poco normalizado, pero nos servirá para el ejemplo. Concretamente vamos a crear un informe que será nada más que una impresión de una factura. Como voy a trabajar con un simple DataTable pero mi informe requerirá datos de dos tablas, me crearé primero una vista en MySQL con la siguiente instrucción:

CREATE VIEW zbl_bill2print AS 
(
SELECT
    blh_num AS BILL_NUMBER,
    blh_dat AS BILL_DATE,
    blh_cus AS BILL_CUSTOMER,
    blp_pos AS LINE_NUMBER,
    blp_art AS LINE_ARTICLE,
    blp_pri AS LINE_UNITPRICE,
    blp_qty AS LINE_UNITS,
    blp_pri * blp_qty AS LINE_TOTALPRICE
FROM
    blh_billheader LEFT JOIN blp_billposits ON blh_num = blp_num
WHERE
    blh_num = 4
);

Así, mi informe a partir de ahora se realizará sobre esta vista zbl_bill2print. Vamos pues a empezar con la parte que incumbe a .NET.

Paso 1. Creación del archivo XML con la estructura de la tabla/vista.

Para todo el ejemplo jugaremos con:

1) un formulario frmMain donde tendremos el objeto visualizador de informes.
2) una clase clsReportCreator que crearemos a continuación.
3) un informe rptBill que representará la factura que queremos imprimir.

Comenzamos pues creando la clase clsReportCreator, que constará de un único atributo (el nombre de la tabla o vista), un método constructor, un método para cargar el DataTable correspondiente y un último método para generar el archivo XML. El código completo de esta clase es el siguiente:

'--------------------------------------------------------------------
' Author:      Albert Mata (www.albertmata.net)
' Date:        20080731
' Needs:       MySQL.Data reference.
' Description: Class to create a report using just an XML file. 
'--------------------------------------------------------------------
Imports MySql.Data.MySqlClient

Public Class clsReportCreator

    '----------------------------------------------------------------
    ' Attributes.
    '----------------------------------------------------------------
    Private TableOrView As String

    '----------------------------------------------------------------
    ' Constructor method.
    '----------------------------------------------------------------
    Public Sub New(ByVal TableOrView As String)
        Me.TableOrView = TableOrView
    End Sub

    '----------------------------------------------------------------
    ' Returns DataTable corresponding to TableOrView.
    '----------------------------------------------------------------
    Public Function GetDataTable() As DataTable
        Dim DA As MySqlDataAdapter
        Dim DS As New DataSet
        Dim DT As DataTable
        Dim ConnectionString As String
        Dim SQL As String

        'Setting connection string to connect to MySQL database.
        ConnectionString = "Database = blog; " _
                         & "Data Source = localhost; " _
                         & "User ID = root; " _
                         & "Password = mypassword"

        'Setting SQL string.
        SQL = "SELECT * FROM " & Me.TableOrView

        'Getting data and filling DataSet and DataTable.
        DA = New MySqlDataAdapter(SQL, ConnectionString)
        DA.Fill(DS, Me.TableOrView)
        DT = DS.Tables(Me.TableOrView)

        'Returning DataTable.
        Return DT
    End Function

    '----------------------------------------------------------------
    ' Creates XML file in desired path.
    '----------------------------------------------------------------
    Public Sub CreateXMLFile(ByVal FilePath As String)
        Dim DT As DataTable

        'Creating DataTable.
        DT = Me.GetDataTable()

        'Writting XML file in desired path.
        DT.WriteXmlSchema(FilePath & Me.TableOrView & ".xml")
    End Sub

End Class

Y creamos también el formulario frmMain cuyo único código por el momento (después cambiará un poco) será el que sigue:

'--------------------------------------------------------------------
' Author:      Albert Mata (www.albertmata.net)
' Date:        20080731
' Description: Form to show how to create a report using just an XML
'              file. 
'--------------------------------------------------------------------
Public Class frmMain

    '----------------------------------------------------------------
    ' As a first step, creates XML file.
    '----------------------------------------------------------------
    Private Sub frmMain_Load(ByVal sender As System.Object, _
    ByVal e As System.EventArgs) Handles MyBase.Load
       'Creating XML file.
        Dim RC As New clsReportCreator("zbl_bill2print")
        RC.CreateXMLFile("C:\")
    End Sub

End Class

Con esto tenemos una primera aplicación que al ejecutarla nos creará el archivo C:\zbl_bill2print.xml con la estructura de la vista zbl_bill2print. Lo probamos pues y obtenemos un archivo como éste.

Paso 2. Creación del informe e inserción del origen de datos.

Añadimos al proyecto un informe al que llamaremos rptBill.rpt y que crearemos seleccionando la alternativa Como informe en blanco y por tanto desestimando plantillas.

A continuación en el menú Explorador de campos seleccionamos la primera opción Campos de base de datos y en su menú contextual hacemos click en la opción Asistente de base de datos.

En el menú que se despliega (Orígenes de datos disponibles) seleccionamos Crear nueva conexión y a continuación la opción ADO.NET.

Con esto se nos abrira un nuevo formulario en el que nos solicitará la Ruta del archivo. Debemos aquí ir a buscar el archivo XML que hemos creado anteriormente (en mi caso el C:\zbl_bill2print.xml) y acto seguido pulsar en Finalizar. Con ello, en el menú anterior (Orígenes de datos disponibles) se nos mostrará ya la opción NewDataSet incluyendo el zbl_bill2print que acabamos de añadir.

Lo marcamos y le damos al botón para trasladarlo al menú de Tablas seleccionadas y pulsamos en Aceptar.

Con esto hemos conseguido que en el menú Explorador de campos nos aparezca ya la estructura de zbl_bill2print con sus campos, tal como se muestra a continuación:

Paso 3. Diseño del informe.

No tiene ningún misterio. Se trata de añadir los campos desde el menú Explorador de campos donde corresponda, insertarle los objetos de texto que nos parezcan adecuados, los totales cuando sea preciso, dar formato a los textos, incorporar imágenes y demás florituras a nuestro antojo…

Yo me inclino por un diseño sobrio como éste:

Paso 4. Últimos pasos para obtener la factura.

Por último vamos ya a crear la factura. Para ello en el formulario frmMain añadiremos un objeto de tipo CrystalReportViewer al que llamaremos por ejemplo crvBill. Y modificamos el código de frmMain para dejarlo como sigue:

'--------------------------------------------------------------------
' Author:      Albert Mata (www.albertmata.net)
' Date:        20080731
' Description: Form to show how to create a report using just an XML
'              file. 
'--------------------------------------------------------------------
Imports CrystalDecisions.CrystalReports.Engine

Public Class frmMain

    '----------------------------------------------------------------
    ' Creates XML file (just once) and creates and loads a report.
    '----------------------------------------------------------------
    Private Sub frmMain_Load(ByVal sender As System.Object, _
    ByVal e As System.EventArgs) Handles MyBase.Load
        'Creating XML file.
        Dim RC As New clsReportCreator("zbl_bill2print")
        'RC.CreateXMLFile("C:\")

        'Creating report.
        Dim RD As ReportDocument = New rptBill()

        'Setting data source for report.
        Dim DT As DataTable = RC.GetDataTable()
        RD.SetDataSource(DT)

        'Setting data source for possible subreports.
        For Each SR As ReportDocument In RD.Subreports
            If SR.Database.Tables.Count > 0 Then
                SR.SetDataSource(DT)
            End If
        Next

        'Setting recently created report must be shown in viewer.
        Me.crvBill.ReportSource = RD
    End Sub

End Class

Nótese que ahora ya he comentado la línea en que creamos el archivo XML, puesto que sólo necesitamos crearlo una única vez para luego poder generar el origen de datos, pero a partir de aquí no necesitaremos andar creándolo cada vez.

En este código lo que estamos haciendo fundamentalmente es crear un objeto del tipo informe que hemos diseñado en el paso 3, obtener un DataTable con los datos que queremos mostrar (en este caso y tal como tenemos definida la vista de MySQL, queremos mostrar la factura número 4), establecer que el origen de datos del informe será este DataTable y finalmente solicitarle al CrystalReportViewer que nos muestre este informe.

Ejecutamos nuevamente la aplicación y obtenemos la factura que queríamos:

Por supuesto en una factura auténtica faltarían datos fiscales, logotipos, impuestos, condiciones de pago y demás, pero lo que aquí pretendía era únicamente mostrar cómo llevar a cabo el informe en sí mismo.

Con esto queda visto cómo simplemente utilizando un archivo XML podemos crear un informe en VisualBasic.NET. Por supuesto habría que mejorar muchas cosas, por ejemplo optimizar cómo se realiza la conexión con la base de datos (particularmente tengo un clase para llevar a cabo esa serie de cuestiones), también evitar poner la condición WHERE directamente en la vista de MySQL y sí por ejemplo cuando recuperamos el DataTable… en fin, unas cuantas cosas. Pero lo que buscaba con este ejemplo era hacer algo muy minimalista para que quedara claro el funcionamiento.

Actualización.

A raíz de uno de los comentarios he añadido una pequeña segunda parte a este post, en la que se explica cómo pasar parámetros desde el formulario hasta el informe.




Creative Commons License
El blog de Albert Mata by Albert Mata is licensed under a Creative Commons Reconocimiento-Compartir bajo la misma licencia 2.5 España License.