【问题标题】:VBA Comparing from two sheets is too slow? [duplicate]VBA 从两张纸比较太慢了? [复制]
【发布时间】:2015-03-25 10:43:08
【问题描述】:

所以这是我的代码,我试图将包含 3000 行的工作表与另一个 5000 行的工作表进行比较,但是它的工作速度太慢,谁能帮忙?

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

【问题讨论】:

  • 如果缩进,您的代码会更容易阅读和理解。我懒得做,这取决于你。
  • 嗨,马克,我更新了它,但是由于某种原因,缩进并没有出现。
  • 这对您来说将是一个很大的改变,但是任何在很多单元格上循环的代码都可能需要很长时间,所以在这种情况下我总是使用数组。基本概念是读取单元的循环的每次迭代实际上是代码的软件层和工作表之间的 I/O,因此更多的单元 = 更多的 i/o。您是否使用数组方法,将两张表的内容读入一个数组(每个 1 个)= 2 个 I/O - 然后在代码中执行您想要的任何操作,可能写出另一个数组或更新现有数组,并且最后,将任何更新的或新的数组写回您的目标。 3 个 I/O
  • 随着您的代码运行,尽管速度很慢,您的问题可能会在Code review得到更多答案

标签: excel vba


【解决方案1】:

一些建议:

  • 由于您正在禁止 ScreenUpdating,并且您(非常正确)不使用复制和粘贴将数据从 X.ActiveSheet 移动到 Sheet1,因此您真的不需要“ThisWorkbook1.Sheets(” Sheet1").Activate" 在循环中一遍又一遍地重复。即使 Sheet1 已经激活,Activate 调用也可能非常耗时,而且不像您在翻转哪个工作表处于活动状态。

  • 此外,您在循环中一遍又一遍地重新打开“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

【讨论】:

  • 非常感谢!节省了我很多时间:)
【解决方案2】:

除了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)

删除每个循环上的所有这些分配将节省一些处理时间。不过,阅读代码有点困难,因此您可能希望在 cmets 中留下一些伪代码,以帮助记住所有这些不同单元格所代表的含义。

【讨论】:

  • 也很有帮助,谢谢 :)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多