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