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

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

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

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

Причина проблемы: почему колонки «затираются»?

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

Рассмотрим основные способы решения этой задачи.

Способ 1. Программное формирование таблицы значений в ПКГС (наиболее универсальный)

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

Разберем по шагам, как это реализовать:

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

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


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

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

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

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

Способ 2. Использование структуры «ВходящиеДанные»

Если логика сбора данных очень сложная и затрагивает не только ТЧ самого документа, но и связанные регистры или другие документы, удобно использовать структуру ВходящиеДанные. Этот метод позволяет «подготовить» таблицу еще до того, как начнется обработка табличных частей.

Разберем алгоритм действий:

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

Пример кода в обработчике Перед выгрузкой ПКО документа:


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

// Логика заполнения ТЗ из разных источников
// ... (заполнение ТЗ)

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

Затем в ПКГС табличной части вы указываете имя входящих данных — ТаблицаСводная. Система автоматически подставит эту таблицу вместо стандартного обхода ТЧ источника.

Способ 3. Объединение через поиск строк (Склейка)

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

Посмотрим на пример логики «склеивания» по ключевому полю Номенклатура:


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

Способ 4. Обработка на стороне приемника (После загрузки)

Иногда (хотя и реже) бывает удобно передать дополнительные данные во временную структуру или «невидимые» колонки, а финальное объединение выполнить уже в базе-приемнике. Для этого используется обработчик После загрузки в ПКО документа в базе-приемнике.

Рассмотрим этот вариант:

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

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

Важные рекомендации при настройке ПКС

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

Почему не стоит использовать ПВД в данном случае?

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

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

← На главную