如何加速这个宏?

huangapple go评论124阅读模式
英文:

How could I speed up this macro?

问题

我是您的中文翻译,以下是您提供的 VBA 代码的翻译部分:

  1. 我对VBA相对陌生,而这个宏在仅有少数几个条目时可能需要几分钟才能运行完成,我只是好奇我在做什么错误以及如何提高运行速度。
  2. 我尝试输入一些据说可以加快代码速度的行,然而,在测试后,运行时间没有任何差异。
  3. 子过程 CompareMacro()
  4. Application.ScreenUpdating = True
  5. Application.EnableEvents = True
  6. Application.AskToUpdateLinks = True
  7. Application.DisplayAlerts = True
  8. Application.Calculation = xlAutomatic
  9. ThisWorkbook.Date1904 = False
  10. Application.StatusBar = False
  11. Dim currentRow As Long
  12. Dim currentSearch As String
  13. Dim compareCount, arrCount As Long
  14. Dim columnCount, compareColumnCount As Variant
  15. Dim partListCount As Variant
  16. partListCount = Worksheets("PART LIST").UsedRange.Value
  17. columnCount = Worksheets("PART LIST").UsedRange.Columns.Count
  18. compareColumnCount = Worksheets("COMPARE").UsedRange.Columns.Count
  19. compareCount = 0
  20. arrCount = 0
  21. currentRow = 2
  22. For x = 1 To columnCount
  23. If InStr(Worksheets("PART LIST").Cells(1, x).Value, "modelno") Then
  24. compareCount = compareCount + 1
  25. End If
  26. Next x
  27. ReDim arr(1 To compareCount) As Variant
  28. ReDim arr2(1 To compareCount) As Variant
  29. For y = 1 To columnCount
  30. If InStr(Worksheets("PART LIST").Cells(1, y).Value, "modelno") Then
  31. arrCount = arrCount + 1
  32. arr(arrCount) = y
  33. arr2(arrCount) = Worksheets("PART LIST").Cells(1, y).Value
  34. End If
  35. Next y
  36. While (Not (IsEmpty(Worksheets("COMPARE").Cells(currentRow, 1))))
  37. For b = 1 To compareCount
  38. For c = 1 To UBound(partListCount)
  39. If (partListCount(c, arr(b)) = Worksheets("COMPARE").Cells(currentRow, 1).Value) Then
  40. For d = 1 To compareColumnCount
  41. If (Worksheets("COMPARE").Cells(1, d) = arr2(b)) Then
  42. Worksheets("COMPARE").Cells(currentRow, d) = partListCount(c, 1)
  43. End If
  44. Next d
  45. End If
  46. Next c
  47. Next b
  48. currentRow = currentRow + 1
  49. Wend
  50. Application.ScreenUpdating = False
  51. Application.EnableEvents = False
  52. Application.AskToUpdateLinks = False
  53. Application.DisplayAlerts = False
  54. Application.Calculation = xlAutomatic
  55. ThisWorkbook.Date1904 = False
  56. ActiveWindow.View = xlNormalView
  57. End Sub

如果您需要进一步的帮助或翻译,请告诉我。

英文:

I'm relatively new to VBA, and this macro can take minutes to wrong on only a few entries and I'm just curious as to what I'm doing wrong and how to improve the runtime speeds.

I tried inputting some lines that were supposedly able to speed up my code, however, after testing there's no difference in runtime whatsoever.

  1. Sub CompareMacro()
  2. Application.ScreenUpdating = True
  3. Application.EnableEvents = True
  4. Application.AskToUpdateLinks = True
  5. Application.DisplayAlerts = True
  6. Application.Calculation = xlAutomatic
  7. ThisWorkbook.Date1904 = False
  8. Application.StatusBar = False
  9. Dim currentRow As Long
  10. Dim currentSearch As String
  11. Dim compareCount, arrCount As Long
  12. Dim columnCount, compareColumnCount As Variant
  13. Dim partListCount As Variant
  14. partListCount = Worksheets("PART LIST").UsedRange.Value
  15. columnCount = Worksheets("PART LIST").UsedRange.Columns.Count
  16. compareColumnCount = Worksheets("COMPARE").UsedRange.Columns.Count
  17. compareCount = 0
  18. arrCount = 0
  19. currentRow = 2
  20. For x = 1 To columnCount
  21. If InStr(Worksheets("PART LIST").Cells(1, x).Value, "modelno") Then
  22. compareCount = compareCount + 1
  23. End If
  24. Next x
  25. ReDim arr(1 To compareCount) As Variant
  26. ReDim arr2(1 To compareCount) As Variant
  27. For y = 1 To columnCount
  28. If InStr(Worksheets("PART LIST").Cells(1, y).Value, "modelno") Then
  29. arrCount = arrCount + 1
  30. arr(arrCount) = y
  31. arr2(arrCount) = Worksheets("PART LIST").Cells(1, y).Value
  32. End If
  33. Next y
  34. While (Not (IsEmpty(Worksheets("COMPARE").Cells(currentRow, 1))))
  35. For b = 1 To compareCount
  36. For c = 1 To UBound(partListCount)
  37. If (partListCount(c, arr(b)) = Worksheets("COMPARE").Cells(currentRow, 1).Value) Then
  38. For d = 1 To compareColumnCount
  39. If (Worksheets("COMPARE").Cells(1, d) = arr2(b)) Then
  40. Worksheets("COMPARE").Cells(currentRow, d) = partListCount(c, 1)
  41. End If
  42. Next d
  43. End If
  44. Next c
  45. Next b
  46. currentRow = currentRow + 1
  47. Wend
  48. Application.ScreenUpdating = False
  49. Application.EnableEvents = False
  50. Application.AskToUpdateLinks = False
  51. Application.DisplayAlerts = False
  52. Application.Calculation = xlAutomatic
  53. ThisWorkbook.Date1904 = False
  54. ActiveWindow.View = xlNormalView
  55. End Sub

