2015-03-25 121 views
0

所以这里是我的代码,即时试图比较一个包含3000行与另一个5000行的工作表,但它工作太慢,任何人都可以帮忙吗?VBA从两张纸比较太慢?

Dim G As Long 
Dim K As Long 
Dim CardBrand As String 
Dim STD As String 
Dim CardBrand2 As String 
Dim ASI 
Dim ID As String 
Dim X As Workbook 
Dim FinalRow As Long 
Dim Finalrow2 As Long 
Dim I As Long 
Dim TC_STD As String 
Dim TC_ASI As String 
Dim TC_Perc As Double 
Dim TC_Base As Double 
Dim TC_ID As String 


    Application.ScreenUpdating = False 
    FinalRow = Cells(Rows.Count, "I").End(xlUp).Row 


    For G = 5 To FinalRow 

     CardBrand = Sheets("sheet1").Cells(G, 9).Value 
     STD = Sheets("sheet1").Cells(G, 10).Value 
     ID = Sheets("sheet1").Cells(G, 5).Value 

     For K = 2 To 51 

      CardBrand2 = Sheets("sheet2").Cells(K, 3).Value 

      If CardBrand = CardBrand2 Then 

       ASI = Sheets("sheet2").Cells(K, 1).Value 
       Set X = Workbooks.Open("E:\Partner_Commission_Compiler\Repository\Transaction_Charges.xlsx") 
       Finalrow2 = X.ActiveSheet.Cells(Rows.Count, "A").End(xlUp).Row 

       For I = 1 To Finalrow2 

        TC_ASI = X.ActiveSheet.Cells(I, 6).Value 
        TC_STD = X.ActiveSheet.Cells(I, 11).Value 
        TC_ID = X.ActiveSheet.Cells(I, 1).Value 

         If (TC_ASI = ASI) And (TC_STD = STD Or TC_STD = "All") And TC_ID = ID Then 

          TC_Perc = X.ActiveSheet.Cells(I, 19).Value 
          TC_Base = X.ActiveSheet.Cells(I, 20).Value 
          ThisWorkbook1.Sheets("Sheet1").Activate 

          Sheets("sheet1").Cells(G, 13).Value = TC_Perc 
          Sheets("sheet1").Cells(G, 14).Value = TC_Base 
         End If 
       Next I 
      End If 
     Next K 
    Next G 

    X.Close (False) 
    Application.ScreenUpdating = True 
+0

如果代码是缩进的,你的代码会更容易阅读和理解。我不能为此而烦恼,所以这取决于你。 – 2015-03-25 10:51:12

+0

嗨马克,iv更新它,但缩进不是因为它应该是有原因或另一个。 – 2015-03-25 11:03:25

+1

这对你来说会是一个很大的改变,但是任何在许多单元上循环的代码可能需要很长时间,所以在这种情况下我总是使用数组。基本概念是读取单元的循环的每次迭代实际上是代码和工作表的软件层之间的I/O,因此更多的单元=更多的I/O。你是否使用数组方法,将两张表的内容读入一个数组(每个数据为1)= 2个I/O - 然后在代码中执行任何你想要的操作,也许写出另一个数组或更新现有的数组,最后,将任何更新或新的阵列写回您的目标。 3 I/O's – 2015-03-25 11:08:45

回答

1

几点建议:

  • 既然你没有使用复制和粘贴从X.ActiveSheet移动数据到工作表Sheet1抑制ScreenUpdating,你是(非常正确),那么你真的不要不需要线“ThisWorkbook1.Sheets(”Sheet1“)。激活”循环中重复。即使Sheet1已被激活,激活呼叫也可能非常耗时,并且不像您在翻转哪张纸张处于活动状态。

  • 此外,您正在循环中重复打开“E:\ Partner_Commission_Compiler \ Repository \ Transaction_Charges.xlsx”。再次不必要的,毫无疑问,当你不需要的时候,会消耗越来越多的CPU时间。

的以下两行之前的任何您的循环移动:

Set X = Workbooks.Open("E:\Partner_Commission_Compiler\Repository\Transaction_Charges.xlsx") 
Finalrow2 = X.ActiveSheet.Cells(Rows.Count, "A").End(xlUp).Row 
+0

感谢非常有帮助!为我节省了很多时间:) – 2015-03-25 18:31:40

1

除了cybermike的优良建议(而不是在每个循环中打开该文件应该保存显著时间),你可以尝试这些变化。

更改此:

CardBrand2 = Sheets("sheet2").Cells(K, 3).Value 
If CardBrand = CardBrand2 Then 

这个

If Sheets("sheet2").Cells(K, 3) = Sheets("sheet2").Cells(K, 3).Value 

您有:

Dim ASI 

它声明它Variant。每次您的代码使用ASI时,Excel都必须解密ASI中存储的数据类型,以确定如何分配或比较它。如果您将其声明为特定类型,则可以跳过该加速执行的确定步骤。由于您将其分配给单元格的内容,因此可以指定StringInteger。如果它有时是一个,有时是另一个,然后是Dim as String,然后是明确的CStr(cell).value,并以字符串形式进行所有比较。它将再次消除Excel找出如何处理值的时间。

您可以更换:

TC_ASI = X.ActiveSheet.Cells(I, 6).Value 
TC_STD = X.ActiveSheet.Cells(I, 11).Value 
TC_ID = X.ActiveSheet.Cells(I, 1).Value 
If (TC_ASI = ASI) And (TC_STD = STD Or TC_STD = "All") And TC_ID = ID Then 
    TC_Perc = X.ActiveSheet.Cells(I, 19).Value 
    TC_Base = X.ActiveSheet.Cells(I, 20).Value 
    ThisWorkbook1.Sheets("Sheet1").Activate 
    Sheets("sheet1").Cells(G, 13).Value = TC_Perc 
    Sheets("sheet1").Cells(G, 14).Value = TC_Base 

有:

If x.cells(i,6) = Sheets("sheet2").Cells(K, 1) AND _ 
    (x.cells(1,11) = Sheets("sheet1").Cells(G, 10) OR _ 
    x.cells(1,11) = "All") AND _ 
    x.Cells(i,1) = Sheets("sheet1").Cells(G, 5) Then 
    Sheets("sheet1").Cells(G, 13).Value = X.Cells(I, 19) 
    Sheets("sheet1").Cells(G, 14).Value = X.Cells(I, 20) 

删除每个回路所有这些任务将节省一些处理时间。然而,阅读代码有点困难,所以你可能想在注释中留下一些伪代码来帮助记住所有这些不同的单元格代表什么。

+0

也非常有帮助谢谢:) – 2015-03-25 18:31:56