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