1C-Code → Основы 1С → СКД: схема, настройки, ресурсы
Система компоновки данных — то, на чём в 1С делают все отчёты. Разбор устройства и главного заблуждения: запрос здесь не главный.
Глава 29 из 36 · чтение примерно 34 минут
Почти каждый отчёт в 1С сделан на СКД. Написать отчёт запросом и вывести в таблицу можно, но так почти не делают: тогда придётся самому писать отборы, группировки, итоги, сортировку, настройки пользователя и сохранение вариантов. СКД делает это всё сама.
Цена — устройство, которое поначалу кажется переусложнённым. Разберём его по частям.
Главное заблуждение
Новичок думает: «СКД — это способ показать результат запроса». И пишет запрос, который сразу считает итоги, группирует и сортирует.
Это неверно и приводит к отчёту, который нельзя настроить. В СКД запрос отдаёт сырые строки, а группировки, итоги, отборы и сортировка живут в настройках. Платформа сама перепишет запрос под текущие настройки: уберёт ненужные поля, добавит условия, соберёт итоги.
Отсюда правило: всё, что можно отдать настройкам, — отдаём настройкам.
Наборы данных — откуда берутся строки. Чаще всего один набор типа «Запрос». Бывают «Объект» (таблица из кода) и «Объединение» (несколько наборов вместе).
Поля набора — то, что схема объявляет наружу. Настройки выбирают только из объявленных полей: не объявили — в отчёт не попадёт, как бы запрос его ни возвращал.
Ресурсы — поля, по которым считаются итоги. Сумма, количество. Поле, не объявленное ресурсом, в итогах не появится никогда.
Параметры — значения, которые подставляются в запрос: период, организация.
Настройки по умолчанию — структура отчёта: какие группировки, какие колонки, какие отборы. То, что человек потом меняет под себя.
Схема = Новый СхемаКомпоновкиДанных;
Набор = Схема.НаборыДанных.Добавить(Тип("НаборДанныхЗапросСхемыКомпоновкиДанных"));
Набор.Запрос = "ВЫБРАТЬ Склад, Сумма ИЗ …";
Поле = Набор.Поля.Добавить(Тип("ПолеНабораДанныхСхемыКомпоновкиДанных"));
Поле.Поле = "Склад";
| Часть | Что означает |
|---|---|
Новый СхемаКомпоновкиДанных | схему можно собрать кодом, не только мышью |
НаборыДанных.Добавить | откуда берутся строки; тип указывается явно |
Набор.Запрос | запрос отдаёт СЫРЫЕ строки, без итогов и группировок |
Набор.Поля.Добавить | что схема объявляет наружу — иначе поле невидимо настройкам |
Эти два понятия отвечают на «что складывать» и «в каком разрезе».
Ресурс — поле, которое суммируется. В настройках у ресурса указывают выражение: Сумма(Сумма), Максимум(Дата).
Группировка — уровень отчёта. Группировка по складу даст строку на каждый склад и итог по нему. Группировка без полей — детальные записи, то есть строки как есть.
Вложенные группировки дают вложенные итоги: склад → товар → детальные записи.
Различие, которое спрашивают, чтобы понять, работали вы с СКД или читали про неё.
Параметр схемы подставляется в запрос. Отбор происходит в базе, до того как данные пришли. Так делают с периодом: тянуть год данных, чтобы показать месяц, — бессмысленно.
Отбор настроек применяется к полученным данным или дописывается компоновщиком в запрос — в зависимости от того, где поле доступно. Его человек меняет сам, не открывая конфигуратор.
Правило: то, что режет объём, — параметр; то, что человек крутит, — отбор.
Поле, которого нет в запросе, добавляют в схему: вычисляемое поле с выражением на языке выражений СКД. Так делают цену из суммы и количества, процент, признак «просрочено».
И тут же попадают в ловушку, которую надо знать наизусть. Вычисляемое поле считается на каждом уровне группировки заново, а не складывается из строк.
Поэтому «средняя цена» как Сумма / Количество в итоговой строке посчитается от ИТОГОВЫХ суммы и количества — и это правильно. А вот если написать её как ресурс с выражением Среднее(Цена), в итоге окажется среднее арифметическое по строкам, что совсем другое число.
Почему в итоге «пусто» или «ноль»
Три причины, и все три встречаются в первый же день работы с СКД.
Поле не объявлено ресурсом. Тогда в строках оно есть, а в итогах — пусто: складывать платформе никто не разрешал.
Ресурс просуммирован не по тому уровню. У ресурса можно указать, по каким группировкам он считается; ошибка здесь даёт «в строках верно, в итоге ерунда».
Поле не выведено в настройках. Схема отдаёт его, а в выбранных полях его нет — и отчёт молча показывает меньше, чем умеет.
У поля в схеме есть роль, и от неё зависит поведение, которое иначе выглядит как магия.
Роль периода — поле с датой, по которому СКД умеет строить периоды: «по месяцам», «по дням», с дополнением пустых промежутков. Без роли это просто дата, и пустые месяцы в отчёт не попадут.
Роль измерения и роль ресурса в наборе — из них платформа понимает, что группировать, а что складывать.
Игнорировать значения NULL и обязательное поле — то, из-за чего строки то появляются, то исчезают при добавлении соединения.
Отбор настроек, который попадает в запрос
Есть способ получить и гибкость, и скорость: у параметра схемы можно включить «Использовать отбор настроек» — или, в типовом приёме, связать параметр виртуальной таблицы с выражением, куда СКД подставит пользовательский отбор.
Тогда отбор, выбранный человеком в отчёте, уезжает внутрь виртуальной таблицы, а не применяется после. На большом регистре это та же разница, что «секунда» против «минуты» из главы про производительность.
Схема живёт в отчёте и меняется разработчиком. Настройки меняет пользователь, и они сохраняются отдельно — на пользователя, на вариант отчёта.
Из-за этого возникает самый частый вопрос поддержки: «я исправил отчёт, а у человека по-старому». Обычно это значит, что у него сохранён свой вариант настроек, и правка схемы его не касается.
Что делают: правят вариант отчёта в конфигураторе или просят человека сбросить настройки к стандартным. В типовых для этого есть готовая команда.
Иногда отчёт нужен не на экране, а в виде данных: выгрузить в файл, отправить, посчитать что-то дальше. СКД для этого не нужно обходить — её вызывают программно.
Последовательность всегда одна: получить схему и настройки, скомпоновать макет компоновщиком макета, выполнить процессором компоновки и вывести — в табличный документ или сразу в таблицу значений.
Схема = ПолучитьМакет("ОсновнаяСхемаКомпоновкиДанных");
Компоновщик = Новый КомпоновщикМакетаКомпоновкиДанных;
Макет = Компоновщик.Выполнить(Схема, Настройки);
Процессор = Новый ПроцессорКомпоновкиДанных;
Процессор.Инициализировать(Макет);
Вывод = Новый ПроцессорВыводаРезультатаКомпоновкиДанныхВКоллекциюЗначений;
Таблица = Новый ТаблицаЗначений;
Вывод.УстановитьОбъект(Таблица);
Вывод.Вывести(Процессор);
| Часть | Что означает |
|---|---|
ПолучитьМакет | схема лежит макетом в отчёте — её берут по имени |
КомпоновщикМакета | соединяет схему с настройками и даёт готовый макет |
ПроцессорКомпоновки | исполняет макет: выполняет запросы и считает итоги |
ВКоллекциюЗначений | вывод не в табличный документ, а в таблицу значений — с ней дальше работает код |
иерархия | в плоскую таблицу группировки схлопываются; для дерева есть свой процессор вывода |
Когда СКД не нужна
СКД сильна тем, что даёт человеку настраивать отчёт самому: группировки, отборы, поля, оформление. Всё это бесплатно для разработчика.
Но если результат — одна цифра или фиксированная печатная форма, которую нельзя менять, СКД добавляет только сложность. Запрос и табличный документ будут понятнее.
Признак, что нужна именно СКД: в задании есть слова «с возможностью отбора», «в разрезе», «по выбору пользователя». Признак, что не нужна: «печатная форма по утверждённому образцу».
КомпоновщикНастроек — объект, который держит текущие настройки отчёта: то, что человек накрутил поверх настроек по умолчанию.
Порядок работы всегда один:
1. Загрузить схему в компоновщик: Инициализировать(Новый ИсточникДоступныхНастроекКомпоновкиДанных(Схема)). 2. Загрузить настройки: ЗагрузитьНастройки(Схема.НастройкиПоУмолчанию). 3. Дописать своё поверх — отбор, группировку. 4. Скомпоновать макет и выполнить.
Важно: свои настройки добавляют, а не заменяют. Заменить целиком — значит выбросить всё, что человек настроил до вас.
Компоновщик = Новый КомпоновщикНастроекКомпоновкиДанных;
Макет = Новый МакетКомпоновкиДанных;
Процессор = Новый ПроцессорКомпоновкиДанных;
Процессор.Инициализировать(Макет);
| Часть | Что означает |
|---|---|
КомпоновщикНастроек | держит то, что человек накрутил |
МакетКомпоновкиДанных | схема плюс настройки, скомпонованные вместе |
ПроцессорКомпоновкиДанных | выполняет макет и отдаёт результат |
Инициализировать | без него процессор не знает, что выполнять |
На чём спотыкаются
Считают итоги в запросе. Тогда отчёт нельзя перегруппировать: итоги уже посчитаны по чужому разрезу. Запрос отдаёт строки, итоги считает СКД.
Забывают объявить поле. Запрос возвращает колонку, а в настройках её нет. Ошибки не будет — просто поле недоступно.
Не объявляют ресурс. Поле есть, суммы нет. Ресурс — отдельное объявление, а не свойство поля.
Заменяют настройки вместо дополнения. Пользователь настроил отчёт, открыл заново — всё сброшено.
Отбирают период отбором настроек, а не параметром. Тогда из базы приезжает вся история, а лишнее отбрасывается уже в памяти.
Один отчёт может иметь несколько вариантов — готовых наборов настроек. «По складам», «По менеджерам», «Только просроченные».
Это лучше, чем несколько отчётов: схема одна, поддерживать одну. И пользователь сам сохраняет свои варианты, не трогая конфигурацию.
Упражнение 1. Параметр или отбор
Функция КудаОтбор(Что) получает описание отбора и возвращает, где его место: "ПараметрСхемы" или "ОтборНастроек". Правило: если в описании есть "период" или "организац" — это режет объём, значит параметр схемы. Остальное человек крутит сам — отбор настроек.
Решается в тренажёре: код запускается и проверяется сразу.
В СКД запрос отдаёт сырые строки, а группировки, итоги, отборы и порядок живут в настройках — платформа сама перепишет запрос под них. Поле надо объявить, иначе настройки его не увидят; итог считается только по ресурсу. Параметр схемы режет объём в базе, отбор настроек крутит человек. Компоновщик держит текущие настройки, и свои к ним добавляют, а не подменяют ими чужие.
Читать про код и писать код — разные умения. В тренажёре к этой главе идут упражнения: вы пишете решение, оно запускается на настоящем интерпретаторе 1С и проверяется сразу, без установки платформы.