更快地运行小VBA宏?

时间:2016-10-27 14:04:19

标签: excel vba performance range

我正在使用这个耗费近250毫秒的小代码:(i是行上循环的增量)

Sheets("sheet1").Select
val1 = Sheets("sheet2").Range("D" & Sheets("sheet1").Range("A" & i).Value + 1)
val2 = Sheets("sheet2").Range("E" & Sheets("sheet1").Range("A" & i).Value + 1)
Sheets("sheet1").Range("G" & i).Value = val1
Sheets("sheet1").Range("O" & i).Value = val2

我不确定为什么现在这么长时间。 是因为我将数据从一张纸移到另一张纸上吗?也许使用variant会更快?

你有什么指示我可以做些什么来加快速度? (此循环完成300-400次,因此总时间太长。)

(不确定这里有更好的地方还是#34;代码评论",如果我错了,请告诉我)

感谢您的帮助!

[编辑] 这是您建议的更改后的循环,谢谢大家,将花费的时间减少了30%。 但是对我来说还是太长了,我已经注意到你建议将所有表sh1sh2复制到一个表中,我会尝试实现它。如果您有其他想法,请告诉我发布=)

i = 2
While sh1.Cells(i, 1).Value <> ""
    val5 = sh1.Cells(i, 1).Value2 + 1
    With sh2
        val3 = .Cells(val5, 4).Value2
        val4 = .Cells(val5, 5).Value2
    End With

    With sh1
        .Cells(i, 7).Value2 = val3
        .Cells(i, 15).Value2 = val4
    End With

    i = i + 1
Wend

4 个答案:

答案 0 :(得分:3)

  • 不要使用。选择(之后你似乎没有对选择做任何事情)
  • 将工作表存储在两个变量中:dim oSheet1作为工作表; set oSheet = Sheets(“Sheet1”)。或者使用代码名称:Sheet1和Sheet2(最有可能)
  • 使用.Cells()比.Range()避免字符串连接可能更快
  • 如果有的话,尽可能避免变体并声明类型安全变量

答案 1 :(得分:3)

您的代码可以修改为:

select *
  from t1;

        UN FLAG
---------- ----
         1 T   
         2 T   
         3 F   

3 rows selected.

进一步减少(除非您需要在其他地方使用Dim sh as Worksheet, sh2 as Worksheet Dim val1, val2 Set sh = Sheets("Sheet1") Set sh2 = Sheets("Sheet2") With sh val1 = sh2.Cells(.Cells(1, i).Value2 + 1, 4) val2 = sh2.Cells(.Cells(1, i).Value2 + 1, 5) .Cells(i, 7).Value = val1 .Cells(i, 15).Value = val2 End With val1

val2

有关如何避免使用select / activate以及正确使用变量的更多信息,请访问:

How to avoid using Select in Excel VBA macros

答案 2 :(得分:1)

摆脱Sheets("sheet1").Select - 它没有在您发布的代码中执行任何操作,如果这是在循环中,它将反复执行任何操作。

删除中间变量var1var2,并在单元格之间直接指定值。

使用With块和存储的对象引用以避免重复解除引用对象。您正在Excel表格集合中执行重复的对象查找。

使用带有数字索引的.Cells而不是带有字符串连接和alpha引用的Range - Excel无论如何都必须将它们转换回来。

缓存将重复使用的中间值(即Sheets("sheet1").Range("A" & i).Value + 1)。

更像是:

'Outside loop:
Dim source As Worksheet
Dim target As Worksheet
Set source = Sheets("sheet2")
Set target = Sheets("sheet1")

'...
'Inside loop:
Dim targetRow As Long
With target
    targetRow = .Cells(i, 1).Value + 1
    .Cells(i, 7).Value = source.Cells(targetRow, 4)
    .Cells(i, 15).Value = source.Cells(targetRow, 5)
End With

如果这仍然不够快,请考虑将整个工作范围拉入Variant阵列并改为使用它。当你完成后,一次性写完整个东西。

答案 3 :(得分:0)

正如@ScottCraner评论的那样,最小化对应用程序的调用是更快的VBA宏的关键之一。例如,立即复制整个列而不是逐个单元格:

Dim c As Long
c = Sheet2.Cells(2, 1).End(xlDown).Row - 1  ' count = last row - first row - 1
Application.ScreenUpdating = False          ' optional
Sheet1.Cells(2,  7).Resize(c).Value2 = Sheet2.Cells(2, 4).Resize(c).Value2
Sheet1.Cells(2, 15).Resize(c).Value2 = Sheet2.Cells(2, 5).Resize(c).Value2
Application.ScreenUpdating = True           ' optional