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

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

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

В этой статье мы подробно разберем, как решать такие задачи правильно, красиво и в соответствии со стандартами разработчиков КД 2. Мы рассмотрим работу с обработчиками событий, использование предопределенных переменных, механизмы передачи параметров и гибкую настройку правил конвертации.

Часть 1. Динамическое изменение значения реквизита по условию

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

Для реализации этой задачи у нас есть два основных и наиболее эффективных варианта решения.

Вариант 1. Прямое переопределение значения в ПКС через переменную «Значение»

Это самый простой и лаконичный способ. Мы создаем одно Правило Конвертации Свойств (ПКС) для реквизита Контрагент. При этом поле «Источник» в настройках ПКС мы оставляем пустым, а в поле «Приемник» указываем наш реквизит Контрагент. Также для данного ПКС мы выбираем соответствующее Правило Конвертации Объектов (ПКО) для справочника Контрагенты.

Всю логику сопоставления мы пишем в обработчике события «Перед выгрузкой» этого ПКС. В данном обработчике нам доступна специальная предопределенная переменная Значение. Если мы присвоим ей какое-либо значение, система проигнорирует стандартный механизм получения данных и выгрузит именно то, что мы определили программно.

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


Если Источник.ВидОперации = Перечисления.ВидыОпераций.ОплатаОтПокупателя Тогда
    Значение = Источник.Покупатель;
ИначеЕсли Источник.ВидОперации = Перечисления.ВидыОпераций.ОплатаПоставщику Тогда
    Значение = Источник.Поставщик;
Иначе
    // Если операция не подошла под условия, можно отменить выгрузку конкретного свойства
    Отказ = Истина;
КонецЕсли;

Этот способ идеален, если тип выгружаемого значения (в нашем случае ссылка на справочник «Контрагенты») совпадает во всех ветках условия, и для его конвертации используется одно и то же ПКО.

Вариант 2. Использование нескольких ПКС с условием отказа

Бывают ситуации, когда в зависимости от условий нам нужно использовать принципиально разные ПКО для выгрузки реквизита. Например, если в одном случае контрагент должен создаваться как физическое лицо, а в другом — как юридическое, или если мы переносим данные в разные реквизиты приемника.

В этом случае мы можем создать два (или более) ПКС для одного и того же реквизита-приемника Контрагент:

  1. Первое ПКС: Источник — Покупатель, Приемник — Контрагент. В обработчике «Перед выгрузкой» пишем условие отказа:
    
    Если Источник.ВидОперации <> Перечисления.ВидыОпераций.ОплатаОтПокупателя Тогда
        Отказ = Истина;
    КонецЕсли;
    
  2. Второе ПКС: Источник — Поставщик, Приемник — Контрагент. В обработчике «Перед выгрузкой» пишем:
    
    Если Источник.ВидОперации <> Перечисления.ВидыОпераций.ОплатаПоставщику Тогда
        Отказ = Истина;
    КонецЕсли;
    

Во время выполнения обмена платформа поочередно проверит оба правила. Выполнится только то ПКС, где переменная Отказ останется равной Ложь. Это гарантирует гибкость и чистоту структуры метаданных без написания сложных переопределений ПКО в коде.

Часть 2. Как из одной строки источника получить две строки в приемнике

Теперь разберем более сложную и интересную задачу. Допустим, в документе-источнике у нас есть только шапка или табличная часть с одной строкой, содержащей информацию и о покупателе, и о поставщике. Нам необходимо принудительно сформировать в табличной части (ТЧ) документа-приемника две строки со следующей структурой:

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

Шаг 1. Переопределение коллекции в обработчике «Перед обработкой» ПКГС

Найдем в правилах обмена ПКГС нашей табличной части приемника. Перейдем в его обработчик события «Перед обработкой». Здесь мы переопределим стандартную выборку данных с помощью переменной КоллекцияОбъектов.

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

Ниже приведена правильная инициализация и заполнение таблицы значений для платформы 1С v8.x:


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

// Формируем первую строку (для Покупателя)
НоваяСтрока1 = ТаблицаВременная.Добавить();
НоваяСтрока1.Контрагент = Источник.Покупатель;
НоваяСтрока1.Сумма = Источник.СуммаОперации; // К примеру, берем сумму из шапки источника

// Формируем вторую строку (для Поставщика)
НоваяСтрока2 = ТаблицаВременная.Добавить();
НоваяСтрока2.Контрагент = Источник.Поставщик;
НоваяСтрока2.Сумма = Источник.СуммаОперации;

// Передаем нашу таблицу в переменную КоллекцияОбъектов
КоллекцияОбъектов = ТаблицаВременная;

Если база-источник работает на платформе 1С v7.7, синтаксис работы с коллекцией будет несколько иным:


ТаблицаВременная = СоздатьОбъект("ТаблицаЗначений");
ТаблицаВременная.НоваяКолонка("Контрагент");
ТаблицаВременная.НоваяКолонка("Сумма");

ТаблицаВременная.НоваяСтрока();
ТаблицаВременная.Контрагент = Источник.Покупатель;
ТаблицаВременная.Сумма = Источник.СуммаОперации;

ТаблицаВременная.НоваяСтрока();
ТаблицаВременная.Контрагент = Источник.Поставщик;
ТаблицаВременная.Сумма = Источник.СуммаОперации;

КоллекцияОбъектов = ТаблицаВременная;

