СКД не только для отчетов









СКД позволяет получать данные из информационной базы не только для вывода в отчеты, но и для других целей. Пример такого использования рассматривается в настоящей статье.

Отчеты это слишком просто!

Всем разработчикам, имеющим дело с платформой 1С:Предприятие 8.x, наверняка знаком хотя бы в общих чертах механизм системы компоновки данных (СКД). В большинстве ситуаций он используется для создания отчетов. Общую информацию о назначении и возможностях СКД Вы можете узнать здесь.

В конфигурациях, работающих в режиме управляемого приложения, практически все отчеты создаются с использованием СКД. И это понятно! Используя систему компоновки, мы сокращаем время на разработку отчета, а также даем пользователям относительно большую свободу действий для "игры" с его настройками.

Однако, СКД может быть использована для решения иных задач, не только разработка отчетов. В настоящей статье это и будет продемонстрировано. Материал больше ориентирован на разработчиков, которые только начинают свой путь в мир СКД. Хотя, может и все разработчики найдут здесь что-то интересное.

Пример задачи

В справочнике "Товары" для группы "Группа — 1" и всех входящих в нее элементов необходимо вести историю изменения. Касаться вопроса почему для этого не подошел журнал регистрации не будем. Для решения задачи нужно создать отдельный регистр сведений с измерением "Товар", с типом ссылки на соответствующий справочник, и ресурсом "Ответственный" с типом "СправочникСсылка.Пользователи".

Самый простой путь решения подобной задачи — это создать подписку на событие "ПриЗаписи" справочника и выполнять запись для текущего элемента в описанный ранее регистр сведений. Так, например, выглядела бы добавленная подписка на события и программный код в обработчике подписки.

Процедура ПриЗаписиТовара(Источник, Отказ) Экспорт

// Запрос на проверку вхождения номенклатуры в группу "Группа - 1"
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Товары.Ссылка
|ИЗ
| Справочник.Товары КАК Товары
|ГДЕ
| Товары.Ссылка В ИЕРАРХИИ (&Ссылка)
| И Товары.Ссылка = &ТекущийЭлемент";

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

Результат = Запрос.Выполнить();

// Если результат не пустой, тогда номенклатура входит в группу "Группа - 1"
Если НЕ Результат.Пустой() Тогда

ПериодЗаписи = ТекущаяДатаСеанса();
Набор = РегистрыСведений.ИзмененныеТовары.СоздатьНаборЗаписей();
Набор.Отбор.Период.Установить(ПериодЗаписи);
Набор.Отбор.Товар.Установить(Источник.Ссылка);

Запись = Набор.Добавить();
Запись.Период = ПериодЗаписи;
Запись.Товар = Источник.Ссылка;
Запись.Ответственный = Пользователи.ТекущийПользователь();

Набор.Записать();

КонецЕсли;

КонецПроцедуры

Однако у подобной реализации есть большие минусы:

  1. Мы жестко привязаны к имени группы "Группа — 1". Если пользователь изменит наименование группы, то алгоритм перестанет работать. В листинге есть раздел "TODO" по этому поводу.
  2. Если завтра пользователь захочет включить наблюдение не только для этой группы или наложить дополнительные условия на реквизиты товаров, то нужно будет снова подключать к работе программиста.

Вот тут то и вступает в бой СКД, предлагая более универсальное решение!

С нуля

В регистр сведений "ИзмененныеТовары" добавим макет с типом "СхемаКомпоновкиДанных". В нем нужно лишь написать запрос к справочнику "Товары" и настроить структуру схемы:

Схема готова! С ее помощью при каждой записи товара мы будем проверять удовлетворяет ли записываемый элемент условиям отбора, заданных пользователем. Настройки отбора задает сам пользователь в режиме 1С:Предприятия, которые сохраняются в константе "НастройкиОтборов" с типом "ХранилищеЗначения". 

Для начала рассмотрим как изменится программный код обработчика подписки на событие "ПриЗаписи" справочника "Товары":

Процедура ПриЗаписиТоваровСобытиеПриЗаписи(Источник, Отказ) Экспорт

// Таблица результатов проверки
РезультатПроверки = Новый ТаблицаЗначений;

Настройки = Константы.НастройкиОтборов.Получить().Получить();
Если Настройки = Неопределено Тогда
Возврат;
КонецЕсли;

// Устанавливаем отбор по текущему элементу
ЭлементыОтбора = Настройки.Отбор.Элементы;
ЭлементОтбора = ЭлементыОтбора.Добавить(Тип("ЭЛементОтбораКомпоновкиДанных"));
ЭлементОтбора.ВидСравнения = ВидСравненияКомпоновкиДанных.Равно;
ЭлементОтбора.Использование = Истина;
ЭлементОтбора.ЛевоеЗначение = Новый ПолеКомпоновкиДанных("Товар");
ЭлементОтбора.ПравоЗначение = Источник.Ссылка;