答案1

得分: 2

我看不到你的工作簿的结构,但是如果我们假设你的原始代码按预期执行但速度较慢,那么可以通过一次性读取和写入所有单元格来提高速度(尽可能多)。

然而,这有一定限制。如果"COMPARE"工作表上有公式,那么你不能一次性覆盖所有单元格,因为单元格将不再包含像=1+2这样的公式,而会被覆盖为3。

所以,选项A是一次性覆盖所有内容,选项B是逐个覆盖要修改的单元格。我(未经测试的)宏如下:

  1. Public Sub CompareMacro()
  2. ' 代码部分
  3. End Sub

Application.ScreenUpdatingApplication.StatusBar 的内容在这种情况下没有任何改进,只会降低代码的可读性,并且如果宏失败会让用户感到不便。因此,可以将其删除。

如果你想进一步提高性能,应该重新考虑你的工作表结构,并规范化你的数据库。

英文:

I can't see the structure of your workbook, however, if we assume that your original code does what it is supposed to do but slowly, then it can be made faster by reading and writing all cells in one call (as much as possible).

There is a limitation to this, however. If there are formulas on the COMPARE worksheet, then you can't overwrite all cells at once because the cell would not contain, e.g. =1+2 anymore but would be overwritten with 3.

So Option A is to overwrite everything at once, Option B is to overwrite only cells that you want to modify, one by one. My (untested) macro is the following:

  1. Public Sub CompareMacro()
  2. Dim partlist() As Variant: partlist = ThisWorkbook.Worksheets("PART LIST").UsedRange.Value
  3. Dim mCount As Long: mCount = 0
  4. Dim mCols() As Long
  5. Dim mVals() As Variant
  6. Dim pCol As Long: For pCol = LBound(partlist, 2) To UBound(partlist, 2)
  7. If InStr(1, partlist(1, pCol), "modelno") <> 0 Then
  8. mCount = mCount + 1
  9. ReDim Preserve mCols(1 To mCount)
  10. mCols(mCount) = pCol
  11. ReDim Preserve mVals(1 To mCount)
  12. mVals(mCount) = partlist(1, pCol)
  13. End If
  14. Next
  15. Dim compare() As Variant: compare = ThisWorkbook.Worksheets("COMPARE").UsedRange.Value
  16. Dim cRow As Long: For cRow = LBound(compare, 1) + 1 To UBound(compare, 1)
  17. Dim m As Long: For m = 1 To mCount: Dim mCol As Long: mCol = mCols(m): Dim mVal As Variant: mVal = mVals(m)
  18. Dim pRow As Long: For pRow = LBound(partlist, 1) To UBound(partlist, 1)
  19. If partlist(pRow, mCol) = compare(cRow, 1) Then
  20. Dim cCol As Long: For cCol = LBound(compare, 2) To UBound(compare, 2)
  21. If compare(1, cCol) = mVal Then
  22. ' Option A
  23. compare(cRow, cCol) = partlist(pRow, 1)
  24. ' Option B
  25. ' ThisWorkbook.Worksheets("COMPARE").Cells(cRow, cCol) = partlist(pRow, 1)
  26. End If
  27. Next
  28. End If
  29. Next
  30. Next
  31. Next
  32. ' Option A
  33. ThisWorkbook.Worksheets("COMPARE").UsedRange.Value = compare
  34. End Sub

The Application.ScreenUpdating ... Application.StatusBar stuff does not make any improvement in this case, just makes the code less readable, and annoys the user if the macro fails. So, get rid of it.

If you want to further improve the performance, you should reconsider your worksheets' structure, and normalize your database.

huangapple
  • 本文由 发表于 2023年6月8日 23:36:14
  • 转载请务必保留本文链接:https://go.coder-hub.com/76433532.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定