miércoles, 3 de agosto de 2011

Agrupaciones y totales en el control RadGrid de Telerik

Hoy en el trabajo hemos tenido que lidiar con el RadGrid de Telerik,. Llevamos ya bastante tiempo utilizándola y todavía hoy hay un tema que no tenía excesivamente claro, hablo de las agrupaciones y totales en la grilla.

Mi intención con este post es que perdure en el tiempo como referencia rápida para que, cuando vuelva a tener una crisis de identidad con este control, pueda visitar mi propia entrada y calmar mis ánimos.

Vamos a partir de una tabla sencilla que nos sirva para todos nuestros ejemplos, es un tabla de pedidos pendientes de servir a cliente con los siguientes campos:

CustomerID

Código de cliente

OrderID

Id de pedido

OrderLineID

Id de línea de pedido

ProductID

Id de producto

Units

Unidades

Price

Precio


CREATE TABLE [dbo].[MyOpenOrders](      

                [CustomerID] [nvarchar](20) NOT NULL,

                [OrderID] [nvarchar](20) NOT NULL,

                [OrderLineID] [nvarchar](50) NOT NULL,

                [ProductID] [nvarchar](20) NOT NULL,

                [Units] [int] NOT NULL,

                [Price] [decimal](18, 2) NOT NULL

 CONSTRAINT [PK_MyOpenOrders] PRIMARY KEY CLUSTERED

(

                [CustomerID] ASC,

                [OrderID] ASC,

                [OrderLineID] ASC,

                [ProductID] ASC

)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]

) ON [PRIMARY]

A continuación, algunas filas de ejemplo para tener datos de muestra:

INSERT [dbo].[MyOpenOrders] VALUES (N'1', N'1', N'1', N'1', 5, CAST(2.50 AS Decimal(18, 2)))

INSERT [dbo].[MyOpenOrders] VALUES (N'1', N'1', N'10', N'10', 10, CAST(4.87 AS Decimal(18, 2)))

INSERT [dbo].[MyOpenOrders] VALUES (N'1', N'1', N'11', N'11', 3, CAST(1.00 AS Decimal(18, 2)))

INSERT [dbo].[MyOpenOrders] VALUES (N'1', N'1', N'12', N'12', 2, CAST(3.51 AS Decimal(18, 2)))

INSERT [dbo].[MyOpenOrders] VALUES (N'1', N'1', N'2', N'2', 7, CAST(3.60 AS Decimal(18, 2)))

INSERT [dbo].[MyOpenOrders] VALUES (N'1', N'1', N'3', N'3', 2, CAST(3.00 AS Decimal(18, 2)))

INSERT [dbo].[MyOpenOrders] VALUES (N'1', N'1', N'4', N'4', 6, CAST(6.89 AS Decimal(18, 2)))

INSERT [dbo].[MyOpenOrders] VALUES (N'1', N'1', N'5', N'5', 7, CAST(0.56 AS Decimal(18, 2)))

INSERT [dbo].[MyOpenOrders] VALUES (N'1', N'1', N'6', N'6', 1, CAST(6.23 AS Decimal(18, 2)))

INSERT [dbo].[MyOpenOrders] VALUES (N'1', N'1', N'7', N'7', 4, CAST(9.47 AS Decimal(18, 2)))

INSERT [dbo].[MyOpenOrders] VALUES (N'1', N'1', N'8', N'8', 8, CAST(1.65 AS Decimal(18, 2)))

INSERT [dbo].[MyOpenOrders] VALUES (N'1', N'1', N'9', N'9', 9, CAST(3.78 AS Decimal(18, 2)))

INSERT [dbo].[MyOpenOrders] VALUES (N'1', N'2', N'1', N'1', 8, CAST(2.50 AS Decimal(18, 2)))

INSERT [dbo].[MyOpenOrders] VALUES (N'1', N'2', N'2', N'2', 7, CAST(3.60 AS Decimal(18, 2)))

Nuestro primer RadGrid será el que se muestra a continuación

    <telerik:RadGrid ID="RadGrid1" runat="server" AutoGenerateColumns="False" DataSourceID="SqlDataSource1" GridLines="None" AllowPaging="true">

        <MasterTableView DataSourceID="SqlDataSource1">

            <RowIndicatorColumn>

                <HeaderStyle Width="20px"></HeaderStyle>

            </RowIndicatorColumn>

            <ExpandCollapseColumn>

                <HeaderStyle Width="20px"></HeaderStyle>

            </ExpandCollapseColumn>

            <Columns>

                <telerik:GridBoundColumn DataField="CustomerID" HeaderText="CustomerID" ReadOnly="True"

                    SortExpression="CustomerID" UniqueName="CustomerID">

                </telerik:GridBoundColumn>

                <telerik:GridBoundColumn DataField="OrderID" HeaderText="OrderID" ReadOnly="True"

                    SortExpression="OrderID" UniqueName="OrderID">

                </telerik:GridBoundColumn>

                <telerik:GridBoundColumn DataField="OrderLineID" HeaderText="OrderLineID" ReadOnly="True"

                    SortExpression="OrderLineID" UniqueName="OrderLineID">

                </telerik:GridBoundColumn>

                <telerik:GridBoundColumn DataField="ProductID" HeaderText="ProductID" ReadOnly="True"

                    SortExpression="ProductID" UniqueName="ProductID">

                </telerik:GridBoundColumn>

                <telerik:GridBoundColumn DataField="Units" DataType="System.Int32" HeaderText="Units"

                    SortExpression="Units" UniqueName="Units">

                </telerik:GridBoundColumn>

                <telerik:GridBoundColumn DataField="Price" DataType="System.Decimal" HeaderText="Price"

                    SortExpression="Price" UniqueName="Price">

                </telerik:GridBoundColumn>

            </Columns>

        </MasterTableView>

    </telerik:RadGrid>

 

