为什么这个简单的宏(隐藏行)会导致Excel无响应?

时间:2017-09-18 18:28:17

标签: excel vba excel-vba

作为最近的交通科学项目的一部分,我已经获得了一张包含7094次车祸的数据表。为了过滤掉相关数据 - 在这种情况下涉及行人,死亡或严重伤害的崩溃 - 我尝试调整我在网上找到的宏。

这是我第一次涉足VBA,虽然我在C和Java方面有一些本科经验(以防这种情况证明是相关的)。代码如下:

Sub HideRows()
BeginRow = 2
EndRow = 7095
ChkCol = 10

For RowCnt = BeginRow To EndRow
    If Cells(RowCnt, ChkCol).Value > 0 Or Cells(RowCnt, ChkCol + 1).Value > 0 Or Cells(RowCnt, ChkCol + 2).Value > 0 Then
        Rows(RowCnt).EntireRow.Hidden = False
    Else
        Rows(RowCnt).EntireRow.Hidden = True
    End If
        Next RowCnt
End Sub

问题是它导致Excel无响应。我可以看到宏正在执行预期的功能,但我无法在结束时保存或重新获得对程序的控制权。

苦苦挣扎是浪费了很多时间,我感觉问题(以及随后的修复)非常非常简单 - 希望如此。

非常感谢任何建议。

2 个答案:

答案 0 :(得分:3)

要加快此代码的速度,您只需在开头添加Application.ScreenUpdating = False,在结尾添加Application.ScreenUpdating = True

Sub HideRows()
BeginRow = 2
EndRow = 7095
ChkCol = 10

Application.ScreenUpdating = False
For RowCnt = BeginRow To EndRow
    If Cells(RowCnt, ChkCol).Value > 0 Or Cells(RowCnt, ChkCol + 1).Value > 0 Or Cells(RowCnt, ChkCol + 2).Value > 0 Then
        Rows(RowCnt).EntireRow.Hidden = False
    Else
        Rows(RowCnt).EntireRow.Hidden = True
    End If
Next RowCnt
Application.ScreenUpdating = True
End Sub

现在,您可能还会在每次更新工作表时触发一些事件或条件格式。如果是这样,请在开头包含Application.EnableEvents = False,然后在循环结束时重新打开它们。

如果你真的想要,你可以简单地说:

来简化你的布尔检查
If Cells(RowCnt, ChkCol).Value Or Cells(RowCnt, ChkCol + 1).Value Or Cells(RowCnt, ChkCol + 2).Value 0 Then

因为VBA中0 = False。但这确实不是必要的,而且你的方式肯定更容易阅读。

答案 1 :(得分:3)

除了添加ScreenUpdatingEnableEvent布尔值之外,您还可以重构代码以仅执行一次隐藏/取消隐藏操作(在本例中为两次),而不是在每次循环迭代时执行此操作,这将减慢事情。您也可以关闭计算(如果影响了事情)。

Option Explicit

    Sub HideRows()

        Dim BeginRow As Integer, EndRow As Integer, ChkCol As Integer

        BeginRow = 2
        EndRow = 7095
        ChkCol = 10

        With Application
            .ScreenUpdating = False
            .EnableEvents = False
            .Calculation = xlCalculationManual
        End With

        Application.Calculation xl

        Dim rHide As Range
        Dim rShow As Range


        For RowCnt = BeginRow To EndRow

            If Cells(RowCnt, ChkCol).Value > 0 Or Cells(RowCnt, ChkCol + 1).Value > 0 Or Cells(RowCnt, ChkCol + 2).Value > 0 Then

                If Not rHide Is Nothing Then
                    Set rHide = Cells(1, RowCnt)
                Else
                    Set rHide = Union(rHide, Cells(1, RowCnt))
                End If

            Else

                If Not rShow Is Nothing Then
                    Set rShow = Cells(1, RowCnt)
                Else
                    Set rShow = rShow(rHide, Cells(1, RowCnt))
                End If

            End If

        Next RowCnt

        'show / hide appropriate ranges
        rHide.EntireRow.Visible = False
        rShow.EntireRow.Visible = True

        With Application
            .ScreenUpdating = True
            .EnableEvents = True
            .Calculation = xlCalculationAutomatic
        End With

    End Sub