Как объединить две табличные части в одну при выгрузке через Конвертацию данных 2.1?

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

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

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

Причина проблемы при стандартном сопоставлении

Когда мы создаем несколько ПКГС (Правил конвертации групп свойств) для одной и той же табличной части приемника, алгоритмы 1С работают последовательно. Сначала выгружается первая таблица, затем вторая. При загрузке в приемник вторая таблица просто очищает результаты загрузки первой. Чтобы этого избежать, нам необходимо собрать все данные в одну единую структуру (коллекцию) еще на этапе выгрузки из источника.

Решение 1: Программное формирование коллекции через перебор строк

Это самый наглядный способ. Мы создаем одно ПКГС для табличной части Товары. Поле Источник в заголовке этого правила оставляем пустым. Это критически важно, чтобы система не пыталась автоматически подставить данные. Всю работу мы выполним в обработчике Перед обработкой этого ПКГС.

Рассмотрим алгоритм действий. Мы создаем таблицу значений, описываем её колонки и заполняем строками из обеих таблиц источника. Проанализируем пример кода:


// В обработчике Перед обработкой ПКГС "Товары"
КоллекцияОбъектов = Новый ТаблицаЗначений;
КоллекцияОбъектов.Колонки.Добавить("Номенклатура");
КоллекцияОбъектов.Колонки.Добавить("Количество");
КоллекцияОбъектов.Колонки.Добавить("Сумма");
КоллекцияОбъектов.Колонки.Добавить("СтавкаНДС");
КоллекцияОбъектов.Колонки.Добавить("Цена");

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

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

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

Решение 2: Использование запроса для объединения данных

Если данных много, или логика отбора строк сложная, эффективнее будет использовать запрос к базе данных. Объединение на уровне СУБД (через ОБЪЕДИНИТЬ ВСЕ) работает быстрее, чем циклы в коде 1С.

Разберем, как реализовать этот подход в том же обработчике Перед обработкой:


Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ
    |   Т.Номенклатура КАК Номенклатура,
    |   Т.Количество КАК Количество,
    |   Т.Сумма КАК Сумма
    |ИЗ
    |   Документ.ВозвратТоваровОтПокупателя.Товары КАК Т
    |ГДЕ
    |   Т.Ссылка = &Ссылка
    |
    |ОБЪЕДИНИТЬ ВСЕ
    |
    |ВЫБРАТЬ
    |   У.Номенклатура,
    |   У.Количество,
    |   У.Сумма
    |ИЗ
    |   Документ.ВозвратТоваровОтПокупателя.Услуги КАК У
    |ГДЕ
    |   У.Ссылка = &Ссылка";

Запрос.УстановитьПараметр("Ссылка", Источник.Ссылка);
КоллекцияОбъектов = Запрос.Выполнить().Выгрузить();

Важное замечание: Этот метод подходит только в том случае, если документ уже записан в базу данных. Если вы производите выгрузку объекта, который был изменен в памяти и еще не зафиксирован в СУБД, запрос не увидит актуальных данных. В таких случаях используйте Решение 1.

Решение 3: Оптимизированное слияние через выгрузку таблиц

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


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

// Добавляем данные из второй ТЧ
Для Каждого СтрокаУслуг Из Источник.Услуги Цикл
    НоваяСтрока = КоллекцияОбъектов.Добавить();
    ЗаполнитьЗначенияСвойств(НоваяСтрока, СтрокаУслуг);
КонецЦикла;

Этот метод хорош тем, что КоллекцияОбъектов автоматически получает все колонки, существующие в ТЧ Товары источника. Однако помните: если в ТЧ Услуги есть реквизиты, которых нет в Товары, но они нужны в приемнике, их придется добавить в таблицу программно через КоллекцияОбъектов.Колонки.Добавить().

Тонкости настройки ПКС внутри группы

После того как мы программно сформировали КоллекцияОбъектов, нам нужно настроить ПКС (Правила конвертации свойств), которые находятся внутри этого ПКГС (например, Номенклатура, Количество и т.д.):

  1. В поле Источник каждого ПКС следует указать имя колонки из нашей созданной таблицы значений.
  2. Если имена колонок в таблице и имена реквизитов в приемнике совпадают, КД 2.1 может сопоставить их автоматически, но для надежности лучше прописать их вручную.
  3. Если в приемнике есть обязательные поля (например, Склад или СчетУчета), которых нет в таблице Услуги, в цикле обхода услуг обязательно подставляйте эти значения (например, из шапки документа или констант).

Борьба с дублями и порядок строк

Иногда одна и та же номенклатура может присутствовать и в товарах, и в услугах. Если логика учета в Бухгалтерии требует схлопывания таких строк, в конце обработчика можно выполнить сворачивание коллекции:

КоллекцияОбъектов.Свернуть("Номенклатура, Цена, СтавкаНДС", "Количество, Сумма");

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

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

← На главную