domingo, 27 de febrero de 2011

Crystal Reports – Cargar imagen usando una capa de reportes

 

Introducción


En esta oportunidad se profundizara el trabajo de imágenes pero apuntando a Reportes, concretamente con el uso de Crystal Reports.

Para este artículo se continua con el ejemplo de uno previo:

[WinForms] Edición Empleados – Grabar imagen en base de datos

En el anterior se listaba y editaba los datos del empleado, incluida sus fotografías, en cambio en este artículo se vera como listar en un reporte esta misma información.

El resultado del reporte final del reporte seria:

imagen1

Se analizara además como incluir las imágenes provenientes de una base de datos, y también un logo tomado de un archivo de imagen.

 

Capa de Reportes


Esto quizás aplique un poco mejor con una arquitectura en capas, pero en este caso aunque no las haya definido del todo, se puede separa en un proyecto concreto la responsabilidad de crear los reportes.

Es por eso que se observara en la solución un proyecto de nombre ReportsLayer, este será el encargado de:

- Encapsular la diseño del reporte

- Definición y estructura de datos que requieres el reporte, en este caso implementada en dataset tipados

- La carga de la información, conectándose para ello directamente a los datos, esta capa no hará uso del DataAccess, porque al usar dataset la carga de datos se torna particular, por lo tanto su funcionalidad requiere una conexión directa.

 imagen2

La idea con esto es separar funcionalidad y además cubrir un defecto que tiene Crystal Reports, en donde el diseñador solo toma como entidades objetos que estén local al proyecto donde se encuentra el rpt. Muchas veces poner en la Presentación un reporte implicaría además poner allí mismo los dataset tipados, lo cual ensucia el modelo.

 

Definición y carga de datos en el DataSet


Para este reporte se definió un dataset tipado con dos datatable en su interior.

imagen3

Para al carga de los empleados se hará uso de la funcionalidad de la clase EmpleadosDAL definida dentro del propio proyecto de Reportes.

internal static class EmpleadosDAL
    {

        internal static Empleados ObtenerTodos()
        {
            Empleados empleados = new Empleados();

            using (SqlConnection conn = new SqlConnection(ConfigurationManager.ConnectionStrings["default"].ToString()))
            {
                conn.Open();

                string query = @"SELECT IdEmpleado, Nombre, Apellido, FechaNacimiento, EstadoCivil, Imagen
                                 FROM Empleados";

                SqlCommand cmd = new SqlCommand(query, conn);

                SqlDataAdapter da = new SqlDataAdapter(cmd);
                //es necesario indicar la tabla del dataset que se quiere cargar
                da.Fill(empleados, "Empleados"); 

            }

            return empleados;
        }
    }

Allí se define la consulta en donde las columnas coinciden en nombre con los definidos en timepo de diseño en el dataset tipado, además vale aclarar que la clase ha sido declarada como internal de forma intencional, para que solo la capa de Reportes pueda usar esta funcionalidad, es mas la idea es que se limite al máximo el acceso a funcionalidad que solo esta clase debería utilizar, por eso el dataset tipado también tiene el modificador de acceso asignado a internal.

 imagen4

Un punto adicional es la carga de una imagen externa que representa el logo de la empresa, el mismo no se encuentra en la db sino que es un archivo, es por eso que luego de cargar el reporte se observan las líneas:

Empleados.EmpresaRow row = empleado.Empresa.NewEmpresaRow();
row.Logo = ImageHelper.ImageToByteArray(ImageHelper.ObtenerImagenLogoEmpresa());
empleado.Empresa.Rows.Add(row);

encargadas justamente de crear una row en al datatable con la imagen del logo. En este caso se hace uso de la funcionalidad del Helper de Imágenes creado para tomar la imagen embebida como recurso.

 

Retorno del Reporte


Esta cada de reportes solo debería ser accedida por medio de la clase Reports con su metodo ObtenerReporteEmpleados() este devolverá la instancia del reporte con la información asignada lista para ser mostrada en pantalla, o exportada si es necesario.

public static class Reports
    {

        public static ReporteEmpleados ObtenerReporteEmpleados()
        {
            ReporteEmpleados report = new ReporteEmpleados();

            //
            // Se obtienen los datos de la lista de empleados
            //
            Empleados empleado = EmpleadosDAL.ObtenerTodos();

            //
            // Se agrega el logo de la empresa a la informacion del listado
            //
            Empleados.EmpresaRow row = empleado.Empresa.NewEmpresaRow();
            row.Logo = ImageHelper.ImageToByteArray(ImageHelper.ObtenerImagenLogoEmpresa());
            empleado.Empresa.Rows.Add(row);

            //
            // Se asigna los datos a la instancia del reporte
            //
            report.SetDataSource(empleado);

            return report;
        }

    }

