При разработке правил обмена в конфигурации «1С:Конвертация данных 2.0» (КД 2.0) программисты часто используют выгрузку данных из произвольных алгоритмов (ПВД — Правила выгрузки данных) с помощью функции ВыгрузитьПоПравилу(). Этот механизм незаменим, когда данные в базе-источнике отсутствуют в виде готовых объектов метаданных или требуют сложной предварительной сборки в структуру. Однако при попытке связать выгружаемый по структуре объект с другими зависимыми объектами (например, при заполнении измерений регистра сведений) легко столкнуться с неприятной ошибкой: «Ошибка получения свойства объекта из входящих данных... Получение элемента по индексу для значения не определено».
В этой статье мы подробно разберем, почему возникает данная ошибка, проанализируем внутренние механизмы работы КД 2.0 со структурами и рассмотрим несколько эффективных способов решения этой проблемы.
Когда мы выгружаем объект не на основании ссылки на базу-источник, а передаем готовую структуру (в качестве третьего параметра функции ВыгрузитьПоПравилу()), правила конвертации свойств (ПКС) внутри ПКО начинают работать в особом режиме. Для каждого свойства, которое должно заполниться из переданной структуры, в настройках ПКС обязательно должен быть установлен флаг «Получить из входящих данных».
В этот момент КД 2.0 ожидает, что в структуре ВходящиеДанные (или ИсходящиеДанные, в зависимости от контекста вызова) будет находиться ключ, имя которого строго совпадает с именем ПКС. Если правило настроено таким образом, оно перестает обращаться к реквизитам объекта-источника напрямую и полностью переходит на чтение из переданной структуры.
Рассмотрим ситуацию, с которой столкнулся автор темы на форуме. У него была задача: выгрузить договор в справочник приемника и одновременно записать данные в регистр сведений, где одним из измерений является ссылка на этот самый договор. Данные для договора собирались запросом в ПВД и помещались в структуру ИсходящиеДанныеДоговор.
Ниже приведен фрагмент исходного кода ПВД:
// Первый этап: выгрузка самого договора по структуре
Пока ВыборкаДетальныеЗаписи.Следующий() Цикл
ИсходящиеДанные = Новый Структура;
ИсходящиеДанные.Вставить("2_Key", ВыборкаДетальныеЗаписи.2_Key);
ИсходящиеДанные.Вставить("ОсновнаяСтатьяДвиженияДенежныхСредств", ВыборкаДетальныеЗаписи.СтатьяДвиженияДенежныхСредств);
// ... заполнение остальных свойств
ВыгрузитьПоПравилу(,,ИсходящиеДанные,,"ДоговорыКонтрагентов");
// Сохраняем структуру договора для последующего использования
ИсходящиеДанныеДоговор = ИсходящиеДанные;
КонецЦикла;
// Второй этап: попытка выгрузить регистр сведений
Пока ВыборкаДетальныеЗаписи.Следующий() Цикл
ИсходящиеДанные = Новый Структура;
// Ошибка здесь: в качестве договора передается вся структура предыдущей выгрузки
ИсходящиеДанные.Вставить("Договор", ИсходящиеДанныеДоговор);
ИсходящиеДанные.Вставить("Проект", ВыборкаДетальныеЗаписи.Проект);
// ...
ВыгрузитьПоПравилу(,,ИсходящиеДанные,,"ас_КураторыСтатейДДС");
КонецЦикла;
При такой реализации обработчик КД 2.0 начинает выгружать регистр сведений по правилу ас_КураторыСтатейДДС. Доходя до свойства Договор, система видит, что для выгрузки договора назначено ПКО ДоговорыКонтрагентов, и передает туда значение свойства из структуры — то есть вложенную структуру ИсходящиеДанныеДоговор.
Поскольку ПКО ДоговорыКонтрагентов настроено на чтение свойств из входящих данных, оно ожидает, что структура будет передана корректно в контексте вызова. Однако при вложенной выгрузке КД 2.0 теряет контекст ВходящиеДанные для подчиненного правила или пытается прочитать свойства у объекта, который не является ссылкой или ожидаемым типом. В результате платформа выдает ошибку в модуле обработки обмена: «Получение элемента по индексу для значения не определено». КД пытается обратиться к индексам (ключам) там, где это невозможно из-за смешения типов данных.
Самый простой, надежный и архитектурно правильный способ — разделить логику создания/обновления объекта и логику ссылки на него в других правилах.
Для регистра сведений не нужно заново передавать структуру со всеми реквизитами договора. Нам достаточно передать в регистр обычную ссылку на договор базы-источника, чтобы в приемнике система смогла найти этот договор по ключевым полям (например, по УИД или Коду).
Давайте разберем этот способ по шагам:
ДоговорыКонтрагентов_ТолькоПоиск. В качестве источника и приемника указываем соответствующие справочники договоров.УникальныйИдентификатор, Код или Наименование). У этих свойств устанавливаем флаг «Поиск». При этом флаги «Получить из входящих данных» ставить не нужно.Договор в колонке «Правило конвертации» указываем наше новое ПКО ДоговорыКонтрагентов_ТолькоПоиск.
Пока ВыборкаДетальныеЗаписи.Следующий() Цикл
ИсходящиеДанные = Новый Структура;
// Передаем реальную ссылку на объект-договор из выборки запроса
ИсходящиеДанные.Вставить("Договор", ВыборкаДетальныеЗаписи.Договор);
ИсходящиеДанные.Вставить("Проект", ВыборкаДетальныеЗаписи.Проект);
ИсходящиеДанные.Вставить("Статья", ВыборкаДетальныеЗаписи.Статья);
ИсходящиеДанные.Вставить("Сумма", ВыборкаДетальныеЗаписи.Сумма);
ВыгрузитьПоПравилу(,,ИсходящиеДанные,,"ас_КураторыСтатейДДС");
КонецЦикла;
При таком подходе при выгрузке регистра КД 2.0 получит ссылку на договор, передаст ее в облегченное правило поиска, выгрузит ключевые поля, и в приемнике запись регистра успешно свяжется с существующим (или созданным на первом этапе) договором без каких-либо ошибок типизации.
Если по какой-то причине вы не хотите плодить дополнительные ПКО и желаете использовать существующее ПКО ДоговорыКонтрагентов, работающее исключительно со структурами, вам придется вручную управлять передачей вложенных данных.
Для этого в правиле конвертации регистра в ПКС Договор необходимо прописать специальный алгоритм в обработчике «Перед выгрузкой»:
// В обработчике "Перед выгрузкой" ПКС "Договор"
// Явно формируем ВходящиеДанные для подчиненного правила конвертации (ПКО ДоговорыКонтрагентов)
ВходящиеДанные = Новый Структура;
ВходящиеДанные.Вставить("2_Key", НашИсточникДоговора.2_Key);
ВходящиеДанные.Вставить("ОсновнаяСтатьяДвиженияДенежныхСредств", НашИсточникДоговора.СтатьяДДС);
// Заполняем абсолютно все ключи, которые ожидает ПКО ДоговорыКонтрагентов
// Сбрасываем значение, чтобы система не пыталась конвертировать сам объект-источник напрямую
Значение = "ПустаяСсылка";
Этот способ более трудоемок, так как при изменении состава реквизитов договора вам придется поддерживать этот код в актуальном состоянии. Однако он позволяет обойтись без создания дублирующих ПКО.
Проанализировав проблему, можно сделать следующие выводы:
Получение элемента по индексу для значения не определено возникает из-за попытки КД 2.0 обработать структуру данных правилом, которое ожидает объектный тип, или наоборот — когда в ПКО, настроенное на входящие данные, передается несовместимый тип.