Excel vba:如果更新状态栏,程序需要很长时间

问题描述 投票:0回答:2

我有一个程序,创建类100 000Client对象,将它们放入数组,然后通过该数组100次,每次通过Client函数分配每个Rnd()一个不同的随机数:

主要子:

Sub start()
    Dim i As Long
    Dim j As Long

    Dim clientsColl() As Client
    ReDim clientsColl(1 To 100000) As Client

    For j = 1 To 100000
        Set clientsColl(j) = New Client
        clientsColl(j).setClientName = "Client_" & j

        Application.StatusBar = "Getting client " & j

        DoEvents
    Next


    Dim tempCount As Long
    Dim clientCopy As Variant
    For i = 1 To 100
        tempCount = 0
        For Each clientCopy In clientsColl
            tempCount = tempCount + 1

            clientCopy.generateRandom

            'Application.StatusBar = "Calculating " & i & ": " & tempCount & "/" & 100000  '(1)

            'DoEvents
        Next

        Application.StatusBar = "Calculating " & i

        DoEvents
    Next

    MsgBox ("done")
End Sub

Client类:

Option Explicit

Dim clientName As String
Dim randomNumber As Double

Public Sub generateRandom()
    randomNumber = Rnd()
End Sub

Public Property Get getClientName()
    getClientName = clientName
End Property

Public Property Let setClientName(value As String)
    clientName = value
End Property

问题是,执行时间取决于行(1)是否被注释掉。如果它被执行,状态栏将被更新,但执行时间非常慢。如果没有执行,程序会很快完成。

为什么会这样?

excel vba excel-vba
2个回答
1
投票

只要你呆在里面,VBA就够快了。每当你转向Excel时,它可能会变得更慢,因为Excel每次控制时都会进行数千次操作。你可以考虑像我在我的应用程序中那样关闭一些Excel服务:

Application.Calculation = xlCalculationManual
Application.ScreenUpdating = False
Application.DisplayStatusBar = False
Application.EnableEvents = False
ActiveSheet.DisplayPageBreaks = False

...据我所知,当您关闭自动更新时,DoEvents是使Excel更新状态栏的最佳方式。另一个省时的解决方法可以是仅显示内循环内的每第100或第1000条消息。


1
投票

在进行进度条或状态栏时,您需要明智地使用它。

基本上,进度信息只需每0.1秒左右刷新一次。

知道你的最大循环次数和所需的时间,你可能只想每次(在你的情况下)更新信息,比如说,循环的100次迭代。

这是这样完成的:如果j mod 100 = 0则application.statusbar =“...”:doevents

通常我甚至可以使用少于我的进度条的doevents(如果是j mod则使用第二个)。

© www.soinside.com 2019 - 2024. All rights reserved.