Как перенести реквизит из шапки документа в табличную часть приёмника в Конвертации данных 2.x

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

При настройке правил обмена в конфигурации 1С:Конвертация данных 2.x (КД 2) разработчики часто сталкиваются с нетипичными задачами трансформации данных. Одна из самых распространенных — необходимость перенести одиночный реквизит из шапки документа источника (например, общую сумму документа, склад или контрагента) в строки новой или существующей табличной части документа приёмника. Напрямую сопоставить такие реквизиты в интерфейсе правил конвертации свойств (ПКС) нельзя, поскольку структура данных шапки и табличной части принципиально отличается. Для миграции из 1С:Бухгалтерии 3.0 в 1С:Комплексную автоматизацию 2 готовый набор правил предоставляет Перенос данных БП 3.0 — КА 2.

В этой статье мы подробно разберем, как решить эту задачу несколькими способами. Мы проанализируем частые ошибки начинающих разработчиков, подробно рассмотрим рабочий код и разберем альтернативные, более изящные методы архитектурного построения правил обмена. Для регулярного выполнения подготовленных XML-правил по расписанию применяется МС:Автообмен для автоматизации синхронизации.

Сценарий и суть проблемы

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

---

Решение 1. Классический метод через ВходящиеДанные в ПКО

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

Давайте разберем по шагам, как настроить этот механизм и избежать критических ошибок при написании кода.

Шаг 1. Инициализация таблицы в обработчике ПКО

Откроем настройки ПКО для нашего документа. В обработчике события «Перед выгрузкой» нам необходимо программно создать и наполнить объект типа ТаблицаЗначений. Колонки этой таблицы должны строго соответствовать именам реквизитов табличной части документа-получателя. При необходимости можно воспользоваться доработанной конфигурацией «Конвертация данных» с подсказками по обработчикам.

Посмотрим на пример правильной инициализации и заполнения таблицы значений:


// Инициализируем новую таблицу значений
ТЗ = Новый ТаблицаЗначений;

// Добавляем колонки, соответствующие реквизитам ТЧ "ЭтапыГрафикаОплаты" в приёмнике
ТЗ.Колонки.Добавить("Заказ");
ТЗ.Колонки.Добавить("СверхЗаказа");
ТЗ.Колонки.Добавить("ВариантОплаты");
ТЗ.Колонки.Добавить("ДатаПлатежа");
ТЗ.Колонки.Добавить("Сдвиг");
ТЗ.Колонки.Добавить("ПроцентПлатежа");
ТЗ.Колонки.Добавить("СуммаПлатежа");
ТЗ.Колонки.Добавить("ПроцентЗалогаЗаТару");
ТЗ.Колонки.Добавить("СуммаЗалогаЗаТару");
ТЗ.Колонки.Добавить("СуммаВзаиморасчетов");
ТЗ.Колонки.Добавить("СуммаВзаиморасчетовПоТаре");

// Добавляем новую строку в таблицу значений и получаем на неё ссылку
НоваяСтрока = ТЗ.Добавить();

// Заполняем реквизиты строки ТЗ данными из шапки источника и статическими значениями
НоваяСтрока.СуммаПлатежа = Источник.СуммаДокумента;
НоваяСтрока.ВариантОплаты = "ПредоплатаДоПоступления";
НоваяСтрока.ДатаПлатежа   = '20191010'; // Пример фиксированной даты
НоваяСтрока.ПроцентПлатежа = 100;

// Помещаем таблицу во "ВходящиеДанные" под именем нашей табличной части в приёмнике
ВходящиеДанные = Новый Структура;
ВходящиеДанные.Вставить("ЭтапыГрафикаОплаты", ТЗ);

Шаг 2. Настройка ПКГС (Табличной части) в правилах

Теперь перейдем к настройке структуры свойств внутри этого ПКО:

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

Разбор типичных ошибок при реализации этого метода:

Ошибка №1: Переменная не определена (ЭтапыГрафикаОплаты)

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

