简体   繁体   中英

How to change a DataTable structure so columns values are in multiple columns?

If i have a datatable with structure like that :

emp_num name  status  session_id

  22    john     0       4

  22    john     0       5

  34    moh      1       3

  35    Ran      0       3

  35    Ran      0       4

How to convert it to datatable like that :

emp_num name  status  session_id1  session_id2  session_id3  session_id4 session_id5 

  22    john     0       0             0               0            1          1

  34    moh      1       0             0               1            0          0   

  35    Ran      0       0             0               1            1          0

I try to create custom data table with looping but it's not generic ,I want something so generic so if i add more columns or the number of sessions increased i get no out of range exceptions ..

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

Calling code:

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

The result is:

在此处输入图片说明

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM