Расширенный фильтр и немного магии

У подавляющего большинства пользователей Excel при слове "фильтрация данных" в голове всплывает только обычный классический фильтр с вкладки Данные - Фильтр (Data - Filter):

advanced-filter1.png

Такой фильтр - штука привычная, спору нет, и для большинства случаев вполне сойдет. Однако бывают ситуации, когда нужно проводить отбор по большому количеству сложных условий сразу по нескольким столбцам. Обычный фильтр тут не очень удобен и хочется чего-то помощнее. Таким инструментом может стать расширенный фильтр (advanced filter), особенно с небольшой "доработкой напильником" (по традиции).

Основа

Для начала вставьте над вашей таблицей с данными несколько пустых строк и скопируйте туда шапку таблицы - это будет диапазон с условиями (выделен для наглядности желтым):

advanced-filter2.png

Между желтыми ячейками и исходной таблицей обязательно должна быть хотя бы одна пустая строка.

Именно в желтые ячейки нужно ввести критерии (условия), по которым потом будет произведена фильтрация. Например, если нужно отобрать бананы в московский "Ашан" в III квартале, то условия будут выглядеть так:

advanced-filter3.png

Чтобы выполнить фильтрацию выделите любую ячейку диапазона с исходными данными, откройте вкладку Данные и нажмите кнопку Дополнительно (Data - Advanced). В открывшемся окне должен быть уже автоматически введен диапазон с данными и нам останется только указать диапазон условий, т.е. A1:I2:

advanced-filter5.png

Обратите внимание, что диапазон условий нельзя выделять "с запасом", т.е. нельзя выделять лишние пустые желтые строки, т.к. пустая ячейка в диапазоне условий воспринимается Excel как отсутствие критерия, а целая пустая строка - как просьба вывести все данные без разбора.

Переключатель Скопировать результат в другое место позволит фильтровать список не прямо тут же, на этом листе (как обычным фильтром), а выгрузить отобранные строки в другой диапазон, который тогда нужно будет указать в поле Поместить результат в диапазон. В данном случае мы эту функцию не используем, оставляем Фильтровать список на месте и жмем ОК. Отобранные строки отобразятся на листе:

advanced-filter6.png

Добавляем макрос

"Ну и где же тут удобство?" - спросите вы и будете правы. Мало того, что нужно руками вводить условия в желтые ячейки, так еще и открывать диалоговое окно, вводить туда диапазоны, жать ОК. Грустно, согласен! Но "все меняется, когда приходят они ©" - макросы!

Работу с расширенным фильтром можно в разы ускорить и упростить с помощью простого макроса, который будет автоматически запускать расширенный фильтр при вводе условий, т.е. изменении любой желтой ячейки. Щелкните правой кнопкой мыши по ярлычку текущего листа и выберите команду Исходный текст (Source Code). В открывшееся окно скопируйте и вставьте вот такой код:

Private Sub Worksheet_Change(ByVal Target As Range)
    If Not Intersect(Target, Range("A2:I5")) Is Nothing Then
        On Error Resume Next
        ActiveSheet.ShowAllData
        Range("A7").CurrentRegion.AdvancedFilter Action:=xlFilterInPlace, CriteriaRange:=Range("A1").CurrentRegion
    End If
End Sub

Эта процедура будет автоматически запускаться при изменении любой ячейки на текущем листе. Если адрес измененной ячейки попадает в желтый диапазон (A2:I5), то данный макрос снимает все фильтры (если они были) и заново применяет расширенный фильтр к таблице исходных данных, начинающейся с А7, т.е. все будет фильтроваться мгновенно, сразу после ввода очередного условия:

advanced-filter-work.gif

Так все гораздо лучше, правда? :)

Реализация сложных запросов

Теперь, когда все фильтруется "на лету", можно немного углубиться в нюансы и разобрать механизмы более сложных запросов в расширенном фильтре. Помимо ввода точных совпадений, в диапазоне условий можно использовать различные символы подстановки (* и ?) и знаки математических неравенств для реализации приблизительного поиска. Регистр символов роли не играет. Для наглядности я свел все возможные варианты в таблицу:

