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; } }