СКД в 1С

Процедура ПриКомпоновкеРезультата в СКД 1С 8.3: программное формирование отчёта

Коротко

Процедура ПриКомпоновкеРезультата(ДокументРезультат, ДанныеРасшифровки, СтандартнаяОбработка) располагается в модуле объекта отчёта (или внешнего отчёта .erf) и вызывается платформой перед построением отчёта. Чтобы перехватить управление, первой строкой установите СтандартнаяОбработка = Ложь, а актуальные настройки с учётом отборов и периода пользователя получите методом КомпоновщикНастроек.ПолучитьНастройки() — обращение напрямую к свойству КомпоновщикНастроек.Настройки проигнорирует изменения на форме.

Далее выполняется стандартный конвейер из четырёх объектов: КомпоновщикМакетаКомпоновкиДанных.Выполнить(...) собирает макет, ПроцессорКомпоновкиДанных.Инициализировать(...) выполняет запросы и агрегацию (с четвёртым параметром Истина, если в выражениях вызываются функции общих модулей), а ПроцессорВыводаРезультатаКомпоновкиДанныхВТабличныйДокумент выводит готовый результат в ДокументРезультат.

Сигнатура ПриКомпоновкеРезультата и перехват стандартной обработки

Когда пользователь нажимает «Сформировать» в отчёте на системе компоновки данных, платформа 1С:Предприятие 8.3 вызывает обработчик события ПриКомпоновкеРезультата в модуле объекта отчёта. Если этой процедуры в модуле нет или параметр СтандартнаяОбработка остаётся равным Истина, платформа сама собирает макет и выводит результат в поле табличного документа на форме.

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

  • требуется программно вычислить сложные параметры или скрытые отборы перед выполнением запроса;
  • в отчёт передаётся подготовленная в коде ТаблицаЗначений через НаборДанныхОбъектСхемыКомпоновкиДанных;
  • нужно динамически модифицировать текст запроса набора данных или подменить схему компоновки;
  • в вычисляемых полях или ресурсах используются экспортные функции общих модулей (по умолчанию при программной компоновке они заблокированы без флага разрешения);
  • после вывода отчёта нужно дописать подвал с подписями, зафиксировать шапку или настроить параметры печати ДокументРезультат.
Процедура ПриКомпоновкеРезультата(ДокументРезультат, ДанныеРасшифровки, СтандартнаяОбработка)
	
	// 1. Отключаем штатный механизм платформы, чтобы отчёт не вывелся дважды
	СтандартнаяОбработка = Ложь;
	
	// 2. Получаем настройки с наложенными действиями пользователя на форме
	Настройки = КомпоновщикНастроек.ПолучитьНастройки();
	
	// 3. Собираем макет компоновки данных
	КомпоновщикМакета = Новый КомпоновщикМакетаКомпоновкиДанных;
	МакетКомпоновки = КомпоновщикМакета.Выполнить(
		СхемаКомпоновкиДанных,
		Настройки,
		ДанныеРасшифровки
	);
	
	// 4. Инициализируем процессор компоновки данных
	ПроцессорКомпоновки = Новый ПроцессорКомпоновкиДанных;
	ПроцессорКомпоновки.Инициализировать(
		МакетКомпоновки,
		,
		ДанныеРасшифровки,
		Истина
	);
	
	// 5. Выводим результат в табличный документ отчёта
	ПроцессорВывода = Новый ПроцессорВыводаРезультатаКомпоновкиДанныхВТабличныйДокумент;
	ПроцессорВывода.УстановитьДокумент(ДокументРезультат);
	ПроцессорВывода.Вывести(ПроцессорКомпоновки);
	
КонецПроцедуры
ПриКомпоновкеРезультата
ДокументРезультатТабличныйДокумент, в который выводится сформированный отчёт
ДанныеРасшифровкиДанныеРасшифровкиКомпоновкиДанных — приёмник информации для интерактивной расшифровки ячеек
СтандартнаяОбработкаБулево — сбросьте в Ложь при ручном выводе через процессор

Обратите внимание на параметр ДанныеРасшифровки: платформа передаёт в процедуру готовую переменную, связанную с хранилищем расшифровки формы. Если создать вместо неё новый объект или не передать её в КомпоновщикМакета.Выполнить(...) и ПроцессорКомпоновки.Инициализировать(...), двойной клик по ячейкам готового отчёта перестанет работать.

Получение настроек: ПолучитьНастройки() против КомпоновщикНастроек.Настройки

