Construyendo Reportes Para Aplicaciones Web: Parte 3

Bien, continuando con esta última parte de la serie de de reportes para aplicaciones web, vamos a basarnos en el reporte que ya teníamos antes para hacer una construcción de subreportes o reportes anidados.

En primer lugar, debemos decir que un subreporte no es más que un reporte independiente que es definido y llamado desde dentro de otro reporte. En el diseñador de reportes debemos seleccionar el objeto Subreport y arrastrarlo hasta nuestro reporte.

Hay dos requerimientos importantes que debemos mencionar acerca de los subreportes:

1. La estructura del subreporte debe ser por medio de una tabla (diseño en forma de tabla, no se refiere a que los datos deben provenir de una tabla de base de datos).

2. En el reporte padre solamente se muestra la parte de “Body” del subreporte (el header y footer son ignorados).

Entonces, manos a la obra. Empecemos por definir nuestro nuevo reporte que va a ser el subreporte que llamaremos del reporte que ya teníamos (¿parece trabalenguas verdad?). Para empezar, crearemos un nuevo reporte al que llamaremos DetalleOrdenes.rdlc y le agregaremos un objeto Tabla de la caja de herramientas (toolbox).

DetalleOrdenes_Tabla

Ahora, como hicimos antes, vamos a seleccionar la fuente de datos y utilizaremos la tabla dbo.[Order Details] de la base de datos Northwind. Esto creará un nuevo dataset llamado DataSet2 a donde podremos arrastrar la tabla de la conexión de la base de datos.

DataSet2

Arrastramos ahora los campos ProductID, Quantity y UnitPrice a cada uno de los campos en la tabla de la siguiente forma:

Tabla_Con_Campos

Para efectos del artículo no entraremos en detalles del formato y lo dejaremos tal y como está. Ahora es necesario definir un parámetro para el reporte, el parámetro nos servirá para mostrar solamente aquellos registros del detalle de la orden que correspondan con la orden misma, una especie de reporte maestro-detalle. La definición la hacemos en el menú Report y seleccionando la opción Report Parameters. El parámetro lo llamaremos NoOrden y será de tipo Integer (no olvide chequear el checkbox de la opción Allow Null Value).

Report_Parameters

NoOrden

Ahora seleccionamos la tabla y vamos a las propiedades de la misma seleccionando el Tab de Filters. Esto nos servirá para hacer el filtro del parámetro y que se seleccionen solo los datos que corresponden a la orden.

Propiedades_Tabla

Para la definición del filtro, es necesario indicar que el valor para el campo OrderID debe ser igual al del parámetro NoOrden.

Filter

Bien, eso es todo en el subreporte. Ahora regresamos a nuestro reporte principal y hacemos al objeto List un poco más grande para poder ubicar al objeto Subreport dentro de él:

Subreport

Ahora debemos configurar nuestro objeto Subreport. Indicaremos primero que utilice el reporte DetalleOrdenes.rdlc que acabamos de crear, para ello entramos a las propiedades del subreport y en el Tab General seleccionamos:

Subreport_Subreport

Ahora vamos al Tab Parameters donde le daremos el valor a nuestro parámetro y le decimos que el parámetro NoOrden tomará su valor del campo OrderID:

Subreport_Parameters

Ahora, le diremos al objeto List que solamente nos muestre una orden por página, así podremos tener una mejor visión del efecto del subreporte y veremos claramente la información de la orden. Para lograr esto iremos a las propiedades del objeto List y en el Tab General haremos click en el botón “Edit details group”; en la sección Expression seleccionaremos al campo OrderID y luego seleccionaremos la opción “Page break at end”.

List_PageBreak

Ahora podemos ejecutar el reporte para ver el resultado de todo lo que hemos hecho:

Subreport_Error

La ejecución produce dos resultados, uno esperado, uno inesperado. El resultado esperado es que efectivamente se muestra solamente una orden en cada página. El resultado inesperado es un error al mostrar el subreporte.

Este error sucede debido a que el modo en que funciona el subreporte. Es necesario indicarle la fuente de datos, como hasta este momento solamente hemos definido la fuente de datos para el reporte padre el subreporte no tiene fuente de datos, entonces es necesario definirla, pero no se define en cualquier lado. Para ello es necesario escribir un poco de código.

Primero vamos al archivo de CodeBehind de la página default, Default.aspx.cs, y definiremos un método para realizar el procesamiento del evento SubreportProcessing del objeto LocalReport que ya hemos visto antes. Agregamos al inicio del archivo la siguiente directiva:

using Microsoft.Reporting.WebForms;

 

 

Y ahora escribimos el método:

protected static void
        
LocalReport_SubreportProcessing(object sender,
                                   SubreportProcessingEventArgs e)
{           

 

 

}

 

 

