我的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;
}
}
}
}
答案 0 :(得分:3)
读取和写入excel会使程序变慢。尽量避免阅读和不必要的写作:
Union()
的范围。最后,只更改一次范围的颜色。遵循以上几点(没有最后一点),这是一个基本的开始:
这是一个基本的结束,考虑到我们的任务是为每一行着色相同的单元格(这个任务可以很容易地改变):
这是代码:
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声明。