数据去重:通过 C# 删除 Excel 中的重复行

发布时间:2026/7/5 16:19:52
数据去重:通过 C# 删除 Excel 中的重复行 实现思路删除重复行的核心逻辑如下指定关键列确定用于判断重复的列例如第一列 A 列。分组识别遍历数据区域根据关键列的值对每一行进行分组。标记重复行在每个分组中保留第一次出现的行索引最小将其余行的行号记录下来。安全删除按照行号从大到小的顺序删除这些重复行避免因删除操作导致的索引错位。详细步骤解析1. 安装免费库在编写代码之前通过 NuGet 安装所需的免费库Install-Package FreeSpire.XLS或者在 Visual Studio 的“管理 NuGet 程序包”中搜索FreeSpire.XLS并安装。注意免费版提供了大部分基础功能足以应对中小规模数据的处理需求。2. 加载工作簿和工作表using Spire.Xls; using System.Linq; // 创建 Workbook 实例并加载文档 Workbook workbook new Workbook(); workbook.LoadFromFile(Test.xlsx); // 获取第一个工作表 Worksheet sheet workbook.Worksheets[0];3. 确定数据范围为了仅对实际存在数据的行进行操作我们使用工作表的LastRow属性获取最后有效行号并构造一个从 A1 到 A 列最后一行的范围例如A1:A100。实际使用时可以根据需要调整起始行例如跳过标题行。// 假设数据从第1行开始以 A 列作为判重依据 string rangeAddress $A1:A{sheet.LastRow}; var range sheet.Range[rangeAddress];4. 找出需要删除的重复行号利用 LINQ 对范围内的每一行进行分组。DisplayedText属性返回单元格在 Excel 界面上的显示文本会考虑格式、公式计算结果等相比直接使用Value或Text更为可靠。var duplicatedRows range.Rows .GroupBy(row row.Columns[0].DisplayedText) // 按第一列的显示文本分组 .Where(group group.Count() 1) // 只筛选存在重复的分组 .SelectMany(group group.Skip(1)) // 跳过每组的第一行保留行取其余重复行 .Select(row row.Columns[0].Row) // 获取这些行的行号 .ToList();Range.Rows返回范围内的所有行对象。GroupBy根据 A 列的显示文本对行进行分组。Skip(1)忽略每个分组中的第一行即保留的那一行。最终得到Listint其中包含所有待删除行的行号升序排列。5. 删除重复行关键点如果直接按照升序的行号顺序删除会导致后续行号发生偏移。正确的做法是从后往前删除这样可以保证每次删除时行号仍然准确。// 将行号降序排列然后逐个删除 foreach (int rowNum in duplicatedRows.OrderByDescending(r r)) { sheet.DeleteRow(rowNum); }也可以使用索引修正法sheet.DeleteRow(duplicatedRows[i] - i)两种方法效果相同但从后往前删除的逻辑更为直观。6. 保存结果workbook.SaveToFile(RemoveDuplicateRows.xlsx, ExcelVersion.Version2016);默认保存为.xlsx格式也可以指定为.xls或其他 Excel 版本。完整代码示例将以上步骤整合为一个完整的控制台应用程序包含资源释放建议using Spire.Xls; using System.Linq; namespace RemoveDuplicateRows { class Program { static void Main(string[] args) { // 使用 using 语句确保资源被正确释放 using (Workbook workbook new Workbook()) { // 加载文档 workbook.LoadFromFile(Test.xlsx); // 获取第一个工作表 Worksheet sheet workbook.Worksheets[0]; // 定义判重范围A列从第1行到最后有效行 var range sheet.Range[$A1:A{sheet.LastRow}]; // 获取需要删除的重复行号 var duplicatedRows range.Rows .GroupBy(x x.Columns[0].DisplayedText) .Where(x x.Count() 1) .SelectMany(x x.Skip(1)) .Select(x x.Columns[0].Row) .ToList(); // 从后向前删除重复行避免索引错乱 foreach (int rowNum in duplicatedRows.OrderByDescending(r r)) { sheet.DeleteRow(rowNum); } // 保存结果 workbook.SaveToFile(RemoveDuplicateRows.xlsx); } } } }关键点与注意事项1. 判断重复的依据列上面的代码仅基于 A 列进行判重。如果需要根据多列组合例如 A 列和 B 列同时相同才算重复只需修改GroupBy的键.GroupBy(row new { Col1 row.Columns[0].DisplayedText, Col2 row.Columns[1].DisplayedText })2. 保留表头标题行如果第一行是标题行不应参与重复判断和删除。只需将范围的起始行改为第 2 行var range sheet.Range[$A2:A{sheet.LastRow}];同时LastRow属性会自动包含最后一行数据因此标题行不受影响。删除重复行后表头行将保持不变。3.DisplayedText与Value的区别属性说明推荐场景DisplayedText返回单元格在 Excel 界面上显示的内容考虑了数字格式、日期格式、公式等业务上的重复判断推荐Value返回原始值公式计算结果但可能忽略显示格式需要精确原始值的场景在简单文本情况下两者结果一致但推荐使用DisplayedText以避免因格式差异导致的误判。4. 内存与资源释放Workbook类实现了IDisposable接口强烈建议使用using语句或手动调用Dispose()方法以避免内存泄漏尤其是在处理大型文件时。