Как в 1С:Конвертация данных 2.0 загрузить табличную часть из нескольких элементов справочника?

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

При настройке правил обмена в программе 1С:Конвертация данных 2.0 (2.1) разработчики часто сталкиваются со сложными задачами трансформации данных. Одна из классических задач — заполнение табличной части документа-приемника (например, ТЧ Услуги в документе РеализацияТоваровУслуг) на основе данных, которые в базе-источнике хранятся не в аналогичной табличной части, а как отдельные элементы справочника или результат произвольного запроса.

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

Метод 1. Использование предопределенной переменной КоллекцияОбъектов в ПКГС

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

Разберем этот метод подробно по шагам:

  1. Откроем Правило конвертации объектов (ПКО) для нашего документа (например, РеализацияТоваровУслуг).
  2. Найдем в списке свойств нашу табличную часть (это строка типа ПКГС — Правило конвертации группы свойств).
  3. Поле Источник для этой группы свойств мы оставляем абсолютно пустым. Это ключевой момент: мы будем генерировать строки программно.
  4. Откроем обработчик события Перед обработкой для этого ПКГС. Именно здесь мы напишем алгоритм, который выберет нужные элементы справочника.
  5. Результат запроса мы выгрузим в ТаблицуЗначений и присвоим ее специальной предопределенной переменной КоллекцияОбъектов.

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


Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ
    |	Номенклатура.Ссылка КАК Номенклатура,
    |	1 КАК Количество,
    |	100 КАК Цена,
    |	100 КАК Сумма
    |ИЗ
    |	Справочник.Номенклатура КАК Номенклатура
    |ГДЕ
    |	Номенклатура.Родитель.Наименование = &НаименованиеПапки";

Запрос.УстановитьПараметр("НаименованиеПапки", "Консультационные услуги");

// Результат запроса выгружаем в Таблицу Значений и передаем КД
КоллекцияОбъектов = Запрос.Perform().Unload(); // Запрос.Выполнить().Выгрузить();

Важное правило сопоставления полей: Обратите внимание на псевдонимы колонок в запросе (Номенклатура, Количество, Цена, Сумма). Они должны в точности совпадать с именами реквизитов табличной части документа-приемника. Внутри ПКГС для каждого реквизита табличной части создаются обычные правила конвертации свойств (ПКС). Поля Источник в этих ПКС оставляются пустыми, а в поле Приемник указывается соответствующий реквизит. Конвертация данных автоматически сопоставит колонки из таблицы КоллекцияОбъектов с реквизитами приемника по совпадению имен. Никаких галочек "Получить из входящих данных" при этом ставить не требуется!

Метод 2. Использование ПВД и механизма ВходящиеДанные через ВыгрузитьПоПравилу

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

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


// НЕПРАВИЛЬНЫЙ ПОДХОД, КОТОРЫЙ ПРИВЕДЕТ К КРИТИЧЕСКИМ ОШИБКАМ
Для каждого СтрокаВыборки Из ТаблицаРезультатов Цикл
    ВыгрузитьПоПравилу(,, СтрокаВыборки,, "РеализацияТоваровУслуг");
    // Платформа пытается создать НОВЫЙ документ на каждую строку табличной части!
КонецЦикла;

Почему этот код вызывает ошибки? Потому что функция ВыгрузитьПоПравилу при таком вызове пытается создать отдельный документ на каждую строчку вашей таблицы результатов! Так как в строке таблицы нет данных для шапки документа (номера, даты, организации), КД выдает серьезные ошибки объектной структуры.

Выясним, как реализовать этот метод корректно с использованием механизма ВходящиеДанные:

  1. В ПВД создаем правило с типом выборки Произвольный алгоритм.
  2. В обработчике выгрузки формируем общую структуру данных для всего документа целиком.
  3. Табличную часть упаковываем в виде отдельной ТаблицыЗначений и вкладываем её в структуру входящих данных под ключом, имя которого совпадает с именем табличной части в приемнике.
  4. Вызываем функцию ВыгрузитьПоПравилу ровно один раз для одного документа.

Рассмотрим пример правильной реализации в ПВД:


// 1. Создаем таблицу значений для будущей табличной части документа-приемника
ТЗ_Услуги = Новый ТаблицаЗначений;
ТЗ_Услуги.Колонки.Добавить("Номенклатура");
ТЗ_Услуги.Колонки.Добавить("Количество");
ТЗ_Услуги.Колонки.Добавить("Цена");
ТЗ_Услуги.Колонки.Добавить("Сумма");

// Заполняем её данными из нашего запроса к справочнику-источнику
Запрос = Новый Запрос;
Запрос.Текст = "ВЫБРАТЬ Ссылка Из Справочник.Номенклатура ГДЕ ...";
Выборка = Запрос.Выполнить().Выбрать();
Пока Выборка.Следующий() Цикл
    НоваяСтрока = ТЗ_Услуги.Добавить();
    НоваяСтрока.Номенклатура = Выборка.Ссылка;
    НоваяСтрока.Количество = 1;
    НоваяСтрока.Цена = 500;
    НоваяСтрока.Сумма = 500;
КонецЦикла;

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

// 3. Выгружаем документ ОДИН раз, передавая структуру в качестве третьего параметра
ВыгрузитьПоПравилу(,, ВходящиеДанныеДокумента,, "РеализацияТоваровУслуг");

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

Метод 3. Наполнение табличной части при загрузке в обработчике ПослеЗагрузки

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

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

Разберем пример кода для обработчика После загрузки:


// Объект — это готовый к записи документ в базе-приемнике
// Выполним поиск нужной услуги непосредственно в приемнике по коду или наименованию
СсылкаНаНоменклатуру = Справочники.Номенклатура.НайтиПоНаименованию("Консультационные услуги");

Если ЗначениеЗаполнено(СсылкаНаНоменклатуру) Тогда
    // Добавляем строку в табличную часть документа
    НоваяСтрока = Объект.Услуги.Добавить();
    НоваяСтрока.Номенклатура = СсылкаНаНоменклатуру;
    НоваяСтрока.Количество = 1;
    НоваяСтрока.Цена = 1000;
    НоваяСтрока.Сумма = 1000;
КонецЕсли;

Плюсы и минусы метода: Этот способ предельно прост в написании, однако у него есть существенный недостаток: теряется гибкость платформы 1С:Конвертация данных. Логика поиска элементов жестко кодируется на языке 1С базы-приемника, игнорируя стандартные правила поиска и сопоставления полей, настроенные в КД.

Анализ типичных ошибок

Проанализируем, почему у автора темы возникали "страшные ошибки при выгрузке". Главная причина — конфликт между источником данных и флагом "Получить из входящих данных". Если у свойства ТЧ в ПКС указан Источник, но при этом включен флаг «Получить из входящих данных» (или наоборот, незаполненный источник без этого флага), КД начинает искать реквизит в переданной структуре, не находит его и возвращает значение Неопределено, что приводит к ошибкам сопоставления типов при загрузке.

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

Рекомендуем использовать первый метод с переменной КоллекцияОбъектов как основной и наиболее надежный стандарт разработки в 1С:Конвертация данных 2.0!

← На главную