Фильтр с оператором "содержит"

Автор Tillevion, 7 апреля 2024, 15:42

0 Пользователи и 1 гость просматривают эту тему.

Tillevion

У меня возникла сложность с добавлением фильтра макросом для следующего примера (прикладываю файл). Необходимо отфильтровать диапазон B7:F18 по двум признакам:
1. значения в столбце B равны "1".
И 2. значения в столбце C содержат "a".
Не могу подобрать правильный оператор фильтра для "содержит", хотя таковой есть в пользовательском интерфейсе. Подскажите, есть ли такой оператор и как его задать.

sokol92

#1
Используйте TableFilterField2, а не TableFilterField.
Там есть то, что Вас интересует.

И потом setFilterFields2 вместо setFilterFields.

P.S. А ведь есть еще setFilterFields3.   :)
Владимир.

Tillevion

Цитата: sokol92 от  7 апреля 2024, 16:32Используйте TableFilterField2, а не TableFilterField.
Там есть то, что Вас интересует.

И потом setFilterFields2 вместо setFilterFields.

P.S. А ведь есть еще setFilterFields3.   :)
Благодарю! Помогло.

economist

Для 2+ критериев в разных столбцах бывпет лучше подходит Расширенный фильтр. Вставьте вверху 5 пустых строк и легко реализуйте наглядную фильтрацию. Для подстановки частых критериев из списка - Данные, Проверка.
Руб. за сто, что Питоньяк
Любит водку и коньяк!
Потому что мне, без оных, -
Не понять его никак...

Tillevion

Подскажите, а как грамотно удалить примененный фильтр?

sokol92

Сначала несколько замечаний.

Фильтры диапазонов ячеек в Calc (сводные таблицы мы сейчас не рассматриваем) принадлежат объектам, поддерживающим сервис DatabaseRange (далее DBRange).

DBRange бывают двух видов:

1. Именованные: имеют уникальное имя внутри документа, собраны в коллекции, задаваемой свойством DatabaseRanges документа.

2. Не именованные: неявно создаются, когда для диапазона ячеек (не входящего в именованный DBRange) устанавливается фильтр. Такие DBRange специфичны для листа документа, на листе может быть только один неименованный DBRange (а может и не быть).
Функция GetSheetFilterDBRange (см. ниже в этом сообщении) возвращает неименованный DBRange для листа (или Nothing, если фильтр не установлен). Функция использует частично документированные интерфейсы (см. также баг tdf#147257).

Последовательность действий при установке / снятии (авто)фильтра c помощью макросов:
1. Определить DBRange.
2. Установить / удалить критерии отбора для полей.
3. Отобразить / скрыть "стрелочки" автофильтра.

Для отображения / скрытия "стрелочек" автофильтра на листе можно использовать конструкцию:

GetSheetFilterDBRange(oSheet).Autofilter=True ' False - скрыть
Ниже приведены макросы (см. комментарии).

Option Explicit

' Удаляет или очищает автофильтр для листа.
' - oSheet    лист документа Calc
' - bRemove   False - очистить критерии автофильтра (умолчание), True - удалить автофильтр.
Sub Sheet_ClearAutoFilter(ByVal oSheet As Object, Optional ByVal bRemove As Boolean)
  Dim oDBRange As Object, oFilterDesc As Object
  If IsMissing(bRemove) Then bRemove=False
  oDBRange=GetSheetFilterDBRange(oSheet)
  If Not (oDBRange Is Nothing) Then
    If oDBRange.AutoFilter Then 
      oFilterDesc=oDBRange.ReferredCells.createFilterDescriptor(true)
      oFilterDesc.setFilterFields Array()
      oDBRange.ReferredCells.filter oFilterDesc
      If bRemove Then oDBRange.autofilter=False
    End If 
  End If
End Sub


' Возвращает DataBaseRange для автофильтра листа или Nothing.
Function GetSheetFilterDBRange(Byval oSheet As Object) as Object
  Dim i as Long, oDoc As Object
  GetSheetFilterDBRange=Nothing
  oDoc=oSheet.Drawpage.Forms.Parent
  i=oSheet.RangeAddress.Sheet
  With oDoc.getPropertyValue("UnnamedDatabaseRanges")
    If .hasByTable(i) Then GetSheetFilterDBRange=.getByTable(i)
  End With
End Function


' Очищаем фильтр на первом листе документа.
Sub Test
  Sheet_ClearAutoFilter ThisComponent.Sheets(0)
End Sub

Владимир.

Ezoptron

Немного поправил код. Теперь работает корректно вроде.
Добавил строку oFilterDesc.ContainsHeader = True, иначе фильтр брался по всей таблице с учётом заголовка.
Sub Sheet_ClearAutoFilter(ByVal oSheet As Object, Optional ByVal bRemove As Boolean)
  Dim oDBRange As Object, oFilterDesc As Object
  If IsMissing(bRemove) Then bRemove=False
  oDBRange=GetSheetFilterDBRange(oSheet)
  If Not (oDBRange Is Nothing) Then
    If oDBRange.AutoFilter Then
      oFilterDesc=oDBRange.ReferredCells.createFilterDescriptor(true)
      oFilterDesc.ContainsHeader = True
      oFilterDesc.setFilterFields Array()
      oDBRange.ReferredCells.filter oFilterDesc
      If bRemove Then oDBRange.autofilter=False
    End If
  End If
End Sub