EmpNoNameExpense
001Jeffrey120
001Jeffrey256
001Jeffrey1,024
002Darkthread18
002Darkthread27

這是很常見的一項需求,題目很簡單,JOIN兩個Table得到的清單資料如上表,以DataGrid或GridView方式呈現,要怎麼Group By EmpNo並加上小計,變成以下的格式?

EmpNoNameCombExpense
001Jeffrey120
256
1,024
  
SubTotal1,400
002Darkthread18
27
  
SubTotal45

這個問題的解法有很多種。例如可以從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

Post a comment