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).
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.
Arrastramos ahora los campos ProductID, Quantity y UnitPrice a cada uno de los campos en la tabla de la siguiente forma:
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).
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.
Para la definición del filtro, es necesario indicar que el valor para el campo OrderID debe ser igual al del parámetro NoOrden.
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:
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:
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:
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”.
Ahora podemos ejecutar el reporte para ver el resultado de todo lo que hemos hecho:
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:
Bien, espero les haya gustado y ojalá les sirva mucho para realizar tareas más complejas en sus aplicaciones.
Hasta la próxima.