При разработке отчетов на базе системы компоновки данных (СКД) разработчики часто сталкиваются с задачей гибкого текстового отбора. Пользователю удобно иметь одно поле, в которое можно ввести подстроку для поиска, а если поле оставлено пустым и флажок отбора включен — получить список записей с незаполненным реквизитом.
Однако стандартный вид сравнения Содержит при передаче пустой строки возвращает абсолютно все непустые записи. Выясним причину такого поведения платформы 1С:Предприятие и разберем надежные способы реализации требуемой логики.
Проанализируем механизм трансляции отборов СКД в запрос к СУБД. Когда для поля устанавливается вид сравнения Содержит, платформа формирует условие с оператором ПОДОБНО вида Поле ПОДОБНО "%" + Значение + "%".
Если правое значение отбора является пустой строкой (""), результирующий шаблон превращается в "%%". По правилам языка запросов 1С и стандарта SQL шаблон из двух знаков процента соответствует любой строке произвольной длины (за исключением значений NULL). В результате условие всегда возвращает Истина для всех заполненных строк, а пустые записи при этом могут отсекаться, если содержат NULL.
Для решения этой задачи рассмотрим несколько проверенных подходов.
Разберем вариант, когда вместо стандартного элемента отбора СКД мы используем параметр схемы компоновки данных, например &НаименованиеПоиска. В тексте запроса набора данных опишем логику с помощью конструкции ВЫБОР КОГДА.
Посмотрим на пример текста запроса:
ВЫБРАТЬ
Номенклатура.Ссылка КАК Ссылка,
Номенклатура.Наименование КАК Наименование
ИЗ
Справочник.Номенклатура КАК Номенклатура
ГДЕ
ВЫБОР
КОГДА &НаименованиеПоиска = "" ИЛИ &НаименованиеПоиска ЕСТЬ NULL
ТОГДА Номенклатура.Наименование = "" ИЛИ Номенклатура.Наименование ЕСТЬ NULL
ИНАЧЕ Номенклатура.Наименование ПОДОБНО "%" + &НаименованиеПоиска + "%"
КОНЕЦ
Разберем по шагам, как защитить алгоритм от пробельных символов в значении параметра:
&НаименованиеПоиска.СокрЛП(&НаименованиеПоиска).Благодаря этому выражению, если пользователь случайно введет строку, состоящую только из пробелов, СКД предварительно обрежет их до пустой строки, и сработает ветка отбора незаполненных значений.
Если требуется сохранить стандартный интерфейс отборов СКД в пользовательских настройках, наиболее правильным подходом является динамическая модификация настроек компоновщика перед формированием отчета.
Рассмотрим реализацию в модуле объекта отчета. В процедуре ПриКомпоновкеРезультата мы можем проверить введенное пользователем значение и изменить вид сравнения с Содержит на НеЗаполнено (или Равно с пустой строкой).
Процедура ПриКомпоновкеРезультата(ДокументРезультат, ДанныеРасшифровки, СтандартнаяОбработка)
// Получаем текущие настройки отчета с учетом пользовательских изменений
Настройки = КомпоновщикНастроек.ПолучитьНастройки();
Для Каждого Элемент Из Настройки.Отбор.Элементы Цикл
Если ТипЗнч(Элемент) = Тип("ЭлементОтбораКомпоновкиДанных") Тогда
Если Элемент.ЛевоеЗначение = Новый ПолеКомпоновкиДанных("Наименование") И Элемент.Использование Тогда
Если Элемент.ВидСравнения = ВидСравненияКомпоновкиДанных.Содержит Тогда
Если ПустаяСтрока(Элемент.ПравоеЗначение) Тогда
// Если строка пустая, переключаем вид сравнения на проверку заполненности
Элемент.ВидСравнения = ВидСравненияКомпоновкиДанных.НеЗаполнено;
КонецЕсли;
КонецЕсли;
КонецЕсли;
КонецЕсли;
КонецЦикла;
// Применяем модифицированные настройки для выполнения компоновки
СтандартнаяОбработка = Ложь;
КомпоновщикМакета = Новый КомпоновщикМакетаКомпоновкиДанных;
МакетКомпоновки = КомпоновщикМакета.Выполнить(СхемаКомпоновкиДанных, Настройки, ДанныеРасшифровки);
ПроцессорКомпоновки = Новый ПроцессорКомпоновкиДанных;
ПроцессорКомпоновки.Инициализировать(МакетКомпоновки, , ДанныеРасшифровки, Истина);
ПроцессорВывода = Новый ПроцессорВыводаРезультатаКомпоновкиДанныхВТабличныйДокумент;
ПроцессорВывода.УстановитьДокумент(ДокументРезультат);
ПроцессорВывода.Вывести(ПроцессорКомпоновки);
КонецПроцедуры
Проанализируем преимущества данного подхода:
Содержит.NULL) значениями.