【问题标题】:VBA loop efficiencyVBA 循环效率
【发布时间】:2015-01-14 17:40:35
【问题描述】:

我已经多次使用网站上的答案,但这是我的第一篇文章。

在函数或子程序中执行 for 循环或仅将循环的递增值作为参数发送到函数或子程序是否更有效?

我正在将一些文本数据文件导入 Excel,解析出各个字段,然后将一些字段拆分为单个字符。我正在使用的一个文件是医生名单。我有姓名、地​​址、电话、DEA 号码、NPI 等。

在检查 DEA 号码时,我有一个接收要检查的行号的子程序,它将 DEA 拆分为各个数字,一次对这些数字执行一个检查,然后使用该 DEA 的状态修改另一个字段.如果该状态单元格包含“GOOD”以外的任何内容,则该状态单元格将显示为红色。此外,如果适用,我正在为个别数字着色。

这个子做了很多工作,我可能会稍微分解一下,但是医生文件中没有任何其他地方可以执行这个确切的步骤,所以我想我应该保持原样.

无论如何,真正的问题是我应该将行号发送到 sub 还是应该只调用 sub 并让 sub 计算行数并进行检查。在第一种情况下,我将调用 sub 的次数等于医生文件中的行数。在第二个中,我将调用 sub 一次,并且 sub 包含每一行的 for 循环。这通常更有效。

抱歉,如果我显得多余。我训练了一些复杂的软件,这种东西有时会渗入生活的其他领域。

编辑:我尝试将此添加到评论中,但在此处发布的经验不足。如果我为此违反了某些规则,请道歉...

这是我目前用来调用 sub 的代码:

'Use the Doctor Last Name as the number of rows count
Dim numRows As Integer
numRows = Application.CountA(Sheets("DoctorDEA").Range("m:m"))

'lineCtr is the Line Counter used to iterate the FOR loops
Dim lineCtr As Integer
    lineCtr = 1

'Call DEACHecking and DisplayIssues Subs
For lineCtr = 1 To numRows - 1
    DEAChecking (lineCtr)
    DisplayIssues (lineCtr)
Next lineCtr

我的问题是:最好只调用不带参数的 DEAChecking 并让 DEAChecking 计算行号,然后使用 FOR 循环还是保持原样?

【问题讨论】:

  • 如果您重复调用具有新条件的子,则子必须设置环境(例如 With Sheets("mySheet") ... End With 或 Set ws = Sheets("mySheet"), last_row = ... 等)来处理程序。如果循环在 sub 内,则环境只设置一次。
  • 性能不是问题,从磁盘或网络读取文件需要更多更长的时间。专注于编写逻辑和可维护的代码。
  • 汉斯,我想这是我问题的本质。我知道它会以任何一种方式工作。我只是不知道哪个更喜欢。

标签: performance excel for-loop vba


【解决方案1】:

这个问题现在太宽泛,无法有效回答。所以我只是提供一个小见解,可能会帮助您构建您的程序。

通常最有效的代码是所有变量都尽可能本地化的代码。如果在循环中使用全局变量或调用其他函数,这将比使用局部变量执行所有计算要糟糕得多。

【讨论】:

  • 即使在同一个模块中?在子范围之外?
  • 这一切都与处理器的 L1/L2 缓存有关。寄存器比附近的内存访问快 × 倍,因此如果您的程序将内容保持在循环范围内,它将会快得多,因为编译器会将其转换为注册表访问命令而不是指针内存访问。
【解决方案2】:

如果您想测试每一个,并为它们计时,您可以使用计时器。如果你有一个很大的差距,你将能够抓住它。如果没有,就处理时间而言,您将得到没有显着差异的答案。

  • 您可以使用它并从TimerTest 调用您的子程序,或者只是在代码开头使用Call TimerStart 并在末尾使用TimerStop
  • 使用计时器运行一些代码
  • 记录结果
  • 重复比较
  • HH:MM:SS:00 格式

计时器代码:

Public strStartTime As String
Public strEndTime As String
Public startTime As Date
Public endTime As Date


Sub timeTest()

    Call TimerStart
        'INSERT CALL TO YOUR SUB HERE
    Call TimerStop   

End Sub

Sub TimerStart()

    startTime = Now

End Sub

Sub TimerStop()

    endTime = Now

'Waited until the timer stopped to perform any additional code, such as formatting the time

    Dim TotalTime As String

    strStartTime = Format(startTime, "hh:mm:ss:" & Right(Format(Timer, "#0.00"), 2))  
    strEndTime = Format(endTime, "hh:mm:ss:" & Right(Format(Timer, "#0.00"), 2))
    TotalTime = Format(endTime - startTime, "hh:mm:ss:" & Right(Format(Timer, "#0.00"), 2))

    MsgBox ("      Start: " & strStartTime & vbNewLine & _
            "        End: " & strEndTime & vbNewLine & _
            "Total Time : " & TotalTime)               
End Sub

学分:@Nick Dandoulakis 在他的回答中设置计时器:Providing this solution to show clock time with accuracy of less than a second

【讨论】:

  • 有趣。我什至没有想过尝试运行某种计时器代码。我会看看这个。谢谢。
  • 感谢您提出问题。我一直想为此做一个计时器,但直到现在才真正开始。在您的特定示例中,它可能不明显,但这可以应用于任何过程,包括比较 WorksheetFunctions 与 VBA 函数或任何东西。它可能对大型数据集最有用。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-04-18
  • 2013-09-04
  • 2014-03-08
  • 1970-01-01
  • 2015-10-08
相关资源
最近更新 更多