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