none
Recorrer una List e imprimir con Crystal Reports RRS feed

  • Pregunta

  • Buenas tardes, otra vez yo con problemas, sigo aprendiendo mucho desde este espacio. Un usuario me plantea poder imprimir varios recibos juntos, voy a compartir un poco de codigo:

    Public Class FormRecibos
        Private Sub FormRecibos_Load(sender As Object, e As EventArgs) Handles MyBase.Load
            Dim objreporte As New ReciboSocio
            For Each item As CCIyS.Entidades.Recibo In FormSocios.ListaRecibos
                objreporte.SetParameterValue("NombreSocio", item.NombreSocio)
                objreporte.SetParameterValue("DomicilioSocio", item.DireccionSocio)
                objreporte.SetParameterValue("MesRecibo", item.Descripcion)
                objreporte.SetParameterValue("ImporteCuota", item.Importe)
                objreporte.SetParameterValue("FechaRecibo", item.FechaRecibo)
                objreporte.SetParameterValue("NumeroRecibo", item.NumeroRecibo)
                CrystalReportViewer1.ReportSource = objreporte
            Next
        End Sub
    End Class

    Este código proviene directamente del form donde tengo el Crystal Reports. Dentro de el instancio un objeto de tipo .rpt, recorro una lista que traigo desde otro form, donde tengo almacenado todos los recibos que debo imprimir.

    Si el usuario solo selecciona un recibo del datagridView, la lista tendrá un solo objeto, por ende este código funciona a la perfección. 

    El tema es cuando el usuario selecciona varios recibos, solo imprime por Crystal Reports el ultimo objeto de la lista.

    Saludos.

    domingo, 26 de mayo de 2019 23:13

Respuestas

  • Hola:
    El orden aseguir para crystal reports es mas o menos asi.
    1.-Crear el fichero RPT con los campos de base de datos, campos de formula, campos de parametro y sus grupos etc.
    2.-Cargar dicho fichero RPT con los datos (Datatable, Lista, variables, etc).
    3.-Cargar el CrystalReportViever con el fichero RPT con sus datos cargados.

    Tiene que ser un codigo parecido a esto (varia segun la fuente de datos, en este ejemplo es manual pero lo logico sea que este en una BD)

    Public Class FrmLista
        Private Sub FrmLista_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
            Dim Lista As New List(Of Cliente)
            Lista.Add(New Cliente("PEPE", "PEREZ", "MARTINEZ"))
            Lista.Add(New Cliente("LOLY", "ATXA", "RUIZ"))
            Lista.Add(New Cliente("MANUEL", "GARCIA", "LOPEZ"))
            Lista.Add(New Cliente("SARA", "REY", "CONDE"))
            '
            Try
                Dim lsFicheroRPT As String = ("..\..\CRLista.rpt")   'Path del fichero RPT
                ' Cargar el objeto informe en el ReportDocument
                Me.rdInforme.Load(lsFicheroRPT)
                'Usa la lista como fuente de dados para el informe
                Me.rdInforme.SetDataSource(Lista)
                ' cargar el ReportDocument en el CrystalReportViewer
                Me.crvInforme.ReportSource = Me.rdInforme
            Catch ex As Exception
                MessageBox.Show("Alguna cosa ha errado, verifique... : " & ex.Message)
            End Try
            Me.WindowState = FormWindowState.Maximized
        End Sub
    End Class

    Un saludo desde Bilbo
    Carlos 

    • Propuesto como respuesta Carlos_Ruiz_M jueves, 30 de mayo de 2019 13:52
    • Marcado como respuesta ggomez115 miércoles, 5 de junio de 2019 16:12
    jueves, 30 de mayo de 2019 7:18
  • Hola:
    Esta forma
            Try
                ' instanciar el objeto informe
                Dim oRptPrueba As New CRLista()
                oRptPrueba.SetDataSource(Lista)
                ' cargar el informe en el control visualizador
                Me.crvInforme.ReportSource = oRptPrueba
            Catch ex As Exception
                MessageBox.Show(ex.Message)
            End Try
    Y esta otra
     Try
                Dim lsFicheroRPT As String = ("..\..\CRLista.rpt")   'Path del fichero RPT
                ' Cargar el objeto informe en el ReportDocument
                Me.rdInforme.Load(lsFicheroRPT)
                Me.rdInforme.SetDataSource(Lista)
                ' cargar el ReportDocument en el CrystalReportViewer
                Me.crvInforme.ReportSource = Me.rdInforme
            Catch ex As Exception
                MessageBox.Show("Alguna cosa ha errado, verifique... : " & ex.Message)
            End Try

    El resultado es exactamente el mismo.

    A primera vista la primera opcion necesita menos lineas de codigo y NO necesita el control rdInforme (Es un ReportDocument). Vease la siguiente imagen

    La ventaja de usar el ReportDocument es que se obtiene una mayor flexibilidad a la hora de manipular el contenido del informe por codigo.

    En cuanto al problema que se te presenta, parece ser que esta en el datatable (o lo que sea) con la que cargas el datasource del fichero RPT.
    Es condicion necesaria que la fuente de datos tenga todos los campos que tiene el fichero RPT

    Un saludo desde Bilbo
    Carlos

    lunes, 3 de junio de 2019 7:30

