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