2008-11-04 111 views
2

什么是枚举工作簿中每个工作表中每个单元格的最有效方法?使用c#在Excel工作簿中枚举单元格的高效方法

下面的方法似乎适用于工作簿约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工作簿的访问属性。

回答

2

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

您应该简单地通过阅读ValueValue2属性选择要解压,就像你与Worksheet.UsedRange财产做,然后阅读整个范围的值,一步到位,范围通过调用get_Value()(或只是,我不记得哪一个)。

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

编辑:我刚刚阅读你的实际代码,并意识到它实际上是我提出的。在回答之前,由于我没有正确地阅读问题而感到羞耻。在这种情况下,你不能更快。 Excel PIA Interop很慢。如果你需要更快的解决方案,你必须将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为空字符串无论如何。

1

我认为,这是最有效的方式,它怎么与PIA。 使用“foreach”代替“for”可能会更快,但它不会有戏剧性的变化。

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

2

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

+0

+1感谢您指向Koogra。这将在我的项目中派上用场。 – dcharles 2010-02-04 18:16:57

相关问题