Критерий Результат
гр* или гр все ячейки начинающиеся с Гр, т.е. Груша, Грейпфрут, Гранат и т.д.
=лук все ячейки именно и только со словом Лук, т.е. точное совпадение
*лив* или *лив ячейки содержащие лив как подстроку, т.е. Оливки, Ливер, Залив и т.д.
=п*в слова начинающиеся с П и заканчивающиеся на В т.е. Павлов, Петров и т.д.
а*с слова начинающиеся с А и содержащие далее С, т.е. Апельсин, Ананас, Асаи и т.д.
=*с слова оканчивающиеся на С
=???? все ячейки с текстом из 4 символов (букв или цифр, включая пробелы)
=м??????н все ячейки с текстом из 8 символов, начинающиеся на М и заканчивающиеся на Н, т.е. Мандарин, Мангостин  и т.д.
=*н??а все слова оканчивающиеся на А, где 4-я с конца буква Н, т.е. Брусника, Заноза и т.д.
>=э все слова, начинающиеся с Э, Ю или Я
<>*о* все слова, не содержащие букву О
<>*вич все слова, кроме заканчивающихся на вич (например, фильтр женщин по отчеству)
= все пустые ячейки
<> все непустые ячейки
>=5000 все ячейки со значением больше или равно 5000
5 или =5 все ячейки со значением 5
>=3/18/2013 все ячейки с датой позже 18 марта 2013 (включительно)

Тонкие моменты:

  • Знак * подразумевает под собой любое количество любых символов, а ? - один любой символ.
  • Логика в обработке текстовых и числовых запросов немного разная. Так, например, ячейка условия с числом 5 не означает поиск всех чисел, начинающихся с пяти, но ячейка условия с буквой Б равносильна Б*, т.е. будет искать любой текст, начинающийся с буквы Б.
  • Если текстовый запрос не начинается со знака =, то в конце можно мысленно ставить *.
  • Даты надо вводить в штатовском формате месяц-день-год и через дробь (даже если у вас русский Excel и региональные настройки).

Логические связки И-ИЛИ

Условия записанные в разных ячейках, но в одной строке - считаются связанными между собой логическим оператором И (AND):

advanced-filter3.png

Т.е. фильтруй мне бананы именно в третьем квартале, именно по Москве и при этом из "Ашана".

Если нужно связать условия логическим оператором ИЛИ (OR), то их надо просто вводить в разные строки. Например, если нам нужно найти все заказы менеджера Волиной по московским персикам и все заказы по луку в третьем квартале по Самаре, то это можно задать в диапазоне условий следующим образом:

advanced-filter7.png

Если же нужно наложить два или более условий на один столбец, то можно просто продублировать заголовок столбца в диапазоне критериев и вписать под него второе, третье и т.д. условия. Вот так, например, можно отобрать все сделки с марта по май:

advanced-filter8.png

В общем и целом, после "доработки напильником" из расширенного фильтра выходит вполне себе приличный инструмент, местами не хуже классического автофильтра.

Ссылки по теме



Страницы: 1  2  3  4  
06.05.2014 19:38:34
Николай, классный фильтр. Спасибо за макрос!
То, что искал!;)
06.05.2014 20:05:56
Спасибо, Андрей! Жаль, что раньше я до такого не додумался - много где применить можно было бы :)
07.05.2014 11:39:42
Николай, добрый день!

Подскажите пожалуйста, как задать несколько отрицающих условий для одного столбца, связав их логическим И?
Например, когда в списке банковских услуг нужно показать НЕ *кредит* И НЕ *вклад*
Если записать в разных строках - фильтр считает их связанными логическим ИЛИ и показывает весь массив.
07.05.2014 11:44:28
Борис, добавьте в желтом диапазоне условий еще один столбец с тем же названием и пропишите под ним второй критерий отрицания.
Спасибо за вопрос, кстати - сейчас допишу к статье этот момент.
05.03.2017 09:29:49
Как правильно написать критерий отрицания? он может быть склеенным из сылок на другие ячейки?
08.05.2014 14:32:18
Николай, а можно исходный диапазон и диапазон условий задавать именами, который всою очередь формируются формулой =СМЕЩ()?
08.05.2014 16:45:52
Можно, почему нет? Только команда CurrentRegion, которая сейчас в коде используется - фактически то же самое делает, что и именованный диапазон на СМЕЩ. Если все-таки хотите имена использовать, то вместо адресов А1 и А7 подставьте их в код (в кавычках), а CurrentRegion уберите.
17.05.2014 11:11:15
Николай, а что Вы посоветуете, чтобы задавать в одну из строк фильтра через пробел контексты поиска , и фильтрация была бы по условию И. Пример "*стул* *офис" - задаем в одной строке  ЧЕРЕЗ ПРОБЕЛ- и показывает все строки содержащие мебель Стулья офисные ....  Нужен ли доп макрос, или такое невозможно. Грубо говоря Сложный фильтр с условием И
09.06.2014 12:24:29
Алексей, а если в диапазоне критериев сделать два столбца для поля Наименование и в одно вписать *стул*, а в другой *офис*?
22.05.2014 07:27:47
Хороший фильтр. как раз пригодился для моей таблички. Фильтр работает, но только почему то у меня проблема. При удалении введенных в фильтр данных( желтый диапазон) excel подвисает и все.
03.06.2014 09:53:23
Николай, добрый день!

