2011-02-28 16 views
0

此問題與我之前的問題有關Link 下面的方法確實激動不已,但我需要使其運行得更快。 有沒有人有任何建議?謝謝。優化C#方法,比較並創建差異Excel文件

 public bool createReport_NewMinusBase(string currentWorkingDirectory, string Book1, string Book2, double tolerance) 
     { 
      tolerance = 0.0001; 
      myExcel.Application excelApp = new myExcel.Application(); // Creates a new Excel Application 
      excelApp.Visible = false; // Makes Excel visible to the user. 
      excelApp.Application.DisplayAlerts = false; 

      //useful for COM object interaction 
      object missing = System.Reflection.Missing.Value; 

      //Return value 
      bool wereDifferences = false; 

      //Comparison objects 
      object objNew = null; 
      object objBase = null; 


      //source: http://www.codeproject.com/KB/office/csharp_excel.aspx 
      //xlApp.Workbooks.Open(reportFolder + reportName, 0, false, 5, "", "", false, myExcel.XlPlatform.xlWindows, "", true, false, 0, true, false, false); 

      //Open BASE FILE 
      myExcel.Workbook excelWorkbook1 = excelApp.Workbooks.Open(@currentWorkingDirectory + Book1, 0, 
               missing, missing, missing, missing, missing, missing, 
               missing,missing, missing, missing, missing, missing, missing); 
      //OPEN NEW FILE 
      myExcel.Workbook excelWorkbook2 = excelApp.Workbooks.Open(@currentWorkingDirectory + Book2, 0, 
               missing, missing, missing, missing, missing, missing, 
               missing, missing, missing, missing, missing, missing, missing); 

      myExcel.Workbook excelWorkbook3 = excelApp.Application.Workbooks.Add(myExcel.XlWBATemplate.xlWBATWorksheet); 

      myExcel.Worksheet wsBase; 
      myExcel.Worksheet wsDiff; 
      myExcel.Worksheet wsNew; 


      try 
      { 
       wsBase = (myExcel.Worksheet)excelApp.Workbooks[Book1].Sheets["Sheet1"]; 
       wsNew = (myExcel.Worksheet)excelApp.Workbooks[Book2].Sheets["Sheet1"]; 
       wsDiff = (myExcel.Worksheet)excelWorkbook3.Worksheets.get_Item(1); 
      } 
      catch 
      { 
       throw new Exception("Excel file does not contain properly formatted worksheets"); 

      } 


      //Copy Sheet from Excel Book "NEW" to "NEW(-)BASE" 
      myExcel.Worksheet source_sheet; 
      source_sheet = (myExcel.Worksheet)excelApp.Workbooks[Book2].Sheets["Sheet1"]; 
      source_sheet.UsedRange.Copy(); 
      wsDiff.Paste(); 




      //Determine working area 
      int row = 0; 
      int col = 0; 
      int maxR = 0; 
      int maxC = 0; 

      int lr1 = 0; 
      int lr2 = 0; 
      int lc1 = 0; 
      int lc2 = 0; 
      { 
       lr1 = wsNew.UsedRange.Rows.Count; 
       lc1 = wsNew.UsedRange.Columns.Count; 
      } 

      { 
       lr2 = wsBase.UsedRange.Rows.Count; 
       lc2 = wsBase.UsedRange.Columns.Count; 
      } 

      maxR = lr1; 
      maxC = lc1; 

      if (maxR < lr2) maxR = lr2; 
      if (maxC < lc2) maxC = lc2; 

      //=================================================== 
      //Compare Cells 
      //=================================================== 

      for (row = 1; row <= maxR; row++) 
      { 
       for (col = 1; col <= maxC; col++) 
       { 
        //Get cell values 
        objNew = ((myExcel.Range)wsNew.Cells[row, col]).Value2; 
        objBase = ((myExcel.Range)wsBase.Cells[row, col]).Value2; 


        //If they are not equivilante 
        if (!equiv(objNew, objBase, tolerance)) 
        { 
         wereDifferences = true; 

         //Mark differing cells 
         ((myExcel.Range)wsNew.Cells[row, col]).Interior.Color = System.Drawing.ColorTranslator.ToOle(System.Drawing.Color.Red); 
         ((myExcel.Range)wsBase.Cells[row, col]).Interior.Color = System.Drawing.ColorTranslator.ToOle(System.Drawing.Color.Red); 

         if ((objNew == null)) 
         {        
          ((myExcel.Range)wsDiff.Cells[row, col]).Interior.Color = System.Drawing.ColorTranslator.ToOle(System.Drawing.Color.Red); 
         } 
         else if (objNew.GetType().ToString() == "System.String") 
         { 
          ((myExcel.Range)wsDiff.Cells[row, col]).Interior.Color = System.Drawing.ColorTranslator.ToOle(System.Drawing.Color.Red); 
         } 
         else 
         { 
          ((myExcel.Range)wsDiff.Cells[row, col]).Interior.Color = System.Drawing.ColorTranslator.ToOle(System.Drawing.Color.Yellow); 
          ((myExcel.Range)wsDiff.Cells[row, col]).Value2 = ((myExcel.Range)wsNew.Cells[row, col]).Value2 - ((myExcel.Range)wsBase.Cells[row, col]).Value2; 
         } 
        } 
        else //They are equivalent 
        {       
         if ((objNew == null)) 
         { 
         } 
         else if (objNew.GetType().ToString() == "System.String") 
         { 
         } 
         else 
         {        
          ((myExcel.Range)wsDiff.Cells[row, col]).Value2 = ((myExcel.Range)wsNew.Cells[row, col]).Value2 - ((myExcel.Range)wsBase.Cells[row, col]).Value2; 
         } 
        } 
       } 
      } 


      // Copy formatting 
      myExcel.Range range1 = wsBase.get_Range((myExcel.Range)wsBase.Cells[1, 1], (myExcel.Range)wsBase.Cells[maxR, maxC]); 
      myExcel.Range range2 = wsDiff.get_Range((myExcel.Range)wsDiff.Cells[1, 1], (myExcel.Range)wsDiff.Cells[maxR, maxC]); 
      range1.Copy(); 
      range2.PasteSpecial(myExcel.XlPasteType.xlPasteColumnWidths); 

      excelApp.Workbooks[Book1].Close(false, false, false); 
      excelApp.Workbooks[Book2].Close(false, false, false); 

      string Book3 = "reporttestpc.xlsx"; //"reportBaseMinusNew.xlsx" 
      if (File.Exists(currentWorkingDirectory + Book3)) 
      { 
       File.Delete(currentWorkingDirectory + Book3); 
      } 

      excelWorkbook3.SaveAs(currentWorkingDirectory + Book3, Type.Missing, Type.Missing, 
           Type.Missing, false, false, myExcel.XlSaveAsAccessMode.xlNoChange, 
           Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing); 

      //excelApp.Workbooks[Book3].Close(false, false, false); 

      excelApp.Visible = true; 
      return wereDifferences; 
     } 


     /// Determines whether two objects are equivalent 
     /// Numbers are equivalent within the specified tolerance 
     /// Strings are equivalent if they are identical 
     /// obj1 and obj2 are the two objects being compared 
     /// tolerance is the maximum difference between two numbers for them to be deemed equivalent 

     private bool equiv(object obj1, object obj2, double tolerance) 
     { 
      if ((obj1 == null) && (obj2 == null)) 
      { 
       return true; 
      } 
      else if ((obj1 == null) || (obj2 == null)) 
      { 
       return false; 
      } 

      //if both are numeric 
      if (IsNumeric(obj1)) 
      { 
       if (IsNumeric(obj2)) 
       { 
        if (Math.Abs(Convert.ToDouble(obj2) - Convert.ToDouble(obj1)) < tolerance) 
        { 
         return true; //If they are within tolerance 
        } 
        else 
        { 
         return false; //If they are outside tolerance 
        } 
       } 
       else 
       { 
        return false;  //If only one is numeric 
       } 
      } 

      //Now assuming both are just random strings 
      else 
      { 
       if ((string)obj1 == (string)obj2) 
       { 
        return true; 
       } 
       else 
       { 
        return false; 
       } 
      } 
     } 


     // Test whether a given object represents a number 
     internal static bool IsNumeric(object ObjectToTest) 
     { 
      if (ObjectToTest == null) 
      { 
       return false; 
      } 
      else 
      { 
       double OutValue; 
       return double.TryParse(ObjectToTest.ToString().Trim(), 
        System.Globalization.NumberStyles.Any, 
        System.Globalization.CultureInfo.CurrentCulture, 
        out OutValue); 
      } 
     } 

    /// 