// Программно делаем вывод результата в таблицу значений
КомпоновщикМакета = Новый КомпоновщикМакетаКомпоновкиДанных;
СхемаКомпоновкиДанных = РегистрыСведений.ИзмененныеТовары.ПолучитьМакет("ПроверкаСхема");
МакетКомпоновки = КомпоновщикМакета.Выполнить(
СхемаКомпоновкиДанных,
Настройки,,,
Тип("ГенераторМакетаКомпоновкиДанныхДляКоллекцииЗначений")
);
ПроцессорКомпоновки = Новый ПроцессорКомпоновкиДанных;
ПроцессорКомпоновки.Инициализировать(МакетКомпоновки);
ПроцессорВывода = Новый ПроцессорВыводаРезультатаКомпоновкиДанныхВКоллекциюЗначений;
ПроцессорВывода.УстановитьОбъект(РезультатПроверки);
ПроцессорВывода.Вывести(ПроцессорКомпоновки);

Если РезультатПроверки.Количеств() > 0 Тогда

ПериодЗаписи = ТекущаяДатаСеанса();

Набор = РегистрыСведений.ИзмененныеТовары.СоздатьНаборЗаписей();
Набор.Отбор.Период.Установить(ПериодЗаписи);
Набор.Отбор.Товар.Установить(Источник.Ссылка);

Запись = Набор.Добавить();
Запись.Период = ПериодЗаписи;
Запись.Товар = Источник.Ссылка;
Запись.Ответственный = Пользователи.ТекущийПользователь();

Набор.Записать();

КонецЕсли;

КонецПроцедуры

Теперь проверку мы осуществляем не запросом, а получением данных через СКД. Условия выборки остались практически такими же, как и в первом предложенном варианте решения. Отбор устанавливается по ссылке на текущий элемент справочника "Товары", а также дополняется отборами, которые установил пользователь. Результат СКД выводится в таблицу значений. Если количество записей в ней больше 0, тогда текущий записываемый элемент справочника "Товары" удовлетворяет всем установленным отборам.

Обратите внимание, что при выводе результата СКД в таблицу значений необходимо установить тип генератора макета в компоновщике, а также использовать процессор вывода результат в коллекцию значений.

Пользовательские отборы хранятся в константе "НастройкиОтборов" в виде хранилища значения. Рассмотрим далее как эти настройки были настроены и установлены.

Особенности работы с компоновщиком настроек

Настройки хранятся в константе, поэтому и редактировать их будем в форме констант. Создадим основную форму констант и в качестве реквизита формы добавим компоновщик настроек компоновки данных.

Чтобы компоновщик работал правильно необходимо:

  1. Инициализировать его для соответствующей схемы компоновки данных.
  2. Загрузить предыдущие настройки, если они были сохранены ранее.
 

 История со времен версии 8.2

В результате, имеем почти готовое решение. Посмотрите на следующий листинг:

&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)

СхемаКомпоновки = РегистрыСведений.ИзмененныеТовары.ПолучитьМакет("ПроверкаСхема");
АдресСхемы = ПоместитьВоВременноеХранилище(СхемаКомпоновки, ЭтаФорма.УникальныйИдентификатор);

Компоновщик.Инициализировать(Новый ИсточникДоступныхНастроекКомпоновкиДанных(АдресСхемы));
Настройки = Константы.НастройкиОтборов.Получить().Получить();
Если Настройки <> Неопределено Тогда

Компоновщик.ЗагрузитьНастройки(Настройки);

Иначе

Компоновщик.ЗагрузитьНастройки(СхемаКомпоновки.НастройкиПоУмолчанию);

КонецЕсли;

КонецПроцедуры

Инициализация компоновщика осуществляется при создании формы констант на сервере. В этом же обработчике мы получаем схему компоновки, помещаем ее во временное хранилище и на основе полученного адреса создаем источник доступных настроек компоновки.

Настройки компоновщика берем либо из константы, либо получаем стандартные из схемы компоновки, если ранее они не были сохранены. 

При записи констант в событии формы "ПриЗаписиНаСервере" выполняем сохранение настроек компоновщика в константу:

&НаСервере
Процедура ПриЗаписиНаСервере(Отказ, ТекущийОбъект, ПараметрыЗаписи)

НастройкиХранилище = Новый ХранилищеЗначения(Компоновщик.ПолучитьНастройки());
Константы.НастройкиОтборов.Установить(НастройкиХранилище);

КонецПроцедуры

