Interop Excel运行缓慢



我正在编写一个应用程序来打开Excel工作表并读取

MyApp = new Excel.Application();
MyBook = MyApp.Workbooks.Open(filename);
MySheet = (Excel.Worksheet)MyBook.Sheets[1]; // Explict cast is not required here
lastRow = MySheet.Cells.SpecialCells(Excel.XlCellType.xlCellTypeLastCell).Row;
MyApp.Visible = false;

这大约需要6-7秒,这在interop Excel中正常吗?

还有比这更快的读取Excel的方法吗?

string[] xx = new string[lastRow];
for (int index = 1; index <= lastRow; index++)
{
   int maxCol = endCol - startCol;
   for (int j = 1; j <= maxCol; j++)
   {
      try
      {
         xx[index - 1] += (MySheet.Cells[index, j] as Excel.Range).Value2.ToString();
      }
      catch
      {    
      }
      if (j != maxCol) xx[index - 1] += "|";
   }
}
MyApp.Quit();
System.Runtime.InteropServices.Marshal.ReleaseComObject(MySheet);
System.Runtime.InteropServices.Marshal.ReleaseComObject(MyBook);
System.Runtime.InteropServices.Marshal.ReleaseComObject(MyApp);

附加@RvdK的答案-是的COM互操作很慢。

为什么它很慢

这是由于它的工作原理。从.NET发出的每个调用都必须封送至本地COM代理。从那里,它必须从一个进程(您的应用程序)封送至COM服务器(Excel)(通过Windows内核内的IPC),然后从服务器的本地代理转换(调度)为本机代码,在本机代码中,参数从OLE Automation兼容类型封送为本机类型,检查它们的有效性并执行该功能。函数的结果通过两个不同过程之间的几个层以大致相同的方式返回。

因此,每一个命令的执行成本都很高,执行的命令越多,整个过程就越慢。你可以在网上找到很多文档,因为COM是一个古老且运行良好的标准(在某种程度上与Visual Basic 6一起消亡)。

此类文章的一个例子如下:http://www.codeproject.com/Articles/990/Understanding-Classic-COM-Interoperability-With-NE

有没有更快的阅读方式

  1. ClosedXML可以使用Microsoft的OpenXml SDK读取和写入Excel xlsx文件(甚至公式、格式等),请参阅此处:https://closedxml.codeplex.com/wikipage?title=Finding%20and%20extracting%20the%20data&referringTitle=文档

  2. Excel数据读取器声称可以读取旧的和新的Excel数据文件,我自己没有尝试过,请看这里:https://exceldatareader.codeplex.com/

  3. 另一种更快读取数据的方法是使用Excel自动化将工作表转换为您可以轻松理解的数据文件,并在没有互操作层的情况下进行批处理(例如XML、CSV)。这个答案显示了如何做到

简短回答:正确,interop很慢。(有同样的问题,读取300行需要几秒钟…

为此使用库:

  • http://epplus.codeplex.com/
  • http://npoi.codeplex.com/

这个答案只是关于问题的第二部分。你在那里使用了很多范围,这并不是预期的,而且确实非常缓慢。

首先读取完整的范围,然后像这样迭代结果:

var xx[,] = (MySheet.Cells["A1", "XX100"] as Excel.Range).Value2;
for (int i=0;i<xx.getLength(0);i++)
{
    for (int j=0;j<xx.getLength(1);j++)
    {
         Console.WriteLine(xx[i,j].toString());
    }
}

这会快得多!

您可以使用这个免费的库,xls&支持xlsx,

Workbook wb = new Workbook();
wb.LoadFromFile(ofd.FileName);

https://freenetexcel.codeplex.com/

最新更新