VBAmacros运行速度非常慢

我有这个macros,终于搞定了,但是运行速度非常慢,大约需要三天的时间才能通过我的一页80万行,我有100页。 我希望在这方面的帮助。

Sub Calculate_Sheet() Dim orderSh As Worksheet Dim wiroSh As Worksheet Dim lastRow As Long, r As Long Dim pctComp As Double With ThisWorkbook 'calculator Set orderSh = .Sheets("ORDER") 'price list Set wiroSh = .Sheets("WiroA3C100gsmI100gsm20-22pp ") End With lastRow = wiroSh.Cells(Rows.Count, 3).End(xlUp).Row For r = 2 To lastRow pctComp = (r / 800000) * 100 Application.StatusBar = "Progress..." & " " & pctComp & " " & "% Complete" 'copy from price list to calculator orderSh.Range("f4") = wiroSh.Range("c" & r) orderSh.Range("f5") = wiroSh.Range("d" & r) orderSh.Range("f6") = wiroSh.Range("e" & r) orderSh.Range("f7") = wiroSh.Range("f" & r) orderSh.Range("f8") = wiroSh.Range("g" & r) orderSh.Range("f9") = wiroSh.Range("h" & r) orderSh.Range("f10") = wiroSh.Range("i" & r) orderSh.Range("f11") = wiroSh.Range("j" & r) orderSh.Range("f12") = wiroSh.Range("k" & r) orderSh.Range("f13") = wiroSh.Range("l" & r) 'copy result wiroSh.Range("m" & r).Value = orderSh.Range("F14") Next r End Sub 

无论如何都不能closures屏幕更新。 它是一种技术,用于加速低效的代码,如果你的代码不是无效的,你不需要担心屏幕更新…….

理论是非常简单的..不要访问/使用范围在你的代码,除非绝对必要的….

而是转储整个工作表数据到一个数组,并从中工作,不仅速度快….我的意思是超快,你可以重新填充整个工作表(即32000列和100万行)立即使用数组.. ….

而你使用完全相同的逻辑来处理数组,就像使用范围一样,所以你真的没有任何理由。

 Dim Arr as variant Arr = Sheet1.Range("A1:Z100") 

现在,而不是Sheet1.Range(“A1”)。值只是使用Arr(1,1)来访问该值

并用数组更新工作表一样简单

 Sheet1.Range("A1:Z100").value = arr 

它的简单,它的快速简单,它的方式,你应该这样做,除非它只是一个小的工作,但即使如此,更好地实践最好的方法吗?

需要注意的一点是,当你将数组的值放回工作表时,需要使用与数组相同或更大的范围……..否则它只会填满你指定的范围。

你也可以尝试复制一个范围,而不是多个范围。 我认为它可以轻微增加你的performance。

我想,你可以取代这个

  orderSh.Range("f4") = wiroSh.Range("c" & r) orderSh.Range("f5") = wiroSh.Range("d" & r) orderSh.Range("f6") = wiroSh.Range("e" & r) orderSh.Range("f7") = wiroSh.Range("f" & r) orderSh.Range("f8") = wiroSh.Range("g" & r) orderSh.Range("f9") = wiroSh.Range("h" & r) orderSh.Range("f10") = wiroSh.Range("i" & r) orderSh.Range("f11") = wiroSh.Range("j" & r) orderSh.Range("f12") = wiroSh.Range("k" & r) orderSh.Range("f13") = wiroSh.Range("l" & r) 

像这样的事情

 orderSh.Range(orderSh.cells(4,"F"),orderSh.cells(13,"F")) = wiroSh.Range(wiroSh.cells(r,"C"),wiroSh.cells(r,"l")) 

正如j.kaspar提到的, application.screenupdating = false用法是个好主意,但是我强烈build议在macros的开始部分使用类似的东西

 Dim previousScreenUpdating as boolean previousScreenUpdating = application.screenUpdating application.screenUpdating = false 

这在你的macros的末尾

 application.screenUpdating = previousScreenUpdating 

哪些可以帮助你,当你有嵌套的function,在其中设置多个screenUpdatings …

而且,如果你在任何一张纸上都有一些公式,请在(开始时)

 Application.Calculation = xlCalculationManual 

这在代码的结尾

 Application.Calculation = xlCalculationAutomatic 

最后,如果你有一些事件监听器,考虑使用这个(和屏幕更新一样)

 application.enableEvents 

在开始处使用Application.ScreenUpdating = False ,在macros的结尾处使用Application.ScreenUpdating = True

当屏幕没有被更新时,它将运行得更快。 但请记住,800.000行和100张是很多,这将需要“一些”的时间…

Excel中有一个叫“数据表”的function。 这个function可以帮助你不写VBA。 但是,对不起,我找不到英文的解释。

所以我采取了arrays的build议,但我错过了一些东西。 这里是我如何调整VBA代码,把任何地方都没有插入值?

  Sub Calculate_Sheet() Dim orderSh As Worksheet Dim wiroSh As Worksheet Dim lastRow As Long, r As Long Dim pctComp As Double Dim Arr1 As Variant Dim Arr2 As Variant With ThisWorkbook 'calculator Set orderSh = .Sheets("ORDER") 'price list Set wiroSh = .Sheets("WiroA3C100gsmI100gsm20-22pp ") End With Arr1 = wiroSh.Range("C1:M800001") Arr2 = orderSh.Range("F4:F14") lastRow = wiroSh.Cells(Rows.Count, 3).End(xlUp).Row For r = 2 To lastRow 'display the row and percentage each 1000 rows If r Mod 1 = 0 Then Application.StatusBar = "Row = " & r & Format(r / lastRow, " #0.00%") End If 'copy from price list to calculator Arr2(1, 1) = Arr1(r, 1) Arr2(2, 1) = Arr1(r, 2) Arr2(3, 1) = Arr1(r, 3) Arr2(4, 1) = Arr1(r, 4) Arr2(5, 1) = Arr1(r, 5) Arr2(6, 1) = Arr1(r, 6) Arr2(7, 1) = Arr1(r, 7) Arr2(8, 1) = Arr1(r, 8) Arr2(9, 1) = Arr1(r, 9) Arr2(10, 1) = Arr1(r, 10) 'copy result Arr1(r, 11) = Arr2(11, 1) Next r End Sub