Colabora .NET

Creación de informes con imágenes dinámicas en Crystal Reports con C#

Manual para crear informes de crystal con imágenes cuya ruta puede variar o depender de una base de datos usando C#.

 

Fecha: 17/Ago/2006 (17-08-06)
Autor: Albert De Nova- ([email protected])

 


Introducción

Este es mi primer tutorial, así que si tienen alguna duda, sugerencia o hay errores no duden en mandarme un correo, espero que no me decapiten después de leer esto.

En este artículo intentaré explicarles como generar reportes a través de Crystal Reports que contengan imágenes que puedan variar según la ruta de la base de datos o simplemente su ruta de archivo puede ser relativa, el lenguaje que usaré para este tutorial es C#. Existe por ahí algún tutorial para hacer-lo en VB.Net, por eso lo escribo en este lenguaje.

Creando el Dataset

En este caso les voy a poner un proyecto que ya icé (así me ahorro faena jejej) pero que se adapta perfectamente para la realización de este tutorial. El primer paso es crear un Dataset. Para los que no sepan, tienen que ir donde tiene el proyecto a mano derecha, y en donde sale el nombre del proyecto pulsar botón derecho>Agregar>Agregar nuevo elemento... y allí seleccionan el Dataset, en mi caso le puse el nombre: imprimirinform.xsd.

Una vez creado el Dataset nos aparecerá una ventana con un color ocre, en el que te saldrá un texto en medio, veras que tiene destacada la palabra explorador de servidores, úsala para seleccionar la base de datos, de esa forma podrás agregar fácilmente una tabla idéntica a la que hay en la base de datos (que estará vacía, pero servirá para linkear el reporte al dataset, posteriormente enseñaré como llenar el Dataset, no os asustéis :p). En mi caso, la tabla se llama Premsa, y la base de datos se llama tr.mdb. Una vez seleccionamos la base de datos, la abrimos con el símbolo + y seleccionamos la tabla que queremos usar y la arrastramos a la pantallita ocre, de esa manera nos saldrá un cuadrado con las tablas y el tipo de tablas que son.

Una vez agregada la tabla al Dataset hay que hacer una cosa muy importante para realizar bien el tutorial, en mi caso, el campo Noticia contiene la ruta de la imagen. Como se puede ver es de tipo String, pues bien, para poder mostrar la imagen el el reporte lo tenemos que cambiar a base64Binary.

Una vez hecho esto ya tenemos el DataSet creado, ya lo podemos guardar, ahora nos vamos a crear el informe en crystal report.

Creando el informe en Crystal Report de VS.Net 2003

Para crear el informe, volveremos a hacer el primer paso que realizamos con el Dataset, Boton derecho>Agregar>Agregar nuevo elemento... Pero esta vez seleccionaremos el objeto de Crystal Reports. En mi caso se llamará imprimir.rpt.

Una vez creado seleccionaremos la opción que debemos crear (yo seleccioné crear informe en blanco, me gusta mas para poderlo crear como yo quiera). De todas formas, si elijes crear informe en blanco, cuando estés en el reporte (en blanco claro jajaja), pulsa Boton derecho>Bases de Datos>Agregar o quitar bases de datos. Y te saldrá algo como en la foto de abajo, a los que lo creen de otra manera, cuando les diga que agreguen la base de datos, hagan lo siguiente:

Es decir, nos iremos a Datos del proyecto, seleccionaremos donde pone DataSets, y seleccionaremos el Dataset que hemos creado antes, y le aremos click normal, luego pulsaremos en donde están las dos flechas >> para agregar el Dataset con su tabla al informe. Luego, una vez creado el informe, (en mi caso ya veréis como ha quedado) agregamos el campo que contiene la foto, y..sorpresa, es un campo cuadrado, mas grande que el resto, bueno esto es porque contiene las fotos. Una vez creado el reporte, en el campo de las fotos..le damos click con el Botón derecho y le apretamos a Formato..

Una vez hecho esto, nos aparecerá una ventana donde debemos apretar en PUEDE CRECER. Inicialmente estará desmarcada, la debemos marcar para que si la foto es mas grande que el cuadrado, se muestre entera, de otra forma la imagen se reduciría al tamaño del cuadrado. Mira la imagen de debajo si no te queda claro.

Una vez hecho esto ya tendremos el Informe creado, ahora vamos a llenar el DataSet.

Llenando el DataSet desde el form

Crearemos 2 Forms, uno con un botón y otro con un CrystalReportViewer en él.

Bueno aquí empieza la diversión, Crystal Report no admite que le pasemos la ruta de la imagen con el .JPG, .GIF, .PNG o lo que sea, ni tampoco que le pasemos la imagen en si abriéndola antes, por lo que la tenemos que pasar a binario, (no os asustéis, es fácil). Para ello creamos la función ConversionImagen, en la que indicamos la ruta de la imagen y la pasamos a Byte. La función es la siguiente:

public static byte[] ConversionImagen(string nombrearchivo)
{
   //Declaramos fs para poder abrir la imagen.
   FileStream fs = new FileStream(nombrearchivo, FileMode.Open);

   // Declaramos un lector binario para pasar la imagen
   // a bytes
   BinaryReader br = new BinaryReader(fs);
   byte[] imagen = new byte[(int)fs.Length];
   br.Read(imagen,0,(int)fs.Length);
   br.Close();
   fs.Close();
   return imagen;
}

