Как правильно передать ссылку 1С в поле anyType при формировании набора записей через XDTO?

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

При работе с механизмом XDTO (XML Data Transfer Objects) программисты часто сталкиваются с задачей программного формирования объектов, которые должны быть десериализованы в стандартные типы 1С, такие как НаборЗаписейМенеджер. Одной из наиболее острых проблем является заполнение свойств с универсальным типом anyType или anySimpleType. Типичный пример — поле Value в структуре FilterItem, которое используется для установки отбора в наборе записей (например, по регистратору).

В этой статье мы подробно разберем, почему возникает ошибка «Отображение типа в anySimpleType», и рассмотрим правильные способы программного заполнения таких полей, чтобы метод ПрочитатьXDTO корректно создавал объект в базе данных.

Анализ проблемы и причины возникновения ошибки

Рассмотрим ситуацию: нам необходимо создать объект AccumulationRegisterRecordSet через фабрику XDTO. Мы успешно создаем записи (строки), но при попытке установить фильтр по регистратору через объект Filter возникает ошибка. Проблема кроется в строке кода, где свойству Value напрямую присваивается ссылка 1С:


ЗаписьФильтра_Объект.Value = Документы.ПоступлениеТоваров.ПолучитьСсылку(Новый УникальныйИдентификатор(Идентификатор));

Ошибка «Отображение типа DocumentRef.ПоступлениеТоваров в тип anySimpleType» возникает из-за того, что механизм XDTO не знает, как автоматически преобразовать сложный объект ссылки 1С в неопределенный тип anyType. Поскольку anyType может содержать практически любую структуру, фабрике XDTO требуется явное указание типа (аннотация xsi:type), чтобы при последующем чтении система понимала, что перед ней именно ссылка на конкретный документ, а не просто строковый GUID.

Решение 1: Явное создание объекта XDTO для ссылки

Самый надежный способ решить проблему — это создать промежуточный объект ОбъектXDTO, который будет жестко типизирован согласно схеме метаданных вашей конфигурации. Проанализируем шаги, необходимые для реализации этого подхода:

  1. Получаем ссылку на объект 1С: Сначала формируем обычную ссылку, которую хотим передать в фильтр.
  2. Определяем тип ссылки в XDTO: Используем метод Тип фабрики, указывая пространство имен текущей конфигурации. Для ссылок это обычно http://v8.1c.ru/8.1/data/enterprise/current-config, а имя типа строится как DocumentRef.ИмяДокумента или CatalogRef.ИмяСправочника.
  3. Создаем объект XDTO: С помощью метода Создать генерируем объект, передавая туда тип и саму ссылку.
  4. Присваиваем объект свойству Value: Теперь, когда у нас есть типизированный объект XDTO, мы можем безболезненно передать его в поле anyType.

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


// 1. Получаем ссылку
СсылкаНаДокумент = Документы.ПоступлениеТоваров.ПолучитьСсылку(Новый УникальныйИдентификатор(СтрокаИдентификатор));

// 2. Находим нужный тип в фабрике XDTO
ТипСсылкаXDTO = ФабрикаXDTO.Тип("http://v8.1c.ru/8.1/data/enterprise/current-config", "DocumentRef.ПоступлениеТоваров");

// 3. Создаем типизированное значение XDTO
СсылкаXDTO = ФабрикаXDTO.Создать(ТипСсылкаXDTO, СсылкаНаДокумент);

// 4. Устанавливаем значение в фильтр
ЗаписьФильтра_Объект.Value = СсылкаXDTO;

В этом случае в итоговом XML-файле или объекте появится атрибут xsi:type, который позволит методу СериализаторXDTO.ПрочитатьXDTO() безошибочно восстановить ссылку при записи набора.

Решение 2: Использование СериализаторXDTO для универсальности