Подскажите, пожалуйста, как результаты фильтра выкинуть на другой лист?
09.06.2014 12:22:24
Стандартными возможностями расширенного фильтра - никак, он только на текущий лист умеет. Можно только макросом скопировать или вручную потом.
01.09.2021 11:21:19
Может с помощью Sort?
24.06.2014 16:22:48
Добрый день. Подскажите может кто-нибудь сталкивался с проблемой: расширенный фильтр не работает в Share Workbook. Как это можно обойти?
04.07.2014 10:00:31
Насколько я знаю - никак.
25.11.2024 18:03:37
Здравствуйте! Нашли решение?
03.07.2014 13:28:55
Класс!
Уважаемый Николай! Как сделать чтобы он работал в книге с общим доступом?
04.07.2014 10:00:45
См. предыдущий комментарий :(
20.07.2014 08:30:11
Здравствуй Николай, очень  признателен за твой сайт и видео уроки, последнее время очень часто их использую. Я очень часто использую расширенный фильтр, только критериев очень много порядка 30 штук на каждую группу, что бы постоянно их не набирать я перечисли их на отдельном листе и присвоил им имена которые использую в расширенном фильтре. Подскажи пожалуйста как использовать не конкретные диапазоны, а таблицы под "названиями" и выводить скажем на лист2.

Спасибо.
30.07.2014 10:07:38
Добрый день. У меня не получается реализовать сложный запрос с датами. В частности не работает >=. может есть какие то особые формы ввода дат?
30.07.2014 10:57:03
он у меня меняет местами месяц с числом. причем только при добавлении >=
04.08.2014 11:40:51
Так и должно быть. При неточном поиске дат нужно задавать их в штатовском формате ММ/ДД/ГГГГ (см. последнюю строку таблицы с шаблонами поиска в статье).
13.10.2014 22:19:19
Задавал в штатовском - не помогает. Либо вообще никакой реакции, либо все строки исчезают. Что еще может быть? Может в настройках включить что-то надо?  
05.08.2014 12:16:41
Добрый день, Николай!

Сделал подобный "расширенный фильтр" для управления фильтром даты сводной таблицы, при вводе даты в ячейку EXCEL воспринимает ее в штатовском формате, как описано выше. Есть ли возможность изменить восприятие как дд/мм/гггг?
06.08.2014 11:35:09
В свое время несколько раз пытался - не вышло. Видимо программно зашито.
08.08.2014 18:42:54
Добрый день! У меня для даты стоял тип данных date  в макросе для фильтра и excel ее переворачивал, поменял тип данных на string и все он теперь ее воспринимает как текст и не переворачивает все работает. Спасибо.
04.12.2022 22:48:59
ещё заметил, что схема глючит, не работает  если формат не совпадает ячеек для ввода параметров фильтра и столбцов соответствующих
02.10.2014 14:10:25
Делаю в таблице с условиями ссылку на ячейку из другого листа и фильтр сразу перестает работать. Что делать в таком случае?
07.10.2014 21:08:26
А не подскажите, как изменить макрос, чтобы фильтр всегда срабатывал по принципу *текст для поиска*?
13.10.2014 22:25:28
Спасибо за скрипт! Скажите, а как можно реализовать фильтрацию на бОльшее количество строк?Если имеем код вида Range("A2:I5")), то разве I5 не должно активировать все 5 строк? В тоже время у меня "работают" только 1-2. Можно конечно добавлять в желтом диапазоне еще столбцы с тем же названием, но тогда таблица начинает расти в право, особенно когда например нужно сделать много исключений например вида <>**.
17.10.2014 00:59:24
Спасибо большое. Все получилось. А можно доработать макрос так, чтобы в графе "Сумма" появлялось "Итого" по отфильтрованным данным? Заранее спасибо.
07.11.2014 17:06:02
Можно просто использовать для подсчета суммы отфильтрованных строк функцию ПРОМЕЖУТОЧНЫЕ.ИТОГИ (SUBTOTALS)
07.11.2014 13:03:49
Здравствуйте, а у меня Ваш макрос не работает. Как только не пробовала, ничего не получается. Если не  трудно, посмотрите, пожалуйста, что я сделала не так. Файл находится по ссылке   https://cloud.mail.ru/public/3d245a94389f/%D0%B3%D0%B5%D0%BC%D0%BE%D1%81%D1%82%D0%B0%D0%B7%20%D0%B8%20apache.xlsm, лист3.

