vba 如何提高VBA宏代码的速度?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/13016249/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to improve the speed of VBA macro code?
提问by Miles
I do not have much experience with writing macros, and therefore need the help of this community for the following issue encountered:
我没有太多编写宏的经验,因此遇到以下问题需要该社区的帮助:
My macro copies a range of values entered in a vertical range in one worksheet and then pastes the values horizontally (transpose) in another worksheet. It would in theory paste the values from the first sheet to first row of the second worksheet which does not have content. Since the first five rows have contents, it thus pastes the values to the sixth row. The problem I have with the running of the macro is that I feel like it is too slow and I would therefore like it to run faster.
我的宏复制了一个工作表中垂直范围内输入的一系列值,然后将这些值水平粘贴(转置)到另一个工作表中。理论上,它会将第一张工作表中的值粘贴到没有内容的第二张工作表的第一行。由于前五行有内容,因此它将值粘贴到第六行。我在运行宏时遇到的问题是我觉得它太慢了,因此我希望它运行得更快。
I have the same macro doing the same thing but that instead pastes the values to another worksheet to the first row, and it runs perfect.
我有相同的宏做同样的事情,但它会将值粘贴到另一个工作表的第一行,并且它运行完美。
My best guess is therefore that the second macro is running slow because it has to start pasting on the sixth row and there may be some contents on the first 5 rows that take a lot of time for the macro to go through (there a lot of cell references to other workbooks) to determine where the next row for pasting should be. That is my best guess though and since I hardly know anything about macros, I cannot say for sure what the problem is.
因此,我最好的猜测是第二个宏运行缓慢,因为它必须在第六行开始粘贴,并且前 5 行上可能有一些内容需要大量时间让宏通过(有很多其他工作簿的单元格引用)来确定下一行粘贴的位置。不过,这是我最好的猜测,因为我对宏几乎一无所知,所以我无法确定问题是什么。
I hereby provide you with the code of my macro and sincerely hope that somebody can tell me what is making my macro slow and provide me with a solution as to how to make it run faster. I am thinking that a solution might potentially be that the macro should not consider the first five rows of data and start pasting immediately on row 6 for the first entry. Then on row 7 the next time, and etc. This might be a solution but I do not know how to write the code in a way that it would do that.
我在此向您提供我的宏代码,并真诚地希望有人能告诉我是什么使我的宏变慢,并为我提供有关如何使其运行更快的解决方案。我认为一个解决方案可能是宏不应该考虑前五行数据并立即开始粘贴第 6 行的第一个条目。然后下一次在第 7 行,等等。这可能是一个解决方案,但我不知道如何以一种可以做到这一点的方式编写代码。
Thank you for taking time and helping me to find a solution, here is the code:
感谢您抽出时间帮助我找到解决方案,这是代码:
Sub Macro1()
Application.ScreenUpdating = False
Dim historyWks As Worksheet
Dim inputWks As Worksheet
Dim nextRow As Long
Dim oCol As Long
Dim myCopy As Range
Dim myTest As Range
Dim lRsp As Long
Set inputWks = wksPartsDataEntry
Set historyWks = Sheet11
'cells to copy from Input sheet - some contain formulas
Set myCopy = inputWks.Range("OrderEntry2")
With historyWks
nextRow = .Cells(.Rows.Count, "A").End(xlUp).Offset(1, 0).Row
End With
With inputWks
Set myTest = myCopy.Offset(0, 2)
If Application.Count(myTest) > 0 Then
MsgBox "Please fill in all the cells!"
Exit Sub
End If
End With
With historyWks
With .Cells(nextRow, "A")
.Value = Now
.NumberFormat = "mm/dd/yyyy hh:mm:ss"
End With
.Cells(nextRow, "B").Value = Application.UserName
oCol = 3
myCopy.Copy
.Cells(nextRow, 3).PasteSpecial Paste:=xlPasteValues, Transpose:=True
Application.CutCopyMode = False
End With
'clear input cells that contain constants
With inputWks
On Error Resume Next
With myCopy.Cells.SpecialCells(xlCellTypeConstants)
.ClearContents
Application.GoTo .Cells(1) ', Scroll:=True
End With
On Error GoTo 0
End With
Application.ScreenUpdating = True
End Sub
采纳答案by whytheq
Just reiterating what has already been said:
只是重申已经说过的话:
Option Explicit
Sub Macro1()
'turn off as much background processes as possible
With Excel.Application
.ScreenUpdating = False
.Calculation = Excel.xlCalculationManual
.EnableEvents = False
End With
Dim historyWks As Excel.Worksheet
Dim inputWks As Excel.Worksheet
Dim nextRow As Long
Dim oCol As Long
Dim myCopy As Excel.Range
Dim myTest As Excel.Range
Dim lRsp As Long
Set inputWks = wksPartsDataEntry
Set historyWks = Sheet11
'cells to copy from Input sheet - some contain formulas
Set myCopy = inputWks.Range("OrderEntry2")
With historyWks
nextRow = .Cells(.Rows.Count, 1).End(Excel.xlUp).Offset(1, 0).Row
End With
With inputWks
Set myTest = myCopy.Offset(0, 2)
If Excel.Application.Count(myTest) > 0 Then
MsgBox "Please fill in all the cells!"
GoTo QuickExit
End If
End With
With historyWks
With .Cells(nextRow, 1)
.Value = Now
.NumberFormat = "mm/dd/yyyy hh:mm:ss"
End With
.Cells(nextRow, 2).Value = Excel.Application.UserName
oCol = 3
myCopy.Copy
.Cells(nextRow, 3).PasteSpecial Paste:=Excel.xlPasteValues, Transpose:=True
Excel.Application.CutCopyMode = False
End With
'clear input cells that contain constants
With inputWks
On Error Resume Next
With myCopy.Cells.SpecialCells(Excel.xlCellTypeConstants)
.ClearContents
Excel.Application.Goto .Cells(1) ', Scroll:=True
End With
On Error GoTo 0
End With
Calculate
QuickExit
With Excel.Application
.ScreenUpdating = True
.Calculation = Excel.xlAutomatic
.EnableEvents = True
End With
End Sub
I'd step through the macro line-by-line to try to locate which line is slow.
我会逐行遍历宏以尝试找出哪条线慢。
Another alternative - although not sure if it'll speed things up - is to avoid the clipboard and lose the copy/paste
so you'd apply a method like the following to move the data:
另一种选择 - 尽管不确定它是否会加快速度 - 是避免剪贴板并丢失剪贴板,copy/paste
因此您可以应用如下方法来移动数据:
Option Explicit
Sub WithoutPastespecial()
'WORKING EXAMPLE
Dim firstRange As Range
Dim secondRange As Range
Set firstRange = ThisWorkbook.Worksheets("Cut Sheet").Range("S4:S2000")
With ThisWorkbook.Worksheets("Cutsheets")
Set secondRange = .Range("A" & .Rows.Count).End(Excel.xlUp).Offset(1)
End With
With firstRange
Set secondRange = secondRange.Resize(.Rows.Count, .Columns.Count)
End With
secondRange.Value = firstRange.Value
End Sub
回答by Potter Rafed
Best way to improve performance based on my experience is to work on variables in code rather than accessing the spreadsheet every time you want to lookup a value. Save any range you want to work with in a variable(variant) and then iterate through it as if it was the sheet.
根据我的经验,提高性能的最佳方法是在代码中处理变量,而不是每次要查找值时都访问电子表格。将您要使用的任何范围保存在变量(变体)中,然后像工作表一样遍历它。
dim maxRows as double
dim maxCols as integer.
dim data as variant
with someSheet
maxRows = .Cells(rows.count, 1).end(xlUp).row 'Max rows in sheet
maxCols = .Cells(1, columns.count).end(xlToLeft).column 'max columns in sheet
data = .Range(.Cells(1,1), .Cells(maxRows, maxCols)) 'copy range in a variable
end with
From here you can access the data variable as if it was the spreadsheet like - data(row, column) with MUCH MUCH faster read speed.
从这里您可以访问数据变量,就像它是电子表格一样 - 数据(行,列)具有更快的读取速度。
回答by bonCodigo
Please take a look at this article as well. How to speed up calculation and improve performance...
也请看看这篇文章。 如何加速计算并提高性能...
By all means, Application.calculation= xlCalculationManual is usually the culprit. But we can notice that volatile Excel sheet functions can mostly kill your application on large scale of data processing and functional aspect.
无论如何, Application.calculation= xlCalculationManual 通常是罪魁祸首。但是我们可以注意到,易变的 Excel 工作表函数主要会在大规模数据处理和功能方面杀死您的应用程序。
Also, for your current code following post might not be directly relevant. I find it useful for tips on over-all Excel/VBA performance optimization.
此外,对于您当前的代码,以下帖子可能不直接相关。我发现它对有关 Excel/VBA 性能优化的提示很有用。
PS: I don't have enough reputation to comment on your post. So added as an answer..
PS:我没有足够的声誉来评论你的帖子。所以添加为答案..
回答by Chris Rae
As suggested by a few others in the comments, you should definitely change Application.Calculation to xlCalculationManual and rememeber to set it back to xlcalculationAutomatic at the end. Also try setting Application.Screenupdating = False (and turning that back on again too). Also, bear in mind that .Copy is a very inefficient way to copy cell values - if you really just want the values, loop through the range setting .Value to the .Values in the old range. If you need all the formatting, you're probably stuck with .Copy.
正如评论中的其他一些人所建议的那样,您绝对应该将 Application.Calculation 更改为 xlCalculationManual 并记住在最后将其设置回 xlcalculationAutomatic。还可以尝试设置 Application.Screenupdating = False(并再次打开它)。另外,请记住, .Copy 是复制单元格值的一种非常低效的方式 - 如果您真的只想要这些值,请循环设置 .Value 到旧范围中的 .Values 范围。如果您需要所有格式,您可能会被 .Copy 困住。
When you turn off the calc/screen refresh flags, please remember to turn them back on in all circumstances (even when your program exits at a different point, or causes a runtime error). Otherwise all sorts of bad things will happen. :)
当您关闭 calc/screen refresh 标志时,请记住在所有情况下都将它们重新打开(即使您的程序在不同的点退出,或导致运行时错误)。否则各种不好的事情都会发生。:)
回答by UberNubIsTrue
Just a few suggestions (would have posted as a comment but I guess I don't have the rep):
只是一些建议(本来可以作为评论发布的,但我想我没有代表):
Try refering to cell addresses instead of named ranges (doubt this would be the cause but may be causing some hit to performance)
Do your workbook formulas contain links to other workbooks? Try testing the code on a file with broken links to see if it improves performance.
If neither of these are the issue, my guess is that if the formulas are overly complex, there is probably some processing overhead being added. Try the code on a file containing only values to see if there is any improved performance.
尝试引用单元格地址而不是命名范围(怀疑这会是原因,但可能会对性能造成一些影响)
您的工作簿公式是否包含指向其他工作簿的链接?尝试在链接断开的文件上测试代码,看看它是否能提高性能。
如果这些都不是问题,我的猜测是如果公式过于复杂,可能会增加一些处理开销。在仅包含值的文件上尝试代码以查看是否有任何改进的性能。
回答by Mohan Prajapati
You can improve the speed by stopping calculation during changing cell value and after that you can enable it. please follow the link. http://webtech-training.blogspot.in/2013/10/how-to-stop-heavy-formula-calculation.html
您可以通过在更改单元格值期间停止计算来提高速度,然后您可以启用它。请点击链接。 http://webtech-training.blogspot.in/2013/10/how-to-stop-heavy-formula-calculation.html
回答by Karthikeyan Natarajan
.Cells(nextRow, 3).PasteSpecial Paste:=xlPasteValues, Transpose:=True Application.CutCopyMode = False
.Cells(nextRow, 3).PasteSpecial Paste:=xlPasteValues, Transpose:=True Application.CutCopyMode = False
I wouldn't do that. Cut,copy & Paste operations are the costliest operations, in terms of processor utilization, in an operating system.
我不会那样做。就处理器利用率而言,剪切、复制和粘贴操作是操作系统中成本最高的操作。
Instead, you could just assign the value from one cell / range to an another cell / range, as in
相反,您可以将值从一个单元格/范围分配给另一个单元格/范围,如
Cells(1,1) = Cells(1,2) or Range("A1") = Range("B1")
Hope you got my point..
希望你明白我的意思..