Привет, Хабр!

СКД — одна из тех вещей в , которые все используют, но мало кто использует на полную.

Большинство знают базу: создал схему компоновки, написал запрос, перетащил поля в настройки — получил отчёт. Но СКД умеет гораздо больше! И многие задачи, которые решают кодом в модуле отчёта, на самом деле решаются средствами самой компоновки — проще, надёжнее и с бонусом в виде пользовательской настройки.

Разберём механизм и приёмы, которые экономят время и код.

Как устроена СКД

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

Архитектура трёхслойная:

  • Схема компоновки — описание данных: запросы (наборы данных), вычисляемые поля, ресурсы, параметры, связи между наборами. Это делает разработчик в конфигураторе или EDT.

  • Настройки компоновки — как данные отобразить: какие группировки, какие отборы, в каком порядке, какое условное оформление. Настройки бывают по умолчанию (задаёт разработчик) и пользовательские (меняет пользователь в режиме «Ещё — Изменить вариант отчёта»).

  • Макет и процессор — движок, который берёт схему + настройки и генерирует результат. Компоновщик макета превращает описание в исполняемый план, процессор компоновки выполняет его, процессор вывода рендерит в табличный документ.

Вычисляемые поля: логика без запроса

Когда нужно добавить поле, которого нет в запросе, — не усложняйте сам запрос. Добавьте вычисляемое поле на закладке «Вычисляемые поля» схемы компоновки.

Простой пример — маржа:

Путь: Маржа
Выражение: Выручка - Себестоимость

Категоризация по диапазону:

Путь: ЦеноваяКатегория
Выражение: Выбор
    Когда Цена > 10000 Тогда "Премиум"
    Когда Цена > 3000  Тогда "Средний"
    Иначе "Эконом"
Конец

Работа с датами:

Путь: ДнейДоОплаты
Выражение: РазностьДат(ДатаОплаты, ДатаОтгрузки, ДЕНЬ)
Путь: Квартал
Выражение: "Q" + Строка(Квартал(ДатаДокумента))

Работа со строками:

Путь: КраткоеНаименование
Выражение: Лев(Наименование, 30)

Вычисляемые поля работают с уже полученными данными,они не попадают в SQL-запрос к СУБД. Это значит две вещи:

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

  2. Вы можете использовать в выражениях любые функции языка выражений СКД, не думая о том, поддерживает ли их СУБД.

По вычисляемым полям можно группировать, сортировать, делать отбор (с оговоркой выше) и даже считать ресурсы. Пользователь увидит их как обычные поля отчёта.

Ресурсы: не только СУММА

Закладка «Ресурсы» — это агрегатные функции для итогов по группировкам. Большинство ставят Сумма(Количество), Сумма(СуммаДокумента) и идут дальше. Но возможности шире.

Процент от общего через ОбщийИтог():

Ресурс: ДоляВВыручке
Выражение: Сумма(СуммаПродажи) / ОбщийИтог(Сумма(СуммаПродажи)) * 100

ОбщийИтог() берёт значение агрегатной функции из самого верхнего уровня группировки (общего итога). Результат — процент каждой строки в общей выручке. Без постобработки, без кода.

Средневзвешенное значение:

Ресурс: СредневзвешеннаяЦена
Выражение: Сумма(Сумма) / Сумма(Количество)

Просто, но многие вместо этого пишут обработку в модуле.

Разные формулы для разных группировок. На вкладке «Ресурсы» можно задать выражение не только общее, но и специфичное для конкретной группировки. Нажимаете «Рассчитывать по...» и задаёте:

Ресурс: СредняяЦена
Для группировки "Номенклатура": Среднее(Цена)
Для общего итога: Сумма(Сумма) / Сумма(Количество)

На уровне конкретного товара простое среднее арифметическое цены. На уровне общего итога — средневзвешенная. Одно поле, разная логика в зависимости от уровня.

Процент выполнения плана:

Ресурс: ВыполнениеПлана
Выражение: Выбор 
    Когда Сумма(План) = 0 Тогда 0 
    Иначе Сумма(Факт) / Сумма(План) * 100
Конец

Защита от деления на ноль — прямо в выражении ресурса.

Параметры: динамический отчёт

Параметры — это входные данные отчёта: период, организация, склад. СКД умеет с ними больше, чем кажется.

Параметр в заголовке:

Запрос: ВЫБРАТЬ ... ГДЕ Организация = &Организация И Дата МЕЖДУ &НачалоПериода И &КонецПериода

Параметры &НачалоПериода и &КонецПериода создаются автоматически, когда вы добавляете параметр типа СтандартныйПериод.

Параметр с выражением по умолчанию. Хотите, чтобы по умолчанию был текущий месяц? В свойствах параметра Период задайте выражение:

НачалоМесяца(ТекущаяДата())

Параметр, влияющий на условное оформление. Добавляете булевский параметр ПоказыватьСебестоимость со значением по умолчанию Ложь, и в условном оформлении ставите: если ПоказыватьСебестоимость = Ложь, то видимость поля «Себестоимость» — Ложь. Пользователь включает галку и видит себестоимость.

Связи наборов данных

Когда отчёт строится на данных из разных источников — не нужно писать один монструозный запрос с пятью левыми соединениями. Разбейте на логические наборы данных и свяжите.

НаборДанных1 (запрос): Продажи
  — Номенклатура, Количество, Сумма
  
