在具有多个列的数据表中查找重复项,但两个

时间:2016-09-30 22:20:44

标签: c# excel linq datatable duplicates

我是新编码并尝试检查电子表格中的重复行。电子表格有50列,除了两列外,每列都要进行比较。如果行是重复的,它会将它们组合成一行,并且REQNUM和AUTHNUM列中的金额将相加。我找到的大多数样本使用" Field("列名")"。由于列数量很大,我想使用一个变量来排除比较中我不需要的两个。

例:
之前。点代表更多列
COL1 | COL2 | COL3 | ... | REQNUM | AUTHNUM
:-----:| :-----:| :----:| ... | :----------:| :-----------:| ....
  x | y | z | ... | 1 | 1
  x | y | z | ... | 2 | 3个

之后 COL1 | COL2 | COL3 | ... | REQNUM | AUTHNUM
------- | ------ | ------ | ... | ------------ | ------------ | ....
  x | y | 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();

感谢Ken的帮助。这对我需要的东西很有用。我使用了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子句为datarow compare创建变量,不需要密钥。                 //创建除三个以外的所有列的变量。它用于下一个查询                 var dtExcelRow = dtExcel.Columns                     .Cast()。其中​​(c =&gt; c.ColumnName!=&#34; TITLE&#34;&amp;&amp; c.ColumnName!=&#34; REQSTR&#34;&amp;&amp; c.ColumnName!= &#34; AUTHSTR&#34;。)ToList();                 var dtListRow = dtList.Columns                     .Cast()。其中​​(c =&gt; c.ColumnName!=&#34; TITLE&#34;&amp;&amp; c.ColumnName!=&#34; REQSTR&#34;&amp;&amp; c.ColumnName!= &#34; AUTHSTR&#34;。)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);

1 个答案:

答案 0 :(得分:0)

您不能只按dtRow.Select(c => x[c])对数据进行分组,因为它是IEnumerable,它们可能具有相同的内容,但它们仍然不同IEnumerable

如果它们是string,您可以按联接字符串对数据进行分组:

x => String.Join("", dtRow.Select(c => x[c]))