切换宏VBA运行缓慢

时间:2017-10-19 13:26:59

标签: vba performance excel-vba excel

我刚刚完成了我的第一个宏,但看起来它运行速度非常慢,经过几次循环就冻结了。之前我遇到了数据显示的问题,但我通过在第一行放置真值来解决它。

宏点是每30秒在仪表板上显示不同的数据。

请在下面找到我的代码:

Public Sub Switch()
    Do
    With ActiveWorkbook.SlicerCaches("Slicer_country1")
        .SlicerItems("NL").Selected = True
        .SlicerItems("SP").Selected = False
        .SlicerItems("GB").Selected = False
    End With
    With ActiveWorkbook.SlicerCaches("Slicer_Project1")
        .SlicerItems("XX").Selected = True
        .SlicerItems("YY").Selected = False
        .SlicerItems("ZZ").Selected = False
        Application.Wait Now + TimeValue("00:00:30")
    End With
    With ActiveWorkbook.SlicerCaches("Slicer_Project1")
        .SlicerItems("XX").Selected = True
        .SlicerItems("YY").Selected = False
        .SlicerItems("ZZ").Selected = False
         Application.Wait Now + TimeValue("00:00:30")
    End With
    With ActiveWorkbook.SlicerCaches("Slicer_Project1")
        .SlicerItems("XX").Selected = True
        .SlicerItems("YY").Selected = False
        .SlicerItems("ZZ").Selected = False
         Application.Wait Now + TimeValue("00:00:30")
    End With
    Loop
End Sub

最近的解决方案及时应用程序,但它只能在最后一次调用时正常工作(我只得到想要的字段,在前2个其他按钮中不会关闭),是否有任何解决方案只能在每个按钮上显示所需的值打电话?

Dim CallNumber As Integer
Sub ScheduleChange()
Change
Application.OnTime Now + TimeValue("00:00:05"), "ScheduleChange"
End Sub

Sub Change()
CallNumber = CallNumber + 1
With ActiveWorkbook.SlicerCaches("Slicer_Project1")
.SlicerItems("XX").Selected = (CallNumber = 1)
.SlicerItems("YY").Selected = False
.SlicerItems("ZZ").Selected = False
End With
With ActiveWorkbook.SlicerCaches("Slicer_Project1")
.SlicerItems("YY").Selected = (CallNumber = 2)
.SlicerItems("XX").Selected = False
.SlicerItems("ZZ").Selected = False
End With
With ActiveWorkbook.SlicerCaches("Slicer_Project1")
.SlicerItems("ZZ").Selected = (CallNumber = 3)
.SlicerItems("XX").Selected = False
.SlicerItems("YY").Selected = False
End With
If CallNumber = 3 Then
CallNumber = 0
End If
End Sub 

嗨再次,我使用下面的代码,但宏仍然不会显示一个按钮,它从第一个按钮到第二个按钮而没有取消选择前一个按钮,是否有任何命令强制它只显示一次价值? Debug显示未设置Object变量或With块变量。

Dim CallNumber As Integer
Sub ScheduleChange()
Change
Application.OnTime Now + TimeValue("00:00:05"), "ScheduleChange"
End Sub

Sub Change()
CallNumber = CallNumber + 1
With ActiveWorkbook.SlicerCaches("Slicer_Project1")
.SlicerItems("XX").Selected = (CallNumber = 1)
.SlicerItems("YY").Selected = (CallNumber = 2)
.SlicerItems("ZZ").Selected = (CallNumber = 3)
End With
If CallNumber = 3 Then
CallNumber = 0
End If
End Sub

2 个答案:

答案 0 :(得分:1)

来自here

应用程序等待将冻结您的应用程序,并不是一种非常有效的方法来管理延迟。

使用此延迟功能代替Application.Wait

Private Sub delay(seconds As Long)
    Dim endTime As Date
    endTime = DateAdd("s", seconds, Now())
    Do While Now() < endTime
        DoEvents
    Loop
End Sub

答案 1 :(得分:0)

正如它所说,使用Application.Wait会阻止Excel。但我认为这样做比Do-LoopDoEvents有更好的方法 - 您可以尝试Application.OnTime安排您希望事件发生的时间:

您当前的代码是这样的:

Sub BlockingChange()
    Dim i As Integer
    i = 0
    Do
        Range("A1").Value2 = i
        Application.Wait Now + TimeValue("0:00:01")
        i = i + 1
    Loop
End Sub

...完全阻止Excel。

OnTime的替代方案是:

Sub NonBlockingChange()
    Update
    Application.OnTime Now + TimeValue("0:00:01"), "NonBlockingChange"
End Sub

Sub Update()
    Range("A1").Value2 = CInt(Range("A1").Value2) + 1
End Sub

现在要警告每次运行它时,它会调度另一个运行子实例,所以如果你运行宏两次,它将每秒运行两次,等等。

要取消这些排队的事件,您只需将False作为第四个参数传递:

Sub StopChanges()

On Error GoTo Catch
    Application.OnTime Now + TimeValue("0:00:01"), "NonBlockingChange", , False
    Exit Sub
Catch:
    MsgBox ("Nothing to stop")

End Sub

这应该对你有用。只需将Update的正文替换为您想要更改的内容,并将1秒超时更改为您的值。

修改

Lukas,在您编辑的代码中,您刚刚将Application.Wait替换为Application.OnTime。它们不一样,您需要以不同的方式使用它们,再次阅读示例以了解如何使用它们。

从您编辑的代码中,您需要更改以下内容:

  • 没有更多的Do-Loop。阅读上面的示例,看看我们不再需要循环了,OnTime调用会设置一个调用子程序的计划
  • OnTime需要一个参数,即要调用的子名称
  • 因此,这意味着您需要稍微重构(更改)您的代码以使用新结构

像这样的东西(你需要定制并完成它):

Dim CallNumber As Integer
Sub ScheduleChange()
    Change
    Application.OnTime Now + TimeValue("0:00:10"), "ScheduleChange"
End Sub

Sub Change()
    'Select a different slicer on each call to this function
    CallNumber = CallNumber + 1
    With ActiveWorkbook.SlicerCaches("Slicer_Project1")
        .SlicerItems("XX").Selected = (CallNumber = 1)
        .SlicerItems("YY").Selected = (CallNumber = 2)
        .SlicerItems("ZZ").Selected = (CallNumber = 3)
    End With

    ' When it gets to 3, roll over to the first one again
    If CallNumber = 3 Then
        CallNumber = 0
    End If
End Sub

然后启动它,你会打电话给ScheduleChange。将这些功能放在他们自己的模块中,否则您将收到“无法运行宏”错误。