Очень надеюсь на Вашу помощь. И еще вопрос, я скачала надстройку PLEX, но не могу найти в ней такой же макрос или в надстройке его нет? И где можно почитать подробную помощь по надстройке, для меня это темный лес.
07.11.2014 17:03:10
  1. В макросе надо подправить адреса A2:I5 и А7 на адреса ваших диапазонов.
  2. В вашем файле обрамлено, кстати, чудовищное количество ячеек - от начала и до конца листа - это плохая идея.
  3. В PLEX такого макроса нет и никогда не было. Полная и подробная справка по надстройке PLEX.
17.11.2014 16:51:18
Спасибо. Я пыталась менять, но, все равно, не сработало. Попробую еще раз.
А насчет огромного количества ячеек - это только 10 часть всех данных, я их вынесла на отдельный лист. Но именно для этого мне нужен макрос. Я же вручную все это считать просто сдохну!
Еще не объясните, почему после использования каких-либо формул на странице в Excell , а затем их стирания, другие формулы и макросы перестают работать? Я не знаю, может это только у меня так? Но мне каждый раз приходится все копировать в новую книгу Excel для того, чтобы использовать новые формулы.
10.11.2014 15:12:47
Николай, добрый день!
Подскажите, как правильно составить запрос: что бы отфильтровались значения, которые содержат английские буквы?
Спасибо!
11.11.2014 10:30:21
В любом шрифте английские буквы находятся выше (т.е. до) кириллицы, поэтому имеет смысл попробовать сформулировать критерий как "меньше русской А", т.е.
11.11.2014 17:44:13
Спасибо за макрос!
Допилил его под себя и стало вообще отлично. Теперь он у меня по нажатию одной кнопки устанавливается на любой лист в любой файл. И той же кнопкой сносится, если больше не нужен :)
12.11.2014 10:12:04
Хотя нет, не в любую. Если проект VBA защищен паролем, то не фурычит. Но и так всё равно неплохо получилось :)
17.11.2014 16:52:17
Здравствуйте, Алексей, не поделитесь своим допиленным файлом?
18.11.2014 11:08:22
У меня вот так (не претендую на непогрешимость и суперизящность, но вроде работает) :)
Этот макрос должен быть в личной книге макросов, чтобы запускаться в любой книге Excel.
И в центре управления безопасностью Excel должен быть открыт доступ к объектной модели проектов VBA.
Перед применением макроса нужно выделить заголовки таблицы (все или часть), которые будут скопированы в шапку расширенного фильтра.
Проверял работоспособность в Excel 2007 и 2010.
Ну и повесть макрос на кнопку или горячую клавишу - это совсем просто, если нужно.
Sub Расширенный_фильтр()
'Проверяем защищен ли проект VBA
If ActiveWorkbook.VBProject.Protection = 1 Then MsgBox "Проект защищен. Создание расширенного фильтра невозможно": Exit Sub

'Количество строк расширенного фильтра
kol = 6

