Row.Count подсчитывает невидимые ячейки даже при использовании xlCelltypevisible

Я пытаюсь отфильтровать таблицу, которая иногда может привести к отсутствию данных. Я пытаюсь подсчитать видимые строки, чтобы сделать это определение.

Если только строка заголовка - "Без ячеек" Если есть видимые строки - "Есть провайдер"

В приведенном ниже коде кажется, что отфильтрованные строки все еще подсчитываются...

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
SpecialCells(xlCellTypeVisible) возвращает только видимый диапазон ТекущийpVisible не будет обновляться, если вы позже отфильтруете исходный диапазон.
Tim Williams 20.03.2022 20:01
Преобразование HTML-таблицы в профессиональный документ Excel
Преобразование HTML-таблицы в профессиональный документ Excel
Это самый простой способ создания Excel из HTML-таблицы.
Импорт excel в laravel в базу данных
Импорт excel в laravel в базу данных
Здравствуйте, дорогой читатель, в этой статье я расскажу практическим и быстрым способом, как импортировать файл Excel в вашу базу данных с помощью...
1
1
54
4
Перейти к ответу Данный вопрос помечен как решенный

Ответы 4

Ответ принят как подходящий

Установите 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

Это имеет гораздо больше смысла. Оцените пояснения к шагам.

PMNIServ1 20.03.2022 20:30

Это решение неверно, потому что оно вернет «Нет провайдера» для любого количества видимых строк, если первая строка данных (строка под заголовком) не видна, потому что rows_visible, Rows.Count, вернет 1, поскольку относится только к первому область несмежного диапазона.

VBasic2008 20.03.2022 22:04

Вот как это обычно делается:

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. Гораздо чище.

PMNIServ1 20.03.2022 20:24

Есть ли отфильтрованные строки?

  • Вы можете использовать On Error Resume Next, как показано в ответе Тима Уильямса.
  • Вы не можете использовать количество строк для несмежного диапазона, потому что он относится только к первой области диапазона. Таким образом, если первая строка данных не видна, она вернет 1 независимо от того, сколько строк будет видно после нее.
  • Но вы можете использовать количество ячеек в несмежном диапазоне одного столбца.
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 использовалось внутри окна сообщения. Довольно умно.

PMNIServ1 20.03.2022 20:46

Это самый простой метод для меня:

 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 20.03.2022 21:46

@ VBasic2008 Я изменил свой код на .ListColumns(22). OP применяет фильтр к этому столбцу. Я предполагаю, что фильтр не включает пробелы. Я должен был упомянуть об этом.

TinMan 20.03.2022 21:49

Извините, мое утверждение несколько неточное: если вы только что отфильтровали столбец по значению (с длиной больше 0), то совершенно безопасно использовать для него SubTotal(103...) (думаю COUNTA).

VBasic2008 20.03.2022 21:56

@ VBasic2008 Хорошо сказано! Я процитировал вас в своем посте. Спасибо!

TinMan 20.03.2022 22:05

Другие вопросы по теме