Как настроить отбор «Содержит» в СКД для поиска по подстроке и фильтрации пустых строк?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

При разработке отчетов на базе системы компоновки данных (СКД) разработчики часто сталкиваются с задачей гибкого текстового отбора. Пользователю удобно иметь одно поле, в которое можно ввести подстроку для поиска, а если поле оставлено пустым и флажок отбора включен — получить список записей с незаполненным реквизитом.

Однако стандартный вид сравнения Содержит при передаче пустой строки возвращает абсолютно все непустые записи. Выясним причину такого поведения платформы 1С:Предприятие и разберем надежные способы реализации требуемой логики.

Почему вид сравнения «Содержит» не отбирает пустые строки

Проанализируем механизм трансляции отборов СКД в запрос к СУБД. Когда для поля устанавливается вид сравнения Содержит, платформа формирует условие с оператором ПОДОБНО вида Поле ПОДОБНО "%" + Значение + "%".

Если правое значение отбора является пустой строкой (""), результирующий шаблон превращается в "%%". По правилам языка запросов 1С и стандарта SQL шаблон из двух знаков процента соответствует любой строке произвольной длины (за исключением значений NULL). В результате условие всегда возвращает Истина для всех заполненных строк, а пустые записи при этом могут отсекаться, если содержат NULL.

Для решения этой задачи рассмотрим несколько проверенных подходов.

Способ 1. Использование параметра и ветвления в тексте запроса

Разберем вариант, когда вместо стандартного элемента отбора СКД мы используем параметр схемы компоновки данных, например &НаименованиеПоиска. В тексте запроса набора данных опишем логику с помощью конструкции ВЫБОР КОГДА.

Посмотрим на пример текста запроса:


ВЫБРАТЬ
    Номенклатура.Ссылка КАК Ссылка,
    Номенклатура.Наименование КАК Наименование
ИЗ
    Справочник.Номенклатура КАК Номенклатура
ГДЕ
    ВЫБОР
        КОГДА &НаименованиеПоиска = "" ИЛИ &НаименованиеПоиска ЕСТЬ NULL
            ТОГДА Номенклатура.Наименование = "" ИЛИ Номенклатура.Наименование ЕСТЬ NULL
        ИНАЧЕ Номенклатура.Наименование ПОДОБНО "%" + &НаименованиеПоиска + "%"
    КОНЕЦ

Разберем по шагам, как защитить алгоритм от пробельных символов в значении параметра:

  1. Откроем схему компоновки данных и перейдем на вкладку Параметры.
  2. Найдем наш параметр &НаименованиеПоиска.
  3. В колонке Выражение пропишем функцию очистки от пробелов: СокрЛП(&НаименованиеПоиска).

Благодаря этому выражению, если пользователь случайно введет строку, состоящую только из пробелов, СКД предварительно обрежет их до пустой строки, и сработает ветка отбора незаполненных значений.

Способ 2. Программная корректировка вида сравнения в событии «ПриКомпоновкеРезультата»

Если требуется сохранить стандартный интерфейс отборов СКД в пользовательских настройках, наиболее правильным подходом является динамическая модификация настроек компоновщика перед формированием отчета.

Рассмотрим реализацию в модуле объекта отчета. В процедуре ПриКомпоновкеРезультата мы можем проверить введенное пользователем значение и изменить вид сравнения с Содержит на НеЗаполнено (или Равно с пустой строкой).


Процедура ПриКомпоновкеРезультата(ДокументРезультат, ДанныеРасшифровки, СтандартнаяОбработка)
    
    // Получаем текущие настройки отчета с учетом пользовательских изменений
    Настройки = КомпоновщикНастроек.ПолучитьНастройки();
    
    Для Каждого Элемент Из Настройки.Отбор.Элементы Цикл
        Если ТипЗнч(Элемент) = Тип("ЭлементОтбораКомпоновкиДанных") Тогда
            Если Элемент.ЛевоеЗначение = Новый ПолеКомпоновкиДанных("Наименование") И Элемент.Использование Тогда
                
                Если Элемент.ВидСравнения = ВидСравненияКомпоновкиДанных.Содержит Тогда
                    Если ПустаяСтрока(Элемент.ПравоеЗначение) Тогда
                        // Если строка пустая, переключаем вид сравнения на проверку заполненности
                        Элемент.ВидСравнения = ВидСравненияКомпоновкиДанных.НеЗаполнено;
                    КонецЕсли;
                КонецЕсли;
                
            КонецЕсли;
        КонецЕсли;
    КонецЦикла;
    
    // Применяем модифицированные настройки для выполнения компоновки
    СтандартнаяОбработка = Ложь;
    
    КомпоновщикМакета = Новый КомпоновщикМакетаКомпоновкиДанных;
    МакетКомпоновки = КомпоновщикМакета.Выполнить(СхемаКомпоновкиДанных, Настройки, ДанныеРасшифровки);
    
    ПроцессорКомпоновки = Новый ПроцессорКомпоновкиДанных;
    ПроцессорКомпоновки.Инициализировать(МакетКомпоновки, , ДанныеРасшифровки, Истина);
    
    ПроцессорВывода = Новый ПроцессорВыводаРезультатаКомпоновкиДанныхВТабличныйДокумент;
    ПроцессорВывода.УстановитьДокумент(ДокументРезультат);
    ПроцессорВывода.Вывести(ПроцессорКомпоновки);
    
КонецПроцедуры

Проанализируем преимущества данного подхода:

  1. Пользовательский интерфейс не перегружается дополнительными служебными полями и переключателями.
  2. Если пользователь вводит строку с символами, выполняется полноценный поиск подстроки по условию Содержит.
  3. Если поле очищено, но флаг активности отбора установлен, отчет корректно отбирает записи с незаполненными или отсутствующими (NULL) значениями.
← На главную