2

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

下面的方法似乎适用于具有约 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 和互操作来访问直接使用 Excel 文件的 API 未公开的 Excel 工作簿的属性。

4

3 回答 3

2

当您逐个单元格地做事时,Excel PIA Interop 真的很慢。

您应该选择要提取的范围,就像您对属性所做的那样,然后通过调用(或仅通过读取or属性,我不记得是哪一个)Worksheet.UsedRange一步读取整个范围的值它。get_Value()ValueValue2

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

编辑:我刚刚阅读了您的实际代码,并意识到它实际上符合我的建议。为在回答之前没有正确阅读问题而感到羞耻。在这种情况下,你不能让它更快。Excel PIA 互操作速度很慢。如果您需要更快的解决方案,您将不得不将 jExcelApi 从 Java 迁移到 C#(这不是一件非常困难的事情)或使用一些商业组件。我建议不惜一切代价避免使用 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为空字符串。

于 2008-11-04T10:11:51.300 回答
2

有一个名为Koogra的 Excel 读取器和写入器的开源实现。它允许您读取 excel 文件并使用纯托管代码对其进行修改。这可能比您现在使用的代码快得多。

于 2008-11-04T10:57:50.707 回答
1

我认为,这是最有效的方法,如何使用 PIA。使用“foreach”代替“for”可能会快一点,但不会发生巨大变化。

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

于 2008-11-04T10:37:56.660 回答