ASP.NET Repeater - Summary totals
Generic approach to adding summary totals to an ASP.NET Repeater control.
Introduction
This is my first article, hope I'm doing it correct, I don't want to bore you with too much talk, so it's pretty much code, hope it suffices. I wanted a simple and& sort of generic approach to add summary totals to the footer record of a data repeater.
Background
My need was for a datatable that gets bound to a
Repeater
, plain and simple, with a summary total for the amount and count columns for every report I had to do. The table is a report coming straight from SQL Server via my backend.
Using the code
I have added all the code into this one file, so you can just copy it into any ASP.NET project and just run it.
- First we need a private variable to hold the summary totals for the fields in the table that need to be summarized.
- The next bit of code is purely to add sample data into the datatable. The data for the actual report will obviously come from your data source.
#region - This code belong in your backend - // In my framework this method is a static in a DbHelper class private void addDataColumn(DataTable table, string colName, string colType, bool colNull, object colDefault) { DataColumn column = new DataColumn(); column.DataType = System.Type.GetType(colType); column.ColumnName = colName; column.AllowDBNull = colNull; column.DefaultValue = colDefault; table.Columns.Add(column); } // Here we create the sample data for this report private DataTable createDataTable() { // This is your variable that will hold the report data DataTable dtData = new DataTable(); addDataColumn(dtData, "RecordId", "System.Int32", false, 0); addDataColumn(dtData, "Description", "System.String", false, 0); addDataColumn(dtData, "TotalCount", "System.Int32", false, 0); addDataColumn(dtData, "TotalAmount", "System.Decimal", false, 0); // Fill Table with data for (int i = 1; i < 6; ++i) { DataRow dr = dtData.NewRow(); dr["RecordId"] = i; dr["Description"] = "Description for row " + i; dr["TotalCount"] = i; dr["TotalAmount"] = i * 3.34m; dtData.Rows.Add(dr); } dtData.AcceptChanges(); return dtData; } #endregion
- The next method is the generic part that loops the table and summarize the fields that you've added in a dictionary. Again, I've added this method to a static helper class because you can then re-use it.
// I have this method in a static helper class private void sumDataTable(DataTable dt, Dictionary<string, decimal> totals) { List<string> keyList = new List<string>(totals.Keys); for (int i = 0; i < dt.Rows.Count; ++i) { foreach (string key in keyList) { totals[key] += Convert.ToDecimal(dt.Rows[i][key]); } } }
- Now we have the source code specifically to the report form, starting with the page load.
protected void Page_Load(object sender, EventArgs e) { bindTableToForm(); }
and then in my bind region, we have:
- Create and get the sample data.
- Add the columns that needs to be totaled into the
Dictionary<fieldName, startvalue>
. - Bind your data.
#region - Bind Methods - private void bindTableToForm() { // This is your variable that will hold the report data DataTable dtReport = createDataTable(); // Do Total columns totals.Add("TotalCount", 0); totals.Add("TotalAmount", 0); sumDataTable(dtReport, totals); // rprData.DataSource = dtReport; rprData.DataBind(); } #endregion
- We need to add a protected / public method to the page for the
Repeater
to access the summary totals in the dictionary.#region - Public methods - protected string getTotalFor(string field, string formatString) { decimal value = 0; totals.TryGetValue(field, out value); return value.ToString(formatString); } #endregion
- And finally the ASP.NET HTML code:
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="RepeaterSummaryTotal.aspx.cs" Inherits="IQ.Web.RepeaterSummaryTotal" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head runat="server"> <title></title> </head> <body> <form id="form1" runat="server"> <div> <div id="reportResults"> <br /> <asp:Repeater ID="rprData" runat="server"> <HeaderTemplate> <table id="tblData""> <thead> <tr> <th colspan="4"> Report sample </th> </tr> <tr> <td> Id. </td> <td> Description </td> <td style="text-align:right"> Total count </td> <td style="text-align:right"> Total amount </td> </tr> </thead> </HeaderTemplate> <ItemTemplate> <tr class="even"> <td> <%# Eval("RecordId")%> </td> <td> <%# Eval("Description")%> </td> <td style="text-align:right"> <%# Eval("TotalCount")%> </td> <td style="text-align:right"> <%#String.Format("{0:C}", Eval("TotalAmount"))%> </td> </tr> </ItemTemplate> <AlternatingItemTemplate> <tr class="odd"> <td> <%# Eval("RecordId")%> </td> <td> <%# Eval("Description")%> </td> <td style="text-align:right"> <%# Eval("TotalCount")%> </td> <td style="text-align:right"> <%#String.Format("{0:C}", Eval("TotalAmount"))%> </td> </tr> </AlternatingItemTemplate> <FooterTemplate> <tr class="subHeadingTr" style="font-weight:bold; background-color: #e8e8e8;"> <td colspan="2"> Totals </td> <td style="text-align:right"> <%# getTotalFor("TotalCount","")%> </td> <td style="text-align:right"> <%# getTotalFor("TotalAmount","C")%> </td> </tr> </table> </FooterTemplate> </asp:Repeater> </div> </div> </form> </body> </html>
#region - Private variables -
// This will be a list of all the fields that needs to be totalled - Dictionary<fieldName, totalValue>
private Dictionary<string, decimal> totals = new Dictionary<string, decimal>();
#endregion