用 C# 轻松删除 Excel 里的重复行
你是不是也经常遇到这种烦心事:打开一个 Excel 表格,里面乱七八糟一大堆,光重复的数据就占了一半?无论是做数据清洗、出报表,还是搞分析,去重几乎是逃不掉的“必修课”。今天咱就聊聊怎么用 Free Spire.XLS for .NET 这个免费组件(不用装 Office ),几行 C# 代码就把重复行安排得明明白白。
实现思路
先理清楚核心逻辑,弄懂原理再写代码会更轻松:
- 选好关键列——比如按 A 列的值判断是否重复。
- 遍历数据,把相同值的行归到一组。
- 每组里只留第一行(索引最小的),其他的统统记下来。
- 从后往前删掉这些“多余”的行,避免删着删着索引乱套。
简单说:分组→保留第一个→删后面的。
准备工作
打开你的项目,在 NuGet 里搜一下 FreeSpire.XLS 这个包并安装,或直接使用:
Install-Package FreeSpire.XLS
这款免费组件足以应对绝大多数中小型项目的数据处理需求。
分步代码解析
下面咱们一步步拆解代码,边写边理解。假设本地有一份 Test.xlsx 文件,A 列存在大量重复数据,我们要保留首次出现的行,删掉后续所有重复行。
1. 加载文件,拿到工作表
using Spire.Xls;
using System.Linq;
Workbook workbook = new Workbook();
workbook.LoadFromFile("Test.xlsx");
Worksheet sheet = workbook.Worksheets[0];
2. 确定数据范围
用 sheet.LastRow 拿到最后有数据的行,构造一个从 A1 到 A 列末尾的范围。如果你想跳过表头,把 A1 改成 A2 就行。
var range = sheet.Range[$"A1:A{sheet.LastRow}"];
3. 找出需要删除的重复行号
用 LINQ 极简实现分组筛选,省去手写循环的繁琐。
这里特意提一句:优先用 DisplayedText,它能拿到单元格最终展示效果,适配格式、公式计算值,比单纯取 Value 靠谱得多,能避免很多莫名的判重错误。
var duplicatedRows = range.Rows
.GroupBy(row => row.Columns[0].DisplayedText) // 按 A 列显示的内容分组
.Where(group => group.Count() > 1) // 只要有重复的分组
.SelectMany(group => group.Skip(1)) // 跳过每组第一个,剩下的就是要删的
.Select(row => row.Columns[0].Row) // 取出这些行的行号
.ToList();
简单梳理下这段代码的逻辑:按单元格内容分组后,只保留有重复的组,每组跳过第一条,剩下的就是我们要删掉的行。
4. 删除重复行
直接按行号正着删,后面的行号会变,容易删错。所以咱们从后往前删,或者动态调整索引。下面两种写法都可以:
方式一:倒序删(推荐,易懂)
foreach (int rowNum in duplicatedRows.OrderByDescending(r => r))
{
sheet.DeleteRow(rowNum);
}
方式二:循环里减 i
for (int i = 0; i < duplicatedRows.Count; i++)
{
sheet.DeleteRow(duplicatedRows[i] - i);
}
5. 保存结果
处理完成后,直接导出新文件,还能自由指定 Excel 版本格式:
workbook.SaveToFile("RemoveDuplicateRows.xlsx");
完整代码示例
整合所有步骤,直接复制到控制台项目就能运行测试:
using Spire.Xls;
using System.Linq;
namespace RemoveDuplicateRows
{
class Program
{
static void Main(string[] args)
{
Workbook workbook = new Workbook();
workbook.LoadFromFile("Test.xlsx");
Worksheet sheet = workbook.Worksheets[0];
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");
}
}
}
几个你可能关心的小细节
想按多列判断重复?改一下 GroupBy 就行
比如 A 列和 B 列都相同才算重复:
.GroupBy(row => new {
Col1 = row.Columns[0].DisplayedText,
Col2 = row.Columns[1].DisplayedText
})
第一行是表头,不想删它?
那就从 A2 开始取范围:
var range = sheet.Range[$"A2:A{sheet.LastRow}"];
别忘了释放资源
Workbook 实例使用完后,建议手动释放资源,或者用 using 语句包裹,避免程序长时间运行造成内存堆积。
using (Workbook workbook = new Workbook())
{
// 你的代码
}
整体看下来,这套方案上手简单、适配性强,既能满足单列、多列去重,也能适配带表头的业务表格。把这段代码稍作封装,就能直接用到日常数据自动化、后台报表生成等场景里,省去大量手动处理表格的重复工作。
更多推荐

所有评论(0)