Este método nos servirá como manejador del evento donde diremos que fuente de datos debe usar el subreporte. Observen la estructura, debe ser igual a la mostrada. Ahora indicamos la fuente de datos:

protected static void 
         
LocalReport_SubreportProcessing (object sender,
                           SubreportProcessingEventArgs
e)
{
  
ObjectDataSource ObjectDataSource2 = new ObjectDataSource(“Report.Part1.DataSet2TableAdapters.Order_DetailsTableAdapter”, “GetData”);
  
e.DataSources.Add(new ReportDataSource 
                       (“DataSet2_Order_Details”

                         objectDataSource2));
}

 

 

Pero esto no es todo. Hay que indicarle al evento SubreportProcessing del objeto LocalReport que use ese método. Esto lo logramos agregando la siguiente línea de código al final del evento Page_Load:

ReportViewer1.LocalReport.SubreportProcessing += LocalReport_SubreportProcessing;

Luego de esto podemos ejecutar nuevamente la aplicación y veremos el siguiente resultado:

Subreport_final

Bien, espero les haya gustado y ojalá les sirva mucho para realizar tareas más complejas en sus aplicaciones.

Hasta la próxima.

8 Responses to “Construyendo Reportes Para Aplicaciones Web: Parte 3”

  • CEsar Cardenas says:

    Jose, he aprendido mucho acerca de los reportes con tus tutoriales y de verdad que estoy muy agradecido.
    En este momento tengo un reporte que me tira el “TimeOut Expired”. Te comento un poco:
    Este reporte esta creado en la version 2008 y utiliza una base de datos sql 2005. Lei en el MSDN que por default viene una opcion en los reportes de un tiempo maximo de 30 segundos pero no he encontrado con exito en donde cambiarlo, lo movi en el connection string pero no funciono.
    Espero me puedas echar una mano.
    Desde ya y por tu atencion muchisimas gracias

    • admin says:

      @Cesar, no tengo tu codigo para poder confirmar, pero si has seguido los ejemplos de los articulos, creo que hay una propiedad del ReportDataSource que te permite configurar el tiempo de TimeOut. Puedes verificar eso por favor?

      Saludos.
      Jose

  • Cesar De Azambuja says:

    Buenas yo tengo un problema con el ObjectData Source, el tema esq yo estoy trabajando con un proyecto y para tome de prueba una tabla simple pero al ejecutar me sale este mensaje “Error al procesar el informe.No se pudo encontrar el tipo especificado en la propiedad TypeName de ObjectDataSource ‘ObjectDataSource1’. ” pero eh creado un proyecto aparte nuevo donde ejecute ese mismo formulario de prueba y no tengo ningun problema me jala la informacion, quisiera saber como solucionarlo ya q el formulario es el mismo q esta en mi proyecto y en el proyecto nuevo pero en mi proyecto no levanta

    desde ya agradesco su ayuda saludos

  • Martin says:

    Tengo el mismo problema pero en windows forrm :

    el siguiente query donde va ? en un evento del reportviwer?

    protected static void
    LocalReport_SubreportProcessing (object sender,
    SubreportProcessingEventArgs e)
    {
    ObjectDataSource ObjectDataSource2 = new ObjectDataSource(“Report.Part1.DataSet2TableAdapters.Order_DetailsTableAdapter”, “GetData”);
    e.DataSources.Add(new ReportDataSource
    (“DataSet2_Order_Details”,
    objectDataSource2));
    }

  • admin says:

    @Martin:

    LocalSubrport_SubreportProcessing es un event handler para el evento SubreportProcessing del report viewer. Se declara en la misma forma donde tienes el report viewer y se ejecuta una vez por cada subreport que tengas definido en el reporte.

    Para informar al report viewer que use ese event handler debes hacer en el evento load de la forma (no recuerdo bien si ese es el evento en winforms):

    ReportViewer1.LocalReport.SubreportProcessing += LocalReport_SubreportProcessing;

    Saludos.
    Jose

  • Marcos says:

    Hola, vi todos tus articulos referente a este tea y de verdad que me sirvio de mucho la parte de paso de parametros con objectdatasource, pero ahora tengo un problema, ni en internet explorer, ni firefox ni Chrome me muestra el report viewer, queda en blanco el espacio, ni los botones superiores de la herramienta aparecen, cuando le coo “inspeccionar elemento” aparece el div marcado pero sin nada dentro, ya revise el visible true y todo y ya no se que mas hacer.

    • admin says:

      Hola Marcos.
      La verdad no se que decirte. Nunca habia visto un comportamiento asi. Creo que podrias empezar reinstalando el runtime del report viewer que puedes descargar de Microsoft. Luego verificar que en tu aplicacion estas usando la version correcta y que las referencias estan correctas.

      Saludos.
      Jose


Leave a Reply to admin Cancel reply

Your email address will not be published. Required fields are marked *