viernes, 6 de febrero de 2015

Enlazando a Crystal Reports con .NET

En esta entrada vamos a crear una clase genérica que nos permita interactuar con informes realizados en Crystal Reports. La clase se logará en la base de datos, ejecutará los informes y nos los devolverá en el formato que nos interese. Si examinamos el código de la clase, realizado en C#, no son necesarias muchas explicaciones. Veámoslo pues:
// *************************************************************************
// CLASE PARA CREAR INFORMES UTILIZANDO CRYSTAL REPORTS (BUSINESS OBJECT)
//
// Referencias a importar (C:\Archivos de Programa\Business Objects\Common\3.5\managed\dotnet2)
//    CrystalDecisions.CrystalRports.Engine
//    CrystalDecisions.Shared
//
// Manuel Toscano Blancas
// *************************************************************************

using CrystalDecisions.CrystalReports.Engine;
using CrystalDecisions.Shared;
using System;
using System.Collections;

namespace GestorInformes
{
  class InformesCrystalReports
  {

    #region " Variables miembro "

    // Informacion de conexion a la BD
    private static string _bbdd_servidor;
    private static string _bbdd_nombre;
    private static string _bbdd_usuario;
    private static string _bbdd_clave;
    private static bool _bbdd_seguridadIntegrada;

    #endregion

    #region " Métodos públicos "

    /// <summary>
    /// Establecer las propiedades de conexión a la base de datos para los informes.
    /// </summary>
    /// <param name="servidor"></param>
    /// <param name="nombreBBDD"></param>
    /// <param name="usuario"></param>
    /// <param name="clave"></param>
    /// <param name="seguridadIntegrada"></param>
    public static void SetInfoConexion(string servidor, string nombreBBDD, string usuario, string clave, bool seguridadIntegrada)
    {
      _bbdd_servidor = servidor;
      _bbdd_nombre = nombreBBDD;
      _bbdd_usuario = usuario;
      _bbdd_clave = clave;
      _bbdd_seguridadIntegrada = seguridadIntegrada;
    }

    /// <summary>
    /// Generar informe y devolver resultado en forma de fichero en PDF.
    /// </summary>
    /// <param name="ficheroRPT"></param>
    /// <param name="hashTableFormulas"></param>
    /// <param name="ficheroPDF"></param>
    public static void ReportToPDF(string ficheroRPT, Hashtable hashTableFormulas, string ficheroPDF)
    {
      try
      {
        ReportDocument rpt;
        rpt = GetResultadoRPT(ficheroRPT, hashTableFormulas);
        rpt.ExportToDisk(ExportFormatType.PortableDocFormat, ficheroPDF);
        rpt.Close();
        rpt.Dispose();
      }
      catch (Exception ex)
      {
        throw new Exception(ex.InnerException.ToString());
      }
    }

    /// <summary>
    /// Generar informe y devolver resultado por impresora.
    /// </summary>
    /// <param name="ficheroRPT"></param>
    /// <param name="hashTableFormulas"></param>
    /// <param name="nombreImpresora"></param>
    /// <param name="numeroCopias"></param>
    /// <param name="dobleCara"></param>
    public static void ReportToPrinter(string ficheroRPT, Hashtable hashTableFormulas, string nombreImpresora = "", int numeroCopias = 1, bool dobleCara = false)
    {
      try
      {
        ReportDocument rpt;
        rpt = GetResultadoRPT(ficheroRPT, hashTableFormulas);
        // Se podrian configurar otras opciones de impresion con rpt.PrintOptions 
        rpt.PrintOptions.PrinterName = nombreImpresora;
        rpt.PrintOptions.PaperOrientation = CrystalDecisions.Shared.PaperOrientation.DefaultPaperOrientation;
        rpt.PrintOptions.PaperSize = CrystalDecisions.Shared.PaperSize.DefaultPaperSize;
        rpt.PrintOptions.PrinterDuplex = CrystalDecisions.Shared.PrinterDuplex.Default;
        rpt.PrintOptions.PaperSource = CrystalDecisions.Shared.PaperSource.Auto;
        if (dobleCara)
        {
          if (rpt.PrintOptions.PaperOrientation == PaperOrientation.Portrait)
            rpt.PrintOptions.PrinterDuplex = CrystalDecisions.Shared.PrinterDuplex.Vertical;
          else if (rpt.PrintOptions.PaperOrientation == PaperOrientation.Landscape)
            rpt.PrintOptions.PrinterDuplex = CrystalDecisions.Shared.PrinterDuplex.Horizontal;
          else
            rpt.PrintOptions.PrinterDuplex = CrystalDecisions.Shared.PrinterDuplex.Default;
        }
        // Imprimir
        rpt.PrintToPrinter(numeroCopias, true, 0, 0);
        rpt.Close();
        rpt.Dispose();
      }
      catch (Exception ex)
      {
        throw new Exception(ex.InnerException.ToString());
      }
    }