Самая частая ошибка при написании ПриКомпоновкеРезультата — передача в компоновщик макета свойства КомпоновщикНастроек.Настройки вместо результата метода КомпоновщикНастроек.ПолучитьНастройки(). В конструкторе эти два обращения выглядят похоже, но работают принципиально по-разному.

В объекте КомпоновщикНастроекКомпоновкиДанных настройки разделены на два слоя:

  • КомпоновщикНастроек.Настройки — базовые настройки варианта отчёта, заданные разработчиком в Конфигураторе;
  • КомпоновщикНастроек.ПользовательскиеНастройки — быстрые отборы, параметры (например, период или организация) и условное оформление, выведенные в шапку формы отчёта для пользователя.

Когда пользователь меняет период или ставит галочку быстрого отбора в режиме «1С:Предприятие», он меняет именно ПользовательскиеНастройки. Метод ПолучитьНастройки() автоматически накладывает значения из ПользовательскиеНастройки на базовые Настройки и возвращает результирующий объект НастройкиКомпоновкиДанных.

Свойство или метод Тип значения Учитывает быстрые отборы на форме? Безопасно менять в ПриКомпоновкеРезультата?
КомпоновщикНастроек.ПолучитьНастройки() НастройкиКомпоновкиДанных (слепок) Да, объединяет базовые и пользовательские настройки Да, изменения действуют только на текущий запуск и не портят форму
КомпоновщикНастроек.Настройки НастройкиКомпоновкиДанных Нет, пользовательские изменения с формы перезатрутся при сборке Нет, модификация ломает эталонный вариант настроек в сеансе
КомпоновщикНастроек.ПользовательскиеНастройки ПользовательскиеНастройкиКомпоновкиДанных Содержит только элементы с заполненным ИдентификаторПользовательскойНастройки Только если нужно принудительно поменять значение поля на самой форме

Поэтому правило простое: всегда начинайте работу с вызова Настройки = КомпоновщикНастроек.ПолучитьНастройки() и все программные корректировки вносите в переменную Настройки.

Программная установка параметров, отборов и изменение запроса схемы

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

Установка параметров данных

Для записи значения в параметр СКД используйте метод УстановитьЗначениеПараметра коллекции Настройки.ПараметрыДанных. Он сам находит элемент в коллекции по имени (объект ПараметрКомпоновкиДанных), устанавливает значение и включает флаг Использование = Истина.

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

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

Если параметр является периодом или массивом и в запросе к нему обращаются как к списку или через виртуальные таблицы, убедитесь, что у параметра схемы (ПараметрСхемыКомпоновкиДанных) включено свойство ДоступенСписокЗначений = Истина (флажок «Доступен список значений» в конструкторе СКД), а если параметр должен отображаться в выборе и отборах — свойство ВключатьВДоступныеПоля = Истина.

Программное добавление отбора

Чтобы добавить или перезаписать условие в отборе отчёта, добавьте элемент типа ЭлементОтбораКомпоновкиДанных в коллекцию Настройки.Отбор.Элементы:

ПолеСклада = Новый ПолеКомпоновкиДанных("Склад");

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

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

Динамическая подмена текста запроса в схеме

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

Набор = СхемаКомпоновкиДанных.НаборыДанных.Найти("ОсновнойНабор");
Если Набор <> Неопределено И ТипЗнч(Набор) = Тип("НаборДанныхЗапросСхемыКомпоновкиДанных") Тогда
	Набор.Запрос = СтрЗаменить(
		Набор.Запрос,
		"//ДОПОЛНИТЕЛЬНОЕ_УСЛОВИЕ",
		"И ПродажиОбороты.Подразделение В (&ДоступныеПодразделения)"
	);
КонецЕсли;
Выписывать вручную шаблонный код ПриКомпоновкеРезультата, сверять имена параметров с запросом и проверять, не сломалась ли расшифровка при подмене настроек, не обязательно. В ИИ Консоли отчётов 1С агент сам изучает структуру вашей базы, собирает схему компоновки данных, формирует модуль объекта с ПриКомпоновкеРезультата и СведенияОВнешнейОбработке и проверяет готовый внешний отчёт .erf в 1С.

Четыре шага конвейера: Компоновщик макета, Процессор компоновки и Процессор вывода

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

// Шаг 1. Сборка макета компоновки из схемы и настроек
КомпоновщикМакета = Новый КомпоновщикМакетаКомпоновкиДанных;

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

На этапе КомпоновщикМакета.Выполнить(...) запросы к базе данных ещё не выполняются. Платформа проверяет корректность полей, подставляет отборы в расширения языка запросов СКД, отсекает неиспользуемые таблицы и формирует итоговый текст запросов внутри объекта МакетКомпоновкиДанных. Именно здесь возникает исключение «Поле не найдено», если в настройках осталась ссылка на удалённое поле.

