Как исправить ошибку «Получение элемента по индексу для значения не определено» при выгрузке структуры в КД 2.0?

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

При разработке правил обмена в конфигурации «1С:Конвертация данных 2.0» (КД 2.0) программисты часто используют выгрузку данных из произвольных алгоритмов (ПВД — Правила выгрузки данных) с помощью функции ВыгрузитьПоПравилу(). Этот механизм незаменим, когда данные в базе-источнике отсутствуют в виде готовых объектов метаданных или требуют сложной предварительной сборки в структуру. Однако при попытке связать выгружаемый по структуре объект с другими зависимыми объектами (например, при заполнении измерений регистра сведений) легко столкнуться с неприятной ошибкой: «Ошибка получения свойства объекта из входящих данных... Получение элемента по индексу для значения не определено».

В этой статье мы подробно разберем, почему возникает данная ошибка, проанализируем внутренние механизмы работы КД 2.0 со структурами и рассмотрим несколько эффективных способов решения этой проблемы.

Введение: Механизм работы КД 2.0 со структурами

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

В этот момент КД 2.0 ожидает, что в структуре ВходящиеДанные (или ИсходящиеДанные, в зависимости от контекста вызова) будет находиться ключ, имя которого строго совпадает с именем ПКС. Если правило настроено таким образом, оно перестает обращаться к реквизитам объекта-источника напрямую и полностью переходит на чтение из переданной структуры.

Анализ проблемы: Почему возникает ошибка индексации?

Рассмотрим ситуацию, с которой столкнулся автор темы на форуме. У него была задача: выгрузить договор в справочник приемника и одновременно записать данные в регистр сведений, где одним из измерений является ссылка на этот самый договор. Данные для договора собирались запросом в ПВД и помещались в структуру ИсходящиеДанныеДоговор.

Ниже приведен фрагмент исходного кода ПВД:


// Первый этап: выгрузка самого договора по структуре
Пока ВыборкаДетальныеЗаписи.Следующий() Цикл
    ИсходящиеДанные = Новый Структура;
    ИсходящиеДанные.Вставить("2_Key", ВыборкаДетальныеЗаписи.2_Key);
    ИсходящиеДанные.Вставить("ОсновнаяСтатьяДвиженияДенежныхСредств", ВыборкаДетальныеЗаписи.СтатьяДвиженияДенежныхСредств);
    // ... заполнение остальных свойств
            
    ВыгрузитьПоПравилу(,,ИсходящиеДанные,,"ДоговорыКонтрагентов");
    
    // Сохраняем структуру договора для последующего использования
    ИсходящиеДанныеДоговор = ИсходящиеДанные;
КонецЦикла;

// Второй этап: попытка выгрузить регистр сведений
Пока ВыборкаДетальныеЗаписи.Следующий() Цикл
    ИсходящиеДанные = Новый Структура;
    // Ошибка здесь: в качестве договора передается вся структура предыдущей выгрузки
    ИсходящиеДанные.Вставить("Договор", ИсходящиеДанныеДоговор); 
    ИсходящиеДанные.Вставить("Проект", ВыборкаДетальныеЗаписи.Проект);
    // ...
            
    ВыгрузитьПоПравилу(,,ИсходящиеДанные,,"ас_КураторыСтатейДДС");
КонецЦикла;

При такой реализации обработчик КД 2.0 начинает выгружать регистр сведений по правилу ас_КураторыСтатейДДС. Доходя до свойства Договор, система видит, что для выгрузки договора назначено ПКО ДоговорыКонтрагентов, и передает туда значение свойства из структуры — то есть вложенную структуру ИсходящиеДанныеДоговор.

