Приведу пример из своей практики создания отчета на СКД с использованием нескольких схем, в том числе из схем основной конфигурации (в нашем случае «1С:ERP Управление предприятием 2») и определенных схем в создаваемом нами отчете.

Есть задача: создать отчет, который берет данные из отчетов ERP и из запросов, что мы определили в текущем отчете. Последние, в свою очередь, могут зависеть от результата выборки по схемам ERP. Отчет должен иметь возможность передавать пользовательские параметры, определенные в шапке отчета, по всем нашим схемам.

Для чего нужно использовать уже существующие отчеты ERP в том виде, как они есть, а не «копировать» их в наш отчет. Возможна ситуация, когда схемы основной конфигурации будут громоздкими и переносить их дольше, чем использовать уже готовую схему. Есть вероятность обновления ERP, и нужно учесть все изменения,  а вот следить за ними каждый раз при обновлении – задача, которой нам бы хотелось избежать.

Например, в нашем отчете используется результат типового отчета «ОстаткиИДоступностьТоваров» из ERP. пример

Отчет на поддержке и уже выдает нужный нам результат. Мы только воспользуемся его схемой СКД (об этом чуть позже).

Так выглядит форма самого отчета:

пример

В данном случае чем проще отборы, тем лучше. Минимизируем вариативность отборов, убираем варианты настроек и предлагаем пользователю фиксированный набор параметров.

О нашем отчете без лишней информации. Отчет строится так:

  1. Данные по заказам (запрос, схема СКД, определенная в отчете).
  2. Остатки и доступность товаров (схема СКД, определенная в ERP).
  3. Определены этапы производства (запрос, схема СКД, определенная в отчете).
  4. Определен норматив по полуфабрикату (запрос, схема СКД, определенная в отчете, разузлование номенклатуры по спецификации).
  5. Остатки полуфабриката на цеховой кладовой (схема СКД, определенная в ERP).
  6. Факт выполнения (схема СКД, определенная в ERP).
  7. Время выполнения (запрос и расчет по алгоритму).
  8. Основная СКД для вывода в отчет.

Параметры отбора должны быть «проброшены» через все схемы СКД. Также к нашим параметрам добавляются «Заказы на производство», «Заказ клиента», «Номенклатура» и «Характеристика из результата выполнения первого пункта (Данные по заказам)». Для выполнения определения «Факта выполнения» (пункт 6) и алгоритма расчета «Времени выполнения» (пункт 7) нужны данные по этапам производства, которые определяются в пункте 3.

Макеты, определенные в отчете:

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

В первом и втором случае набор данных – запрос. Далее параметры передаются из шапки отчета. Результат – детальные записи со всеми полями:

НормативПФ

Тут остановлюсь поподробнее. Набор данных – запрос. Задача – выбрать по списку спецификаций КоличествоУпаковок (он же норматив) из табличной части «Материалы и услуги» методом разузлования номенклатуры. То есть если в табличной части «Материалы и услуги» присутствует номенклатура со спецификацией (которая изготавливается), то нужно выбрать норматив по деталям и для этого узла. Вся разузлованная номенклатура (детали) относится к основной спецификации изготавливаемой продукции.

Это можно реализовать на СКД. Правда расчет по количеству входимостей в узел нужно будет сделать отдельно.

Сам запрос выглядит так:

ВЫБРАТЬ

                РесурсныеСпецификацииМатериалыИУслуги.Ссылка КАК Спецификация,

                РесурсныеСпецификацииМатериалыИУслуги.Номенклатура КАК Номенклатура,

                РесурсныеСпецификацииМатериалыИУслуги.Характеристика КАК Характеристика,

                РесурсныеСпецификацииМатериалыИУслуги.Упаковка КАК Упаковка,

                РесурсныеСпецификацииМатериалыИУслуги.КоличествоУпаковок КАК Норматив,

                ВЫРАЗИТЬ(РесурсныеСпецификацииМатериалыИУслуги.ИсточникПолученияПолуфабриката КАК Справочник.РесурсныеСпецификации) КАК ИсточникПолученияПолуфабриката

ИЗ

                Справочник.РесурсныеСпецификации.МатериалыИУслуги КАК РесурсныеСпецификацииМатериалыИУслуги

ГДЕ

                РесурсныеСпецификацииМатериалыИУслуги.Ссылка В(&МассивСпецификаций)

                И РесурсныеСпецификацииМатериалыИУслуги.СпособПолученияМатериала = ЗНАЧЕНИЕ(Перечисление.СпособыПолученияМатериаловВСпецификации.ПроизвестиПоСпецификации)

На закладке «Связи наборов данных» нужно указать связь таблицы к самой себе. Это и даст нам нужное разузлование.

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

Получаем детальные записи с выбором всех полей.

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

Там же определяется макет и расшифровка полей.

Немного кода

Идем по нашим пунктам. Все выполнение на сервере по кнопке «Сформировать»

Пункт 1. Данные по заказам

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

Пункт 2. Остатки и доступность товаров без назначения, типовой отчет ERP

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

Пункт 3 – Пункт 7. Все аналогично. Или выполняем свою схему и выводим результат в таблицу значений, или выполняем типовую схему и выводим результат в таблицу значений. Также можно сделать постобработку любого результата. В моем случае рассчитывались факт выполнения, время выполнения, была постобработка разузлования номенклатуры.

Пункт 8. Основная схема. Собираем все таблицы воедино.

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

Заключение

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

Словарь

СКД (СКД)Система компоновки данных — механизм 1С для построения отчетов
QueryЗапрос — SQL-подобный язык платформы 1С для выборки данных
DatasetНабор данных — источник данных схемы компоновки (таблица, запрос)
LayoutМакет — шаблон отчета СКД с областями и параметрами