Как передать настройки компоновщика СКД из одной формы в другую?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

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

Разберем причины такого поведения платформы 1С, выясним, почему попытка передать настройки напрямую дает сбой, и рассмотрим по шагам надежные способы передачи данных.

Почему прямая передача настроек не работает в клиент-серверной базе

Проанализируем разницу в поведении файловой базы и клиент-серверного режима при передаче параметров в метод ОткрытьФорму:

  1. Единое адресное пространство в файловом режиме: При отладке в тонком клиенте файловой базы вызовы могут выполняться в одном процессе, где сложные структуры памяти не сериализуются полностью, и ссылка на объект настроек СКД может сработать напрямую.
  2. Сериализация по сети в клиент-серверной архитектуре: В клиент-серверном режиме все параметры формы обязательно сериализуются для передачи между клиентом и сервером. Объект НастройкиКомпоновкиДанных является сложным составным типом, тесно связанным со схемой компоновки. При стандартной передаче в параметрах формы десериализация теряет контекст доступных полей, из-за чего настройки приходят пустыми.

Основное решение: передача настроек через временное хранилище

Наиболее эффективным и стандартным способом передачи больших и сложных структур данных в управляемом приложении является использование временного хранилища. Однако здесь разработчики часто совершают распространенную ошибку: путают адрес во временном хранилище и уникальный идентификатор владельца.

Посмотрим на частую ошибку: разработчик пытается вызвать метод ПолучитьИзВременногоХранилища(Параметры.УИД), передав туда GUID формы. В результате платформа выдает исключение: Ошибка получения значения из временного хранилища: Неправильный путь к файлу. Метод ПолучитьИзВременногоХранилища ожидает специальный URL-адрес (начинающийся с e1cib/tempstorage/...), а не строковое представление UUID.

Разберем по шагам, как правильно реализовать передачу настроек.

Шаг 1. Помещение настроек в хранилище в исходной форме

В форме-источнике нам необходимо получить настройки, сохранить их во временное хранилище и передать полученный строковый адрес в параметры открываемой формы. Важно учитывать время жизни данных: если форма-источник сразу после открытия второй формы закрывается, привязывать данные к УникальныйИдентификатор текущей формы нельзя (хранилище очистится вместе с формой). В таком случае генерируем новый идентификатор сеанса.


&НаКлиенте
Процедура ОткрытьФормуНастроек()
    
    // Помещаем настройки во временное хранилище на сервере
    АдресХранилища = ПоместитьНастройкиВХранилищеНаСервере();
    
    // Передаем именно полученный URL, а не УИД
    ПараметрыОткрытия = Новый Структура;
    ПараметрыОткрытия.Вставить("АдресНастроекСКД", АдресХранилища);
    
    ОткрытьФорму("ВнешнийОтчет.ПрайсДляКонтрагента.Форма.ФормаНастроек", ПараметрыОткрытия, ЭтотОбъект);

КонецПроцедуры

&НаСервере
Функция ПоместитьНастройкиВХранилищеНаСервере()
    
    // Получаем результирующие настройки с учетом пользовательских правок
    ТекущиеНастройки = Отчет.КомпоновщикНастроек.ПолучитьНастройки();
    
    // Второй параметр обеспечивает сохранение настроек на время сеанса
    УникальныйИД = Новый УникальныйИдентификатор();
    Возврат ПоместитьВоВременноеХранилище(ТекущиеНастройки, УникальныйИД);

КонецФункции

Шаг 2. Загрузка настроек в принимающей форме

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


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

КонецПроцедуры

Важные нюансы работы с объектом «КомпоновщикНастроек»

Рассмотрим тонкости, из-за которых настройки могут применяться некорректно даже при успешной передаче:

  1. Инициализация источником доступных настроек: Если компоновщик настроек в принимающей форме не был предварительно проинициализирован схемой компоновки через объект ИсточникДоступныхНастроекКомпоновкиДанных, при загрузке настроек отборы, выбранные поля и параметры могут сброситься.
  2. Пользовательские настройки: Если пользователь менял отборы в шапке отчета (быстрые настройки), эти значения лежат в свойстве КомпоновщикНастроек.ПользовательскиеНастройки. Чтобы не потерять их, в источнике следует использовать КомпоновщикНастроек.ПолучитьНастройки(), который собирает полные результирующие настройки воедино, либо передавать и загружать пользовательские настройки отдельно через ЗагрузитьПользовательскиеНастройки().

Альтернативный вариант: сериализация через XDTO

Если по архитектурным причинам нежелательно использовать временное хранилище (например, требуется сохранить настройки в текстовый реквизит или передать через веб-сервис), воспользуемся встроенной сериализацией платформы в XML:


&НаСервере
Функция СериализоватьНастройкиВСтроку(НастройкиСКД)
    
    ЗаписьXML = Новый ЗаписьXML;
    ЗаписьXML.УстановитьСтроку();
    
    СериализаторXDTO.ЗаписатьXML(ЗаписьXML, НастройкиСКД);
    
    Возврат ЗаписьXML.Закрыть();

КонецФункции

&НаСервере
Функция ДесериализоватьНастройкиИзСтроки(СтрокаXML)
    
    ЧтениеXML = Новый ЧтениеXML;
    ЧтениеXML.УстановитьСтроку(СтрокаXML);
    
    Возврат СериализаторXDTO.ПрочитатьXML(ЧтениеXML);

КонецФункции

Полученную строку XML можно без искажений передавать через обычные параметры формы при открытии даже в клиент-серверном режиме.

← На главную