Поскольку ПКО ДоговорыКонтрагентов настроено на чтение свойств из входящих данных, оно ожидает, что структура будет передана корректно в контексте вызова. Однако при вложенной выгрузке КД 2.0 теряет контекст ВходящиеДанные для подчиненного правила или пытается прочитать свойства у объекта, который не является ссылкой или ожидаемым типом. В результате платформа выдает ошибку в модуле обработки обмена: «Получение элемента по индексу для значения не определено». КД пытается обратиться к индексам (ключам) там, где это невозможно из-за смешения типов данных.

Решение 1: Разделение ПКО на «структурное» и «ссылочное» (Рекомендуемый способ)

Самый простой, надежный и архитектурно правильный способ — разделить логику создания/обновления объекта и логику ссылки на него в других правилах.

Для регистра сведений не нужно заново передавать структуру со всеми реквизитами договора. Нам достаточно передать в регистр обычную ссылку на договор базы-источника, чтобы в приемнике система смогла найти этот договор по ключевым полям (например, по УИД или Коду).

Давайте разберем этот способ по шагам:

  1. Создаем новое ПКО. Назовем его, например, ДоговорыКонтрагентов_ТолькоПоиск. В качестве источника и приемника указываем соответствующие справочники договоров.
  2. В новом ПКО настраиваем только те ПКС, которые необходимы для однозначного поиска объекта в базе-приемнике (например, УникальныйИдентификатор, Код или Наименование). У этих свойств устанавливаем флаг «Поиск». При этом флаги «Получить из входящих данных» ставить не нужно.
  3. В правиле конвертации регистра сведений для свойства Договор в колонке «Правило конвертации» указываем наше новое ПКО ДоговорыКонтрагентов_ТолькоПоиск.
  4. Корректируем код в ПВД, передавая в структуру регистра реальную ссылку на договор, а не его структуру:

Пока ВыборкаДетальныеЗаписи.Следующий() Цикл
    ИсходящиеДанные = Новый Структура;
    // Передаем реальную ссылку на объект-договор из выборки запроса
    ИсходящиеДанные.Вставить("Договор", ВыборкаДетальныеЗаписи.Договор);
    ИсходящиеДанные.Вставить("Проект", ВыборкаДетальныеЗаписи.Проект);
    ИсходящиеДанные.Вставить("Статья", ВыборкаДетальныеЗаписи.Статья);
    ИсходящиеДанные.Вставить("Сумма", ВыборкаДетальныеЗаписи.Сумма);
            
    ВыгрузитьПоПравилу(,,ИсходящиеДанные,,"ас_КураторыСтатейДДС");
КонецЦикла;

При таком подходе при выгрузке регистра КД 2.0 получит ссылку на договор, передаст ее в облегченное правило поиска, выгрузит ключевые поля, и в приемнике запись регистра успешно свяжется с существующим (или созданным на первом этапе) договором без каких-либо ошибок типизации.

Решение 2: Переопределение ВходящихДанных в обработчике ПКС

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

Для этого в правиле конвертации регистра в ПКС Договор необходимо прописать специальный алгоритм в обработчике «Перед выгрузкой»:


// В обработчике "Перед выгрузкой" ПКС "Договор"
// Явно формируем ВходящиеДанные для подчиненного правила конвертации (ПКО ДоговорыКонтрагентов)

ВходящиеДанные = Новый Структура;
ВходящиеДанные.Вставить("2_Key", НашИсточникДоговора.2_Key);
ВходящиеДанные.Вставить("ОсновнаяСтатьяДвиженияДенежныхСредств", НашИсточникДоговора.СтатьяДДС);
// Заполняем абсолютно все ключи, которые ожидает ПКО ДоговорыКонтрагентов

// Сбрасываем значение, чтобы система не пыталась конвертировать сам объект-источник напрямую
Значение = "ПустаяСсылка"; 

Этот способ более трудоемок, так как при изменении состава реквизитов договора вам придется поддерживать этот код в актуальном состоянии. Однако он позволяет обойтись без создания дублирующих ПКО.

Резюме и рекомендации

Проанализировав проблему, можно сделать следующие выводы:

← На главную