+3

通常最好列出你試過的東西,以便自己跑得更快。否則,我們只是爲你做你的工作。在這裏幫助,而不是寫你的程序。 – BinaryTox1n 2011-02-28 22:39:59

+1

您可以通過個人資料確定大部分時間在哪裏? – mellamokb 2011-02-28 22:40:48

+0

我的appologies,我認爲這是顯而易見的問題來自嵌套for循環。我發佈了整個方法,不要讓有人爲我做這些工作,但要更容易理解我在做什麼以及如何改進它。我不認爲這是超快速的方法。然而,我希望有人能給我一點建議。 – MicroSumol 2011-03-01 16:14:46

回答

6

建議1:

品牌:

objNew.GetType().ToString() == "System.String" 

此:

objNew is string 

潤通清潔劑,對不對?應該也更快。

建議2:

你做這個調用了很多:

((myExcel.Range)wsDiff.Cells[row, col] 

。結果存儲在一個變量,並重新使用它。所有這些索引器,屬性和裝箱/拆箱都會產生開銷。對於任何你一遍又一遍訪問相同的COM方法,屬性或索引器的地方也是如此。確保你在for循環的範圍之外聲明這些變量,如果循環的每次迭代進入和退出範圍,都會損害性能。

建議3:

你可以重複使用您的Excel應用程序對象?看起來你每次調用這個方法都會創建一個新的。你可以將它存儲在你的類的成員變量中嗎?

0

您可以嘗試使用OleDb讀取和寫入Excel文檔。

我不知道性能如何比較,但您可以爲此進行配置。

0

我認爲你的IsNumeric()函數正在做很多工作。如何簡單地測試對象的類型?

if(ObjectToTest == null) return false; 
else if(ObjectToTest.GetType() == typeof(double)) return Convert.ToDouble(ObjectToTest); 
else if(ObjectToTest.GetType() == typeof(decimal)) return Convert.ToDouble(ObjectToTest); 
else return false; 

此外,我認爲你只需要測試雙打和小數。我可能是錯的。

+0

你也可以在這裏有效地使用「is」運算符:(ObjectToTest是雙精度) – jonathanpeppers 2011-03-01 13:02:18