在 Excel 中,当且仅当行中多个不连续列中的所有单元格都为空白时,如何隐藏行?我的工作表有大约 300 列,因此每次我想要执行此操作时,我无法单独单击其他每一列。
我已经尝试了下面的 VBA 代码,但它不允许超过两个范围。谢谢。
Private Sub Worksheet_Change(ByVal Target As Range)
'Updateby Extendoffice 20160913
Dim xRg As Range
Application.ScreenUpdating = False
For Each xRg In Range("B1:B825","D1:D825","F1:F825")
If xRg.Value = "" Then
xRg.EntireRow.Hidden = True
Else
xRg.EntireRow.Hidden = False
End If
Next xRg
Application.ScreenUpdating = True
End Sub
答案1
尝试这个
Option Explicit
Private Sub Worksheet_Change(ByVal Target As Range)
Dim c As Long
Application.ScreenUpdating = False
With UsedRange
For c = 2 To .Columns.Count Step 2
.AutoFilter Field:=c, Criteria1:="<>"
Next
End With
Application.ScreenUpdating = True
End Sub
答案2
由于需要检查很多列,以下通用解决方案将简化代码输入:
Private Sub Worksheet_Change(ByVal Target As Range)
Const strcRowExtent As String = "1:825"
Const strcColExtent As String = "B:BDB"
Dim boolHideRow As Boolean
Dim lngFirstColNumber As Long
Dim rngRow As Range
Dim rngVisibleRowExtent As Range
Dim rngColumn As Range
Dim rngColExtent As Range
Set rngVisibleRowExtent = Range(strcRowExtent).SpecialCells(xlCellTypeVisible)
Set rngColExtent = Range(strcColExtent)
lngFirstColNumber = rngColExtent.Column
Application.ScreenUpdating = False
For Each rngRow In rngVisibleRowExtent.Rows
boolHideRow = True
For Each rngColumn In rngColExtent.Columns
If (rngColumn.Column - lngFirstColNumber) Mod 2 = 1 Then
'Skip every second column
ElseIf rngColumn.Cells(rngRow.Row).Value2 <> "" Then
boolHideRow = False
Exit For
End If
Next rngColumn
If boolHideRow Then Rows(rngRow.Row).EntireRow.Hidden = boolHideRow
Next rngRow
Application.ScreenUpdating = True
End Sub
解释:
最初,从全套行中提取可见行集。这可以大大提高速度。*
然后代码循环遍历这组可见行。对于每一行,它循环遍历相应的列,检查非空值,并不是一旦找到第一行,就隐藏该行。(仅当所有相应列都为空白时,才会默认隐藏该行。)
编辑#2:
第二个版本(v2.1)也隐藏了列,如下面的 OP 评论所示:
Private Sub Worksheet_Change(ByVal Target As Range)
' v2.1
Const lngcSkipRows As Long = 4
Const strcRowExtent As String = "1:825"
Const strcColExtent As String = "B:BDB"
Dim boolHideRow As Boolean
Dim lngFirstColNumber As Long
Dim rngRow As Range
Dim rngVisibleRowExtent As Range
Dim rngColumn As Range
Dim rngColExtent As Range
Dim rngCol As Range
Dim rngVisibleColExtent As Range
Dim rngCroppedCol As Range
Application.ScreenUpdating = False
' Hide rows
Set rngVisibleRowExtent _
= Range(strcRowExtent).Columns(1).SpecialCells(xlCellTypeVisible).EntireRow
Set rngColExtent = Range(strcColExtent)
lngFirstColNumber = rngColExtent.Column
For Each rngRow In rngVisibleRowExtent.Rows
boolHideRow = True
For Each rngColumn In rngColExtent.Columns
If (rngColumn.Column - lngFirstColNumber) Mod 2 = 1 Then
'Skip every second column
ElseIf rngColumn.Cells(rngRow.Row).Value2 <> "" Then
boolHideRow = False
Exit For
End If
Next rngColumn
If boolHideRow Then Rows(rngRow.Row).EntireRow.Hidden = boolHideRow
Next rngRow
'Hide Columns
Set rngVisibleColExtent _
= Range(strcColExtent).Rows(1).SpecialCells(xlCellTypeVisible).EntireColumn
For Each rngCol In rngVisibleColExtent.Columns
Set rngCroppedCol _
= rngCol _
.Resize(Range(strcRowExtent).Rows.Count - lngcSkipRows) _
.Offset(lngcSkipRows)
If WorksheetFunction.CountA(rngCroppedCol) = 0 Then rngCol.Hidden = True
Next rngCol
Application.ScreenUpdating = True
End Sub
解释:
事实证明,当存在隐藏行时提取可见列集(反之亦然)需要对提取公式进行轻微修改。
循环遍历可见列集的代码比循环遍历行的代码更简单,因为不需要内部循环。CountA()
而是使用工作表函数。
请注意,可能仍有未隐藏的列,这些列全为空白。这些列的值位于隐藏行中。不隐藏这些列是故意的,完全符合您的评论。
注意:如果你对我的变量命名约定感到好奇,它基于右心室瓣膜炎球菌。
*代价是无法撤消编辑工作表时自动隐藏的行。如果需要,可以补救。