Если в вашем коде типы документов могут меняться или вы хотите написать более универсальную обработку, использование жестких строк вида "DocumentRef.ПоступлениеТоваров" не всегда удобно. Проанализируем более гибкий метод с использованием встроенного сериализатора.

Метод СериализаторXDTO.ЗаписатьXDTO(Значение) возвращает готовый ОбъектXDTO. Он автоматически определяет тип переданного объекта и подбирает соответствующее описание из фабрики. Это идеальное решение для заполнения полей anyType.

Разберем пример реализации:


// Вместо ручного поиска типа используем возможности сериализатора
Ссылка = Документы.ПоступлениеТоваров.ПолучитьСсылку(Новый УникальныйИдентификатор(СтрокаИдентификатор));
ЗаписьФильтра_Объект.Value = СериализаторXDTO.ЗаписатьXDTO(Ссылка);

Этот подход короче, безопаснее и автоматически поддерживает любые типы ссылок (справочники, документы, бизнес-процессы), не требуя ручного формирования имен типов.

Полный цикл создания набора записей через XDTO

Чтобы картина была полной, рассмотрим, как собрать весь объект набора записей регистра накопления целиком. Выясним, какие свойства являются ключевыми для того, чтобы 1С восприняла сформированный XDTO-объект как валидный набор записей.


// Определяем типы для набора записей
ТипНабора = ФабрикаXDTO.Тип("http://v8.1c.ru/8.1/data/enterprise/current-config", "AccumulationRegisterRecordSet.ТоварыОрганизаций");
Набор_Объект = ФабрикаXDTO.Создать(ТипНабора);

// Заполнение самих записей (движений)
ТипЗаписи = ТипНабора.Свойства.Получить("Record").Тип;
Для Каждого ДанныеИзИсточника Из МассивДанных Цикл
    НоваяЗапись = ФабрикаXDTO.Создать(ТипЗаписи);
    НоваяЗапись.Period = ДанныеИзИсточника.Период;
    НоваяЗапись.Recorder = СсылкаРегистратор; // Здесь тоже может потребоваться ЗаписатьXDTO, если тип anyType
    НоваяЗапись.Active = Истина;
    // ... заполнение измерений и ресурсов
    Набор_Объект.Record.Добавить(НоваяЗапись);
КонецЦикла;

// Формирование обязательного фильтра (без него набор не запишется корректно)
ТипФильтра = ФабрикаXDTO.Тип("http://v8.1c.ru/8.1/data/enterprise", "Filter");
ОбъектФильтра = ФабрикаXDTO.Создать(ТипФильтра);

ТипЭлементаФильтра = ФабрикаXDTO.Тип("http://v8.1c.ru/8.1/data/enterprise", "FilterItem");
ЭлементФильтра = ФабрикаXDTO.Создать(ТипЭлементаФильтра);
ЭлементФильтра.Name = "Recorder";
ЭлементФильтра.Value = СериализаторXDTO.ЗаписатьXDTO(СсылкаРегистратор);

ОбъектФильтра.FilterItem.Добавить(ЭлементФильтра);
Набор_Объект.Filter = ОбъектФильтра;

// Десериализация в объект 1С и запись
ЗаписываемыйОбъект = СериализаторXDTO.ПрочитатьXDTO(Набор_Объект);
ЗаписываемыйОбъект.ОбменДанными.Загрузка = Истина;
ЗаписываемыйОбъект.Записать();

Важные рекомендации при работе с XDTO и наборами записей

При использовании данных методов стоит учитывать несколько технических нюансов, которые помогут избежать ошибок в промышленной эксплуатации:

Таким образом, мы выяснили, что ключ к успеху при работе с anyType в XDTO — это предоставление системе информации о типе данных. Используя явное создание объекта через ФабрикаXDTO.Создать или универсальный метод СериализаторXDTO.ЗаписатьXDTO, вы сможете корректно передавать ссылки и другие сложные типы данных, обеспечивая надежный обмен данными между системами.

← На главную