Lanzar el Reporte en al Presentación


El ultimo punto por tratar es como se usara lo anteriormente explicado desde la presentación.

Por un lado contamos con un formulario especialmente creado para desplegar el reporte, el mismo solo cuanta con el CrystalReportViewer y recibe por parámetro la instancia del reporte que debe mostrar.

public partial class Reporte : Form
{
    private ReportClass _report = null;

    public Reporte()
    {
        InitializeComponent();
    }

    public Reporte(ReportClass report)
        :this()
    {
        _report = report;
    }

    private void Reporte_Load(object sender, EventArgs e)
    {
        crystalReportViewer1.ReportSource = _report;
    }
}

Se define un nuevo constructor del formulario para pasar la instancia del reporte al formulario y es en el Load del mismo que se asigna al Viewer, para desplegar el reporte en pantalla.

Por otro lado tenemos un botón en la pantalla de ListaEmpleados, el cual recupera el reporte, con los datos asignados, y se la pasa a la instancia del formulario para que la muestre en pantalla.

private void btnListar_Click(object sender, EventArgs e)
{

    ReporteEmpleados report = Reports.ObtenerReporteEmpleados();

    Reporte frmReporte = new Reporte(report);
    frmReporte.Show();

}

 

Código de ejemplo


La base de datos utilizada en el ejemplo es la Sql Server Express 2008 R2, como ver en la solución el mdf esta integrado al Visual Studio, por lo tanto con solo tener el sql server express instado esta debería funciona adjuntándose sola al servicio.

En la carpeta “script” del proyecto “DataAccess”  se encuentra un archivo .sql con las instrucciones para crear la estructura de tablas y datos que se requieren para este articulo.

 