clip_image001

Nada nuevo que no sepamos ya hacer con el RadGrid.

Ahora y a partir de aquí, vamos a ver las capacidades de agrupación y cálculo de totales y subtotales que tiene la rejilla.

Lo que queremos hacer es lo siguiente:

1.       Sumar en el pie de la rejilla, tanto unidades como precio.

2.       Agrupar por OrderID, y tener un sumatorio tanto del pedido agrupado como también de todos los pedidos, todo ello en unidades y en precio.

Para incluir sumatorios en el pie de página, lo que hay que hacer es lo siguiente:

·         Agregar ShowFooter="true" en MasterTableView.

·         Agregar Aggregate="Sum" y FooterAggregateFormatString="{0:C2}" por cada GridBoundColumn que intervenga en el sumatorio.

<MasterTableView DataSourceID="SqlDataSource1" ShowFooter="true">

 

                <telerik:GridBoundColumn DataField="Units" DataType="System.Int32" HeaderText="Units" SortExpression="Units" UniqueName="Units"
Aggregate="Sum" FooterAggregateFormatString="{0:#,##0}"
>

                </telerik:GridBoundColumn>

                <telerik:GridBoundColumn DataField="Price" DataType="System.Decimal" HeaderText="Price" SortExpression="Price" UniqueName="Price"
Aggregate="Sum" FooterAggregateFormatString="{0:C2}"
>

                </telerik:GridBoundColumn>

 

Ahora nuestro RadGrid suma correctamente en el pie, tanto unidades como precio, y además esta suma es para todo el conjunto de resultados, no sólo para la página activa.

clip_image002

clip_image003

Nuestro siguiente paso será agrupar por OrderID y tener un sumatorio tanto del pedido agrupado como también de todos los pedidos. Antes de continuar te diré que el pedido 1 tiene 63 unidades y un valor de 47,06 €. Para lograr esta agrupación haremos lo siguiente:

·         Agregar ShowGroupFooter="true" en MasterTableView.

·         Agregar una expresión de agrupación con GridGroupByExpression.

<MasterTableView DataSourceID="SqlDataSource1" ShowFooter="true" ShowGroupFooter="true">

 

            <GroupByExpressions>

                <telerik:GridGroupByExpression>

                    <GroupByFields>

                       <telerik:GridGroupByField FieldName="OrderID" SortOrder="Ascending" />

                    </GroupByFields>

                    <SelectFields>

                        <telerik:GridGroupByField FieldName="OrderID" />

                    </SelectFields>

                </telerik:GridGroupByExpression>

            </GroupByExpressions>

 

El resultado es el siguiente:

clip_image004

clip_image005

Si nos fijamos, el sumatorio de grupo del pedido 2 es correcto porque todas las líneas del pedido están en la misma página del RadGrid. Sin embargo, el pedido 1 nos muestra el valor de las líneas que hay en cada página, no el total de todas las líneas. Así, por ejemplo, para la página 1 nos da 47 unidades y para la página 2 nos da 17 unidades, que sumadas dan 63 unidades, pero… en ningún sitio podemos ver esto, así que el total de grupo no parece ser muy acertado.

El porqué de esto no pretendo averiguarlo, pero simplemente te informo de cómo funciona el total de grupo, que quizás podrían haber llamado “total de grupo por página”.

Aun así nosotros somos muy cabezones y queremos dar al usuario el total de unidades del pedido 1 por pantalla (sin que importe la paginación). Para lograrlo hay que hacer lo siguiente:

·         Agregar 2 nuevos GridGroupByField en SelectFields.

<telerik:GridGroupByField FieldName="OrderID"/>

<telerik:GridGroupByField FieldName="Units" FieldAlias="Unidades" Aggregate="Sum" />

<telerik:GridGroupByField FieldName="Price" FieldAlias="Precio" Aggregate="Sum" />

 

Finalmente, ahora ya podemos ver la suma total del pedido, tanto en unidades como en precio. El lugar donde aparecerán estos valores no será en el pie de grupo, sino en el encabezado de grupo (que si toma en cuenta para el cálculo de agregado todos los elementos del origen de datos).

clip_image006

Otras propiedades del RadGrid que podrían resultarte útiles durante la agrupación son:

RetainGroupFootresVisibility, indica si los pies de grupo tienen que ser visibles aun cuando el usuario colapse el grupo. Por defecto, no son visibles, es False

<GroupingSettings RetainGroupFootersVisibility="true" />


GroupsDefaultExpanded (en MasterTableView), indica si los grupos tienen que estar expandidos o colapsados por defecto. Por defecto están expandidos, es True.
GroupsDefaultExpanded="true"

FooterText (en GridBoundColumn), permite escribir un texto literal en el pie de la columna, luego puede servirnos para etiquetar el gran total que aparece en la rejilla en el pie. Por ejemplo, si agregamos el texto “Total global” en la columna ProductID:

clip_image007

Espero que después de esto, ya sepamos todos, agrupar y mostrar totales en un RadGrid de forma más efectiva.

Un saludo!

3 comentarios:

  1. Hola , solo una pregunta es posible condicionar la sumatoria?
    por ejemplo que solo sume cuando los Units sean mayor a 1??

    saludos

    ResponderEliminar