隐藏表格行*除非*(该行中的)三列中的任何一列都不为空

时间:2018-11-28 03:48:33

标签: excel vba hide rows

我已经构建了此代码,并且工作正常。但是,我希望必须有一种更优雅的方法来将范围“ c”嵌入到Evaluate函数中,而不是如何使用“ r”来确定行号并将其构建到引用中。

(我正在学习)。 (非常精简的)xlsm的副本可在此处获取:https://www.dropbox.com/s/e6pcugqs4zizfgn/2018-11-28%20-%20Hide%20table%20rows.xlsm?dl=0

Sub HideTableRows()

Application.ScreenUpdating = False

Dim c As Range
Dim r As Integer

For Each c In Range("ForecastTable[[Group]:[Item]]").Rows
    r = c.Row
    If Application.Evaluate("=COUNTA(B" & r & ":D" & r & ") = 0") = True Then
        c.EntireRow.Hidden = True
    Else: c.EntireRow.Hidden = False
    End If
Next c

Application.ScreenUpdating = True

End Sub

3 个答案:

答案 0 :(得分:2)

没有特定的问题/问题,但这是我建议的代码改进。

  • 最值得注意的是,直到您拥有所有行,我才会执行Hidden过程。这样,您就不必重复执行只需要完成一次的操作。在循环和处理数据时,这始终是最佳实践。 在确定范围后对工作表进行更改。
  • 通过上述更改,您无需关闭ScreenUpdating
  • Evaluate函数很好,但是isEmpty可能是最好的选择。可能有一些更快的方法,也许检查多个if语句,但是在数千行中花了不到一秒的时间(可能不值得研究)。
  • 从技术上讲,您实际上并不需要遍历rows。您可以连续使用一个单元格,然后检查下两个单元格,请参见Offset的使用以生成该范围。与使用硬编码的列(“ A” /“ B” ... etc“)相比,这也带来了更大的动态性
  • Long相比,推荐使用
  • Integer,但是它很小,我仅提及because I posted about it here.。从技术上讲,您甚至不需要上述更改即可。

代码如下:

Sub HideTableRows()
    Dim c As Range, hIdeRNG As Range, WS As Worksheet

    'based on OP xlsm file.
    Set WS = Sheet4


    'used range outside of used range to avoid an if-statement on every row
    Set hIdeRNG = WS.Cells(Rows.Count, 1)

    'loops through range of single cells for faster speed
    For Each c In Range("ForecastTable[Group]").Cells

        If IsEmpty(Range(c, c.Offset(0, 2))) = 0 Then
            'only need a single member in the row.
            Set hIdeRNG = Union(hIdeRNG, c)
        End If

    Next c

    'Hides rows only if found more than 1 cell in loop
    If hIdeRNG.Cells.Count > 1 Then
        Intersect(WS.UsedRange, hIdeRNG).EntireRow.Hidden = True
    End If

End Sub

最终思想:如果您正在寻找非VBA解决方案,那么Excel可能会在2019年初发布一些重要增强功能,这些功能可能会对此类情况有用。 Click here for more info from MS.

答案 1 :(得分:1)

稍微翻转一下逻辑,为什么不只过滤这三列的空白,然后一次隐藏所有可见的过滤后的空白行呢?

类似这样的东西:

Sub DoTheHide()

    Dim myTable As ListObject
    Set myTable = Sheet4.ListObjects("ForecastTable")
    With myTable.Range
        .AutoFilter Field:=1, Criteria1:="="
        .AutoFilter Field:=2, Criteria1:="="
        .AutoFilter Field:=3, Criteria1:="="
    End With

    Dim rowsToHide As Range
    On Error Resume Next
        Set rowsToHide = myTable.DataBodyRange.SpecialCells(xlCellTypeVisible)
    On Error GoTo 0

    myTable.AutoFilter.ShowAllData

    If Not rowsToHide Is Nothing Then
        rowsToHide.EntireRow.Hidden = True
    End If

End Sub

答案 2 :(得分:1)

由于使用c来对行进行迭代,并且每行包含有问题的3个单元,所以("=COUNTA(B" & r & ":D" & r & ") = 0")等效于("=COUNTA(" & c.Address & ") = 0")。但是直接使用WorksheetFunction是更好的方法。

应注意,Range("[Table]") will return the proper result as long as the table is in the ActiveWorkbook. It would be better to use ThisWorkbook.Worksheets(“ Sheet1”)。Range(“ [Table]”)`。

Sub HideTableRows()

    Application.ScreenUpdating = False

    Dim row As Range, target As Range

    With Range("ForecastTable[[Group]:[Item]]")
        .EntireRow.Hidden = False
        For Each row In .rows
            If Application.WorksheetFunction.CountA(row) = 0 Then
                If target Is Nothing Then
                    Set target = row
                Else
                    Set target = Union(target, row)
                End If
            End If
        Next
    End With

    If Not target Is Nothing Then target.EntireRow.Hidden = True
    Application.ScreenUpdating = True

End Sub