Я пытаюсь отфильтровать таблицу, которая иногда может привести к отсутствию данных. Я пытаюсь подсчитать видимые строки, чтобы сделать это определение.
Если только строка заголовка - "Без ячеек" Если есть видимые строки - "Есть провайдер"
В приведенном ниже коде кажется, что отфильтрованные строки все еще подсчитываются...
Sub Add_New_Name()
Dim pTable1 As Range
Dim pVisible As Range
'Application.DisplayAlerts = False
'Application.ScreenUpdating = False
' Select Roster & Clear Roster Table Filters
Sheet8.Activate
Sheet8.ListObjects("Table1").AutoFilter.ShowAllData
' Set Variables
Set pTable1 = Range("B2").CurrentRegion
Set pVisible = pTable1.SpecialCells(xlCellTypeVisible)
' Check for New Associate
With Sheet8.ListObjects("Table1")
.Range.AutoFilter Field:=23, Criteria1: = "0"
.Range.AutoFilter Field:=22, Criteria1: = "Associate"
End With
If pVisible.Rows.Count > 1 Then
MsgBox "No Cells"
Else
MsgBox "Has Provider"
End If
End Sub
Установите pVisible после автофильтра.
With Sheet8.ListObjects("Table1")
.Range.AutoFilter Field:=23, Criteria1: = "0"
Range.AutoFilter Field:=22, Criteria1: = "Associate"
End With
Set pVisible = pTable1.SpecialCells(xlCellTypeVisible)
Альтернативное решение
Dim pTable As ListObject 'use instead of range
Dim pVisible As Range
Set pTable = Sheet8.ListObjects("Table1")
With pTable
.Range.AutoFilter Field:=23, Criteria1: = "0"
.Range.AutoFilter Field:=22, Criteria1: = "Associate"
End With
On Error Resume Next
Set pVisible = pTable.DataBodyRange.SpecialCells(xlCellTypeVisible)
On Error GoTo 0
'Stores range of visible cells. Does not raise error in case of not data.
If Not pVisible Is Nothing Then 'Checks if some info is present.
MsgBox "Has Provider"
Else
MsgBox "No Provider"
End If
Это имеет гораздо больше смысла. Оцените пояснения к шагам.
Это решение неверно, потому что оно вернет «Нет провайдера» для любого количества видимых строк, если первая строка данных (строка под заголовком) не видна, потому что rows_visible
, Rows.Count
, вернет 1, поскольку относится только к первому область несмежного диапазона.
Вот как это обычно делается:
Sub Add_New_Name()
Dim pVisible As Range
Sheet8.Activate
With Sheet8.ListObjects("Table1")
.AutoFilter.ShowAllData
.Range.AutoFilter Field:=23, Criteria1: = "0"
.Range.AutoFilter Field:=22, Criteria1: = "Associate"
On Error Resume Next 'ignore error if no visible rows
Set pVisible = .DataBodyRange.SpecialCells(xlCellTypeVisible) 'ignore headers
On Error GoTo 0 'stop ignoring errors
End With
If pVisible Is Nothing Then
MsgBox "No Cells"
Else
MsgBox "Has Provider"
End If
End Sub
Лучше исключить заголовки из вызова SpecialCells
и перехватить/игнорировать ошибку, если строки не видны.
Таким образом, если вы продолжите работать с pVisible
, у вас не будет заголовков.
Спасибо. Мне нравится, как вся фильтрация живет внутри With. Гораздо чище.
On Error Resume Next
, как показано в ответе Тима Уильямса.Option Explicit
Sub Add_New_Name()
Application.ScreenUpdating = False
Dim cc As Long
With Sheet8.ListObjects("Table1")
If .ShowAutoFilter Then ' remove filter
If .AutoFilter.FilterMode Then .AutoFilter.ShowAllData
End If
.Range.AutoFilter Field:=23, Criteria1: = "0"
.Range.AutoFilter Field:=22, Criteria1: = "Associate"
' Get the cells count of any single column range!
cc = .ListColumns(1).Range.SpecialCells(xlCellTypeVisible).Cells.Count
.AutoFilter.ShowAllData ' remove filter
End With
Application.ScreenUpdating = True ' before the message box
MsgBox IIf(cc = 1, "No Cells", "Has Provider")
End Sub
Никогда не видел, чтобы If использовалось внутри окна сообщения. Довольно умно.
Это самый простой метод для меня:
VisibleRowCount = WorksheetFunction.SUBTOTAL(103, Sheet2.ListObjects("Table1").ListColumns(22).DataBodyRange)
Но если вы не уверены, что таблица пуста или не используется:
If not Sheet2.ListObjects("Table1").DataBodyRange is Nothing then _ VisibleRowCount = WorksheetFunction.SUBTOTAL(103, Sheet2.ListObjects("Table1").ListColumns(22).DataBodyRange)
Как указал VisualBasic2008:
If you have just filtered the column by a value, then it's perfectly safe to use SubTotal.
Оглядываясь назад, я бы включил весь ListColumn.Range и -1 из подсчета, чтобы избежать ошибок.
VisibleRowCount = WorksheetFunction.SUBTOTAL(103, Sheet2.ListObjects("Table1").ListColumns(22).Range) -1
Я тоже так думал. Но что, если, например. столбец Associate
фильтруется по пробелам или пустым ячейкам? Поэтому я отказался от него (работает, пока не работает).
@ VBasic2008 Я изменил свой код на .ListColumns(22)
. OP применяет фильтр к этому столбцу. Я предполагаю, что фильтр не включает пробелы. Я должен был упомянуть об этом.
Извините, мое утверждение несколько неточное: если вы только что отфильтровали столбец по значению (с длиной больше 0), то совершенно безопасно использовать для него SubTotal(103...)
(думаю COUNTA
).
@ VBasic2008 Хорошо сказано! Я процитировал вас в своем посте. Спасибо!
SpecialCells(xlCellTypeVisible)
возвращает только видимый диапазон Текущий —pVisible
не будет обновляться, если вы позже отфильтруете исходный диапазон.