But today I wanted to try to find a solution that was less work, where I could still use BoundFields. I found a good solution on Microsoft.com using the RowDataBound event. With this solution, you can still use BoundFields, but you have to add code to the function for each column that you want to sum up. I have a grid with over 60 columns (because we hide and show different ones for different scenarios) so I was really hoping to find some way where I didn't have to write code for each field.
So the solution I came up with is below, in C#. It's very similar to the Microsoft.com solution, but with a couple modifications. First, I'm using Hashtables again, two this time: one for the totals and one for the type of the field -- integer or currency. Second is the automatic check for whether a field is numeric or not, and if its is, what kind of number -- integer or currency. I check this simply by looking for the dollar sign in the text of the cell. Note that when parsing the text to number format, the System.Globalization.NumberStyles.Any parameter is very important because it handles characters like the $ and parentheses for negative numbers in accounting format.
One drawback of this method is that it will total every numeric field, including zip codes, for example. But it could be easily modified to either list specific columns to total or specific columns to exclude. One other drawback is that it doesn't work for percentage columns. You can't total up different percentage values anyway to get a percentage that is accurate for the total line, but at least with a TemplateField solution, you can divide the appropriate totals to get the correct percentage in the FooterTemplate.
Listing, in C#:
Hashtable total = new Hashtable();
Hashtable fieldType = new Hashtable();
protected void reportGrid_RowDataBound(object sender, GridViewRowEventArgs e)
{
int i;
double result;
string cellText;
if (e.Row.RowType == DataControlRowType.DataRow)
{
for (i = 0; i < e.Row.Cells.Count; i++)
{
cellText = e.Row.Cells[i].Text;
try
{
result = Double.Parse(cellText, System.Globalization.NumberStyles.Any);
// if this didn't go to the catch, then field was a number
// if it has a $ in it, save in Hashtable that it is currency field
// this code assumes that the field won't change type from row to row
if (cellText.Contains("$"))
{
fieldType[i] = "C";
}
else
{
fieldType[i] = "N0";
}
if (total.ContainsKey(i))
{
total[i] = double.Parse(total[i].ToString()) + result;
}
else
{
total[i] = result;
}
}
catch
{
// do nothing
}
}
}
else if (e.Row.RowType == DataControlRowType.Footer)
{
for (i = 0; i < e.Row.Cells.Count; i++)
{
// display the value of any Hashtable total field that has a key
if (total.ContainsKey(i))
{
e.Row.Cells[i].Text = String.Format("{0:" + fieldType[i].ToString() + "}", total[i]);
}
}
}
}

0 comments:
Post a Comment