TIPS-Add Group-By And Sub-Total To DataGrid
0 |
EmpNo | Name | Expense |
001 | Jeffrey | 120 |
001 | Jeffrey | 256 |
001 | Jeffrey | 1,024 |
002 | Darkthread | 18 |
002 | Darkthread | 27 |
這是很常見的一項需求,題目很簡單,JOIN兩個Table得到的清單資料如上表,以DataGrid或GridView方式呈現,要怎麼Group By EmpNo並加上小計,變成以下的格式?
EmpNo | Name | CombExpense | ||
001 | Jeffrey | 120 256 1,024 | ||
| ||||
002 | Darkthread | 18 27 | ||
|
這個問題的解法有很多種。例如可以從Client-Side以Javascript操弄Table Object,隱去不想顯示的資料及加上TR;而我個人則偏好善用DataTable的豐富功能。
廢話不多說,請看Sample Code,說明則在註解中。
protected void Page_Load(object sender, EventArgs e)
{
//懶得建DB,直接用DataTable Object建資料源
DataTable origTbl = new DataTable();
origTbl.Columns.Add("EmpNo", typeof(string));
origTbl.Columns.Add("Name", typeof(string));
origTbl.Columns.Add("Expense", typeof(int));
origTbl.Rows.Add("001", "Jeffrey", 120);
origTbl.Rows.Add("001", "Jeffrey", 256);
origTbl.Rows.Add("001", "Jeffrey", 1024);
origTbl.Rows.Add("002", "Darkthread", 18);
origTbl.Rows.Add("002", "Darkthread", 27);
DataGrid1.DataSource = origTbl;
DataGrid1.DataBind();
//建立另一個加上加總的DataTable
//DataTable.Clone()可以只建Schema,不複製資料
DataTable sumTbl = origTbl.Clone();
//移去原本的費用欄
sumTbl.Columns.Remove("Expense");
//加上綜合整理過的費用欄,用字串格式
sumTbl.Columns.Add("CombExpense", typeof(string));
//加上配合增加小計列及排序用的PK欄位
sumTbl.Columns.Add("PK", typeof(string));
//加上主鍵值,方便查找
sumTbl.PrimaryKey =
new DataColumn[] { sumTbl.Columns["PK"] };
//用個Hashtable來計加總值(.NET 2.0可用Dictionary<string, int>)
Hashtable htSubTotal = new Hashtable();
foreach (DataRow row in origTbl.Rows)
{
string empNo = row["EmpNo"].ToString();
int exp = (int)row["Expense"];
string dispExp = string.Format("{0:#,###}", exp);
//Rows.Find(pkValues)可以快速找到某一筆資料
DataRow findRow = sumTbl.Rows.Find(empNo);
//資料已存在,用Append的
if (findRow != null)
{
findRow["CombExpense"] =
findRow["CombExpense"].ToString() + "<br />" + dispExp;
htSubTotal[empNo] = (int)htSubTotal[empNo] + exp;
}
else //否則新增一筆
{
sumTbl.Rows.Add(empNo, row["Name"], dispExp, empNo);
htSubTotal.Add(empNo, exp);
}
}
//加上小計欄
foreach (string empNo in htSubTotal.Keys)
sumTbl.Rows.Add("", "",
string.Format("<table width='100%'><tr>" +
"<td align='left'>SubTotal</td>" +
"<td align='rigt'>{0:#,###}</td></tr></table>",
htSubTotal[empNo]), empNo+"zSUM");
//要求Sort By PK,如此,小計會跟在各EmpNo資料下方
DataGrid2.DataSource =
new DataView(sumTbl, "", "PK", DataViewRowState.CurrentRows);
DataGrid2.DataBind();
}
Comments
Be the first to post a comment