You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何优化C#中对比Excel两列的嵌套For循环以缩短执行时间

优化Excel数据对比代码的几种方法

你的代码慢主要有两个核心问题:一是嵌套循环带来的O(n*m)时间复杂度,数据量上来后计算量直接爆炸;二是频繁读写Excel单元格,每次和Excel的COM交互都属于跨进程操作,效率极低。下面是具体的优化方案:

1. 一次性把数据读入内存数组,减少Excel交互

不要每次循环都去访问ws5.Cells[i,3].Value,这种反复跨进程调用是拖慢速度的关键。先把两个工作表的UsedRange数据一次性读取到内存二维数组里,后续所有对比逻辑都在内存中完成:

// 读取ws5全部数据到内存数组
object[,] ws5Data = ws5.UsedRange.Value;
int ws5RowCount = ws5.UsedRange.Rows.Count;
// 读取ws6全部数据到内存数组
object[,] ws6Data = ws6.UsedRange.Value;
int ws6RowCount = ws6.UsedRange.Rows.Count;

2. 用哈希表建立索引,替换嵌套循环

把ws6的第2列(匹配键)和对应的第3列数值、行号存入Dictionary,这样遍历ws5时直接通过键查找匹配项,把嵌套循环的O(n*m)时间复杂度降到O(n+m):

// 键:第2列的字符串值,值:存储第3列数值+对应行号的列表
Dictionary<string, List<(double Col3Value, int RowNum)>> ws6Index = new Dictionary<string, List<(double, int)>>();

// 遍历ws6数据构建索引(注意Excel行从2开始,对应数组索引是1,因为数组从0起始)
for (int n = 2; n <= ws6RowCount; n++)
{
    string col2Str = Convert.ToString(ws6Data[n, 2]);
    double col3Val = Convert.ToDouble(ws6Data[n, 3]);
    
    if (!ws6Index.ContainsKey(col2Str))
    {
        ws6Index[col2Str] = new List<(double, int)>();
    }
    ws6Index[col2Str].Add((col3Val, n));
}

3. 批量更新Excel,避免逐个单元格操作

先在内存中记录需要修改的单元格信息(颜色、数值),最后一次性写入Excel,大幅减少和Excel的交互次数。同时关闭Excel的实时刷新和事件触发,进一步提升速度:

// 关闭Excel屏幕更新和事件触发,临时禁用界面刷新
ws5.Application.ScreenUpdating = false;
ws5.Application.EnableEvents = false;

// 遍历ws5数据做对比
for (int i = 2; i <= ws5RowCount; i++)
{
    string ws5Col2Str = Convert.ToString(ws5Data[i, 2]);
    double ws5Col3Val = Convert.ToDouble(ws5Data[i, 3]);
    
    if (ws6Index.TryGetValue(ws5Col2Str, out var matches))
    {
        foreach (var match in matches)
        {
            if (match.Col3Value == ws5Col3Val)
            {
                // 标记橙色
                ws5.Cells[i, 2].Interior.Color = System.Drawing.ColorTranslator.ToOle(System.Drawing.Color.Orange);
                ws5.Cells[i, 3].Interior.Color = System.Drawing.ColorTranslator.ToOle(System.Drawing.Color.Orange);
                ws6.Cells[match.RowNum, 2].Interior.Color = System.Drawing.ColorTranslator.ToOle(System.Drawing.Color.Orange);
                ws6.Cells[match.RowNum, 3].Interior.Color = System.Drawing.ColorTranslator.ToOle(System.Drawing.Color.Orange);
            }
            else
            {
                // 计算差值并写入
                double diff = match.Col3Value - ws5Col3Val;
                ws5.Cells[i, 4].Value = diff;
                ws6.Cells[match.RowNum, 4].Value = -diff;
                
                // 标记黄色
                ws5.Cells[i, 2].Interior.Color = System.Drawing.ColorTranslator.ToOle(System.Drawing.Color.Yellow);
                ws5.Cells[i, 3].Interior.Color = System.Drawing.ColorTranslator.ToOle(System.Drawing.Color.Yellow);
                ws6.Cells[match.RowNum, 2].Interior.Color = System.Drawing.ColorTranslator.ToOle(System.Drawing.Color.Yellow);
                ws6.Cells[match.RowNum, 3].Interior.Color = System.Drawing.ColorTranslator.ToOle(System.Drawing.Color.Yellow);
            }
        }
    }
    // 进度条只在外层循环更新,避免频繁刷新
    progressBar1.Value = (100 * (i - 1)) / (ws5RowCount - 1);
}

// 恢复Excel的屏幕更新和事件触发
ws5.Application.ScreenUpdating = true;
ws5.Application.EnableEvents = true;

额外优化细节

  • 提前转换数据:把需要用到的列数据提前转换为字符串/数值,避免循环中重复执行转换操作
  • 唯一值优化:如果ws6的第2列是唯一值,Dictionary的值可以不用列表,直接存储单个元组,进一步提升查找效率
  • 批量格式设置:如果需要标记的行很多,可以先收集行号范围,再一次性设置整行/整列的格式,比逐个单元格设置更快

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.14 00:05:40