Шаг 2. Заполнение реквизитов строк через «ОбъектКоллекции» в подчиненных ПКС

Создать саму таблицу значений в КоллекцияОбъектов — это только половина дела. Теперь нам нужно объяснить системе, как сопоставить колонки нашей программно созданной таблицы с реквизитами табличной части документа-приемника.

Для этого мы делаем следующее:

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

В обработчике «Перед выгрузкой» для ПКС Контрагент пишем:

Значение = ОбъектКоллекции.Контрагент;

В обработчике «Перед выгрузкой» для ПКС Сумма пишем:

Значение = ОбъектКоллекции.Сумма;

При выгрузке данных платформа 1С автоматически обойдет в цикле все строки, добавленные нами в КоллекцияОбъектов, и для каждой строки вызовет подчиненные ПКС, подставляя данные из ОбъектКоллекции. Это простое и надежное решение, избавляющее от необходимости использовать параметры или глобальные переменные.

Часть 3. Использование механизма «Входящие данные»

Хотя первый способ с генерацией таблицы значений непосредственно в ПКГС отлично работает, с точки зрения методологии разработки правил конвертации более красивым решением является использование механизма «Входящие данные».

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

Шаг 1. Подготовка данных в ПКО документа

В ПКО нашего документа в обработчике события «Перед выгрузкой» мы создаем и наполняем таблицу значений, после чего упаковываем её в структуру ВходящиеДанные:


ТаблицаДляТЧ = Новый ТаблицаЗначений;
ТаблицаДляТЧ.Колонки.Добавить("Контрагент");
ТаблицаДляТЧ.Колонки.Добавить("Сумма");

// Добавляем записи
Строка1 = ТаблицаДляТЧ.Добавить();
Строка1.Контрагент = Источник.Покупатель;
Строка1.Сумма = Источник.СуммаОперации;

Строка2 = ТаблицаДляТЧ.Добавить();
Строка2.Контрагент = Источник.Поставщик;
Строка2.Сумма = Источник.СуммаОперации;

// Передаем таблицу во входящие данные под определенным ключом
ВходящиеДанные = Новый Структура;
ВходящиеДанные.Вставить("МояПрограммнаяТаблица", ТаблицаДляТЧ);

Шаг 2. Настройка ПКГС табличной части

Переходим к настройкам нашей группы свойств (ПКГС) табличной части документа. Нам необходимо выполнить следующие действия:

  1. Открываем настройки ПКГС табличной части и устанавливаем флаг «Получить из входящих данных».
  2. В поле «Имя входящих данных» указываем наш ключ — МояПрограммнаяТаблица.

Благодаря этому система КД 2 при выгрузке автоматически возьмет таблицу из входящих данных и положит её в КоллекцияОбъектов. Нам больше не нужно писать код инициализации таблицы в ПКГС. Подчиненные ПКС настраиваются точно так же, как описано во второй части статьи (через обращение к ОбъектКоллекции).

Часть 4. Программный поиск объектов при загрузке

Иногда при программном формировании строк ТЧ возникает сложность: в базе-источнике у нас нет полноценных ссылок на объекты-контрагенты (или они представлены в виде строковых представлений, кодов, ИНН), либо эти объекты еще не выгружены.

В этом случае передавать в колонку ОбъектКоллекции.Контрагент саму ссылку на источник может быть нецелесообразно. Вместо этого мы можем использовать текстовые поисковые значения:


// В обработчике формирования коллекции вместо ссылки передаем ИНН или уникальный Код
НоваяСтрока1.Контрагент = Источник.Покупатель.ИНН;

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

Часть 5. Альтернативный метод: передача данных через параметры

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

Для реализации такой схемы в КД 2 предусмотрен механизм передачи параметров объекта:

  1. В ПКС реквизита или группы свойств взводится флаг «Передавать данные в параметр» и указывается символьное имя параметра (например, ПараметрПоставщик).
  2. В обработчике «Перед выгрузкой» мы присваиваем переменной Значение нужные данные.
  3. На стороне приемника в обработчике события «После загрузки» (или в обработчиках загрузки ТЧ) мы можем прочитать эти данные из структуры ПараметрыОбъекта:
    
    Если ПараметрыОбъекта <> Неопределено Тогда
        ПоставщикСсылка = ПараметрыОбъекта.Получить("ПараметрПоставщик");
        Если ЗначениеЗаполнено(ПоставщикСсылка) Тогда
            // Выполняем ручное заполнение или дозапись в ТЧ на стороне приемника
            НоваяСтрока = Объект.ИмяТабличнойЧасти.Добавить();
            НоваяСтрока.Контрагент = ПоставщикСсылка;
        КонецЕсли;
    КонецЕсли;
    

Данный подход является резервным и используется тогда, когда стандартный механизм КоллекцияОбъектов не позволяет реализовать специфические алгоритмы конфигурации-приемника.

Заключение

Мы подробно разобрали, как гибко управлять процессом заполнения данных в 1С:Конвертации данных 2.x. Для изменения одиночных реквизитов по условию всегда лучше использовать переопределение переменной Значение в ПКС или разделение на несколько ПКС с флагом Отказ = Истина. Для трансформации строк табличных частей наиболее эффективным и лаконичным решением является переопределение переменной КоллекцияОбъектов в сочетании с механизмом ВходящиеДанные. Использование этих штатных возможностей делает ваши правила обмена быстрыми, надежными и легкими для поддержки другими разработчиками.

← На главную