Как исправить ошибку сериализации XDTO при формировании внешнего отчета в тонком клиенте 1С?

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

При разработке или доработке внешних отчетов на управляемых формах разработчики нередко сталкиваются с ошибкой передачи данных между сервером и клиентом. Текст ошибки часто содержит упоминания XDTO, userSettings, additionalProperties или dataSource, из-за чего может сложиться ложное впечатление, что проблема кроется в формируемом объекте ТабличныйДокумент. Разберем механизм возникновения этой ошибки и выясним, как правильно организовать формирование отчета.

Анализ ошибки и механизм ее возникновения

Проанализируем типовое проявление ошибки при вызове серверной функции формирования отчета из управляемой формы:

«Ошибка передачи данных между клиентом и сервером. Значение недопустимого типа. Ошибка преобразования данных XDTO: НачалоСвойства: userSettings... additionalProperties... dataSource...»

Посмотрим, что происходит в этот момент на уровне платформы:

  1. В толстом клиенте клиентский и серверный код работают в едином адресном пространстве, поэтому объекты передаются по прямым ссылкам в памяти без конвертации.
  2. В тонком клиенте при выполнении контекстного серверного вызова (&НаСервере) платформа выполняет полную сериализацию контекста всей управляемой формы в XML/XDTO-пакет для передачи обратно на клиент.
  3. Если в реквизитах формы или во вложенных структурах настроек компоновки данных (например, в свойствах ПользовательскиеНастройки или Настройки) сохраняются сугубо серверные объекты, не поддерживающие сериализацию XDTO, процесс упаковки данных завершается аварийно.

В типовых отчетах или при ручном вызове метода СкомпоноватьРезультат() в коллекцию ДополнительныеСвойства могут программно помещаться такие объекты, как МакетКомпоновкиДанных, ПроцессорКомпоновкиДанных, МенеджерВременныхТаблиц или источники данных схемы. Поскольку они не предназначены для передачи на тонкий клиент, попытка вернуть управление из процедуры &НаСервере вызывает ошибку XDTO.

Способ 1. Очистка несериализуемых дополнительных свойств перед возвратом на клиент

Если логика формирования отчета выполняется в контекстной процедуре формы &НаСервере, перед завершением серверного вызова необходимо принудительно очистить коллекции дополнительных свойств компоновщика настроек, в которые могли записаться серверные структуры.

Посмотрим на пример кода очистки свойств в обработчике компоновки:


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

Этот прием позволяет оставить форму в валидном состоянии, готовом к сериализации для тонкого клиента.

Способ 2. Использование бесконтекстных вызовов (&НаСервереБезКонтекста)

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

Разберем реализацию этого метода по шагам:

  1. На клиенте получаем текущие пользовательские настройки отчета.
  2. Передаем во временное хранилище или напрямую в функцию &НаСервереБезКонтекста только сериализуемые параметры.
  3. На сервере генерируем табличный документ и помещаем его во временное хранилище.
  4. На клиенте получаем адрес результата и отображаем его в элементе формы.

Рассмотрим пример реализации:


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

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

Способ 3. Локализация переменных компоновки

Если программная компоновка реализуется вручную через КомпоновщикМакетаКомпоновкиДанных и ПроцессорВыводаРезультатаКомпоновкиДанныхВТабличныйДокумент, важно следить за областью видимости создаваемых объектов.

Проанализируем правила работы с объектами компоновки:

  1. Никогда не сохраняйте переменные типов МакетКомпоновкиДанных, ПроцессорКомпоновкиДанных и СхемаКомпоновкиДанных в реквизитах управляемой формы.
  2. Инициализируйте эти объекты только в виде локальных переменных внутри конкретной процедуры формирования.
  3. После завершения вывода в ТабличныйДокумент не передавайте промежуточные служебные структуры в параметры расшифровки или пользовательские настройки.

Соблюдение этих правил гарантирует отсутствие ошибок преобразования XDTO при работе отчетов в любых клиентских режимах 1С:Предприятия.

← На главную