2012-01-29 137 views
1

我開始寫一個小包裝類來把我的Excel操作的護理:爲什麼搜索多張表很慢?

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using Excel = Microsoft.Office.Interop.Excel; 
using System.Reflection; 

namespace CSVReader 
{ 
    class ExcelManager 
    { 
     // Holds instance of application. 
     public Excel.Application application; 

     /** 
     * Class Constructor. 
     */ 
     public ExcelManager() 
     { 
      // Create a new application instance. 
      application = new Excel.Application(); 
     } 

     /** 
     * Helper to open workbooks. 
     */ 
     public void Open(string filename) { 
      application.Workbooks.Open(filename, Type.Missing, Type.Missing, Type.Missing, Type.Missing, 
               Type.Missing, Type.Missing, Type.Missing, Type.Missing, 
               Type.Missing, Type.Missing, Type.Missing, Type.Missing, 
               Type.Missing, Type.Missing); 
     } 

     /** 
     */ 
     public Excel.Range Find(string search) 
     { 
      Excel.Workbooks books = application.Workbooks; 

      Excel.Range currentFind = null; 
      Excel.Range firstFind = null; 

      // Search all workbooks. 
      foreach(Excel.Workbook book in books) 
      { 
       // Get first sheet. 
       Excel.Worksheet sheet = book.Worksheets.get_Item(1); 

       // Get all data for sheet. 
       Excel.Range firstCell = sheet.Range["A1", Type.Missing]; 
       Excel.Range lastCell = sheet.Cells.SpecialCells(Excel.XlCellType.xlCellTypeLastCell, Type.Missing); 
       Excel.Range sheetData = sheet.Range[firstCell, lastCell]; 

       currentFind = sheetData.Find(search, Type.Missing, 
        Excel.XlFindLookIn.xlValues, Excel.XlLookAt.xlPart, 
        Excel.XlSearchOrder.xlByRows, Excel.XlSearchDirection.xlNext, false, 
        Type.Missing, Type.Missing); 

       while (currentFind != null) 
       { 
        // Keep track of the first range you find. 
        if (firstFind == null) 
        { 
         firstFind = currentFind; 
        } 

        // If you didn't move to a new range, you are done. 
        else if (currentFind.get_Address(Type.Missing, Type.Missing, Excel.XlReferenceStyle.xlA1, Type.Missing, Type.Missing) 
          == firstFind.get_Address(Type.Missing, Type.Missing, Excel.XlReferenceStyle.xlA1, Type.Missing, Type.Missing)) 
        { 
         break; 
        } 

        currentFind = sheetData.FindNext(currentFind); 
       } 
      } 

      return currentFind; 
     } 
    } 
} 

我實例化類,並告訴它加載兩個工作簿和搜索字符串:

ExcelManager manager = new ExcelManager(); 

manager.Open(@"c:\test\test1.xls"); 
manager.Open(@"c:\test\test2.XLS"); 

Excel.Range result = manager.Find('test cell'); 
if (result != null) 
{ 
    // Do something funky. 
} 
else 
{ 
    // Use a log file instead. 
    Console.WriteLine("item was not found found in the current sheet."); 
} 

問題當我運行這個代碼時,它的速度非常慢,即使是小型的工作簿也是如此。我的C#知識很少,所以我一整天都在關注教程。這是一個很好的方式去搜索多張表嗎?會使用OLE更快嗎?此應用程序的目的僅僅是運行檢查來彙總未顯示在打開的工作簿中的任何工作表中的值。

+0

定義令人難以置信的緩慢。主要的問題是你搜索了很多領域,這意味着全部閱讀(excel實際上並沒有索引或其他的概念)。這通常是要避免的 - 沒有多大意義。只要你需要它,你必須吃,這需要一些時間。 – TomTom 2012-01-29 12:43:55

+0

令人難以置信的慢10分鐘。我明白你對很多領域的看法。也許我可以縮小它的範圍。我希望能夠搜索各個欄目。 – backdesk 2012-01-29 12:48:53

+0

我有一個問題,看看所有的領域是如何合理的 - 但這純粹來自商業點。問題是 - 這可能是非常多的非數據字段。 – TomTom 2012-01-29 12:54:07

回答

0

我的第一反應是互操作使用你的Excel安裝來收集信息。任何來自Excel安裝的初始化邏輯都將運行,並且會使代碼的加載時間非常緩慢。

你可以做什麼來測試是否是這種情況: 基準測試哪個函數調用使搜索變慢。 find函數或者你的ExcelManager類/ open函數的加載。

如果事實證明速度損失不是由find函數引起的,你可能會考慮一個解析文件本身而不是使用interop的庫。