2017-02-26 66 views
-2

這是我當前的代碼。打開以接收任何評論以改善內存優化。用於比較兩個Excel表格的Excel工具

當我以1000000 * 8的數據取其1000000 * 8的樣本時,其導致的內存不足異常。很想有優化內存使用的建議。

比較名爲「之前」和「之後」的數據集中的兩個表並填充所有結果表。

private bool CompareAndFillResultTable(DataSet ds) 
    { 
     Stopwatch stopWatch = new Stopwatch(); stopWatch.Start(); 
     System.Data.DataTable dt_copy; 
     dt_copy = new System.Data.DataTable(); 
     dt_copy = ds.Tables["Before"].Copy(); 
     dt_copy.TableName = "BeforeBackup"; 
     ds.Tables.Add(dt_copy); 
     dt_copy = new System.Data.DataTable(); 
     dt_copy = ds.Tables["After"].Copy(); 
     dt_copy.TableName = "AfterBackup"; 
     ds.Tables.Add(dt_copy); 
     dt_copy = new System.Data.DataTable(); 
     dt_copy = ds.Tables["Before"].Clone(); 
     dt_copy.TableName = "BeforeSingular"; 
     ds.Tables.Add(dt_copy); 
     dt_copy = new System.Data.DataTable(); 
     dt_copy = ds.Tables["Before"].Clone(); 
     dt_copy.TableName = "AfterSingular"; 
     ds.Tables.Add(dt_copy); 
     dt_copy = new System.Data.DataTable(); 
     dt_copy = ds.Tables["Before"].Clone(); 
     dt_copy.TableName = "Duplicates"; 
     ds.Tables.Add(dt_copy); 
     dt_copy = new System.Data.DataTable(); 
     dt_copy = ds.Tables["Before"].Clone(); 
     dt_copy.TableName = "Mismatch"; 
     ds.Tables.Add(dt_copy); 

     foreach (System.Data.DataTable table in ds.Tables) 
     { 
      table.Columns.Add("Source_Label"); 
     } 

     //Remove identical from before, then after 
     for (int i = 0; i < ds.Tables["Before"].Rows.Count; i++) 
     { 
      string BeforeCompareKeyVal = ds.Tables["Before"].Rows[i][Inputs.SortColumn].ToString(); 
      if (ds.Tables["After"].Rows.Count > 0) 
      { 
       for (int j = 0; j < ds.Tables["After"].Rows.Count; j++) 
       { 
        string AfterCompareKeyVal = ds.Tables["After"].Rows[j][Inputs.SortColumn].ToString(); 

        if (ds.Tables["Before"].Rows[i].ItemArray.SequenceEqual(ds.Tables["After"].Rows[j].ItemArray)) 
        { 
         //copy Aftter row to duplicate Table and Remove row from After 
         DataRow rw = ds.Tables["After"].Rows[j]; 
         rw[ds.Tables["After"].Columns.Count - 1] = "NA"; 
         ds.Tables["Duplicates"].ImportRow(rw); 
         ds.Tables["After"].Rows.RemoveAt(j); 
         j--; 
         break; 
        } 
        if (Int64.Parse(BeforeCompareKeyVal) > Int64.Parse(AfterCompareKeyVal))// Review - 7 
        { 
         if (true)//all dup after + a before - set logic 
         { 
          //Copy After row to AfterSingular Table and Remove row from After 
          DataRow rw = ds.Tables["After"].Rows[j]; 
          rw[ds.Tables["After"].Columns.Count - 1] = "After"; 
          ds.Tables["AfterSingular"].ImportRow(rw); 
          ds.Tables["After"].Rows.RemoveAt(j); 
          j--; 
          if (ds.Tables["After"].Rows.Count == 0) 
          { 
           rw = ds.Tables["Before"].Rows[i]; 
           rw[ds.Tables["Before"].Columns.Count - 1] = "Before"; 
           ds.Tables["BeforeSingular"].ImportRow(rw); 
          } 
          continue; 
         } 

        } 
        if (Int64.Parse(BeforeCompareKeyVal) < Int64.Parse(AfterCompareKeyVal))// Review - 7 
        { 
         if (true)//all dup after and a before set logic 
         { 
          //Copy Before row to BeforeSingular Table 
          DataRow rw = ds.Tables["Before"].Rows[i]; 
          rw[ds.Tables["Before"].Columns.Count - 1] = "Before"; 
          ds.Tables["BeforeSingular"].ImportRow(rw); 
          break; 
         } 
        } 
        if (Int64.Parse(BeforeCompareKeyVal) == Int64.Parse(AfterCompareKeyVal))// Review - 7 
        { 
         //Copy Before, After row to Mismatch Table and Remove row from After 
         if (true)//all dup after and a before set logic 
         { 
          DataRow rwB = ds.Tables["Before"].Rows[i]; 
          rwB[ds.Tables["Before"].Columns.Count - 1] = "Before"; 
          DataRow rwA = ds.Tables["After"].Rows[j]; 
          rwA[ds.Tables["After"].Columns.Count - 1] = "After"; 
          ds.Tables["Mismatch"].ImportRow(rwB); 
          ds.Tables["Mismatch"].ImportRow(rwA); 
          ds.Tables["After"].Rows.RemoveAt(j); 
          j--; 
          break; 
         } 
        } 
       } 
      } 
      else 
      { 
       DataRow rw = ds.Tables["Before"].Rows[i]; 
       rw[ds.Tables["Before"].Columns.Count - 1] = "Before"; 
       ds.Tables["BeforeSingular"].ImportRow(rw); 
       continue; 
      } 
     } 
     //Add remaining after table rows to AfterSingular table 
     ds.Tables["AfterSingular"].Merge(ds.Tables["After"]); 

     //ds.Tables["AfterSingular"].Columns.Add("Source_Label", System.Type.GetType("System.String"), "After_Singular"); 
     //ds.Tables["BeforeSingular"].Columns.Add("Source_Label", System.Type.GetType("System.String"), "Before_Singular"); 

     //foreach (System.Data.DataTable table in ds.Tables) 
     //{ 
     // DataRow colNames = table.NewRow(); 
     // //foreach (var col in table.Columns) 
     // //{ 

     // //}     
     // for (int i = 0; i < table.Columns.Count; i++) 
     //  colNames[i] = table.Columns[i].ColumnName; 
     // table.Rows.InsertAt(colNames, 0); 
     //} 

     foreach (System.Data.DataTable table in ds.Tables) 
     { 
      table.Columns.Remove(Inputs.SortColumn); 
      table.AcceptChanges(); 
     } 

     stopWatch.Stop(); lbAlert.Text = lbAlert.Text + "\n\n" + "Total Comparison time for B: " + Inputs.RowNoBeforeTable + " x " + Inputs.ColumnNoBeforeTable + " A: " + Inputs.RowNoAfterTable + " x " + Inputs.ColumnNoAfterTable + " is " + stopWatch.ElapsedMilliseconds + " ms, " + stopWatch.ElapsedMilliseconds/1000 + " s"; 
     return true; 
    } 