// Шаг 2. Выполнение запросов и расчёт ресурсов в процессоре компоновки
ТаблицаСвертки = ПодготовитьТаблицуДанныхНаСервере();
ВнешниеНаборы = Новый Структура("ТаблицаДанных", ТаблицаСвертки);

ПроцессорКомпоновки = Новый ПроцессорКомпоновкиДанных;
ПроцессорКомпоновки.Инициализировать(
	МакетКомпоновки,
	ВнешниеНаборы,
	ДанныеРасшифровки,
	Истина // Разрешаем вызов экспортных функций общих модулей в выражениях СКД
);
ПроцессорКомпоновкиДанных.Инициализировать
МакетКомпоновкиДанныхМакетКомпоновкиДанных — сформированный макет компоновки
ВнешниеНаборыДанныхСтруктура — ключ совпадает с ИмяОбъекта набора данных «Объект»
ДанныеРасшифровкиДанныеРасшифровкиКомпоновкиДанных — тот же экземпляр, что передан в компоновщик макета
ВозможностьИспользованияВнешнихФункцийБулево — Истина разрешает вызовы ОбщийМодуль.Функция() (по умолчанию Ложь)

Второй параметр ВнешниеНаборыДанных обязателен, если в схеме есть хотя бы один НаборДанныхОбъектСхемыКомпоновкиДанных (например, с именем объекта в схеме ТаблицаДанных). Если все наборы в схеме — обычные запросы, второй параметр пропускают: ПроцессорКомпоновки.Инициализировать(МакетКомпоновки, , ДанныеРасшифровки, Истина).

Особое внимание уделите четвёртому параметру — ВозможностьИспользованияВнешнихФункций. В штатном режиме (когда ПриКомпоновкеРезультата не переопределена) платформа разрешает вызывать функции неглобальных общих модулей из вычисляемых полей и пользовательских полей. Но при ручном создании ПроцессорКомпоновкиДанных значение по умолчанию равно Ложь: без передачи Истина отчёт упадёт с ошибкой «Функция не найдена».

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

// Вариант А: вывод одной командой
ПроцессорВывода.Вывести(ПроцессорКомпоновки, Истина);

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

При вызове ПроцессорВывода.Вывести(ПроцессорКомпоновки) (а точнее — внутри НачатьВывод()) целевой табличный документ автоматически очищается перед записью. Если нужно вывести в один ДокументРезультат два разных отчёта СКД или две схемы подряд (например, сводную таблицу и под ней детализацию из другой схемы), выводите вторую схему во временный ТабличныйДокумент и присоединяйте его методом ДокументРезультат.Вывести(ВременныйТабДок).

Постобработка ДокументРезультат после вывода отчёта

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

// 1. Фиксируем шапку отчёта при прокрутке (например, первые 5 строк и 1 левую колонку)
ДокументРезультат.ФиксацияСверху = 5;
ДокументРезультат.ФиксацияСлева = 1;

// 2. Настраиваем параметры страницы для печати (альбомная ориентация, по ширине листа)
ДокументРезультат.ОриентацияСтраницы = ОриентацияСтраницы.Ландшафт;
ДокументРезультат.АвтоМасштаб = Истина;

// 3. Дописываем подвал с подписями ответственных лиц из макета отчёта
МакетПодвала = ПолучитьМакет("МакетПодписей");
ОбластьПодписи = МакетПодвала.ПолучитьОбласть("Подвал");
ОбластьПодписи.Параметры.ГлавныйБухгалтер = "Иванова И. И.";
ОбластьПодписи.Параметры.ДатаФормирования = Формат(ТекущаяДатаСеанса(), "ДФ=dd.MM.yyyy");
ДокументРезультат.Вывести(ОбластьПодписи);

Если точная высота шапки заранее неизвестна (например, пользователь включил или выключил вывод параметров и отборов), вместо жёсткого числа ФиксацияСверху = 5 можно найти первую строку таблицы данных по тексту или имени области после вывода, либо отключить вывод параметров в СКД (Настройки.ПараметрыВывода.УстановитьЗначениеПараметра("ВыводитьПараметрыДанных", ТипВыводаТекстаКомпоновкиДанных.НеВыводить)) и вывести собственную шапку фиксированной высоты перед вызовом ПроцессорВывода.

