如何使用C#优化Excel中每行的循环?

时间:2018-04-04 12:38:54

标签: c# excel

我的Excel工作表中有大约6000行和600列。有一个ID列,如果ID相等,我会突出显示所有单元格中的差异值。但是我的代码花了很长时间才能遍历每一行并突出显示。我的代码如何优化?

 private void worker_DoWork(object sender, System.ComponentModel.DoWorkEventArgs e)
{
    for (r = 2; r <= totalRow; r++)
    {
        Duplicate();
        int percentage = (r + 1) * 100 / totalRow;
        worker.ReportProgress(percentage);
    }             
}

private void Duplicate()
{
    if (xlWorksheet.Cells[r, ssid].Value == xlWorksheet.Cells[r + 1, ssid].Value)
    {
        for (int c = 1; c <= columnCount; c++)
        {
            if (Convert.ToString(xlWorksheet.Cells[r, c].Value) != Convert.ToString(xlWorksheet.Cells[r + 1, c].Value))
            {
                Excel.Range cellRange = (Excel.Range)xlWorksheet.Cells[r + 1, c];
                cellRange.Interior.Color = Excel.XlRgbColor.rgbRed;
            }
        }
    }
}

2 个答案:

答案 0 :(得分:3)

读取和写入excel会使程序变慢。尽量避免阅读和不必要的写作:

  • 读取Excel文件一次,并将其值写入二维矩阵,其中包含维度行和列;
  • 循环遍历矩阵并检查值。对于3.6M,它会很快;
  • 将结果记录在另一个二维布尔矩阵中。
  • 循环通过booelan矩阵,只写在你需要写的单元格上;
  • 您甚至可以做更好的事情 - 循环遍历布尔矩阵并将相应的单元格分配到Union()的范围。最后,只更改一次范围的颜色。

遵循以上几点(没有最后一点),这是一个基本的开始:

enter image description here

这是一个基本的结束,考虑到我们的任务是为每一行着色相同的单元格(这个任务可以很容易地改变):

enter image description here

这是代码:

using System;
using Excel = Microsoft.Office.Interop.Excel;

class StartUp
{
    static void Main()
    {
        string filePath = @"C:\Sample.xlsx";

        int rowsCount = 5;
        int colsCount = 6;

        Excel.Application excel = new Excel.Application();
        excel.Visible = false; 
        excel.EnableAnimations = false;

        Excel.Workbook wkb = Open(excel, filePath);
        Excel.Worksheet wk = (Excel.Worksheet)excel.Worksheets.get_Item(1);

        Excel.Range startCell = wk.Cells[1, 1];
        Excel.Range endCell = wk.Cells[rowsCount, colsCount];
        Excel.Range currentRange = wk.get_Range(startCell, endCell).Cells;
        currentRange.Interior.Color = Excel.XlRgbColor.rgbWhite;

        object[,]  matrixRead = (object[,])currentRange.Value;
        bool[,] matrixResult = new bool[rowsCount+1,colsCount+1];

        for (int rows = 1; rows <= rowsCount; rows++)
        {
            for (int cols = 1; cols < colsCount; cols++)
            {
                if (matrixRead[rows,cols].ToString()==matrixRead[rows,cols+1].ToString())
                {
                    matrixResult[rows, cols] = true;
                    matrixResult[rows, cols + 1] = true;
                }
            }
        }

        for (int rows = 1; rows <= rowsCount; rows++)
        {
            for (int cols = 1; cols <= colsCount; cols++)
            {
                if (matrixResult[rows, cols])
                {
                    currentRange.Cells[rows, cols].interior.color = 
                                                Excel.XlRgbColor.rgbRed;
                }                
            }
        }

        excel.EnableAnimations = true;
        wkb.Close(true);
        excel.Quit();
        Console.WriteLine("Finished!");
    }

    private static Excel.Workbook Open(Excel.Application excelInstance, 
            string fileName, bool readOnly = false, 
            bool editable = true, bool updateLinks = true)
    {
        Excel.Workbook book = excelInstance.Workbooks.Open(
            fileName, updateLinks, readOnly,
            Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing,
            Type.Missing, editable, Type.Missing, Type.Missing, Type.Missing,
            Type.Missing, Type.Missing);
        return book;
    }
}

大约95%的速度(或更多的3.6M单元)可能来自这两行:

excel.Visible = false; 
excel.EnableAnimations = false;

一般来说,可以避免两对嵌套循环,并且很容易将它们组成一对 - 就像这样:

for (int rows = 1; rows <= rowsCount; rows++)
{
    for (int cols = 1; cols < colsCount; cols++)
    {
        if (matrixRead[rows,cols].ToString()==matrixRead[rows,cols+1].ToString())
        {
            currentRange.Cells[rows, cols].interior.color = Excel.XlRgbColor.rgbRed;
            currentRange.Cells[rows, cols+1].interior.color = Excel.XlRgbColor.rgbRed;
        }
    }
}

但是我的想法是通过Union()将matrixResult呈现为一个范围,并立即更新整个范围的背景。因此,第二对嵌套循环不应该存在,而应该是这样的:currentRange.Interior.Color = Excel.XlRgbColor.rgbRed

答案 1 :(得分:-1)

尝试读取数据集中的整个excel文件。 然后你可以使用下面的代码来

基本示例:

DataSet ResultDataSet= new DataSet();
DataTable customers = myDataset.Tables.Add("Customers");
customers.Columns.Add("Name");
customers.Columns.Add("Age");
customers.Rows.Add("Chris", "25");
int records=10;   // split the  10 records per table. if 50 records will be there then 5 tables will generate.

var splittedTables = ResultDataSet.AsEnumerable()
                                .Select((row, index) => new { row, index })
                                .GroupBy(x => x.index / records)
                                .Select(g => g.Select(x => x.row).CopyToDataTable())
                                .ToArray();

尝试这可以快速比较foreach声明。