НаборДанных2 (запрос): ОстаткиНаСкладах
  — Номенклатура, Склад, Остаток

Связь наборов данных:
  Источник: НаборДанных1
  Приёмник: НаборДанных2
  Выражение источника: Номенклатура
  Выражение приёмника: Номенклатура

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

Можно связать и три, и четыре набора. Можно связать по нескольким полям. Можно сделать набор данных не запросом, а объектом — тогда данные берутся из объектной модели.

Связь работает в памяти, не на уровне СУБД. То есть СКД вытаскивает данные из обоих наборов, а потом соединяет. Если оба возвращают по миллиону строк — будет медленно и емко по памяти. Для больших объёмов с чёткими условиями соединяйте в запросе.

Условное оформление

Условное оформление — мощный инструмент, который почему-то редко используют на полную. Раскраска строк — лишь верхушка.

Подсветка критических значений:

Условие: ОстатокНаСкладе < МинимальныйОстаток
Оформление: ЦветФона — красный, ЦветТекста — белый
Область: поле "ОстатокНаСкладе"

Раскраска целых строк по статусу:

Условие: Статус = "Просрочен"
Оформление: ЦветФона — светло-красный
Область: вся строка (не указываем конкретное поле)

Скрытие столбца по параметру:

Условие: &ПоказыватьСебестоимость = Ложь
Оформление: Видимость — Ложь
Область: поле "Себестоимость"

Форматирование чисел:

Условие: (без условия — применяется всегда)
Оформление: Формат — "ЧДЦ=2; ЧРГ=' '"
Область: поле "Сумма"

Условия можно комбинировать (И/ИЛИ), использовать вычисляемые поля и параметры.

Программная работа с СКД

Иногда визуального конструктора мало.

Нужно сформировать отчёт из кода: подставить отборы по данным формы, вывести в табличный документ, отправить по почте. Полный скелет:

// 1. Получить схему
Схема = Отчёт.ПолучитьСхемуКомпоновкиДанных();

// 2. Получить настройки (или создать свои)
Настройки = Схема.НастройкиПоУмолчанию;

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

// 4. Подставить параметры
Настройки.ПараметрыДанных.УстановитьЗначениеПараметра(
    Новый ПараметрКомпоновкиДанных("НачалоПериода"), 
    НачалоМесяца(ТекущаяДата()));
Настройки.ПараметрыДанных.УстановитьЗначениеПараметра(
    Новый ПараметрКомпоновкиДанных("КонецПериода"), 
    КонецМесяца(ТекущаяДата()));

// 5. Скомпоновать макет
КомпоновщикМакета = Новый КомпоновщикМакетаКомпоновкиДанных;
Макет = КомпоновщикМакета.Выполнить(Схема, Настройки, , ,
    Тип("ГенераторМакетаКомпоновкиДанных"));

// 6. Выполнить
Процессор = Новый ПроцессорКомпоновкиДанных;
Процессор.Инициализировать(Макет);

// 7. Вывести в табличный документ
ТабДок = Новый ТабличныйДокумент;
ПроцессорВывода = Новый ПроцессорВыводаРезультатаКомпоновкиДанныхВТабличныйДокумент;
ПроцессорВывода.Вывести(Процессор, ТабДок);

Вышла такая вот цепочка.

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

// Создаём таблицу значений с данными
ТЗ = Новый ТаблицаЗначений;
ТЗ.Колонки.Добавить("Товар", Новый ОписаниеТипов("Строка"));
ТЗ.Колонки.Добавить("Цена", Новый ОписаниеТипов("Число"));
// ... заполняем ТЗ

// Передаём как внешний набор данных
ВнешниеНаборы = Новый Структура;
ВнешниеНаборы.Вставить("ДанныеИзAPI", ТЗ);

Процессор = Новый ПроцессорКомпоновкиДанных;
Процессор.Инициализировать(Макет, , ВнешниеНаборы);

В схеме компоновки при этом создаёте набор данных типа «Объект» с именем «ДанныеИзAPI» и описываете его поля. СКД будет работать с ним как с обычным набором — группировки, отборы, ресурсы, связи с другими наборами.

Характеристики: поля, которые заранее неизвестны

У товаров есть произвольные свойства: цвет, размер, материал. Набор свойств разный для разных категорий. Как вывести их в отчёте столбцами?

В схеме компоновки на наборе данных задаёте: поле объекта характеристики (Номенклатура), поле типа характеристики (Свойство — «Цвет», «Размер»), поле значения характеристики (Значение — «Красный», «XL»). СКД сама развернёт характеристики в столбцы. Пользователь увидит «Цвет», «Размер», «Материал» как обычные поля и сможет группировать, фильтровать, сортировать.

СКД не всегда подходит

СКД не для всего. Печатные формы с фиксированной вёрсткой (счета-фактуры, акты, накладные) — там обычный макет табличного документа. СКД для аналитики, не для документов.

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

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

Когда понимаешь внутреннюю механику 1С, многие задачи перестают решаться «ещё одним модулем». На курсе по разработке на 1С как раз разбирают архитектуру платформы, встроенные механизмы и интеграции — чтобы писать не больше кода, а более осмысленные и устойчивые решения.

А чтобы узнать больше о формате обучения и задать вопросы экспертам, приходите на бесплатные уроки: