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