[C#] 
[VB.NET] 

75 comentarios:

  1. Hola Leandro muy bueno tu blog me ha servido bastante, pero tengo una dificultad y por mas que he buscado no encuentro como hacerlo, estoy haciendo un programa para un colegio pero al tratar de imprimir el boletin de notas no se como hacerlo sera que me puedes ayudar yo estoy imprimiendo con crystal report y c#, la dificulta esta en que no se como manejar bien el crystal report y hacer le informe para que me salga todos los estudiantes con su respectivo boletin y sus notas. te agradesco de antemano

    ResponderEliminar
  2. hola rafa

    En principio imagino has definido el dataset tipado que usaras como origen de datos del reporte. Recuerda que puedes crear la estructura del datatable de forma manual, no necesariamente deberas arrastrarlo desde una tabla de tu db, puedes crear el datatable en el xsd y definir columnas y tipos de datos.
    Algo como esto

    Crystal Reports – Usar DataSet Tipado con dos DataTable

    Luego deberas definir la consulta usando los JOIN que sean necesario y defiendido los campos que coincidan con los nombres que ahs puesto en el datatable del xsd.

    El resto solo seria cargar los registros y pasarselo a Crystal.

    El tema del diseñador deberia ser simple, en la seccion de detalle pondrias los registrso que se repetiran, por ahi esto ayude:

    Crystal Reports Para Visual Studio.net Visual Basic.net

    saludos

    ResponderEliminar
  3. Hola leandro, genial tus post, una consulta yo no tengo el SQL 2008 Xpress, tan solo el SQL2005 Managament Studio, me pregunto si podrias subir el script de tu BD, es que estoy teniendo ese problemita con todos tus ejemplos, gracias!!

    ResponderEliminar
  4. Sorry, me equivoke de post, era para escribirlo en otro de tus post, mil disculpas!!!

    ResponderEliminar
  5. hola hgjhgj

    Dime de cual articulo requieres los script


    saludos

    ResponderEliminar
  6. Hola leandro. Primeramente gracias por la disponibilidad. Tengo una pequeña duda: como puedo generar los reports en VISUAL STUDIO pero en la version EXPRESS o en SHARPDEVELOP (ambos no incluyen CRYSTAL REPORT). La idea que tengo es desarrollar todas mis aplicaciones en un software libre.
    Aguardo tus comentarios. Saludos

    ResponderEliminar
  7. hola VICTOR DANIEL

    El tema es que no puedes, justamente una de las limitantes de la versiones Express es que no incluyen soporte para reportes.

    Deberias conseguir una version Professional o superior para poder usar Crystal (o Reporting Service)

    saludos

    ResponderEliminar
  8. Gracias por la aclaracion y la disposicion

    ResponderEliminar
  9. Hola Leandro recurro a ti como mi última opción ojala me puedas ayudar de verdad, lo que pasa que estoy trabajando con VS 2010 y Crystal Report y me funciona muy bien todo, pero tengo que hacer un reporte con multiples columnas es decir algo así

    cliente1 cliente2

    cliente3 cliente4

    Algo así no se si me dejo entender bueno lo estoy plasmando en un crystal report y he visto por la red que se configura una sección detalles y todo lo he hecho, pero nada aún sigo sin poder hacerlo espero que me ayudes lo antes posible que de verdad lo necesito gracias

    ResponderEliminar
  10. hola Chamako De Barrio

    Te refierea a algo como lo explicado aqui

    Crystal Reports: Multiple Columns and Header Groups


    saludos

    ResponderEliminar
  11. Si ya lo logre hacer muchas gracias por tu pronta respuesta ese mismo día me salió, pero tuve que quedarme hasta un poco más tarde en el trabajo una consulta más no tendras ejemplos con crystal report pero para estadisticos, es decir con barras o el pie porfavor si tienes algo publica una entrada o sino envíamelo a eflorespalma@hotmail.com y nuevamente muchas gracias por todo.

    ResponderEliminar
  12. Muy bueno tu blog Leandro, pero tengo un problema con el manejo de imagen, te cuento yo tengo un reporte en .Asp con imagen que funciona normal localmente pero cuando lo público el proyecto no carga el imagen como que no lo encuentra la imagen podrías darme una sugerencia amigo Leandro.

    ResponderEliminar
  13. hola Jhon

    has validado que la ruta relativa a la imagen es correcta?

    seguramente estes usando una url que define ../ o algo similar para referenciar la imagen
    pero esto puede variar si en el entorno local donde defines un sitio que usa un directorio virtual, porque al publicar este ya no esta, y las rutas pueden quedar mal

    si usas controles de asp.net recuerda que puedes usar el
    ~/
    este crea el path desde el root del sitio


    saludos

    ResponderEliminar
  14. Buenas tardes Leandro, encontre ese link: http://www.businessobjects.com/jump/xi/crvs2010/us2_default.asp para descargar el Crystal Reports, y quería saber si es GRATUITO, osea para uso comercial y si funciona para Visual Studio 2010 en Español. Muchas gracias, espero su respuesta master.

    ResponderEliminar
  15. hola fer007

    si ese link permite obtener los redistribuibles de Crystal que puedes usar libremente

    para VS 2010 mejor valida

    http://social.msdn.microsoft.com/Forums/en/vscrystalreports/thread/f129440e-2fd2-4c2f-a330-33b24d9ea011

    saludos

    ResponderEliminar
  16. Disculpa Leandro, es un buen link el que me pasaste, pero a que refieres con "validar", ps en el foro hay muchas discrepancias, cual es la mejor forma?, yo utilizo el: Visual Studio 2010 Ultimate en Español, q' problema habria al instalar los "redistribuibles Crystal Reports SAP"?. Help me pleaseeeee. ...no sé si será mucho pedir una muestra en el blog acerca de la instalación SAP Crystal Reports y complementarlo con el VS2010. Gracias.

    ResponderEliminar
  17. hola fer007

    por validar apuntaba que en el link del foro de msdn se mencionan los link correctos a los redistribuibles de VS2010
    por eso decia que valides, o sea que revises porque alli mencionas lo de 2010, el link que hacias mencion al principio solo estan los redistribuibles hasta el 2008

    saludos

    ResponderEliminar
  18. Buenos días Leandro, gracias por tu respuesta, pero como decía en el contenido del link enviado: "SAP Crystal Reports, version for Visual Studio 2010", osea para Visual 2010, y no 2008, de todos modos chequearé tu observación. Gracias, y si se pudiera especificar el LINK para descargar directamente el Crystal Reports no habría problema...

    ResponderEliminar
  19. Que tal Leandro, de antemano agradezco vuestra respuesta. tengo un problema al momento de llevar a producción mi aplicación especificamente para visualizar los reportes de Crystal Report.
    http://social.msdn.microsoft.com/Forums/es-xl/vsrepcrystales/thread/ce3d6dee-ee0a-4290-a774-ebad95dcccce

    ResponderEliminar
  20. Hola Leandro... muy bueno el blog y tus ejemplos... se puede adaptar este al uso del objeto report que trae vs2010? porque no tengo Crystal y llego hasta una parte, luego no me reconoce el reporte como un objeto de la ReportLayer.

    ResponderEliminar
  21. Hola, tengo una bd y en un campo guardo el path de mi foto, ¿podrias decirme como le hago para mostrar esa foto en mi reporte de Crystal? lo tengo en VB y mi BD esta en SQLite

    ResponderEliminar
  22. hola Bonifacio

    lo haces de la misma forma que se explcia en el articulo, solo que tendrias un paso previo que consiste en recuperar la ruta de la db

    puedes usar el

    File.ReadAllBytes()

    para pasar de un archivo con al imagen a el campo del datatable

    saludos

    ResponderEliminar
  23. Saludos, antes que nada quiero agradecer por sus exelentes aporte, pero quiero comentarle que en el proyacto que usted subio C#, no esta completo, falta la carpeta EmpleadoLayer, donde esta el rpt y el DataSet.

    ResponderEliminar
  24. Les pongo las lineas que le cambie al metodo para que pudiera obtener la imagen desde una URL, y poderla mostrar en el RPT, sin necesidad de estar en el mismo servidor de la aplicación.

    Saludos

    public static Image ObtenerImagenLogoEmpresa()
    {
    Assembly assembly = System.Reflection.Assembly.GetExecutingAssembly();

    string sURL;
    sURL = "http://www.microsoft.com/presspass/images/gallery/logos/web/ms_net_rgb_web.jpg";

    WebRequest wrGETURL;
    wrGETURL = WebRequest.Create(sURL);

    Stream objStream;
    objStream = wrGETURL.GetResponse().GetResponseStream();

    return Image.FromStream(objStream);
    }

    ResponderEliminar
  25. Hola Leanro muy bueno tu blog quisiera saber si podria visualizar imagenes de carpetas en el crystal, descarge tu aplicacion en c# y veo que todo lo ingresas en la BD pero como haria con una ruta de imagen

    ResponderEliminar
  26. hola Francisco

    si en principio se puede lograr, en la db imagino tendrias la ruta relativa a la imagen o al menos el nombre del archivo de imagen

    podrias poner en el campo imagen en el reporte, pero en este vas a tener que definir una formula que arme de forma correcta la ruta a la imagen que debe mostrar

    saludos

    ResponderEliminar
  27. Hola Leandro. Segui paso a paso el diseño de la capa de reportes, todo perfecto hasta alli, pero al publicar la aplicacion con el asistente de .net, no me carga el reporte, no entiendo por qué: reportEtnia.SetDataSource(ds_Principal)
    Asumo que podria ser que no encuentra los reportes para asociarle los datos cargados.!!
    Agradeceria una ayuda. saludos Victor

    ResponderEliminar
  28. hola victor

    pero simplemente no muestra el reporte, o estas obteniendo algun mensaje de error ? porque es raro que solo no lo muestre sin ningun fallo

    valida que los .rpt este con el .exe en la misma carpeta

    valida ademas que hayas instalado el redistribuible de crystal en la pc del usuario, para la version de crystal que estes usando

    saludos

    ResponderEliminar
  29. Hola Leandro podrias hacer este mismo sistema en ASP.NET porfa SALUDOS

    ResponderEliminar
  30. hola back up

    claro que se puede, crystal tambien se puede implementar en un entorno web, aplica de la misma forma

    saludos

    ResponderEliminar
  31. Buenos Dias Leandro, estoy tratando de Correr Los Proyectos en Vb.net pero me dice que el motor de base de ddatos no es compatible con Sql Server 2005, siendo que en pi Pc tengo instalado Sql Server 2008 R2, el mismos, que se hace referencia en el proyecto, ahora la base de datos debe estar creada en el Motor?

    ResponderEliminar
  32. hola Marco

    asi es el motor de base datos que utilizo es sql express 2008 R2

    no validaste si de casualidad hay alguna instancia de sql 2005 ejecutando ?

    si tienes instalado el VS 2005, este incluye este motor quizas te quedo la instancia ejecutando

    saludos

    ResponderEliminar
  33. Hola Leandro Gracias por ejemplo

    yo al fin pude instalar las librerias nuevas de Crystal 12 en Sharp Develop pero ahora tengo un error con mi SQL yo no tengo el express tengo el sql2008 por lo cual me manda un error necesito cambiarle el string de conexión y me marca el error pero no veo donde se lo puedo cambiar en que archivo me puedes ayudar?

    ResponderEliminar
  34. hola bLaCkLaDy

    los datos como los obtienes de la db? estas usando codigo ado.net para lanzar una query que carga un dataset (el cual asignas luego al reporte)

    has validado si no esta el connection string en el app.config

    saludos

    ResponderEliminar
  35. Hola Leandro ¿qué tal?
    Cheque tu ejemplo de VB.Net para mostrar imágenes en un reporte de CR y no me funciono o posiblemente no supe como implementar tu código.

    Checa, estoy haciendo un sistema de facturación digital y tengo que imprimir un código bidimensional o QR en la factura, siempre va a ser el mismo a menos que el usuario lo cambie; ya intente varias opciones y no logro que el reporte me cargue la imagen. En la BD solo tengo la ruta y el nombre del archivo y esos si logro traerlos y almacenarlos temporalmente pero no logro asignarlos al PictureBox del reporte para que los muestre, me marca el siguiente error:

    "El índice no es válido. (Excepción de HRESULT: 0x8002000B (DISP_E_BADINDEX))" y de ahí se sale y nunca muestra el reporte.

    ¿qué podría ser lo que este fallando? :S

    ResponderEliminar
  36. hola VaLeK

    pero para poder ver la imagen en el reporte deberias poner el array de byte de esta en un campo del datatable que vincules con el reporte

    poner la ruta no va a funcionar

    saludos

    ResponderEliminar
  37. Hola Leandro ya me carga el formulario principal con las imagenes, pero cuando doy clic en el boton Nuevo me manda un Error:
    El valor 'Null' no es valido para 'stream'.
    El error me lo manda en una linea de código de ImageHelper.vb en la funcion Obtenerimagennodisponible.
    La linea es la de "Return Image.FromStream(file)"....
    Nota: estoy usando vb.net y Visual Studio 2010

    ResponderEliminar
  38. hola Manuel

    ese error se produce porque seguramente la imagen de no disponible no esta correctamente embebida dentro del componente, o sea no la cambiaste para que sea un embedded resource

    o porque el path que indicas usando el namespace.nombrearch.extension, no esta correcto
    recuerda que si hay una carpeta esta tambien forma parte del nombre

    saludos

    ResponderEliminar
  39. Gracias Leandro
    Disculpa mi ignorancia pero no entendi en realidad lo que tengo que hacer...

    ResponderEliminar
  40. hola manuel

    cuando en el ejemplo uso esto
    ImageHelper.ObtenerImagenLogoEmpresa()
    estoy tomando la imagen embebida como recurso en el proyecto, para eso selecciona la imagen y ve a sus propiedades, hay una que dice

    embedded resource

    eso es lo primero que debes validar si lo has asignado

    saludos

    ResponderEliminar
  41. Hola Leandro excelente aporte de implementacion de reportes en una arquitectura de capas. Pero tengo la siguiente duda: Este desarrollo funciona perfecto si todo se monta en un mismo PC pero en un escenario de 1 servidor de BD y 50 PC clientes ¿tendria que replicar los reportes fuentes en cada PC, lo cual resultaria engorroso si posteriormente hay cambios? ¿de acuerdo a la pregunta anterior como se resolveria este escenario?

    ResponderEliminar
  42. hola Rony

    podrias ver si se puede serializa el ReportDocument, entonces enviarlo desde un servidor central
    por supuesto apunto a implementar una capa de negocio remota con servicio web, quizas con WCF

    entonces el cliente pide el reporte al servicio y este le responde con la serializacion del reporte

    en este punto tambien vi que se recomienda exportar el reporte quizas a pdf, en el servidor entonces envias al cliente el archivo generado y no un reporte de crystal el cual queda en el servidor

    ReportDocument serialization


    saludos

    ResponderEliminar
  43. Hola Leandro, Mi duda es la siguiente, tengo un reporte que No tengo problemas para imprimr una sola Guia, es un reporte creado con Crystal Reports desde una aplición web. Envío los parámetros de la guía, y todo me funciona bien pero para una sola Guía.

    Mi idea seria es obtener un sólo documento con varias Guias (para imprimirlas todas de golpe y no ir generando una por una) a partir del mismo reporte.


    El código que estaba haciendo era con un for sabiendo la cantidad de veces que se quería imprimir las guías

    For i As Long = 1 To NumeroPagina
    Dim oReporte As New rptGuia ' INSTANCIA DE TU ARCHIVO *.RPT
    oReporte.SetParameterValue("numeroGuia", NumeroGuia)
    oReporte.SetParameterValue("nombreTecnico", Nombre)
    Me.crvReporte.ReportSource = oReporte ' ASIGNANDO AL CRYSTAL REPORT VIEWER

    NumeroGuia = NumeroGuia + 1
    oReporte = Nothing

    Next i

    Pero el problema es que siempre me visualiza es el ultima Guía.

    Ejemplo le digo que me visualice 10 guías y debería de visualizarme 10 documentos, pero me visualiza un documento y es el ultimo.

    ResponderEliminar
  44. hola Adolfredo

    no se puede mostrar en un mismo control viewer varios reportes porque es logico que solo mostrara uno y sera el ultimo asignado

    podrias crear dinamicamente controles viewer en el form
    o podrias hacer que los datos se unan en un solo origen de datos y lo asignes a un solo reporte pero este genere N paginas, una pagina por cada valor que envies

    por supuesto los parametros deberian ir junto a los datos

    tambien se podria lanzar los reportes en difernetes ventanas, haciendo un form.Show() por cada reporte, en donde cada forma tendria un viewer para ver cada reporte por separado
    como cada instancia de forma es un reporte cada uno tendria su juego de datos

    saludos

    ResponderEliminar
  45. Hola leandro muy interesante tu articulo queria saber para hacer un reporte avanzado con graficos estadisticos, diagramas de pastel, etc, existe algun otro metodo de hacer reportes aparte del crystal, a nivel web, saludos

    ResponderEliminar
  46. hola nyvlem25

    En asp.net existen controles, es mas si usas VS2010 este ya incluye el control Chart

    Asp.net Chart Control

    saludos

    ResponderEliminar
  47. Hola Leandro, estoy trabajando con vs2010 y crystal reports a 3 capas, no estoy trabajando con dataset, estoy trabajando con store procedure .Los reportes los estoy cargando directo (este es mi codigo), el reporte contiene un subreporte a la vez.
    Dim Reporte As New ReportDocument
    Dim pf As New ParameterField
    Dim pfs As New ParameterFields
    Dim pv As New ParameterValues
    Dim pdv As New ParameterDiscreteValue

    En el load de a pagina:
    pf.Name = "@numero"

    Dim numero As Int32 = Request.QueryString("numero")

    Dim Tipo As String = Request.QueryString("Tipo")

    If Tipo = "CN" Then
    pfs.Clear()
    pdv.Value = numero
    pf.CurrentValues.Add(pdv)
    pfs.Add(pf)
    CrystalReportViewer1.ParameterFieldInfo = pfs
    Reporte.Load(Server.MapPath("Reportes\MiReporte.rpt"))
    CrystalReportViewer1.ReportSource = Reporte
    Reporte.SetDatabaseLogon("user", "pass", "servidor", "BD")

    hasta aqui normal, el reporte se muestra en el Form. Ahora necesito exportar este reporte en pdf, word, excel, para eso he creado un boton exportar y dropdown con las opciones, pero al exportar me muestra el error: "Faltan los valores del parametro"

    Btn_Exportar
    Dim rptStream As New System.IO.MemoryStream

    rptStream = CType(Reporte.ExportToStream(CInt(ddlTipos.SelectedValue)), System.IO.MemoryStream)

    Response.Clear()
    Response.Buffer = True

    Response.ContentType = FormatoDocumento()
    Response.AddHeader("Content-Disposition", "attachment;filename=" + "Reporte")

    Response.BinaryWrite(rptStream.ToArray())
    Response.End()

    Para llenar el combo:
    Private Function FormatoDocumento() As String

    Dim tipo As String
    Dim nombreReporte As String = "Reporte"

    Select Case Integer.Parse(ddlTipos.SelectedValue)

    Case ExportFormatType.Excel
    tipo = "application/vnd.ms-excel"
    nombreReporte &= ".xls"
    Case ExportFormatType.RichText
    tipo = "application/rtf"
    nombreReporte &= ".rtf"
    Case ExportFormatType.WordForWindows
    tipo = "application/msword"
    nombreReporte &= ".doc"
    Case Else
    tipo = "application/pdf"
    nombreReporte &= ".pdf"
    End Select
    Return tipo

    End Function

    Espero me puedas ayudar a resolver esto, ya no se que hacer, he probado diferentes formas de exportar y siempre me muestra el mismo error.

    ResponderEliminar
  48. Leandro, en principio agradecerte por compartir tus conocimientos tan desinterasadamente.
    Te comento que estoy tratando de imprimir una imagen contenida en un picturebox pero no lo consigo. Siguiendo tus artículos he logrado armar un reporte con crystal reports directamente dese los datos de un form, sin conexion a BD, el problema es que entre estos datos esta una imagen contenida en un picturebox, lo que no logro es cargar en el dataset tipado esta imagen para que el cystal lo pueda imprimir. El campo lo he creado con el tipo de datos System.Byte[], como recomiendas en otro articulo, pero al momento de asignar la imagen me marca como error, esta es la forma en la que lo estoy haciendo:

    Dim myImage As Bitmap = PictureBox1.Image
    Dim rowDatosVentas As ds_Factura.DT_VENTASRow = facturacion.DT_VENTAS.NewDT_VENTASRow
    rowDatosVentas.ventas_qr() = myImage
    facturacion.DT_VENTAS.AddDT_VENTASRow(rowDatosVentas)
    el error me dice: Un valor de tipo 'System.Drawing.Bitmap' no se puede convertir en '1-matriz dimensional de Byte'.
    Te agradecería me orientes un poco. Gracias.

    ResponderEliminar
  49. hola yeso

    esta claro que un bitmap no se puede asignar directo a un byte[] debes convertirlo

    Convertir Imagen a binario en C#

    saludos

    ResponderEliminar
  50. Leandro,
    Gracias por la aclaración, efectivamente ese era mi error. Al final la parte donde se carga la imagen ha quedado asi:

    rowDatosVentas.ventas_qr() = Image2Bytes(myImage)

    Image2Bytes es una función que convierte una imagen en un array, el ejemplo lo he tomado de aqui:
    http://www.elguille.info/net/ADONET/SQL2005Express/imagenes_base_SQLServer.htm

    con esta modificación el codigo funciona correctamente.

    Gracias de nuevo.

    ResponderEliminar
  51. Buenos Días alguien me puede ayudar, en como poner un marco a un reporte

    ResponderEliminar
  52. hola Jose

    puedes dibujar lineas en el reporte

    pero hay un detalle, deberias definir estas en cada seccion, si tienes un header, details y footer las lineas del reporte se arman dibujando lineas en cada seccion

    la linea es un control que esta en la toolbox

    saludos

    ResponderEliminar
  53. HOLA MI NOMBRE ES JEANCARLO SE PUEDE APLICAR EN VISUAL 2012

    ResponderEliminar
  54. hola jeancarlo

    si claro que puedes aplicarlo

    VS2012 tiene plugin de crystal que debes instalar
    recuerda que a partir de VS2010 crystal se instala por separado

    saludos

    ResponderEliminar
  55. Hola Leandro, lo que comentabas en su momento sobre las entidades que reconoce CR (que deben estar en el mismo proyecto que el reporte), sigue siendo asi en la version actual? Saludos!

    ResponderEliminar
  56. Hola Leandro, sera que puedas ayudarme? Cree un reporte en Crystal Report con C#, necesito enviar dos imagenes de mis logos al reporte. Ya tengo el codigo, no me marca ningun error pero no se muestran las imagen. Defini un archivo llamado Encabezado, con los campos: Titulo_Reportes string, Logo_Izquierdo blob, Logo_Derecho blob, y este archivo es el que esta ligado a mi archivo RepProductos.rpt, los campos Logo_Izquierdo y Logo_Derecho en la tabla Empresa de mi base de datos, son de tipo image y los datos que alli se almacenan ya estan convertidos a byte[].

    Aqui te paso mi codigo:

    private void MostrarReporte()
    {

    nGral = new Negocio.CnGenerico();
    Compañia = new Entidad.Catalogos.cCompania();
    DtCompañia = nGral.DTBuscarRecord("Select Titulo_Reportes,Logo_Izquierdo,Logo_Derecho from Empresa");
    DsGral = new DataSet("Reporte");
    Reportes.Catalogos.RepProductos Reporte = new Reportes.Catalogos.RepProductos();
    DsGral.Tables.Add(DtCompañia);
    DsGral.Tables[0].TableName = "Encabezado";
    Reporte.SetDataSource(DsGral);
    this.crystalReportViewer1.ReportSource = Reporte;

    }

    Saludos y espero que puedas responderme, no se que me esta faltando, gracias

    ResponderEliminar
  57. hola Leandro, me puedes ayudar un con problema que tengo, te comento que tengo una tabla en donde guardo la ruta de las imagenes y en un sp que llamo del crystal report tengo un campo que me entrega la siguiente informacion "\\Aries\Documentos_Adjuntos\Cortes\Tacas\a2-aisa5.PNG" esta la combierto en image con el siguiente
    codigo cast ('\\Aries\Documentos_Adjuntos\Cortes\Tacas\a2-aisa5.PNG' as image). y este campo lo deje incorporado en el report pero no me muestra ninguna imagen. me puedes ayudar por favor gracias

    ResponderEliminar
    Respuestas
    1. hola Fabian

      aplicar un CAST a image no te va a devolver una imagen
      creo que vas a tener que iterar por lo datos desde codigo, tomar la ruta de la imagen, usar el File.ReadAllLines() para recuperar el byte[] y asignarlo a un campo imagen del datatable

      es que desde t-sql no creo que puedas convertir una ruta en imagen, por eso planteo hacerlo desde codigo

      saludos

      Eliminar
  58. Leandro, primero que nada te quiero dar las gracias por tus grandes aportes y aprovecho a pedirte ayuda con un problema que tengo. Quiero utilizar Crystal SAP con Visual Studio 2013 con capas (por ejemplo como lo explica esta publicación) pero con la diferencia que mi capa de presentación es ASP.NET.

    Trate reproducir tus pasos pero no tuve éxito, sabes si se puede? o conoces otra forma de hacerlo?

    Desde ya muchas gracias!

    Saludos!

    ResponderEliminar
    Respuestas
    1. hola
      En principio deberia ser igual la tecnica para usar un reporte en una presentacion web, es mas el control CrystalReportViewer es identico, ya que asignarias el reporte que devuelve la capa de reporte al control de la misma forma que lo haces en winform
      Cuando dices que no tuviste existo es porque se produce algun mensaje de error ?
      saludos

      Eliminar
    2. Hola Leandro un gusto saludarte, he estado leyendo tus comentarios y son maravillosos. Recurro a ti porque tengo un problema que quizás para ti sea fácil. Debo ajustar mi Reporte en CrystalReports en donde el logo debe cambiar acorde a la empresa o tienda. Las imágenes están en una subcarpeta dentro de mi proyecto. Llevo dos días intentándolo siguiendo tus pasos pero aún no tengo resultados. Ncesitas que te proporcione algo? me puedes referir un blog o site algo que me de luces para resolver mi issue.
      Gracias de antemano desde Panamá! slds.Silverio

      Eliminar
    3. hola
      como estas vinculando los datos al reporte? usas dataset tipados
      lo pregunto porque podrias definir un datatable que contenga un campo de tipo imagen o binario para contener el array de byte de la imagen
      entonces pasarias el logo junto a los datos
      para obtener el byte array del archivo del logo usarias File.ReadAllByte()
      saludos

      Eliminar
    4. Si utilizo un DataSet. Te adjunto la parte en donde armo el reporte:

      Dim id_ordenservicio = String.Copy(Request.QueryString("ID_ORDENSERVICIO"))
      Dim prod As New Producto()
      Dim rep As New CrystalDecisions.CrystalReports.Engine.ReportDocument
      Dim NombrePrint = ""
      Dim rutaReportes As String = ""
      rutaReportes = Server.MapPath(".") & "/" & "rptOrdenServicio.rpt"

      'Busco el nombre de la impresora por defecto
      For i As Integer = 0 To PrinterSettings.InstalledPrinters.Count - 1
      Dim a As New PrinterSettings()
      a.PrinterName = PrinterSettings.InstalledPrinters(i).ToString()
      If a.IsDefaultPrinter Then
      NombrePrint = PrinterSettings.InstalledPrinters(i).ToString()
      End If
      Next

      rep.Load(rutaReportes)
      rep.SetDataSource(prod.ordenCliente(System.Configuration.ConfigurationManager.ConnectionStrings("conexionCarrito").ConnectionString, id_ordenservicio).Tables(0))
      CrystalReportViewer1.ReportSource = rep
      rep.PrintOptions.PrinterName = NombrePrint
      rep.PrintToPrinter(1, False, 0, 0)
      Me.CrystalReportViewer1.DataBind()

      Eliminar
    5. hola
      bien entonces no evaluaste en ese mismo dataset definirle un datatable con un campo del tipo image
      quizas asignar el SetDataSource() directo no sea buena idea, sino que deberias crear una row en ese datatable que contendra la imagen

      DataSet ds = prod.ordenCliente(System.Configuration.ConfigurationManager.ConnectionStrings("conexionCarrito").ConnectionString, id_ordenservicio)

      //aqui agregas un segundo datatable con un row con la imagen

      rep.SetDataSource(ds)


      saludos

      Eliminar
  59. Hola Leandro, necesito imprimir fotografias de buena calidad. Con Crystal Report es posible hacerlo?, Saludos

    ResponderEliminar
  60. Hola Leandro. Estoy desarrollando mi primera aplicacion en c#. Utilizo Visual Studio Ultimate 2013 y las bases de datos en Postgresql. Mi pregunta es si puedo utilizar Crystal Report, o cual otro me sugieres.

    ResponderEliminar
  61. Hola Leandro. Tambien estoy desarrollando en visual studio ultimate 2013 y sql server
    Tengo una pregunta en reportviewer también se puede hacer este ejemplo??
    Gracias.

    ResponderEliminar
    Respuestas
    1. hola
      Claro por supuesto se puede realizar usando Reporting Service (ya sea un .rdl o .rdlc), el diseño del ejemplo del articulo es muy simple.
      saludos

      Eliminar
  62. Este comentario ha sido eliminado por el autor.

    ResponderEliminar
  63. Hola Leandro,
    Muchas gracias por tus aportes.
    De dónde me puedo descargar el proyecto, ya que el link no me conduce a poder descargarlo.
    Saludos,
    Eusebio.

    ResponderEliminar
  64. Otra pregunta por favor:
    Y es obligatorio usar Dataset tipados? si no es obligatorio, como se haria?
    Gracias!

    ResponderEliminar
  65. Hola leandro este ejemplo me parece muy bueno pero como seria pasar el reporte si en lugar de usar crystal reports uso Microsoft Report Viewer Control for Asp. Net Web Forms.

    Esta inquietud la tengo ya que Crystal Reports me esta dando problemas debido a que las actualizaciones se demoran en ser publicadas y no son compatibles con las ultimas versiones de visual studio.

    Desde ya muchas gracias por tus consejos y experiencias que compartes con nosotros.

    ResponderEliminar