'Проверяем установлин ли уже расширенный фильтр. Если да, то удаляем.
If Rows(2).Interior.Color <> 49407 Then

    If Selection.Rows.Count > 1 Then MsgBox "Нужно выделить не более одной строки", vbCritical: Exit Sub
    'Определяем границы выделенной области
    row1 = Selection.Row
    col1 = Selection.Column
    col2 = col1 + Selection.Cells.Count - 1
    'Вставляем строчки для расширенного фильтра
    For i = 1 To kol
        Range("A1").EntireRow.Insert
        If i > 1 Then Rows(1).Interior.Color = 49407
    Next i
    'Копируем шапку
    Range(Cells(row1 + kol, col1), Cells(row1 + kol, col2)).Select
    Selection.Copy
    Cells(1, col1).Select
    Selection.PasteSpecial Paste:=xlPasteValues
    Application.CutCopyMode = False

    'Формируем текст макроса
    MacroText = "Private Sub Worksheet_Change(ByVal Target As Range)" & Chr(13)
    MacroText = MacroText & "If Not Intersect(Target, Range(cells(2," & col1 & "),cells(" & kol - 1 & "," & col2 & "))) Is Nothing Then" & Chr(13)
    MacroText = MacroText & "On Error Resume Next" & Chr(13)
    MacroText = MacroText & "ActiveSheet.ShowAllData" & Chr(13)
    MacroText = MacroText & "cells(" & row1 + kol & "," & col1 & ").CurrentRegion.AdvancedFilter Action:=xlFilterInPlace, CriteriaRange:=cells(1," & col1 & ").CurrentRegion" & Chr(13)
    MacroText = MacroText & "End If" & Chr(13)
    MacroText = MacroText & "End Sub"

    'Добавляем макрос
    ActiveWorkbook.VBProject.VBComponents(ActiveSheet.CodeName).CodeModule.AddFromString (MacroText)
    
Else:
    
    'Удаляем строки расширенного фильтра
    Range("A1:A" & kol).EntireRow.Delete
    Application.CutCopyMode = False
    
    'Удаляем макрос
    With ActiveWorkbook.VBProject.VBComponents(ActiveSheet.CodeName).CodeModule
             If .Find("Worksheet_Change", 1, 1, .CountOfLines, 1) = True Then
                iStartLine = .ProcStartLine("Worksheet_Change", 0)
                iCountLines = .ProcCountLines("Worksheet_Change", 0)
                .DeleteLines iStartLine, iCountLines
             End If
    End With
    
End If

End Sub 
21.11.2014 11:32:27
Спасибо. Класный макрос. Только при сортировке более 5000 строчек он сильно притормаживает при каждом новом вводе в фильтр.  Ну можно ли так задать, чтобы сортировал не всю таблицу с нуля, а уже отсортированную часть? Или как по другому облегчить?
08.12.2014 16:28:05
Спасибо за урок. С вашей помощью я сделал то, что хотел, но не совсем. Если есть такая возможность, то подскажите, как управлять фильтром с автоматическим запуском, но только так, что бы запуск производился при помощи выпадающего меню. У меня это не вышло. Спасибо
09.12.2014 18:09:32
Cпасибо. Как выше писали макрос подтормаживает на больших таблицах и  при каждом новом вводе в фильтр. Eсть способ ускорить работу макроса?
11.12.2014 10:47:04
Ну, на действительно больших таблицах тормозить будет все :)
У вас сколько строк?
19.12.2014 19:08:59
Николай! Умная штука! Только не могу понять почему у меня не работает нормально фильтр по датам?! Воспользовался вашим примером очень все хорошо только вот мой файл с датами работать не хочет что не так?

Range("I1:O2").Select
    Range("A1:G3000").AdvancedFilter Action:=xlFilterCopy, CriteriaRange:=Range _
        ("I1:O2"), CopyToRange:=Range("I9:O3039"), Unique:=False
 
что не так? Делаю в вашем примере сортировку по датам тоже не работает правильно.
23.12.2014 13:16:24
Николай, доброго времени суток.
Подскажите, пожалуйста, как переписать макрос , чтобы копировать результат в другое место, а не преобразовывать текущую таблицу?
Возможно ли такое?
14.02.2015 19:10:36
Здравствуйте! При применении макроса, диапазон фильтрации распространяется только на 4 строки. Что сделал не так? Помогите...
02.03.2015 20:17:24
у меня ничерта не получается..... аж бесит
Страницы: 1  2  3  4  
Наверх