You need to enable JavaScript to run this app. C# WinForm 导入CSV至DataGrid/DataTable前如何按ID与名称组合去重
优惠活动
大模型
产品
解决方案
定价
更多

C# WinForm 导入CSV至DataGrid/DataTable前如何按ID与名称组合去重

C# WinForm CSV导入双字段去重实现

业务需求说明

  • 原有CSV导入逻辑仅支持整行文本简单去重,无法满足实际业务规则
  • 去重判定规则:仅当记录的ID字段与名称字段同时完全匹配时,才判定为重复记录并移除
  • 保留规则:ID重复但名称不同、名称重复但ID不同的记录需全部保留,不可误删
  • 去重操作必须在数据写入DataTable、绑定DataGridView控件之前完成

原有实现的问题

  • 导入逻辑中使用Lines.Distinct()做整行去重,没有针对ID+名称双字段的匹配判断逻辑
  • 硬编码按逗号拆分行解析,未定位业务字段位置,无法适配列顺序变动的CSV文件

修正后的完整代码实现

using System;
using System.Collections.Generic;
using System.Data;
using System.IO;
using System.Linq;
using System.Windows.Forms;

namespace Export_Import_CSV
{
    public partial class Form1 : Form
    {
        // 全局DataTable存储导入数据
        private readonly DataTable dt = new DataTable();

        public Form1()
        {
            InitializeComponent();
            // 初始化DataTable结构
            BindDataGridView();
        }

        /// <summary>
        /// 初始化DataTable列结构
        /// </summary>
        private void BindDataGridView()
        {
            // 根据实际CSV列定义,此处示例为ID、Name及其他业务列
            dt.Columns.Add("ID", typeof(string));
            dt.Columns.Add("Name", typeof(string));
            // 可按需补充其他业务列
        }

        /// <summary>
        /// 导入按钮点击事件
        /// </summary>
        private void ImportBtn_Click(object sender, EventArgs e)
        {
            dt.Rows.Clear();
            OpenFileDialog dlg = new OpenFileDialog();
            dlg.Multiselect = false;
            dlg.Filter = "CSV文件(*.csv)|*.csv";
            if (DialogResult.OK == dlg.ShowDialog())
            {
                string path = dlg.FileName;
                ImportCsvWithDedup(path);
                MessageBox.Show("导入流程执行完成");
            }
        }

        /// <summary>
        /// 带ID+名称双字段去重的CSV导入方法
        /// </summary>
        /// <param name="filePath">CSV文件路径</param>
        private void ImportCsvWithDedup(string filePath)
        {
            // 读取所有非空行
            string[] allLines = File.ReadAllLines(filePath)
                .Where(line => !string.IsNullOrWhiteSpace(line))
                .ToArray();

            // 校验文件行数
            if (allLines.Length < 2)
            {
                MessageBox.Show("CSV文件中无有效数据行");
                return;
            }

            // 解析表头,定位ID、Name列的索引
            string[] headerCells = allLines[0].Split(',');
            int idColIndex = Array.FindIndex(headerCells, cell => cell.Trim().Equals("ID", StringComparison.OrdinalIgnoreCase));
            int nameColIndex = Array.FindIndex(headerCells, cell => cell.Trim().Equals("Name", StringComparison.OrdinalIgnoreCase));

            // 校验必需列是否存在
            if (idColIndex == -1 || nameColIndex == -1)
            {
                MessageBox.Show("CSV文件缺少ID或Name列,无法执行去重校验");
                return;
            }

            // 存储已出现的ID+名称组合,用于快速去重
            HashSet<string> existedCombos = new HashSet<string>();
            int filteredDuplicateCount = 0;

            // 从第二行开始遍历数据行
            for (int i = 1; i < allLines.Length; i++)
            {
                string[] rowCells = allLines[i].Split(',');
                // 跳过列数不足的异常行
                if (rowCells.Length <= Math.Max(idColIndex, nameColIndex))
                {
                    continue;
                }

                string idValue = rowCells[idColIndex].Trim();
                string nameValue = rowCells[nameColIndex].Trim();
                // 生成双字段唯一匹配键
                string uniqueKey = $"{idValue}|{nameValue}";

                // 判断是否为重复行
                if (!existedCombos.Add(uniqueKey))
                {
                    filteredDuplicateCount++;
                    continue;
                }

                // 非重复行写入DataTable
                DataRow dr = dt.NewRow();
                for (int colIndex = 0; colIndex < dt.Columns.Count; colIndex++)
                {
                    dr[colIndex] = colIndex < rowCells.Length ? rowCells[colIndex] : string.Empty;
                }
                dt.Rows.Add(dr);
            }

            // 绑定数据到DataGridView
            dataGridView1.DataSource = dt;

            // 提示去重结果
            if (filteredDuplicateCount > 0)
            {
                MessageBox.Show($"导入完成,共过滤{filteredDuplicateCount}条ID与名称同时匹配的重复记录");
            }
        }
    }
}

实现效果说明

  • 严格匹配去重规则:仅ID、名称双值同时一致的记录会被过滤,单字段重复的记录全部保留
  • 性能优化:使用HashSet存储唯一组合,整体遍历时间复杂度为O(n),适配大体积CSV文件导入场景
  • 异常兼容:对列缺失、行格式不规范的情况做了校验,避免程序运行异常崩溃

内容的提问来源于stack exchange,提问作者Divya Shree

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.11.08 07:36:04