После выполнения всех описанных действий пользователь самостоятельно может изменять настройки отборов номенклатуры, для которых нужно вести историю изменений. 

Все проще чем кажется.

Вместо заключения

Сегодня в статье мы рассмотрели применение системы компоновки данных для решения задач, не связанных с выводом отчета пользователю. В представленном примере результат был выведен в таблицу значений и далее обработан.

Подобный прием используется, например, в настройках обмена данными с сайтом на 1С:Битрикс в типовой конфигурации "Управление торговлей 11".

Кроме того, СКД используется и в таких механизмах платформы как динамически список. Вы же уже замечали схожесть настроек в отчетах и настройках списков? 🙂

В 1С:Документооборот по такому же принципу работают произвольные условия в бизнес-процессах, причем весьма эффективно (опять же зависит от того, кто эти условия настраивает). Настройки сегментов для партнеров также использует примерной такой же принцип.

Также очень часто можно увидеть обработки, в шапке которых имеются настройки СКД для установки отборов, а в основной области добавлена таблица значений. Последняя заполняется данными, с учетом этих отборов. Наверное, самая популярная обработка с таким механизмом работы — это "Универсальные подбор и обработка объектов" от Сергея Ожерельева.

Если после прочтения статьи появятся вопросы об оптимальности выполнения кода, то волноваться есть о чем. Если обратиться к нашему примеру, то при записи номенклатуры время, затраченной платформой на получение данных с помощью СКД, составляет всего 0.01 секунды.

В этом случае вроде бы ничего страшного. Но есть пару НО:

  1. Что, если таких проверочных условий и получения данных с помощью СКД будет не одно, а 100! Время уже значительно вырастет.
  2. А если пользователь поставит сложный отбор с несколькими "ИЛИ", "Содержит", "В группе", "Не равно" и т.д. Запрос может очень сильно измениться, а его время катастрофически увеличиться.

Таким образом, использование системы компоновки данных позволяет решать задачи не только по созданию различного рода отчетов, но и любые практические задачи, связанные с получением данных. Но нужно быть осторожным, ведь универсальность настроек создает риски для стабильности работы информационной системы.

Подходите к задачам рационально!

Другие ссылки

Особо отметить статьи по СКД от Дмитрия Иванова. Всем рекомендую:

