При разработке произвольных отчетов или обработок на платформе 1С:Предприятие 8.3 часто используется объект КомпоновщикНастроекКомпоновкиДанных. Однако начинающие разработчики могут столкнуться с неприятной особенностью: при попытке настроить отбор на форме в колонке Вид сравнения доступен только вариант Равно. Это существенно ограничивает возможности пользователя, лишая его возможности использовать фильтры типа "В списке", "Содержит", "Больше" или "Меньше".
В этой статье мы подробно разберем, почему возникают такие ограничения, как расширить список доступных видов сравнения и как автоматизировать работу пользователя, программно добавляя нужные поля отбора при открытии формы.
Проанализируем ситуацию: почему система «скрывает» от нас другие виды сравнения? Основная причина кроется в типизации полей в схеме компоновки данных (СКД). Система компоновки данных — это мощный механизм, который строит запросы динамически. Для того чтобы предложить пользователю вид сравнения «Больше», СКД должна быть уверена, что поле имеет числовой тип или тип даты. Чтобы предложить «В списке» — она должна понимать, что это ссылочный тип или набор значений.
Рассмотрим основные факторы, влияющие на доступность видов сравнения:
&Период). Отбор — это динамическое условие ГДЕ. Именно в отборах доступен весь спектр сравнений.Выясним причину на примере. Если в макете СКД нет текста запроса, а поля добавлены вручную в «Набор данных - объект», обязательно проверьте колонку Тип значения. Как только вы укажете там конкретный справочник или примитивный тип (Число, Дата), список видов сравнения расширится автоматически.
Как было замечено в обсуждении, добавление простейшего запроса сразу решает проблему. Это происходит потому, что при сохранении запроса 1С автоматически считывает метаданные и назначает типы полям. Если же запрос вам не нужен (например, вы заполняете данные программно), необходимо имитировать структуру данных.
Рассмотрим шаги по правильной настройке макета:
СправочникСсылка.Номенклатура или Число.Для того чтобы компоновщик на форме работал корректно, его нужно правильно инициализировать. Разберем пример кода в процедуре ПриСозданииНаСервере. Мы должны связать компоновщик с макетом и его источником настроек.
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
// Получаем макет из объекта или реквизита
МакетСКД = РеквизитФормыВЗначение("Объект").ПолучитьМакет("ОсновнаяСхемаКомпоновкиДанных");
// Помещаем во временное хранилище для инициализации источника доступных настроек
АдресСхемы = ПоместитьВоВременноеХранилище(МакетСКД, УникальныйИдентификатор);
// Инициализируем источник доступных настроек
ИсточникДоступныхНастроек = Новый ИсточникДоступныхНастроекКомпоновкиДанных(АдресСхемы);
// Связываем компоновщик с источником
КомпоновщикНастроек.Инициализировать(ИсточникДоступныхНастроек);
// Загружаем настройки по умолчанию из схемы
КомпоновщикНастроек.ЗагрузитьНастройки(МакетСКД.НастройкиПоУмолчанию);
КонецПроцедуры
После такой инициализации, если в схеме (СКД) типы полей определены верно, компоновщик на форме предоставит все стандартные виды сравнения (в списке, не равно, заполнено и т.д.).
Теперь решим вторую задачу: как сделать так, чтобы пользователю не нужно было каждый раз нажимать кнопку «Добавить», а нужные поля отбора уже висели в списке при открытии формы? Для этого нам нужно программно модифицировать коллекцию ЭлементыОтбора.
Рассмотрим алгоритм добавления элемента отбора:
Отбор.Элементы.ЛевоеЗначение — это поле, по которому фильтруем.ВидСравнения.ПравоеЗначение (если нужно предустановить значение).Посмотрим на пример кода, который добавляет отбор по полю «Склад»:
&НаСервере
Процедура ДобавитьОтборНаФорму(ИмяПоля, ЗначениеОтбора = Неопределено)
// 1. Создаем новый элемент отбора
НовыйЭлемент = КомпоновщикНастроек.Настройки.Отбор.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
// 2. Указываем поле. Имя поля должно совпадать с именем в СКД
НовыйЭлемент.ЛевоеЗначение = Новый ПолеКомпоновкиДанных(ИмяПоля);
// 3. Устанавливаем вид сравнения (например, Равно или В списке)
НовыйЭлемент.ВидСравнения = ВидСравненияКомпоновкиДанных.Равно;
// 4. Настраиваем использование
НовыйЭлемент.Использование = Истина;
// 5. Если передано значение, устанавливаем его
Если ЗначениеОтбора <> Неопределено Тогда
НовыйЭлемент.ПравоеЗначение = ЗначениеОтбора;
КонецЕсли;
// 6. Чтобы отбор появился в "Пользовательских настройках" на форме:
НовыйЭлемент.ИдентификаторПользовательскойНастройки = "ОтборПоПолю_" + ИмяПоля;
КонецПроцедуры
Проанализируем ситуацию: вы добавили отбор программно, код отработал без ошибок, но на форме в таблице отборов пусто. Почему? Дело в том, что современные управляемые формы часто отображают не все настройки компоновщика, а только те, которые помечены как пользовательские.
Когда вы устанавливаете свойство ИдентификаторПользовательскойНастройки, вы сообщаете системе: «Этот элемент должен быть доступен пользователю для редактирования в упрощенном интерфейсе». Если идентификатор не задан, отбор будет применен к данным «за кулисами», но визуально на форме в списке быстрых отборов он не появится.
Совет: Если вы хотите, чтобы пользователь видел отбор, но не мог его удалить, вы можете управлять свойствами РежимОтображения элемента отбора, установив его в РежимОтображенияЭлементаНастройкиКомпоновкиДанных.БыстрыйДоступ.
Соберем все знания воедино и создадим процедуру, которая полностью подготавливает компоновщик к работе при открытии формы обработки.
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
// Инициализация схемы
МакетСКД = РеквизитФормыВЗначение("Объект").ПолучитьМакет("Макет");
АдресХранилища = ПоместитьВоВременноеХранилище(МакетСКД, УникальныйИдентификатор);
КомпоновщикНастроек.Инициализировать(Новый ИсточникДоступныхНастроекКомпоновкиДанных(АдресХранилища));
КомпоновщикНастроек.ЗагрузитьНастройки(МакетСКД.НастройкиПоУмолчанию);
// Программное добавление отборов, чтобы пользователь их сразу видел
// Отбор по Организации
ДобавитьОтборНаФорму("Организация");
// Отбор по периоду (если есть поле Дата в СКД)
ДобавитьОтборНаФорму("Дата");
КонецПроцедуры
&НаСервере
Процедура ДобавитьОтборНаФорму(ИмяПоля)
ЭлементыОтбора = КомпоновщикНастроек.Настройки.Отбор.Элементы;
// Проверим, нет ли уже такого отбора, чтобы не дублировать
Для Каждого Элемент Из ЭлементыОтбора Цикл
Если ТипЗнч(Элемент) = Тип("ЭлементОтбораКомпоновкиДанных")
И Строка(Элемент.ЛевоеЗначение) = ИмяПоля Тогда
Возврат;
КонецЕсли;
КонецЦикла;
НовыйЭлемент = ЭлементыОтбора.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
НовыйЭлемент.ЛевоеЗначение = Новый ПолеКомпоновкиДанных(ИмяПоля);
НовыйЭлемент.ВидСравнения = ВидСравненияКомпоновкиДанных.Равно;
НовыйЭлемент.Использование = Ложь; // Пусть будет в списке, но не активен сразу
// Привязываем к пользовательским настройкам
НовыйЭлемент.ИдентификаторПользовательскойНастройки = "УникальныйID_" + ИмяПоля;
КонецПроцедуры
Для корректной работы КомпоновщикНастроекКомпоновкиДанных необходимо соблюдать три условия:
ИсточникДоступныхНастроекКомпоновкиДанных, связанный с актуальной схемой.ИдентификаторПользовательскойНастройки.Соблюдение этих правил позволит вам создавать гибкие и удобные интерфейсы для фильтрации данных, экономя время пользователя и делая работу с программой более интуитивной.