使用c#枚举Excel工作簿中的单元格的有效方法

枚举工作簿中每个工作表中的每个单元格的最有效方法是什么?

下面的方法似乎适用于约130,000个单元的工作簿。 在我的机器上,打开文件需要约26秒,枚举单元约需5秒钟。 不过,我不是Excel专家,想要validation这个代码片段与更广泛的社区。

DateTime timer = DateTime.Now; Microsoft.Office.Interop.Excel.Application excelApplication = new Microsoft.Office.Interop.Excel.Application(); try { exampleFile = new FileInfo(Path.Combine(System.Environment.CurrentDirectory, "Large.xlsx")); excelApplication.Workbooks.Open(exampleFile.FullName, false, false, missing, missing, missing, true, missing, missing, true, missing, missing, missing, missing, missing); Console.WriteLine(string.Format("Took {0} seconds to open file", (DateTime.Now - timer).Seconds.ToString())); timer = DateTime.Now; foreach(Workbook workbook in excelApplication.Workbooks) { foreach(Worksheet sheet in workbook.Sheets) { int i = 0, iRowMax, iColMax; string data = String.Empty; Object[,] rangeData = (System.Object[,]) sheet.UsedRange.Cells.get_Value(missing); if (rangeData != null) { iRowMax = rangeData.GetUpperBound(0); iColMax = rangeData.GetUpperBound(1); for (int iRow = 1; iRow < iRowMax; iRow++) { for(int iCol = 1; iCol < iColMax; iCol++) { data = rangeData[iRow, iCol] != null ? rangeData[iRow, iCol].ToString() : string.Empty; if (i % 100 == 0) { Console.WriteLine(String.Format("Processed {0} cells.", i)); } i++; } } } } workbook.Close(false, missing, missing); } Console.WriteLine(string.Format("Took {0} seconds to parse file", (DateTime.Now - timer).Seconds.ToString())); } finally { excelApplication.Workbooks.Close(); excelApplication.Quit(); } 

编辑

值得说明的是,我想使用PIA和interop来访问excel工作簿的属性,而这些属性并不是直接与Excel文件一起工作的API公开的。

Excel PIA Interop在逐个细胞处理时非常慢。

你应该select你想要提取的范围,就像你对Worksheet.UsedRange属性所做的那样,然后通过调用get_Value()来读取整个范围的值(或者只是通过读取ValueValue2属性,I不记得哪一个)就可以了。

这将产生一个object[,] ,也就是一个二维数组,它可以很容易枚举并且很快被读取。

编辑 :我刚刚阅读你的实际代码,并意识到它实际上是我所build议的。 在回答之前,对我没有正确地阅读问题感到羞耻。 在这种情况下,你不能做得更快。 Excel PIA Interop很慢。 如果你需要一个更快的解决scheme,你将不得不从Java迁移jExcelApi到C#(不是一件非常困难的事情)或使用一些商业组件。 我build议不惜一切代价避免OLEDB接口,以保持您的理智。

无关,但有用的提示:你应该使用?? 运营商。 这真的很方便。 代替

 data = rangeData[iRow, iCol] != null ? rangeData[iRow, iCol].ToString() : string.Empty; 

你可以写

 data = Convert.ToString(rangeData[iRow, iCol]) ?? string.Empty; 

在这种情况下,即使String.Empty也不是必需的,因为Convert.ToString(object)无论如何都将null转换为空string。

有一个名为Koogra的Excel读者和作者的开源实现。 它允许你读取excel文件并使用纯托pipe代码进行修改。 这可能会比现在使用的代码快得多。

我认为,这是最有效的方式,与PIA是如何做到的。 用“foreach”代替“for”可能会更快,但不会有太大的变化。

如果效率是您的主要目标,那么您应该直接使用excel文件 – 无需使用excel应用程序。

有关使用C#.Net和VB .Net的每个循环枚举器(使用Excel表单的Foreach ADO.NET架构行集枚举器)和编程集成服务(SSIS)的更多信息,请访问以下链接: http://www.sqllion。 COM / 2009/06 /编程-的foreach -环-容器- %E2%80%93-列举-Excel的张/