枚举工作簿中每个工作表中每个单元格的最有效方法是什么?
对于具有~130,000个单元格的工作簿,下面的方法似乎合理地工作。在我的机器上打开文件大约需要26秒,枚举单元需要大约5秒钟。但是,我不是Excel专家,并希望与更广泛的社区验证此代码段。
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文件的API公开的excel工作簿的属性。
答案 0 :(得分:2)
Excel PIA Interop在您逐个进行操作时非常慢。
您应该选择要提取的范围,就像使用Worksheet.UsedRange
属性一样,然后通过调用get_Value()
(或只是通过阅读)一步读取整个范围的值<{1}}或Value
属性,我记不起哪个属性了。
这将产生一个Value2
,即一个二维数组,可以很容易地枚举,并且可以快速读取。
编辑:我刚刚阅读了您的实际代码,并意识到它实际上是我提出的建议。在回答之前没有正确阅读问题让我感到羞耻。在这种情况下,你不能让它更快。 Excel PIA Interop很慢。如果您需要更快的解决方案,则必须将jExcelApi从Java迁移到C#(这不是一件非常困难的事情)或使用一些商业组件。我建议不惜一切代价避免使用OLEDB接口,以保持理智。
无关,但有用的提示:你应该使用??运营商。这真的很方便。而不是
object[,]
你可以写
data = rangeData[iRow, iCol] != null ? rangeData[iRow, iCol].ToString() : string.Empty;
在这种情况下,即使是String.Empty也不是必需的,因为Convert.ToString(object)无论如何都会将data = Convert.ToString(rangeData[iRow, iCol]) ?? string.Empty;
转换为空字符串。
答案 1 :(得分:2)
有一个名为Koogra的Excel阅读器和编写器的开源实现。它允许您读取excel文件并使用纯托管代码进行修改。 这可能比你现在使用的代码快得多。
答案 2 :(得分:1)
我认为,这是最有效的方式,PIA如何做到这一点。 使用“forach”的“forach”可能会更快,但它不会发生戏剧性的变化。
如果效率是您的主要目标,您应该直接使用excel文件 - 无需excel应用程序。