31 Comments

  1. leosoft

    Спасибо, очень полезная информация! Пишите еще 🙂

    Reply
  2. Жолтокнижниг

    (0) Идея описанная в статье правильная.

    Но пример так себе

    1. Использование СКД при часто выполняемых операция — просадка производительности

    2. Предоставление пользователю очень гибкого инструмента — потеря контроля, неожиданное поведение и опять же вероятная просадка производительности.

    Reply
  3. rpgshnik

    Ещё можно концепты печатных форм мутить 🙂 мне лично быстрее печатную форму накидать в СКД чем макет выравнивать, да она формироваться может подольше, но когда идёт внедрение удобно пока их оставить в таком состояние и позже сделать нормальную форму, которая к тому времени уже при терпит ряд множество. Именно для этих целей сделал макет — https://infostart.ru/public/1021869/ 🙂

    Reply
  4. feva

    Идея не свежа, но материал представлен хорошо!

    Reply
  5. Darklight
    Reply
  6. VmvLer

    (2) согласен и с 1 и с 2.

    Reply
  7. karpik666

    Как туториал по скд, может быть, однако реализация задачи ужасна, что мешает завести флажок в группе номенклатуры «вести историю изменения», и проверять родителя по нему и убрать вообще запрос «в иерархии»?

    Reply
  8. YPermitin

    (6) со всем согласен. Об этом даже в статье отметил. Подходить нужно разумно.

    Reply
  9. YPermitin

    (7) за пример не бить, он примитивный. Все самое интересное в типовых. Объем публикации ограничен)

    Reply
  10. Поручик

    В нашей конфигурации программная генерация и выполнение СКД сплошь и рядом.

    Reply
  11. lmnlmn

    Освоив программную работу с СКД стал активно ее использовать вместо запросов для выборок данных. Вплоть до того что получаю через СКД данные в таблицу значений, обрабатываю и подсовываю в другую СКД для компоновки отчета. Надо бы обертки какие-то написать под типовые задачи типа установки параметров и отбров, но руки не доходят.

    Reply
  12. ids79

    Спасибо, Юрий. Интересная тема. Можно также реализовать проверку реквизитов при записи документов используя СКД, да кучу всего.

    На счет проблемы, которую Вы описываете в 8.2. В 8.3, на сколько я знаю, она тоже осталась. По моему даже где-то на ИТС написано, что использовать схему компоновки для инициализации настроек можно только при работе с обычной формой. Для управляемой формы — только через хранилище.

    Отдельное спасибо за ссылки на мои статьи )).

    Reply
  13. Prince_1

    Интересная статья!

    Reply
  14. Nefilimus

    Спасибо за интересную статью. Зачерпал некоторую новую информацию =) Спасибо

    Reply
  15. igo1

    Доброго

    тоже хотел написать статью с таким же смыслом, применил СКД для работы с билингом, 1 отчет, а проверки по все БД.

    -проверка сумм

    -вывод в отче

    -проверка количества

    -проверка сроков

    -проверка расходов …..

    Reply
  16. triviumfan

    Очередной баян, жаль нету баянометра. А сколько благодарностей …я в шоке.

    Reply
  17. YPermitin

    (15) я думаю, что в любом случае можно статью написать.

    ИС от этого только выйграет.

    Reply
  18. YPermitin

    (16) спасибо 🙁

    Reply
  19. bulpi

    Как и все, что связано с СКД, очень сложно. Гора родит мышь — без использования СКД все получается гораздо проще.

    Reply
  20. DedMoroz1983

    Это вариант, будем пробовать.

    Reply
  21. Alexx48

    Почему бы в константу просто не добавить группу «Группа — 1» и не городить с СКД?

    Reply
  22. Yashazz

    Идея, конечно, чудовищный баян и давно очевидна, но статья хороша — проста и понятна, для новичков, наверное, самое то. Времена сейчас такие на ИС — множество неофитов радостно плюсует очевидности и баяны, т.к. для них это всё откровение свыше)

    Я пользуюсь СКД или в случаях, когда надо проверить выполнение некоего условия, слишком сложного для ПостроителяЗапроса, или когда надо прикрутить системное поле, вроде «Порядковый номер» итд, и лень крутиться запросом. Иногда для хитрых группировок применяю.

    Инициализация СКД действительно провальный момент с точки зрения производительности, хоть как её делай. Приходится кэшировать.

    Reply
  23. YPermitin

    (21) посыл был в том, что условия могут меняться. А в простых случаях конечно можно и константой.

    Reply
  24. YPermitin

    (22) думаю, что нужно порадоваться за тех, кто узнал что-то новое в статье 🙂 Все мы когда-то были новичками, главное об этом не забывать.

    Можно, конечно, писать все время хардкорные статьи про производительность, индексы, кластеризацию, интеграцию с .NET, компоненты на C++, как прикрутить Assembler к 1С и т.д. Но иногда и это надоедает 🙂

    Reply
  25. Yashazz

    Когда я был новичком, не было ни ИС, ни подобных статей. И нам никто не помогал продираться через эти дебри. А теперь появляются «пионэры», которые пару таких статей прочитали, свет в глазах воссиял, и айда называть себя «программистами 1С» да требовать шестизначную зарплату… С одной стороны, это плохо, ибо роняет планку профессии ниже плинтуса, а с другой — хорошо, ибо за такими горе-спецами требуется починка и можно взять здорово дороже)

    Reply
  26. YPermitin

    (25)

    Когда я был новичком

    Да, условия старта сейчас совсем другие. Но это не умиляет успехов разработчиков. которые сейчас начинают.

    А горе-специалисты были всегда, вне зависимости от качества туториалов.

    Зато во времена без инструкций всегда был простор для экспериментов 🙂 Хотя, если сейчас захотеть, то тоже можно.

    Reply
  27. Yashazz

    (26)

    если сейчас захотеть, то тоже можно

    Естественно, только вот вопрос времени. Когда всё разжёвано и в рот положено — время сэкономлено, а когда мы осваивали ХДТО безо всяких примеров и руководств — времени ушло масса, и мне его никто не вернёт…

    Reply
  28. YPermitin

    (27) согласен. Но и времени за статьи мне никто не вернет. Это просто хобби! Как и все программирование.

    Reply
  29. AllexSoft

    Из нестандартного делал такую задачу на СКД, нужно было написать механизм обмена с внешней базой (по COM), причем таким образом что бы пользователь сам делал сопоставление объектов с произвольными условиями. Если конкретнее то из БП некоторые данные (например по амортизации) загружаются в управленку где бюджетирование, и должна быть группировка по группам статей с условиями и статьи затрат в БП и УУ не совпадают, то есть нужны правила сопоставления. Вот условия сопоставления статей были написаны на СКД, на пользовательских полях (их можно вычислять с произвольным условием) — одно пользовательское поле = одна группа статей.

    Reply
  30. Fruit83

    (27) Да, этот факт оправдывает ваше старческое брюзжание 🙂

    Reply
  31. YPermitin

    (29) хороший кейс!

    Reply

Leave a Comment

Ваш адрес email не будет опубликован. Обязательные поля помечены *