Lo que hace esta función es obtiene la ruta de la imagen (ahora os mostrare como se la damos) y la pasa a binario, devolviendo un valor byte[] que será el que se agregara al dataset.

Para llenar el Dataset, en lugar de usar el famoso Fill(dataset, tabla), no lo usaremos ya que tenemos que modificar algunos datos antes de mandarle los datos al Dataset. Para hacerlo agregamos un OleDbDataAdapter (si estas usando access claro), y lo conectamos con la base de datos que va a contener las noticias. Luego en el evento click del botón, vamos a realizar la conexión a la base de datos, y por cada dato que leamos (usando un Read() del executereader) le iremos agregando los valores al Dataset.

private void button1_Click(object sender, System.EventArgs e)
{
  //instanciamos el datatable, datarow i dataset
  DataTable dt = new DataTable("Premsa");
  DataRow dr;
  DataSet rs = new DataSet("imprimirinform");

  //creamos las mismas columnas que hay en el dataset
  dt.Columns.Add("Titular", System.Type.GetType("System.String"));
  dt.Columns.Add("Data", System.Type.GetType("System.DateTime"));
  dt.Columns.Add("Diari", System.Type.GetType("System.String"));
  dt.Columns.Add("Resum", System.Type.GetType("System.String"));
  dt.Columns.Add("Àmbit", System.Type.GetType("System.String"));
  dt.Columns.Add("ID", System.Type.GetType("System.Int32"));
  /*
  * ahora en Noticia (donde ira la imagen),
  * le decimos que el campo sera System.Byte[] ia que
  * contendra el byte[] obtenido en la funcion ConversionImagen
  */
  dt.Columns.Add("Noticia", System.Type.GetType("System.Byte[]"));

  //abrimos la conexion
  objConectar1.Open();
  OleDbCommand comando = new OleDbCommand("Select * From Premsa", objConectar1);

  //creamos el data reader
  OleDbDataReader linia;
  linia = comando.ExecuteReader();

  //mientras el datareader sea true, ira realizando el bucle
  while(linia.Read())
  {
    //se instancia datarow.
    dr = dt.NewRow();

    /*
    * dr["titulocampo"], con esto le decimos que
    * en la fila que esta creando, en la columna
    * titular, o lo que sea, le asigne un valor
    * el linia.valor (si es string, int, datetime...)
    * y lo que hay entre () es la id del campo, se empieza desde 0
    */
    dr["Titular"] = linia.GetString(0);
    dr["Data"] = linia.GetDateTime(1);
    dr["Diari"] = linia.GetString(2);
    dr["Resum"] = linia.GetString(3);
    dr["Àmbit"] = linia.GetString(4);
    dr["ID"] = linia.GetInt32(5);

    /*
    * En el caso de la noticia la cosa canvia, le pasamos
    * el valor del campo de la bd (ruta de la imagen) a
    * la funcion ConversionImagen, que devolvera un byte[]
    * que sera lo que se inserte en el DataSet, asi
    * el datareport nos mostrara la imagen tal como debe
    */
    dr["Noticia"] = ConversionImagen(linia.GetString(6));

    //añadimos la fila al dl datatable
    dt.Rows.Add(dr);
  }

  //cerramos el datareader y la conexión
  linia.Close();
  objConectar1.Close();

  //añadimos la tabla al dataset
  rs.Tables.Add(dt);

  //iniciamos el form y el reporte
  Form2 form = new Form2();
  imprimir report = new imprimir();

  //le indicamos el datasource al report, que sera el recordset
  //que hemos llenado
  report.SetDataSource(rs);

  //le indicamos el reportsource al crviewer del segundo form
  //que sera el report que creamos
  form.crystalReportViewer1.ReportSource = report;

  //mostramos el 2ndo form
  form.Show();
}

Una vez puesto esto en el botón y agregado el crystalReportViewer ya tenemos el proyecto terminado, al ejecutar el programa y pulsar el botón, el report se llenara con las imágenes y todo, y ya nos funcionará, el sistema esta puesto para que las imágenes se vean al 100%, en mi caso como tenían diferentes tamaños las tuve que redimensionar todas usando el photoshop, pero bueno, al final te acostumbras después de hacer 150 artículos jajajaj. Aquí les dejo como queda finalmente el reporte una vez ejecutado el CRViewer:

Nota:
Siempre puedes configurar el CRViewer como tu quieras, yo lo configuré a mi manera porque es el que usé para el proyecto, que era para realizar la impresión de unos artículos de prensa, aunque he usado el mismo proyecto, los textos están en catalán, porque lo tenia que hacer así, si a alguien le resulta mucho problema por alguna razón que me lo comente y haré lo posible para cambiarlo al castellano si lo prefieren, un saludo y gracias por su atención.


Espacios de nombres usados en el código de este artículo:

System; System.Drawing;
System.Collections;
System.ComponentModel;
System.Windows.Forms;
System.Data;
System.Data.OleDb;
System.IO;

 


Código de ejemplo (ZIP):

 

Fichero con el código de ejemplo: slope_TR.zip - 87 KB

(MD5 checksum: BB86A5023AC5D19BF7160CA8AB7CC81D)

 


ir al índice principal del Guille