Имея много столбцов для проверки, следующее обобщенное решение упростит ввод кода:
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()
.
Обратите внимание, что все еще могут показаться скрытые столбцы, которые являются пустыми. Они имеют значения в скрытых строках. Не скрывать эти столбцы намеренно, строго в соответствии с вашим комментарием.
Примечание. Если вам интересно мое соглашение об именовании переменных, оно основано на RVBA.
* Ценой потери возможности отмены строк автоматически скрываются при редактировании листа.Это может быть исправлено при необходимости.