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