using System.Data;
public static class DataTableExtensionMethods
{
public static DataTable TransposeIntegerColumnIntoColumns(this DataTable dt, int indexColumnToEstablishDuplicateRows, int integerColumnIdToTranspose, string transposedColumnName)
{
//Protection if the column to transpose is not an integer or doesn't exist
if (integerColumnIdToTranspose >= dt.Columns.Count) return null;
var columnDataType = dt.Columns[integerColumnIdToTranspose].DataType;
if (columnDataType != typeof(int)) return null;
//Get max sessions number
int maxColumnNumber = 0;
foreach (DataRow dr in dt.Rows)
{
int? number = dr.Field<int?>(integerColumnIdToTranspose);
if (number != null)
{
maxColumnNumber = Math.Max(maxColumnNumber, (int)number);
}
}
//Protection if there are zero rows or the maxColumnNumber is 0
if (dt.Rows.Count == 0 || maxColumnNumber == 0) return null;
//Make a copy of the table so we can remove duplicate rows and add the transposed columns
DataTable result = dt.Copy();
//Add columns to store the session_ids
for (int i = 1; i <= maxColumnNumber; i++)
{
DataColumn dc = new DataColumn(transposedColumnName + i.ToString(), typeof(int));
dc.DefaultValue = 0;
//Possibly make an overloaded method that supports inserting columns
result.Columns.Add(dc);
}
//Remove rows with duplicated employees
for (int i = 0; i < result.Rows.Count; i++)
{
int duplicateRow = GetRowIndexById(result, indexColumnToEstablishDuplicateRows, result.Rows[i][indexColumnToEstablishDuplicateRows].ToString(), i + 1);
if (duplicateRow > -1)
{
result.Rows.RemoveAt(duplicateRow);
}
}
//Populate the transposed columns with values in the integer Column To Transpose
foreach (DataRow dr in dt.Rows)
{
int? sessionNumber = dr.Field<int?>(integerColumnIdToTranspose);
if (sessionNumber == null) continue;
int rowIndex = GetRowIndexById(result, indexColumnToEstablishDuplicateRows, dr[indexColumnToEstablishDuplicateRows].ToString(), 0);
result.Rows[rowIndex][transposedColumnName + sessionNumber.ToString()] = 1; //or +=1 if you want to increment the number
}
//Remove the integerColumnIdToTranspose (again overload this method if you want to keep this column)
result.Columns.RemoveAt(integerColumnIdToTranspose);
return result;
}
//Net 4 implementation with optional parameter
//private static int GetRowIndexById(DataTable dt, int indexColumnToEstablishDuplicateRows, string id, int startLookAtRow = 0)
private static int GetRowIndexById(DataTable dt, int indexColumnToEstablishDuplicateRows, string id, int startLookAtRow)
{
for (int i = startLookAtRow; i < dt.Rows.Count; i++)
{
if (dt.Rows[i][indexColumnToEstablishDuplicateRows].ToString() == id) return i;
}
return -1;
}
}
調用代碼:
private void button1_Click(object sender, EventArgs e)
{
DataTable dt = GetData();
DataTable result = dt.TransposeIntegerColumnIntoColumns(0, 3, "session_id");
}
private DataTable GetData()
{
DataTable dt = new DataTable();
dt.Columns.Add("emp_num", typeof(int));
dt.Columns.Add("name");
dt.Columns.Add("status", typeof(int));
dt.Columns.Add("session_id", typeof(int));
DataRow dr = dt.NewRow();
dr["emp_num"] = 22;
dr["name"] = "John";
dr["status"] = 0;
dr["session_id"] = 4;
dt.Rows.Add(dr);
dr = dt.NewRow();
dr["emp_num"] = 22;
dr["name"] = "John";
dr["status"] = 0;
dr["session_id"] = 5;
dt.Rows.Add(dr);
dr = dt.NewRow();
dr["emp_num"] = 34;
dr["name"] = "Moh";
dr["status"] = 1;
//dr["session_id"] = null;
dt.Rows.Add(dr);
dr = dt.NewRow();
dr["emp_num"] = 35;
dr["name"] = "Ran";
dr["status"] = 0;
dr["session_id"] = 3;
dt.Rows.Add(dr);
dr = dt.NewRow();
dr["emp_num"] = 35;
dr["name"] = "Ran";
dr["status"] = 0;
dr["session_id"] = 4;
dt.Rows.Add(dr);
return dt;
}
結果是:
我覺得有一些根本性的錯誤你的方法。如果您的員工和會話之間存在一對多關係,則需要有兩個表。一張僱員表,每個員工有一行,另一個表用於會話,每個會話有一行。每個會話記錄都應該有一個「emp_num」來將其鏈接回員工。 – Keith 2014-11-06 16:22:23
@Keith:是啊,有兩個表,我讓兩個表之間的連接和設置的結果datatable.now,我想與 以下結構'emp_num名狀態session_id1 session_id2 session_id3 ...'的數量的報告列取決於session_id值 – 2014-11-09 07:18:12