При разработке правил обмена в конфигурации «Конвертация данных 2.1» (КД 2.1) часто возникает задача выгрузить произвольные данные — например, объединить несколько документов поступления в один сводный документ или собрать информацию нестандартным запросом. При использовании произвольного алгоритма в Правилах выгрузки данных (ПВД) разработчики нередко сталкиваются с ошибкой:
Ошибка получения свойства объекта из входящих данных... ОписаниеОшибки = Получение элемента по индексу для значения не определено
Разберем детально, почему возникает это исключение, чем отличаются механизмы ВыборкаДанных и ВходящиеДанные, а также как правильно выгрузить сводный документ вместе с его табличной частью.
Выясним причину возникновения ошибки. В типовом модуле обработки «Универсальный обмен данными XML» данная ошибка происходит в момент, когда в Правиле конвертации свойств (ПКС) или Правиле конвертации группы свойств (ПКГС) включен флаг «Получить из входящих данных», но сама переменная ВходящиеДанные не была инициализирована и равна Неопределено.
Когда мы формируем произвольную таблицу или выборку в ПВД через переменную ВыборкаДанных, эти данные поступают в ПКО в качестве объекта-источника (переменная Источник), а не во ВходящиеДанные. Движок обмена пытается обратиться к несуществующей структуре входящих данных по имени реквизита (как к элементу коллекции по ключу/индексу) и вызывает аварийное завершение процесса.
Важно четко понимать назначение этих контекстных переменных:
Источник.ИсходящиеДанные (например, при программном вызове ПКО из другого правила или при передаче параметров подчиненным объектам).Если нам требуется выгрузить сводный документ, сформированный запросом в ПВД, проще всего представить строки документа как вложенную коллекцию внутри строки шапки.
Разберем по шагам настройку правил:
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| ПоступлениеТоваровУслуг.Контрагент КАК Контрагент,
| ПоступлениеТоваровУслуг.ДоговорКонтрагента КАК ДоговорКонтрагента,
| ПоступлениеТоваровУслуг.Организация КАК Организация,
| ПоступлениеТоваровУслуг.Товары.(
| Номенклатура КАК Номенклатура,
| Количество КАК Количество,
| Цена КАК Цена,
| Сумма КАК Сумма,
| СуммаНДС КАК СуммаНДС,
| ЕдиницаИзмерения КАК ЕдиницаИзмерения
| ) КАК Товары
|ИЗ
| Документ.ПоступлениеТоваровУслуг КАК ПоступлениеТоваровУслуг";
ВыборкаДанных = Запрос.Выполнить().Выгрузить();
При такой структуре каждая строка таблицы ВыборкаДанных представляет собой отдельный документ. Колонка Товары содержит полноценную таблицу значений, которая автоматически сопоставится с ПКГС «Товары», если имена колонок совпадают с именами свойств источника.
Когда требуется выполнить сложную группировку (например, свернуть накладные за месяц по контрагенту и пересчитать суммы), вложенные запросы не всегда удобны. В таком случае оптимально собрать данные в произвольную таблицу и выгрузить каждый документ вызовом функции ВыгрузитьПоПравилу.
Посмотрим на пример кода в обработчике ПВД «Перед обработкой правила»:
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| ПоступлениеТовары.Ссылка.Контрагент КАК Контрагент,
| ПоступлениеТовары.Номенклатура КАК Номенклатура,
| СУММА(ПоступлениеТовары.Количество) КАК Количество,
| СУММА(ПоступлениеТовары.Сумма) КАК Сумма,
| СУММА(ПоступлениеТовары.СуммаНДС) КАК СуммаНДС
|ИЗ
| Документ.ПоступлениеТоваровУслуг.Товары КАК ПоступлениеТовары
|СГРУППИРОВАТЬ ПО
| ПоступлениеТовары.Ссылка.Контрагент,
| ПоступлениеТовары.Номенклатура
|ИТОГИ ПО
| Контрагент";
Результат = Запрос.Выполнить();
ВыборкаКонтрагентов = Результат.Выбрать(ОбходРезультатаЗапроса.ПоГруппировкам);
Пока ВыборкаКонтрагентов.Следующий() Цикл
// Формируем таблицу товаров для текущего сводного документа
ТаблицаТовары = Новый ТаблицаЗначений;
ТаблицаТовары.Колонки.Добавить("Номенклатура");
ТаблицаТовары.Колонки.Добавить("Количество");
ТаблицаТовары.Колонки.Добавить("Цена");
ТаблицаТовары.Колонки.Добавить("Сумма");
ТаблицаТовары.Колонки.Добавить("СуммаНДС");
ВыборкаСтрок = ВыборкаКонтрагентов.Выбрать();
Пока ВыборкаСтрок.Следующий() Цикл
НоваяСтрока = ТаблицаТовары.Добавить();
НоваяСтрока.Номенклатура = ВыборкаСтрок.Номенклатура;
НоваяСтрока.Количество = ВыборкаСтрок.Количество;
НоваяСтрока.Сумма = ВыборкаСтрок.Сумма;
НоваяСтрока.СуммаНДС = ВыборкаСтрок.СуммаНДС;
// Пересчитываем среднюю цену
НоваяСтрока.Цена = ?(ВыборкаСтрок.Количество <> 0, ВыборкаСтрок.Сумма / ВыборкаСтрок.Количество, 0);
КонецЦикла;
// Заполняем структуру исходящих данных
ИсходящиеДанные = Новый Структура;
ИсходящиеДанные.Вставить("Контрагент", ВыборкаКонтрагентов.Контрагент);
ИсходящиеДанные.Вставить("Товары", ТаблицаТовары);
// Вызываем выгрузку по ПКО без объекта-источника
ВыгрузитьПоПравилу(,, ИсходящиеДанные,, "ПоступлениеТоваровУслуг");
КонецЦикла;
В этом сценарии в ПКО «ПоступлениеТоваровУслуг» мы устанавливаем флаг «Получить из входящих данных» для реквизита Контрагент и ПКГС Товары, так как данные передаются через структуру ИсходящиеДанные.
При программном формировании табличных частей важно убедиться, что для всех ссылочных полей настроены свои ПКО. Если реквизит Номенклатура не переносится или создается пустым, проверяем следующие параметры:
Номенклатура).