문제

I have a DataTable with multiple columns. If the value of certain column repeats, I need to remove that row and add the quantities against it. For example, following datatable

ITEM    QTY
------------
1       20
2       10
2       10
3       20

would become:

ITEM    QTY
-----------
1       20
2       20
3       20

This is what I did

var table = dt.AsEnumerable() 
.GroupBy(row => row.Field("ITEM")) 
.Select(group => group.First()) 
.CopyToDataTable();

It removes the extra row but doesn't add up the quantities. So please help me in this regard.

도움이 되었습니까?

해결책

You can use Sum. You just have to find the duplicate-rows first:

var dupGroups = dt.AsEnumerable()
    .GroupBy(row => row.Field<int>("ITEM"))
    .Where(g => g.Count() > 1);

Now you can use them to get the sum and to remove the redundant rows from the table.

foreach (var group in dupGroups)
{
    DataRow first = group.First();
    int sum = group.Sum(r => r.Field<int>("QTY"));
    first.SetField("QTY", sum);
    foreach (DataRow row in group.Skip(1))
        dt.Rows.Remove(row);
}

Or in one query which creates a new DataTable.

DataTable newTable = dt.AsEnumerable()
    .GroupBy(row => row.Field<int>("ITEM"))
    .Select(g => 
    {
        DataRow first = g.First();
        if (g.Count() > 1)
        {
            int sum = g.Sum(r => r.Field<int>("QTY"));
            first.SetField("QTY", sum);
        }
        return first;
    })
    .CopyToDataTable();

However, even the second approach modifies the original table which might be undesired since you use CopyToDatatable to create a new DataTable. You need to clone the original table(DataTable newTable = dt.Clone();) to get an empty table with the same schema. Then use NewRow + ItemArray.Clone() or table.ImportRow to create a real clone without modifying the original data.

See: C# simple way to copy or clone a DataRow?

Edit: Here is an example how you can create a clone without touching the original table:

DataTable newTable = dt.Clone();
var itemGroups = dt.AsEnumerable()
    .GroupBy(row => row.Field<int>("ITEM"));
foreach (var group in itemGroups)
{
    DataRow first = group.First();
    if (group.Count() == 1)
        newTable.ImportRow(first);
    else
    {
        DataRow clone = newTable.Rows.Add((object[])first.ItemArray.Clone());
        int qtySum = group.Sum(r => r.Field<int>("QTY"));
        clone.SetField("QTY", qtySum);
    }
}

다른 팁

var table = dt.AsEnumerable() 
    .GroupBy(row => row.Field<int>("ITEM")) 
    .Select(group => {
        var row = group.First();
        row['QTY'] = group.Sum(x => x.Field<int>('QTY'));
        return row;
    }).CopyToDataTable();

This won't change your original DataTable:

var table = dt.Copy().AsEnumerable()
                      .GroupBy(row=>row["ITEM"])
                      .Select(g=> {
                                DataRow dr = g.First();
                                dr.SetField("QTY", g.Sum(x=>x.Field<int>("QTY")));
                                return dr;
                             })
                      .CopyToDataTable();
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top