Нужен сложный отчёт с объединением данных из нескольких регистров, расчётом в ПриКомпоновкеРезультата и готовым оформлением под БСП? Опишите задачу своими словами в ИИ Консоли отчётов 1С — агент сам проверит структуру вашей базы, напишет запрос и код модуля, соберёт .erf и сверит итоговые суммы с базой.

Частые ошибки при работе с ПриКомпоновкеРезультата

  • Забыли установить СтандартнаяОбработка = Ложь. Если вывести отчёт через ПроцессорВывода и оставить СтандартнаяОбработка = Истина, после выхода из процедуры платформа запустит штатную компоновку поверх вашего результата: все программные параметры, внешние таблицы значений и дописанный подвал будут затёрты.
  • Передали КомпоновщикНастроек.Настройки вместо КомпоновщикНастроек.ПолучитьНастройки(). Отчёт формируется, но полностью игнорирует выбранный пользователем период, организацию и быстрые отборы в шапке формы. Всегда получайте объединённый слепок через метод ПолучитьНастройки().
  • Потеряли ДанныеРасшифровки в конвейере. Если не передать параметр ДанныеРасшифровки одновременно и в КомпоновщикМакета.Выполнить(...), и в ПроцессорКомпоновки.Инициализировать(...), или подменить его на Новый ДанныеРасшифровкиКомпоновкиДанных без обратной записи в параметр процедуры, стандартная расшифровка отчёта перестанет открываться.
  • Ошибка «Функция не найдена» при вызове общего модуля в выражении СКД. Причина — четвёртый параметр метода ПроцессорКомпоновки.Инициализировать(...) по умолчанию равен Ложь. Передайте Истина в ВозможностьИспользованияВнешнихФункций.
  • Установили значение параметра, но не включили Использование = Истина. Если менять параметр напрямую через НайтиЗначениеПараметра(...) и присвоить только свойство .Значение, при снятом флажке Использование компоновщик макета не передаст параметр в запрос. Используйте метод УстановитьЗначениеПараметра(Имя, Значение) или явно ставьте Параметр.Использование = Истина.
  • Модифицировали КомпоновщикНастроек.Настройки напрямую в процедуре. Добавление элементов отбора или группировок в сам КомпоновщикНастроек.Настройки накапливает дубли при каждом повторном нажатии кнопки «Сформировать» и отображает служебные технические отборы пользователю.
  • Разместили процедуру ПриКомпоновкеРезультата в модуле формы вместо модуля объекта. Событие ПриКомпоновкеРезультата принадлежит объекту Отчет (или ВнешнийОтчет). В модуле управляемой формы платформа эту процедуру не вызывает.

Частые вопросы по процедуре ПриКомпоновкеРезультата

В каком модуле должна находиться процедура ПриКомпоновкеРезультата?

Обработчик события ПриКомпоновкеРезультата всегда создаётся в модуле объекта отчёта (или внешнего отчёта .erf). В модуле управляемой формы такого стандартного события нет: при нажатии кнопки «Сформировать» форма передаёт управление на сервер в модуль объекта, где платформа автоматически вызывает ПриКомпоновкеРезультата.

Почему в ПриКомпоновкеРезультата не срабатывают отборы и период, выбранные пользователем на форме?

Это происходит, когда в КомпоновщикМакетаКомпоновкиДанных.Выполнить передают свойство КомпоновщикНастроек.Настройки вместо вызова метода КомпоновщикНастроек.ПолучитьНастройки(). Быстрые отборы и параметры на форме хранятся в коллекции ПользовательскиеНастройки, и только метод ПолучитьНастройки() объединяет их с базовыми настройками варианта отчёта.

Как разрешить вызов экспортных функций общих модулей при программной компоновке в ПриКомпоновкеРезультата?

Передайте значение Истина четвёртым параметром (ВозможностьИспользованияВнешнихФункций) в метод ПроцессорКомпоновки.Инициализировать(МакетКомпоновки, ВнешниеНаборыДанных, ДанныеРасшифровки, Истина). По умолчанию этот параметр имеет значение Ложь, из-за чего процессор компоновки блокирует обращение к функциям общих модулей в вычисляемых и пользовательских полях.

Тарифы

ИИ Консоль отчётов 1С

Лайт

Бесплатно

Для ознакомления с возможностями

  • Все функции бесплатно на 2 дня +2 дня за подписку на Telegram или Max
  • Полный набор инструментов без урезаний
  • Без ввода карты

Ранний доступ

Популярный выбор
Бесплатно

Тестирование продукта в режиме разработки

  • Формирование панелей и виджетов в чате
  • Поддержка таблиц и популярных типов диаграмм
  • Приоритетный сбор обратной связи по развитию продукта