Ошибка №2: Поле объекта не обнаружено (СуммаПлатежа)

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

---

Решение 2. Использование обработчика «Перед обработкой» в самом ПКГС

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

Гораздо более чистым и инкапсулированным решением будет перенос логики непосредственно внутрь самого ПКГС.

Выполним следующие настройки:

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

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

НоваяСтрока = КоллекцияОбъектов.Добавить();
// Мы по-прежнему имеем доступ к объекту Источник (это наш документ-отправитель)
НоваяСтрока.СуммаПлатежа = Источник.СуммаДокумента;
НоваяСтрока.ВариантОплаты = "ПредоплатаДоПоступления";
НоваяСтрока.ДатаПлатежа   = '20191010';
НоваяСтрока.ПроцентПлатежа = 100;

Преимущества этого подхода:

---

Решение 3. Добавление реквизита из шапки при переносе строк "один в один"

Рассмотрим другую частую ситуацию: табличная часть приёмника заполняется на основании аналогичной табличной части источника, но в каждую строку приёмника нужно дополнительно записать значение из шапки документа-источника (например, проставить общий Склад во все строки спецификации).

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

  1. В ПКГС укажем стандартный источник табличной части (например, Товары).
  2. Внутри ПКГС найдем ПКС нужного нам реквизита (например, Склад) и очистим у него поле «Источник».
  3. В обработчике «Перед выгрузкой» этого конкретного ПКС напишем простую строку:

// Переменная Источник на уровне ПКС внутри ПКГС по-прежнему ссылается на объект выгружаемого ДОКУМЕНТА
Значение = Источник.Склад; 

Таким образом, при обходе стандартных строк ТЧ программа будет на каждой строке обращаться к шапке документа-источника и подставлять нужное значение.

Если же требуется программно доработать выгруженную ТЧ, то в обработчике ПКГС «Перед обработкой» можно использовать такой код:


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

// Добавляем новую колонку для реквизита приёмника, которой не было в источнике
КоллекцияОбъектов.Колонки.Добавить("СкладПриемник");

// Быстро заполняем всю колонку значением склада из шапки источника
КоллекцияОбъектов.ЗаполнитьЗначения(Источник.СкладШапки, "СкладПриемник");

---

Решение 4. Перенос через параметры и заполнение «После загрузки»

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

Рассмотрим по шагам реализацию этого механизма:

Шаг 1. Передача параметра при выгрузке

  1. В ПКО документа перейдем на вкладку «Параметры» и добавим новый параметр (например, СуммаДокументаДляТЧ).
  2. В ПКС для этого параметра в обработчике «Перед выгрузкой» укажем: Значение = Источник.СуммаДокумента;

Шаг 2. Заполнение ТЧ в базе-приёмнике

В ПКО документа перейдем в обработчик события «После загрузки». Напишем код, который перехватит переданный параметр и создаст строку в ТЧ уже непосредственно в базе-получателе:


СуммаИзПараметра = Неопределено;
// Проверяем наличие параметра в переданных данных
Если ПараметрыОбъекта <> Неопределено И ПараметрыОбъекта.Свойство("СуммаДокументаДляТЧ", СуммаИзПараметра) Тогда
    
    // Если табличная часть пустая - добавим строку
    Если Объект.ЭтапыГрафикаОплаты.Количество() = 0 Тогда
        НоваяСтрока = Объект.ЭтапыГрафикаОплаты.Добавить();
        НоваяСтрока.СуммаПлатежа = СуммаИзПараметра;
        НоваяСтрока.ВариантОплаты = Перечисления.ВариантыОплатыАванса.ПредоплатаДоПоступления;
        НоваяСтрока.ДатаПлатежа   = ТекущаяДата(); // Или любая другая логика
        НоваяСтрока.ПроцентПлатежа = 100;
    КонецЕсли;
    
КонецЕсли;

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

---

Важные нюансы и правила хорошего тона при работе в КД 2.x

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

← На главную