При создании первого внешнего отчета разработчики часто сталкиваются с путаницей между классическим табличным выводом через код и механизмом системы компоновки данных (СКД). Попытка объединить оба подхода приводит к ошибкам компиляции, дублированию логики и некорректным итогам. Разберем по шагам, как устроен механизм СКД, почему не нужно вручную прописывать вывод областей макета и как правильно организовать получение и отображение данных.
Проанализируем типовую ситуацию: разработчик создал схему компоновки данных, описал вычисляемые поля, а затем в модуле объекта написал функцию формирования с ручным обходом выборки запроса и заполнением областей табличного документа. При этом платформа выдает ошибку о неопределенных переменных.
Выясним причину этой ошибки. Конструкции вида СсылкаНаОбъект.Количество характерны исключительно для внешних печатных форм, подключаемых через Библиотеку стандартных подсистем (БСП). Во внешнем отчете реквизита СсылкаНаОбъект по умолчанию не существует. Кроме того, метод Макет.ПолучитьОбласть() применим только к макетам с типом Табличный документ. Если макет является Схемой компоновки данных, попытка получить из него область приведет к аварийной остановке выполнения программы.
Главное преимущество СКД заключается в том, что отчету вообще не требуется код в модуле объекта для вывода данных на экран. Платформа берет на себя выполнение запроса, наложение пользовательских отборов, расчет итогов по ресурсам и генерацию результирующего табличного документа. Весь процедурный код вывода из модуля объекта можно полностью удалить — отчет сформируется по кнопке «Сформировать» автоматически на основании настроек схемы.
Рассмотрим ситуации, когда вмешательство в стандартный процесс компоновки все же необходимо. Если нам требуется программно передать в отчет внешнюю таблицу значений, изменить параметры перед запуском или внедрить нестандартную постобработку ячеек, в модуле объекта переопределяют стандартное событие:
Процедура ПриКомпоновкеРезультата(ДокументРезультат, ДанныеРасшифровки, СтандартнаяОбработка)
// Отключаем стандартный вывод отчета платформой
СтандартнаяОбработка = Ложь;
// Получаем схему компоновки и пользовательские настройки
Схема = ЭтотОбъект.СхемаКомпоновкиДанных;
Настройки = ЭтотОбъект.КомпоновщикНастроек.ПолучитьНастройки();
// Формируем макет компоновки
КомпоновщикМакета = Новый КомпоновщикМакетаКомпоновкиДанных;
МакетКомпоновки = КомпоновщикМакета.Выполнить(Схема, Настройки, ДанныеРасшифровки);
// Инициализируем процессор компоновки данными
ПроцессорКомпоновки = Новый ПроцессорКомпоновкиДанных;
ПроцессорКомпоновки.Инициализировать(МакетКомпоновки, , ДанныеРасшифровки);
// Выводим результат в табличный документ
ПроцессорВывода = Новый ПроцессорВыводаРезультатаКомпоновкиДанныхВТабличныйДокумент;
ПроцессорВывода.УстановитьДокумент(ДокументРезультат);
ПроцессорВывода.Вывести(ПроцессорКомпоновки);
КонецПроцедуры
Если подобных специальных задач нет, модуль объекта внешнего отчета должен оставаться абсолютно пустым.
Посмотрим на частую ошибку в тексте запроса: попытку связать документ ПоступлениеТоваров с документом РеализацияТоваров через контрагента или номенклатуру. Прямое левое или внутреннее соединение табличных частей документов приводит к математическому эффекту «декартова произведения» строк. Если по одной позиции номенклатуры было оформлено три прихода и пять реализаций, в результате обычного соединения мы получим пятнадцать дублирующихся строк, что фатально исказит суммы закупок, выручки и остатков.
Чтобы избежать искажения данных, разберем два правильных подхода:
РегистрНакопления.Продажи.Обороты и РегистрНакопления.Закупки.Обороты). Регистры уже содержат агрегированные движения и позволяют легко сопоставить себестоимость и цену продажи без соединения тяжелых документов.Посмотрим на пример правильной структуры запроса при объединении табличных частей документов:
ВЫБРАТЬ
ПоступлениеТовары.Номенклатура КАК Номенклатура,
ПоступлениеТовары.Количество КАК КоличествоПриход,
ПоступлениеТовары.Сумма КАК СуммаПриход,
0 КАК КоличествоРасход,
0 КАК СуммаРасход
ИЗ
Документ.ПоступлениеТоваров.Товары КАК ПоступлениеТовары
ОБЪЕДИНИТЬ ВСЕ
ВЫБРАТЬ
РеализацияТовары.Номенклатура,
0,
0,
РеализацияТовары.Количество,
РеализацияТовары.Сумма
ИЗ
Документ.РеализацияТоваров.Товары КАК РеализацияТовары
Также обратим внимание на ошибку при обращении к табличным частям: нельзя обращаться к реквизитам вложенных таблиц через точку от шапки документа (например, РеализацияТоваров.Товары.Цена). Запрос должен строиться непосредственно к самой табличной части: Документ.РеализацияТоваров.Товары.
Для расчета показателей прибыли и рентабельности перейдем на вкладку Вычисляемые поля в СКД. При расчете процентных соотношений важно учитывать возможность нулевых значений в знаменателе, чтобы отчет не завершался ошибкой деления на ноль.
Используем безопасную конструкцию на языке выражений СКД:
ВЫБОР
КОГДА СуммаПоступление = 0 ТОГДА 0
ИНАЧЕ (СуммаПрибыли * 100) / СуммаПоступление
КОНЕЦ
Часто в требованиях к отчету указано: вывести несколько уровней группировки (например: Организация, далее Номенклатура, далее документы движения) в одну общую колонку со структурой дерева, а не «лесенкой» из множества пустых столбцов.
Разберем, как это настраивается средствами схемы компоновки данных без единой строчки кода:
Организация, внутри него подчиненная группировка — Номенклатура, внутри нее — ДокументДвижения, а на самом нижнем уровне — Детальные записи.После установки этого параметра платформа 1С автоматически сформирует отчет в виде аккуратного дерева: все группировочные поля займут первую общую колонку, а пользователь сможет сворачивать и разворачивать уровни структуры с помощью значков «плюс» и «минус».