【发布时间】:2017-02-09 14:02:17
【问题描述】:
我是编码新手并尝试检查电子表格中的重复行。电子表格有 50 列,除两列外,每一列都必须进行比较。如果行重复,则将它们合并为一行,并将 REQNUM 和 AUTHNUM 列中的金额相加。我发现的大多数示例都使用“字段(”列名“)”。由于列的数量很大,我想使用一个变量来排除我在比较中不需要的两个。
示例:
前。点代表更多列
COL1|COL2|COL3|...|REQNUM|AUTHNUM
:-----: | :-----: | :----: |...| :------------: | :-----------: |....
x |是 | z |...| 1 | 1
x |是 | z |...| 2 | 3
之后
COL1|COL2|COL3|...|REQNUM|AUTHNUM
-------- | ------ | ------ | ...|------------ | ------------|....
x |是 | z |...| 3 | 4
这是我拥有的代码,它看起来很接近但不太正确。我期待一个只有重复行的结果,所以稍后我可以通过一个 foreach 运行它,它将求和并删除额外的行。 dtrow 得到我想要的列。(感谢Linq Excluding a column)。当我尝试在查询中使用这个变量时,我没有得到任何结果,如果我删除“g.Count() > 1”,我会得到所有行,它们缺少两列。我想将所有两列保留在结果中,以后不必再添加。
var dtRow = dtExcel.Columns.Cast<DataColumn>().Where(c => c.ColumnName != "REQNUM" && c.ColumnName != "AUTHNUM").ToList();
var checkExcel = dtExcel.Rows.Cast<DataRow>()
.GroupBy(x => dtRow.Select(c => x[c]))
.Where(g => g.Count() > 1)
.Select(gr => gr);
//.CopyToDataTable();
感谢肯的帮助。这非常适合我需要的东西。我使用了 groupby 子句,因此我可以将重复项合并为一行并添加数字字段。还可以通过创建我在 IF 语句中使用的键进行分组。
var dtRow = dtExcel.Columns.Cast<DataColumn>().Where(c => c.ColumnName != "REQNUM" && c.ColumnName != "AUTHNUM").ToList();
var excelDup = dtExcel.Rows.Cast<DataRow>()
.GroupBy(x => String.Join("", dtRow.Select(c => x[c])))
.Select(g =>
{
var row = g.First();
row.SetField("REQNUM", g.Sum(x => x.Field<double>("REQNUM")));
row.SetField("AUTHNUM", g.Sum(x => x.Field<double>("AUTHNUM")));
return row;
})
.CopyToDataTable();
我还使用 where 子句为数据行比较创建了一个变量,并且不需要键。 //使用除三之外的所有列创建变量。在下一个查询中使用 var dtExcelRow = dtExcel.Columns .Cast().Where(c => c.ColumnName != "TITLE" && c.ColumnName != "REQSTR" && c.ColumnName != "AUTHSTR").ToList(); var dtListRow = dtList.Columns .Cast().Where(c => c.ColumnName != "TITLE" && c.ColumnName != "REQSTR" && c.ColumnName != "AUTHSTR").ToList();
// Querys create datarow list for compare
IEnumerable<DataRow> eRow = dtExcel.AsEnumerable()
.Where(w => dtExcelRow.Select(c => w[c]).Any())
.Select(x => x);
IEnumerable<DataRow> lRow = dtList.AsEnumerable()
.Where(w => dtListRow.Select(c => w[c]).Any())
.Select(x => x);
// 1st compare gets list of new records that have changes or are new. 2nd is list of old records being change.
var newRecords = eRow.AsEnumerable().Except(lRow.AsEnumerable(), DataRowComparer.Default);
var oldRecords = lRow.AsEnumerable().Except(eRow.AsEnumerable(), DataRowComparer.Default);
【问题讨论】:
-
感谢 Ken,这是我想出的,它非常适合我的需要。
-
var dtRow = dtExcel.Columns.Cast
().Where(c => c.ColumnName != "REQNUM" && c.ColumnName != "AUTHNUM").ToList(); var excelDup = dtExcel.Rows.Cast () .GroupBy(x => String.Join("", dtRow.Select(c => x[c]))) .Select(g => { var row = g.First(); row.SetField("REQSTR", g.Sum(x => x.Field ("REQSTR"))); row.SetField("AUTHNUM", g.Sum(x => x.Field ("AUTHNUM"))); 返回行; }).CopyToDataTable();
标签: c# excel linq datatable duplicates