当我运行 VBA 代码时,Excel 进入“无响应”模式。这个可以吗?有办法消除这个吗?

And*_*ton 1 excel performance vba

当我单击按钮运行我的代码时,我会看到蓝色的加载圆圈,如果我等待大约 150 秒,我的代码就会运行,有时会进入“无响应”模式,并且所有内容都会正确输出。但是,如果我单击按钮启动代码并等待 10 秒,然后单击窗口并强制其进入“无响应”模式,我的代码将在大约 30 秒内完成所有正确的输出。

Option Explicit
Option Base 1
Private Sub CommandButton1_Click()
    Dim loadtypemax As Single, column As Single, row As Single
    Dim loadtype As String, number As String
    Dim loadcombosmax As Single

    Application.ScreenUpdating = False
    Application.Calculation = xlCalculationManual

    loadtypemax = ((Cells(Rows.count, "L").End(xlUp).row))
    loadcombosmax = ((Cells(Rows.count, "E").End(xlUp).row))

    column = 6
    For row = 2 To loadcombosmax
        If Cells(row, column) > 0 Then
            number = Cells(row, column)
            loadtype = Cells(row, (column - 2))

            If number = "" Then
            ElseIf number > 0 Then
                ActiveWorkbook.Worksheets("STAADloadtypes").Cells(number, 1) = "Load"
                ActiveWorkbook.Worksheets("STAADloadtypes").Cells(number, 2) =
                ActiveWorkbook.Worksheets("Load Cases").Cells(row, column).Value
                ActiveWorkbook.Worksheets("STAADloadtypes").Cells(number, 4) = "Title"
                ActiveWorkbook.Worksheets("STAADloadtypes").Cells(number, 5) =
                ActiveWorkbook.Worksheets("Load Cases").Cells(row, column - 4).Value
            End If

        ElseIf Cells(row, column) = "" Then
        End If

        If Cells(row, column) > 0 Then
            Call LRFD(loadtype, number, loadcombosmax)
        End If

    Next row
    Application.ScreenUpdating = True
    Application.Calculation = xlCalculationAutomatic

End Sub

Sub LRFD(loadtype As String, number As String, loadcombosmax As Single)
    Dim countrow As Single, countcolumn As Single, row As Single, column As Single


    Application.Calculation = xlCalculationManual
    Worksheets("STAADloadcombos").Activate

    countrow = ActiveWorkbook.Worksheets("LRFD").Cells(Rows.count,
    "A").End(xlUp).row
    countcolumn = (loadcombosmax - 1) * 2

    For row = 1 To countrow
        For column = 4 To countcolumn Step 2
            If loadtype = ActiveWorkbook.Worksheets("LRFD").Cells(row, column).Value
            Then
            Call STAADloadcombos(column, number, countrow, countcolumn, row)
        End If
    Next column
Next row

Application.Calculation = xlCalculationAutomatic

End Sub

Sub STAADloadcombos(column As Single, number As String, countrow As Single, countcolumn As Single, row As Single)
    Dim r As Integer, rowrow As Single, c As Integer
    Dim rr As Single

    Application.Calculation = xlCalculationManual

    r = row * 2
    rowrow = r - 1

    ActiveWorkbook.Worksheets("STAADloadcombos").Cells(rowrow, 3) =
    ActiveWorkbook.Worksheets("LRFD").Cells(row, 1).Value
    ActiveWorkbook.Worksheets("STAADloadcombos").Cells(rowrow, 2) =
    ActiveWorkbook.Worksheets("LRFD").Cells(row, 2).Value
    ActiveWorkbook.Worksheets("STAADloadcombos").Cells(rowrow, 1) = "Load Comb"

    For c = 1 To countcolumn Step 2
        If ActiveWorkbook.Worksheets("STAADloadcombos").Cells(r, c) = "" Then
            ActiveWorkbook.Worksheets("STAADloadcombos").Cells(r, c) = number
            c = countcolumn
        End If
    Next c

    For c = 2 To countcolumn Step 2
        If ActiveWorkbook.Worksheets("STAADloadcombos").Cells(r, c) = "" Then
            ActiveWorkbook.Worksheets("STAADloadcombos").Cells(r, c) =
            ActiveWorkbook.Worksheets("LRFD").Cells(row, column - 1).Value
            c = countcolumn
        End If
    Next c

    Application.Calculation = xlCalculationAutomatic

End Sub

Private Sub CommandButton2_Click()

    Worksheets("STAADloadcombos").Range("A1:BA500").ClearContents
    Worksheets("STAADloadtypes").Range("A1:BA500").ClearContents

End Sub
Run Code Online (Sandbox Code Playgroud)

有什么方法可以清理我的代码以使其运行得更快吗?我读到了有关屏幕更新和计算应用程序命令并将它们放入但它们似乎没有花费任何东西。我是否正确地放置了它们?

Mat*_*don 5

是的,这是正常的。

Excel 和 VBA 是单线程的,这意味着在任何给定时间只能执行一条指令。这意味着当 Excel 忙于执行低效的 VBA 代码时,它无法响应应用程序事件,例如用户单击某处或激活另一个工作表。

您可以DoEvents在代码中的重要位置添加调用,以便 Excel 有机会执行其他事件的处理程序;您的代码将在下一条指令处恢复,并且 Excel 将显得响应更快。

然而,它也会使您的代码执行速度变慢,因为DoEvents本质上允许其他代码运行 - 当其他代码运行时,您的代码本质上被搁置。

此外,允许 Excel 响应用户操作可能会对ActiveSheet(隐式或显式)编写的代码产生灾难性后果 - 因为您不知道返回之前和之后是否ActiveSheet相同DoEvents

与普遍的看法相反,Application.ScreenUpdating切换和Application.EnableEvents关闭不会加速您的代码。它只是削减任何其他可以响应您的操作而执行的代码。Application.Calculation

例如,每当您写入单元格时,Excel 都会评估该单元格是否具有从属单元格,然后重新计算这些单元格:关闭自动计算可以防止这种情况发生。Excel 还会Worksheet.Change在修改后的工作表上触发一个事件,并Workbook.WorksheetChange在该工作簿上触发一个事件 - 如果有处理这些事件的 VBA 代码,则会调用该事件。关闭EnableEvents可以防止这种情况发生。Excel 每次都会重新绘制其 UI:关闭ScreenUpdating该功能可以防止这种情况发生。最终结果是您的代码确实完成得更快,但它并不比以前更高效。

更改代码以提高效率对于本网站来说太过宽泛。为此,请在Code Review Stack Exchange上向审阅者展示您的代码。