При разработке отчетов на схеме компоновки данных (СКД) часто возникает задача вывести результат пользователю в уже свернутом виде (например, показать только первый или второй уровень группировок). Стандартно платформа 1С выводит отчет полностью развернутым. Попытки программно свернуть группировки через предопределенное событие модуля объекта ПриКомпоновкеРезультата часто приводят к неожиданным ошибкам: перестают вычисляться параметры-константы, сбоят внешние функции в вычисляемых полях, либо отчет вовсе отказывается работать в фоновом режиме.
В этой статье мы подробно разберем, почему возникают эти ошибки, рассмотрим правильный шаблон программного вывода СКД с поддержкой внешних функций и параметров, а также изучим альтернативный (и более безопасный) метод свертки группировок непосредственно на управляемой форме.
Когда мы отключаем стандартную обработку в событии ПриКомпоновкеРезультата с помощью свойства СтандартнаяОбработка = Ложь, вся ответственность за формирование отчета ложится на наши плечи. Платформа больше не выполняет автоматическую подготовку макета, инициализацию процессоров и вычисление параметров "под капотом". Это приводит к двум главным проблемам, с которыми столкнулся автор темы:
Константы.ИмяКонстанты.Получить(), то при ручной компоновке макета платформа не всегда может корректно вычислить это выражение в контексте компоновщика.ПроцессорКомпоновкиДанных вызовет ошибку, так как по умолчанию использование внешних функций в нем заблокировано в целях безопасности.Давайте последовательно разберем, как решить эти проблемы программным путем.
Если вам обязательно нужно свернуть группировки именно в модуле объекта отчета, мы должны полностью воссоздать весь процесс компоновки, корректно передав параметры и разрешив использование внешних функций. Рассмотренный ниже шаблон кода решает все описанные проблемы.
Разберем по шагам реализацию в процедуре ПриКомпоновкеРезультата:
Процедура ПриКомпоновкеРезультата(ДокументРезультат, ДанныеРасшифровки, СтандартнаяОбработка)
// 1. Отключаем стандартный вывод платформы
СтандартнаяОбработка = Ложь;
// 2. Явно устанавливаем параметры, которые вызывали ошибку синтаксиса
// Извлекаем текущие настройки компоновщика (с учетом пользовательских изменений)
ТекущиеНастройки = КомпоновщикНастроек.ПолучитьНастройки();
// Заполняем параметр напрямую из кода, обходя вычисление выражения в СКД
ЗначениеКонстанты = Константы.ИмяНужнойКонстанты.Получить();
ПараметрКонстанты = ТекущиеНастройки.ПараметрыДанных.Найти("ИмяПараметраВСКД");
Если ПараметрКонстанты <> Неопределено Тогда
ПараметрКонстанты.Значение = ЗначениеКонстанты;
ПараметрКонстанты.Использование = Истина;
КонецЕсли;
// 3. Создаем макет компоновки данных
КомпоновщикМакет = Новый КомпоновщикМакетаКомпоновкиДанных;
МакетКомпоновки = КомпоновщикМакет.Выполнить(СхемаКомпоновкиДанных, ТекущиеНастройки, ДанныеРасшифровки);
// 4. Инициализируем процессор компоновки и РАЗРЕШАЕМ внешние функции
ПроцессорКомпоновки = Новый ПроцессорКомпоновкиДанных;
// Третий параметр метода Инициализировать отвечает за возможность использования внешних функций
// Передаем Истина, чтобы функции общих модулей в вычисляемых полях отработали без ошибок
ПроцессорКомпоновки.Инициализировать(МакетКомпоновки, , ДанныеРасшифровки, Истина);
// 5. Выводим результат в табличный документ
ПроцессорВывода = Новый ПроцессорВыводаРезультатаКомпоновкиДанныхВТабличныйДокумент;
ПроцессорВывода.УстановитьДокумент(ДокументРезультат);
ПроцессорВывода.Вывести(ПроцессорКомпоновки);
// 6. Сворачиваем группировки строк до нужного уровня (например, до 1-го уровня)
ДокументРезультат.ПоказатьУровеньГруппировокСтрок(1);
КонецПроцедуры
Важное примечание: Обратите внимание на использование метода КомпоновщикНастроек.ПолучитьНастройки() вместо прямого обращения к свойству КомпоновщикНастроек.Настройки. Метод ПолучитьНастройки() собирает воедино как фиксированные настройки отчета, так и все пользовательские изменения (отборы, сортировки, условное оформление), сделанные на форме перед формированием.
Переопределение стандартной обработки в модуле объекта имеет один существенный минус: отчет перестает формироваться в фоновом режиме. На управляемых формах тяжелые отчеты формируются асинхронно, чтобы не "вешать" интерфейс пользователя. Как только мы пишем СтандартнаяОбработка = Ложь, формирование становится синхронным, и пользователь видит зависший экран до окончания процесса.
Чтобы сохранить фоновое формирование и избежать проблем с параметрами и вычисляемыми полями, мы можем выполнить сворачивание группировок непосредственно в модуле управляемой формы отчета после его вывода.
Для этого выполним следующие действия:
ПриОткрытии или используем предопределенные события формы. Если в вашей конфигурации используется Библиотека Стандартных Подсистем (БСП), у формы отчета есть событие ПослеЗаполненияПанелиБыстрыхНастроек или специализированные переопределяемые модули.
&НаКлиенте
Процедура СформироватьОтчет(Команда)
// Очищаем предыдущий результат
Результат.Очистить();
// Вызываем стандартный метод формирования отчета на форме
СкомпоноватьРезультат();
// Сворачиваем группировки до 1 уровня на клиенте
Результат.ПоказатьУровеньГруппировокСтрок(1);
КонецПроцедуры
При таком подходе платформа выполняет компоновку стандартным образом: фоновое задание отрабатывает без ошибок, внешние функции в вычисляемых полях инициализируются автоматически, а параметры-константы вычисляются без сбоев. После завершения формирования табличный документ просто сворачивается до нужного уровня.
Иногда при вызове метода ПоказатьУровеньГруппировокСтрок(1) на сложных иерархических отчетах дочерние группировки внутри свернутых родительских остаются раскрытыми. Из-за этого при ручном раскрытии плюсика пользователю сразу вываливается вся "простыня" вложенных данных.
Чтобы гарантировать красивую и последовательную свертку всех уровней, опытные разработчики используют обход уровней группировок в цикле снизу вверх. Рассмотрим этот алгоритм:
// Получаем максимальное количество уровней группировок в сформированном документе
МаксимальныйУровень = ДокументРезультат.КоличествоУровнейГруппировокСтрок();
// Последовательно сворачиваем уровни, начиная с самых глубоких
Для ТекущийУровень = 1 По МаксимальныйУровень - 1 Цикл
ДокументРезультат.ПоказатьУровеньГруппировокСтрок(МаксимальныйУровень - ТекущийУровень);
КонецЦикла;
// В самом конце устанавливаем желаемый уровень отображения
ДокументРезультат.ПоказатьУровеньГруппировокСтрок(1);
Этот нехитрый прием позволяет аккуратно свернуть абсолютно все вложенные подгруппы, благодаря чему отчет выглядит профессионально, а пользователь может последовательно раскрывать ветки дерева группировок.