СКД не только для отчетов
СКД позволяет получать данные из информационной базы не только для вывода в отчеты, но и для других целей. Пример такого использования рассматривается в настоящей статье.
- Описание
- Подробнее
Описание
Отчеты это слишком просто!
Всем разработчикам, имеющим дело с платформой 1С:Предприятие 8.x, наверняка знаком хотя бы в общих чертах механизм системы компоновки данных (СКД). В большинстве ситуаций он используется для создания отчетов. Общую информацию о назначении и возможностях СКД Вы можете узнать здесь.
В конфигурациях, работающих в режиме управляемого приложения, практически все отчеты создаются с использованием СКД. И это понятно! Используя систему компоновки, мы сокращаем время на разработку отчета, а также даем пользователям относительно большую свободу действий для "игры" с его настройками.
Однако, СКД может быть использована для решения иных задач, не только разработка отчетов. В настоящей статье это и будет продемонстрировано. Материал больше ориентирован на разработчиков, которые только начинают свой путь в мир СКД. Хотя, может и все разработчики найдут здесь что-то интересное.
Пример задачи
В справочнике "Товары" для группы "Группа — 1" и всех входящих в нее элементов необходимо вести историю изменения. Касаться вопроса почему для этого не подошел журнал регистрации не будем. Для решения задачи нужно создать отдельный регистр сведений с измерением "Товар", с типом ссылки на соответствующий справочник, и ресурсом "Ответственный" с типом "СправочникСсылка.Пользователи".
Самый простой путь решения подобной задачи — это создать подписку на событие "ПриЗаписи" справочника и выполнять запись для текущего элемента в описанный ранее регистр сведений. Так, например, выглядела бы добавленная подписка на события и программный код в обработчике подписки.

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


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