+2

[Excel中互操作 - 效率和性能](http://stackoverflow.com/questions/356371/excel-interop-efficiency-and-performance) - 讀取,並通過使用在一個操作將數據寫入到工作表一個'Object [,]' - 參見這裏將你的DataTable轉換爲Object Array http://stackoverflow.com/a/30397080/495455。 –

+0

謝謝你的參考Jeremy。 –

回答

0

你不能只是用VBA腳本來做這種事嗎?

Option Explicit 

Sub test() 

    Dim varSheetA As Variant 
    Dim varSheetB As Variant 
    Dim strRangeToCheck As String 
    Dim iRow As Long 
    Dim iCol As Long 

    strRangeToCheck = "A1:IV65536" 
    ' If you know the data will only be in a smaller range, reduce the size of the ranges above. 
    Debug.Print Now 
    varSheetA = Worksheets("Sheet1").Range(strRangeToCheck) 
    varSheetB = Worksheets("Sheet2").Range(strRangeToCheck) ' or whatever your other sheet is. 
    Debug.Print Now 

    For iRow = LBound(varSheetA, 1) To UBound(varSheetA, 1) 
     For iCol = LBound(varSheetA, 2) To UBound(varSheetA, 2) 
      If varSheetA(iRow, iCol) = varSheetB(iRow, iCol) Then 
       ' Cells are identical. 
       ' Do nothing. 
      Else 
       ' Cells are different. 
       ' Code goes here for whatever it is you want to do. 
        Cells(iRow, iCol).Select 
        With Selection.Interior 
         .Pattern = xlSolid 
         .PatternColorIndex = xlAutomatic 
         .Color = 49407 
         .TintAndShade = 0 
         .PatternTintAndShade = 0 
        End With 

      End If 
     Next iCol 
    Next iRow 

End Sub