1. 程式人生 > >C#中DataTable行轉列示例

C#中DataTable行轉列示例

將下面表(1)格式的資料轉換為表(2)格式的資料。很明顯,這是一個行轉列的要求,本想在資料庫中行轉列,因為在資料庫中行轉列是比較簡單的,方法可以參考本站SQLServer中(行列轉換)行轉列及列轉行且加平均值及彙總值,但因其它需求,最終需將該轉化搬到C#中進行了。

(表1)

 

表(2)

 

不多說了,下面開始在DataTable行轉列示例:

//DataTable行轉列

private DataTable RCC(DataTable _outDataSource)

{

    //從DataTable中讀取不重複的日期行,用來構造新DataTable的列

    DataTable distinct_date = _outDataSource.DefaultView.ToTable(true, "日期");

    DataTable new_DataTable = new DataTable();

    //將客戶名稱列新增到新表中

    DataColumn new_d_col = new DataColumn();

    new_d_col.ColumnName = "客戶名稱";

    new_d_col.Caption = "";

    new_DataTable.Columns.Add(new_d_col);

    StringBuilder str_sum = new StringBuilder();

    //開始在新表中構造日期列

    foreach (DataRow dr in distinct_date.Rows)

    {

        new_d_col = new DataColumn();

        new_d_col.DataType = typeof(decimal);

        new_d_col.ColumnName = dr["日期"].ToString();

        new_d_col.Caption = dr["日期"].ToString();

        new_d_col.DefaultValue = 0;

        new_DataTable.Columns.Add(new_d_col);

        //這個的目的是為合計列構造expression

        str_sum.Append("+[").Append("日期").Append("]");

    }

    //將合計列新增到新表中

    new_d_col = new DataColumn();

    new_d_col.DataType = typeof(decimal);

    new_d_col.ColumnName = "Sum";

    new_d_col.Caption = "合計";

    new_d_col.DefaultValue = 0;

    new_d_col.Expression = str_sum.ToString().substring(1);

    new_DataTable.Columns.Add(new_d_col);

    /*好了,到此新表已經構建完畢,下面開始為新表新增資料*/

    //從原DataTable中讀出不重複的客戶名稱,以客戶名稱為關鍵字來構造新表的行

    DataTable distinct_object = _outDataSource.DefaultView.ToTable(true, "客戶名稱");

    DataRow[] drs;

    DataRow new_dr;

    foreach (DataRow dr in distinct_object.Rows)

    {

        new_dr = new_DataTable.NewRow();

        new_dr["客戶名稱"] = dr["客戶名稱"].ToString();

        foreach (DataRow _dr in distinct_date.Rows)

        {

            drs = _outDataSource.Select("客戶名稱='" + dr["客戶名稱"].ToString() + "' and 日期='" + _dr["日期"].ToString() + "'");

            if (drs.Length != 0)

            {

                new_dr[_dr["日期"].ToString()] = Math.Round(Convert.ToDecimal(drs[0]["金額"]), 2);

            }

        }

        new_DataTable.Rows.Add(new_dr);

    }

     return new_DataTable;

}

從上面的程式碼中看到我們並沒有為新表"合計"這一列賦值,這是因為該列具有表示式str_sum.Append("+[").Append("日期").Append("]"),所以這列的值是會自動填充的。

注意,在上面的表示式中,我們加了[],在DataTable的表示式中,如果列名是中文,一定要為列名加上[],要不然會報錯的,這也是我除錯了好久才發現的。

public DataTable RowsToCol(DataTable DT) {        try         {                         int  rowCount=DT.Rows.Count;                       int  columnsCount=DT.Columns.Count;                       DataTable result=new DataTable();                       DataTable RowsDT=new DataTable();                       DataTable COLSDT=new DataTable();                       for(int i=0;i<RowCount;i++)                       {                               result.Columns.Add(DT.Rows[i][1].ToString());                               RowsDT.Columns.Add(DT.Rows[i][1].ToString());                               COLsDT.Columns.Add(DT.Rows[i][1].ToString());                       }                       string[] RowsName=new string[columnsCount];                       for(int i=0;i<columnsCount;i++)                       {                                                  RowsName[i]=DT.Columns[i].ColumnName.Tostring();                       }                       for(int rowsi=0;rowsi<RowsName.Length;rowsi)                       {                       RowsDT.Rows.Add(new string[] {RowsName[rowsi]});                       }                       //行轉列的核心部分                       for(int columnsi=0;columnsi<columnsCount;columnsi++)                       {                            DataRow dr=COLsDT.NewRow();                            for(int rowj=0;rowj<rowCount;rowj++)                            {                                   dr[rowj]=DT.Rows[rowj][columnsi].toString();                            }                            COLsDT.Rows.Add(dr);                       }                                     for(int columnsi=0;columnsi<columnsCount;columnsi++)              {                  DataRow resultdr=result.NewRow();                  for(int rowj=0;rowj<rowCount;rowj++)                  {                     if(rowj==0)                      {                        resultdr[rowj]=RowsDT.Rows[columnsi][0].ToString();                      }                      else                      {                       resultdr[rowj]=ColsDT.Rows[columnsi][rowj].ToString();                       }                   }                  result.Rows.Add(resultdr);             }                          return   result;        }        catch(Exception ex)        {             throw new Exception(ex.ToString());        } }

要轉的DataTable結構如下圖: privateDataTableConvertDataTable(DataTable dtSrc) { try { DataTable dt =newDataTable(); dt.Columns.Add("姓名"); varcolumns = (frompindtSrc.Rows.Cast<DataRow>()selectp[1].ToString()).Distinct(); foreach(varitemincolumns) dt.Columns.Add(item); vardata =fromkinsource.Rows.Cast<DataRow>() groupkbyk[0]intom selectnew{ Key = m.Key.ToString(), Items = m }; data.ToList().ForEach(n => { string[] array =newstring[dt.Columns.Count]; array[0] = n.Key; for(inti =1; i < dt.Columns.Count; i++) array[i] = (frompinn.Items wherep[1].ToString() == dt.Columns[i].ToString() selectp[2].ToString()) .SingleOrDefault(); dt.Rows.Add(array); }); returndt; } catch { returnnull; } }