Todas las respuestas

  • Hola 

    Gracias por levantar tu consulta en los foros de MSDN. Con respecto a la misma, te hago la recomendación de ingresar al siguiente enlace en donde puedes encontrar una posible solución para tu problema.

    https://social.msdn.microsoft.com/Forums/es-ES/aef72dd5-600f-4867-a3d5-a18f9c87057a/imprimir-verticalmente-crystal-reports?forum=vbes

    https://social.msdn.microsoft.com/Forums/es-ES/205d2376-64b3-4e78-b42a-97b31be3665c/recorrer-listview-para-llenar-dataset?forum=vcses

    Gracias por usar los foros de MSDN.

    Carlos Ruiz
     ____

    Por favor recuerde "Marcar como respuesta" las respuestas que hayan resuelto su problema, es una forma común de reconocer a aquellos que han ayudado, y hace que sea más fácil para los otros visitantes encontrar la solución más tarde. 

    Microsoft ofrece este servicio de forma gratuita, con la finalidad de ayudar a los usuarios y la ampliación de la base de datos de conocimientos relacionados con los productos y tecnologías de Microsoft.  

    Este contenido es proporcionado "tal cual" y no implica ninguna responsabilidad de parte de Microsoft.
    • Propuesto como respuesta Carlos_Ruiz_M miércoles, 29 de mayo de 2019 21:29
    miércoles, 29 de mayo de 2019 14:30
  • Buenas tardes, estudiaré los post que me mencionas.

    Saludos.

    miércoles, 29 de mayo de 2019 20:54
  • Buenas tardes, estuve leyendo los post que me recomendaste. Uno de ellos trabaja con un DataSet enlazado al crystalReportsViewer. Si es necesario podria cambiar mi codigo para probar de hacerlo asi, pero mi ejemplo es algo mas simple. Tengo un form, con un crystalReportViewer, tengo un archivo .rpt que tiene forma de recibo, con variables que seran completadas al momento de instanciar el reporte.rpt, el resto del codigo es simplemente esto:

    Public Class FormRecibos
        Private Sub FormRecibos_Load(sender As Object, e As EventArgs) Handles MyBase.Load
            Dim objreporte As New ReciboSocio
            For Each item As CCIyS.Entidades.Recibo In FormSocios.ListaRecibos

                objreporte.SetParameterValue("NombreSocio", item.NombreSocio)
                objreporte.SetParameterValue("DomicilioSocio", item.DireccionSocio)
                objreporte.SetParameterValue("MesRecibo", item.Descripcion)
                objreporte.SetParameterValue("ImporteCuota", item.Importe)
                objreporte.SetParameterValue("FechaRecibo", item.FechaRecibo)
                objreporte.SetParameterValue("NumeroRecibo", item.NumeroRecibo)
                CrystalReportViewer1.ReportSource = objreporte
            Next
        End Sub
    End Class

    De otro form  (esto ya es indiferente) traigo una lista ya completa, recorro esta lista con for each asignando a las variables del archivo ReciboSocio.rpt sus valores y luego generando el ReportSource.

    Lo que hace este código es solo imprimir el ultimo registro de la lista. Es como que va sobreescribiendo siempre el mismo ReportSource, y al final solo se ve el ultimo. Debe haber alguna manera aquí mismo, sin tener que tocar tanto código de que por cada registro de la lista imprima un ReportSource, generando así la misma cantidad de hojas para imprimir, como registros tenga la lista.

    Saludos. 

    miércoles, 29 de mayo de 2019 21:59
  • Hola:
    El orden aseguir para crystal reports es mas o menos asi.
    1.-Crear el fichero RPT con los campos de base de datos, campos de formula, campos de parametro y sus grupos etc.
    2.-Cargar dicho fichero RPT con los datos (Datatable, Lista, variables, etc).
    3.-Cargar el CrystalReportViever con el fichero RPT con sus datos cargados.

    Tiene que ser un codigo parecido a esto (varia segun la fuente de datos, en este ejemplo es manual pero lo logico sea que este en una BD)

    Public Class FrmLista
        Private Sub FrmLista_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
            Dim Lista As New List(Of Cliente)
            Lista.Add(New Cliente("PEPE", "PEREZ", "MARTINEZ"))
            Lista.Add(New Cliente("LOLY", "ATXA", "RUIZ"))
            Lista.Add(New Cliente("MANUEL", "GARCIA", "LOPEZ"))
            Lista.Add(New Cliente("SARA", "REY", "CONDE"))
            '
            Try
                Dim lsFicheroRPT As String = ("..\..\CRLista.rpt")   'Path del fichero RPT
                ' Cargar el objeto informe en el ReportDocument
                Me.rdInforme.Load(lsFicheroRPT)
                'Usa la lista como fuente de dados para el informe
                Me.rdInforme.SetDataSource(Lista)
                ' cargar el ReportDocument en el CrystalReportViewer
                Me.crvInforme.ReportSource = Me.rdInforme
            Catch ex As Exception
                MessageBox.Show("Alguna cosa ha errado, verifique... : " & ex.Message)
            End Try
            Me.WindowState = FormWindowState.Maximized
        End Sub
    End Class

    Un saludo desde Bilbo
    Carlos 

    • Propuesto como respuesta Carlos_Ruiz_M jueves, 30 de mayo de 2019 13:52
    • Marcado como respuesta ggomez115 miércoles, 5 de junio de 2019 16:12
    jueves, 30 de mayo de 2019 7:18
  • Buen día, estimado voy a probar el código y volveré para comentar resultados.

    Saludos.

    jueves, 30 de mayo de 2019 14:01
  • Buenas tardes, estimado ando de vuelta por aquí, para sacarme algunas dudas. Hay fragmentos de tu código que no entiendo. Sacando la carga de la lista (esta se carga a través de la interacción entre el usuario y la BD)

    .. Dim lsFicheroRPT As String = ("..\..\CRLista.rpt")   'Path del fichero RPT..

    Esta variable string que le asignas como valor la ruta del archivo .rpt es necesaria? Consulto porque mi archivo .rpt esta dentro del proyecto.

    ..Me.rdInforme.Load(lsFicheroRPT)..

    Esta variable rdInforme de que tipo es? Porque no la estas inicializando dentro de tu codigo, directamente la estas utilizando, y le estas asignando la ruta del archivo .rpt como parametro.

    No seria esto similar a hacer: Dim MiReporte as new MiReporte.rpt?? Suponiendo que esto es un SI, si hago estoestaría haciendo un trabajo similar a tu código:

    Dim Reporte as new ReciboSocio 'este es el archivo .rpt incluido dentro del proyecto

    Reporte.SetDataSource(FormSocios.ListaRecibos) 'la lista viene cargada desde otro form

    CrystalReportViewer1.ReportSource = Reporte

    Con este codigo, arroja el siguiente error:

    Dice el informe no tiene tablas.

    Saludos Guille.

    domingo, 2 de junio de 2019 22:33
  • Hola:
    Esta forma
            Try
                ' instanciar el objeto informe
                Dim oRptPrueba As New CRLista()
                oRptPrueba.SetDataSource(Lista)
                ' cargar el informe en el control visualizador
                Me.crvInforme.ReportSource = oRptPrueba
            Catch ex As Exception
                MessageBox.Show(ex.Message)
            End Try
    Y esta otra
     Try
                Dim lsFicheroRPT As String = ("..\..\CRLista.rpt")   'Path del fichero RPT
                ' Cargar el objeto informe en el ReportDocument
                Me.rdInforme.Load(lsFicheroRPT)
                Me.rdInforme.SetDataSource(Lista)
                ' cargar el ReportDocument en el CrystalReportViewer
                Me.crvInforme.ReportSource = Me.rdInforme
            Catch ex As Exception
                MessageBox.Show("Alguna cosa ha errado, verifique... : " & ex.Message)
            End Try

    El resultado es exactamente el mismo.

    A primera vista la primera opcion necesita menos lineas de codigo y NO necesita el control rdInforme (Es un ReportDocument). Vease la siguiente imagen

    La ventaja de usar el ReportDocument es que se obtiene una mayor flexibilidad a la hora de manipular el contenido del informe por codigo.

    En cuanto al problema que se te presenta, parece ser que esta en el datatable (o lo que sea) con la que cargas el datasource del fichero RPT.
    Es condicion necesaria que la fuente de datos tenga todos los campos que tiene el fichero RPT

    Un saludo desde Bilbo
    Carlos

    lunes, 3 de junio de 2019 7:30
  • Hola:
    Esta forma
            Try
                ' instanciar el objeto informe
                Dim oRptPrueba As New CRLista()
                oRptPrueba.SetDataSource(Lista)
                ' cargar el informe en el control visualizador
                Me.crvInforme.ReportSource = oRptPrueba
            Catch ex As Exception
                MessageBox.Show(ex.Message)
            End Try
    Y esta otra
     Try
                Dim lsFicheroRPT As String = ("..\..\CRLista.rpt")   'Path del fichero RPT
                ' Cargar el objeto informe en el ReportDocument
                Me.rdInforme.Load(lsFicheroRPT)
                Me.rdInforme.SetDataSource(Lista)
                ' cargar el ReportDocument en el CrystalReportViewer
                Me.crvInforme.ReportSource = Me.rdInforme
            Catch ex As Exception
                MessageBox.Show("Alguna cosa ha errado, verifique... : " & ex.Message)
            End Try

    El resultado es exactamente el mismo.

    A primera vista la primera opcion necesita menos lineas de codigo y NO necesita el control rdInforme (Es un ReportDocument). Vease la siguiente imagen

    La ventaja de usar el ReportDocument es que se obtiene una mayor flexibilidad a la hora de manipular el contenido del informe por codigo.

    En cuanto al problema que se te presenta, parece ser que esta en el datatable (o lo que sea) con la que cargas el datasource del fichero RPT.
    Es condicion necesaria que la fuente de datos tenga todos los campos que tiene el fichero RPT

    Un saludo desde Bilbo
    Carlos

    Buen día, creo que mi problema puede venir de lo ultimo que mencionas. En primer lugar yo estoy usando CrystalReportViewer y no CrystalReportDocument. En segundo lugar, el archivo.rpt esta creado "como informe en blanco" y los datos (variables) están creados desde la opción parámetros, donde creas el parámetro (nombre y tipo de variable) y luego desde el form donde esta el CrystalReportViewer le das valor al mismo a traves de la opcion Mireporte.SetParameterValue("FechaRecibo", FechaParaRecibo) luego de instanciar el objeto de tipo .rpt

    Si bien la lista contiene los mismos datos como parametros hay en el archivo.rpt, no tengo en el archivo.rpt una tabla asociada con estos campos, como supe ver en algunos tutoriales.

    Voy a hacer las modificaciones correspondientes, para ver si puedo lograr hacer funcionar esto y regreso.

    Saludos.

    martes, 4 de junio de 2019 12:45
  • Buen dia, bueno paso a comentar que mi problema ha sido resuelto, gracias Carlos por la ayuda. Debajo comento como quedo solucionado para que pueda servir a futuros novatos como yo:

    Primero, el titulo queda mal, ya que ya no estoy recorriendo una list e imprimiendo en crystal Reports, lo hago desde una DataSet, cree un archivo DataSet.xsd, con la tabla de mi BD, en la cual selecciono solo los campos que voy a imprimir en el Reporte.

    En un form, coloco el CrystalReportViewer, por otro lado, creo un archivo.rpt de forma estandar. Esto me dara la posibilidad de enlazar el archivo.rpt a la dataSet creada anteriormente, pudiendo colocar los campos de la dataSet dentro del reporte.

    En un form normal, donde interactuo con el usuario tengo lo siguiente:

    Public Shared DtRecibos As New DataTable  'necesito la variable de tipo shared para poder usar en otro form

            If DtRecibos.Columns.Count = 0 Then   'creo las columnas con los mismos nombres de los campos 
                With DtRecibos                                'de la dataSet. En caso de que ya tenga datos la misma, los borro
                    .Columns.Add("NombreSocio")      'para cargarla nuevamente.
                    .Columns.Add("DireccionSocio")
                    .Columns.Add("Descripcion")
                    .Columns.Add("Importe")
                    .Columns.Add("NumeroRecibo")
                    .Columns.Add("FechaRecibo")
                End With

            Else
                DtRecibos.Clear()
            End If

    Dim value As DataGridViewSelectedRowCollection = Me.DataGridView1.SelectedRows

     For Each Fila As DataGridViewRow In value  'con este for each voy creando filas en la dataSet, los datos

         DtRecibos.Rows.Add(AuxNombreSocio,     'introducidos son tomados desde un dataGrid, por eso el for each
                                   AuxDomicilioSocio,        'recorre las filas seleccionadas del dataGridview, almacena en
                                   AuxDescripcionRecibo,   'variables y luego utilizo esas variables para cargar el dataSet
                                   AuxImporteCuota,
                                   UltimoNumeroRecibo,
                                   AuxFechaRecibo)


      Next

    En el otro form, donde tengo el crystalReportViewer tengo solo este codigo:

        Private Sub FormRecibosMultiples_Load(sender As Object, e As EventArgs) Handles MyBase.Load
            Dim ReporteDoc As CrystalDecisions.CrystalReports.Engine.ReportDocument
            ReporteDoc = New RecibosMultiples
            ReporteDoc.SetDataSource(FormSocios.DtRecibos)
            CrystalReportViewer1.ReportSource = ReporteDoc
        End Sub

    Y funciona a la perfeccion, lo demas es todo visual y como uno quiera ordenar los campos en el reporte.

    Ahora bien, de yapa te hago otra consulta, hay manera desde aqui mismo, desde el codigo de generar un salto de pagina en el reporte? Para que por cada fila que recorrer del dataSet haga un salto de pagina?

    Saludos.

    miércoles, 5 de junio de 2019 16:23
  • Hola:

    ¿Porque no abres un nuevo hilo, asi no se mezclan las respuestas?

    Un saludo desde Bilbo
    Carlos

    miércoles, 5 de junio de 2019 20:30
  • Buenas tardes, como podría hacer lo que planteas? Con mi código no tengo control sobre la recorrida del dataSet. Como podría generar un reporte por cada fila del dataSet que recorre?

    Saludos.

    jueves, 6 de junio de 2019 21:37