    #endregion

    #region " Métodos privados para la generación del informe "

    private static ReportDocument GetResultadoRPT(string ficheroRPT, Hashtable hashTableFormulas = null)
    {
      try
      {
        // Validaciones
        if (!System.IO.File.Exists(ficheroRPT)) throw new ApplicationException("No se encontró el fichero de reporte " + ficheroRPT);

        // Informe
        CrystalDecisions.CrystalReports.Engine.ReportDocument rpt = new CrystalDecisions.CrystalReports.Engine.ReportDocument();
        rpt.Load(ficheroRPT);
        // Pasar fórmulas
        if (hashTableFormulas != null && hashTableFormulas.Count > 0)
        {
          foreach (string key in hashTableFormulas.Keys)
            SetFormula(rpt, key, hashTableFormulas[key].ToString());
        }
        // Logarse en todas las tablas
        LoginEnTablas(rpt);

        return rpt;
      }
      catch (Exception ex)
      {
        throw new Exception(ex.InnerException.ToString());
      }
    }

    private static void SetFormula(ReportDocument rpt, string nombre, string valor)
    {
      try
      {
        rpt.DataDefinition.FormulaFields[nombre].Text = "\"" + valor.ToString() + "\"";
      }
      catch (Exception ex)
      {
        throw new Exception("Fórmula no válida. " + ex.Message);
      }
    }

    private static void LoginEnTablas(ReportDocument rpt)
    {
      try
      {
        CrystalDecisions.Shared.TableLogOnInfo tableLogonInfo = new CrystalDecisions.Shared.TableLogOnInfo();
        CrystalDecisions.Shared.ConnectionInfo connectionInfo = new CrystalDecisions.Shared.ConnectionInfo();

        connectionInfo.ServerName = _bbdd_servidor;
        connectionInfo.DatabaseName = _bbdd_nombre;
        connectionInfo.UserID = _bbdd_usuario;
        connectionInfo.Password = _bbdd_clave;
        connectionInfo.IntegratedSecurity = _bbdd_seguridadIntegrada;

        // Tablas del informe
        foreach (CrystalDecisions.CrystalReports.Engine.Table table in rpt.Database.Tables)
        {
          if (table.LogOnInfo.ConnectionInfo.DatabaseName == connectionInfo.DatabaseName)    // Esto permite cambiar el login solo en tablas de la misma BBDD, no interfiere si son otras como por ejemplo XML
          {
            tableLogonInfo = table.LogOnInfo;
            tableLogonInfo.ConnectionInfo = connectionInfo;
            table.ApplyLogOnInfo(tableLogonInfo);
            if (table.Location.Contains("."))
              table.Location = _bbdd_nombre + ".dbo.[" + table.Location + "]";
          }
        }

        // Tablas de los SubInformes
        for (int i = 0; i < rpt.Subreports.Count; i++)
        {
          foreach (CrystalDecisions.CrystalReports.Engine.Table table in rpt.Subreports[i].Database.Tables)
          {
            if (table.LogOnInfo.ConnectionInfo.DatabaseName == connectionInfo.DatabaseName)    // Esto permite cambiar el login solo en tablas de la misma BBDD, no interfiere si son otras como por ejemplo XML
            {
              tableLogonInfo = table.LogOnInfo;
              tableLogonInfo.ConnectionInfo = connectionInfo;
              table.ApplyLogOnInfo(tableLogonInfo);
              if (table.Location.Contains("."))
                table.Location = _bbdd_nombre + ".dbo.[" + table.Location + "]";
            }
          }
        }

        tableLogonInfo = null;
        connectionInfo = null;
      }
      catch (Exception ex)
      {
        throw new Exception(ex.InnerException.ToString());
      }

    }

    #endregion

  }
}
La utilización de la clase genérica anterior, podría resumirse en el código siguiente, que sería el que utilizaríamos en nuestra aplicación:
System.Collections.Hashtable htFormulas = new System.Collections.Hashtable();
htFormulas.Clear();
htFormulas.Add("Codigo",dt.Rows[i]["ParametrosGeneracion"].ToString());
InformesCrystalReports.ReportToPDF(dt.Rows[i]["FicheroOrigen"].ToString(), htFormulas, ficheroDestinoPDF);
Eso crea un PDF con el resultado de ejecutar el informe, pero como hemos incluido otros métodos, podríamos haber hecho que directamente saliera por impresora, o bien recoger el objeto resultante para mostrarlo por pantalla en un contenedor de report.

0 comentarios :

Publicar un comentario

 

Copyright @ 2015 Tosblama