【问题标题】:VBA excel , improve performance without loopsVBA excel,无循环提高性能
【发布时间】:2017-01-18 16:48:47
【问题描述】:

我有两张相同的工作表,我想获取其中的行,它们在多列中是相同的(工作表总是 63 列和 504 行并且还在增加),我正在使用两个 for 循环来增加一行和然后将另一行中的所有行与该行进行比较,然后再次增加该行并将另一行的所有行与该行等进行比较。直到最后一行,然后是一个 if 循环,看看它们是否符合我的条件。问题是它花费了太多时间(大约 8 分钟),我尝试使用查找功能但它失败了,因为它只能取一个值。我添加了错误的屏幕更新、计算和启用事件,甚至将状态栏更改为非常基本的东西以提高性能,但它们都没有给我想要的结果。

我怎样才能以任何可能的方式提高性能,新功能或任何东西??

PS 有时某些条件并不重要,它取决于某些单元格上的真值或假值。

For Row_S = 2 To MAX_Row_S
  SourceMonth = Worksheets(NBG_SourceRegionDataWorksheetName).Cells(Row_S, SOP).Value
  SourceMonth = DatePart("m", SourceMonth)
  SourceYear = Worksheets(NBG_SourceRegionDataWorksheetName).Cells(Row_S, SOP).Value
  SourceYear = DatePart("yyyy", SourceYear)
  SourceCarmaker = Worksheets(NBG_SourceRegionDataWorksheetName).Cells(Row_S, carmaker).Value
  SourceProject = Worksheets(NBG_SourceRegionDataWorksheetName).Cells(Row_S, Project).Value
  SourceFamily = Worksheets(NBG_SourceRegionDataWorksheetName).Cells(Row_S, Family).Value
  SourceStatus = Worksheets(NBG_SourceRegionDataWorksheetName).Cells(Row_S, Status).Value
  SourceShare = Worksheets(NBG_SourceRegionDataWorksheetName).Cells(Row_S, Share).Value
  SourceCst = Worksheets(NBG_SourceRegionDataWorksheetName).Cells(Row_S, "A").Value
  SourcePID = Worksheets(NBG_SourceRegionDataWorksheetName).Cells(Row_S, ProjectID).Value

  ' Take the data from NBG_Data_Region sheet to be Compared with each row of the NBG_Data_Source_Region sheet
  For Row_T = 2 To MAX_Row_T
    If Row_T >= MAX_Row_T Then
        Exit For
    End If

    NBGMonth = Worksheets(NBG_RegionaDataWorksheetName).Cells(Row_T, SOP).Value
    NBGMonth = DatePart("m", NBGMonth)
    NBGYear = Worksheets(NBG_RegionaDataWorksheetName).Cells(Row_T, SOP).Value
    NBGYear = DatePart("yyyy", NBGYear)
    NBGCarmaker = Worksheets(NBG_RegionaDataWorksheetName).Cells(Row_T, carmaker).Value
    NBGProject = Worksheets(NBG_RegionaDataWorksheetName).Cells(Row_T, Project).Value
    NBGFamily = Worksheets(NBG_RegionaDataWorksheetName).Cells(Row_T, Family).Value
    NBGStatus = Worksheets(NBG_RegionaDataWorksheetName).Cells(Row_T, Status).Value
    NBGShare = Worksheets(NBG_RegionaDataWorksheetName).Cells(Row_T, Share).Value
    NBGCst = Worksheets(NBG_RegionaDataWorksheetName).Cells(Row_T, "A").Value
    NBGPID = Worksheets(NBG_RegionaDataWorksheetName).Cells(Row_T, ProjectID).Value

    ' StatusBar Show
    Application.StatusBar = "Running"
    'Application.StatusBar = "VerifyMultipleCustomerProjects. Progress: " & Row_S & " of " & MAX_Row_S
    ' Check if any project in the NBG_Data_Region have multiple customers and add it ti the sheet Issue_MultipleCustomerProjects

    ' NAF 20161208

    'Test with Source of YEAR and MONTH
     If ((NBGMonth = SourceMonth Or Worksheets(Issue_MultipleCustomerProjectsWorksheetName).Range("C21") = True) And _
        (NBGYear = SourceYear Or Worksheets(Issue_MultipleCustomerProjectsWorksheetName).Range("C25") = True) And _
        (SourceCarmaker = NBGCarmaker Or Worksheets(Issue_MultipleCustomerProjectsWorksheetName).Range("G25") = True) And _
        (SourceProject = NBGProject Or Worksheets(Issue_MultipleCustomerProjectsWorksheetName).Range("F25") = True) And _
        (SourceFamily = NBGFamily Or Worksheets(Issue_MultipleCustomerProjectsWorksheetName).Range("E25") = True) And _
        (SourceShare + NBGShare <> 1 Or Worksheets(Issue_MultipleCustomerProjectsWorksheetName).Range("H25") = True) And NBGCst <> SourceCst) Then

【问题讨论】:

  • 使用数组而不是不断地访问工作表。将所有内容加载到两个数组中,然后将数据输出到另一个您将回发一次的数组。这样,您只能访问工作表 3 次。它将运行时间缩短到几秒钟。
  • 我会将数据加载到数组中。然后,您可以在一个事务中分别从工作表中提取两组数据,然后在数组之间进行任何您想要的比较。就目前而言,您正在进行大约 280 万笔交易,这可以解释速度问题。 - @Scott Craner,同时发布,但你有完全相同的逻辑真是太好了:)
  • @ScottCraner 谢谢,数组工作有点棘手,但我正在努力,祝我好运:)

标签: excel vba performance


【解决方案1】:

你有没有尝试添加

Application.ScreenUpdating = False
Application.EnableEvents = False
Application.DisplayAlerts = False

在代码的开头,并且

Application.ScreenUpdating = True
Application.EnableEvents = True
Application.DisplayAlerts = True

在代码的末尾?

这将关闭屏幕更新、事件和警报,从而加快运行时间。

此外,如果您决定采用这条路线,加载和卸载数组是最快的方法。

加载数组的示例:

Dim arr() As Variant ' let brackets empty, not Dim arr(1) As Variant !

For Each a In Range.Cells
    ' change / adjust the size of array
    ReDim Preserve arr(1 To UBound(arr) + 1) As Variant

    ' add value on the end of the array
    arr(UBound(arr)) = a.Value
Next

遍历数组以提取数据的示例:

For Each element In arr 'Each array element
    do_something (element)
Next element

【讨论】:

  • 我做了但是运行时间减少了几秒钟,你能解释一下加载和卸载数组吗??
  • @NasserAlFanek 请查看我的更新答案,因为我提供了一个示例。
  • 非常感谢您的澄清,我将从数组使用开始,谢谢。
  • 只有两个问题,我怎样才能只从我分配的某些列中插入值,我的数组中可以有字符串和整数吗??
猜你喜欢
  • 2020-08-25
  • 1970-01-01
  • 1970-01-01
  • 2013-01-29
  • 2018-11-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-11-11
相关资源
最近更新 更多