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

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

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

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

Механизм связи таблиц через КлючСтроки

Прежде чем переходить к написанию кода, выясним причину, по которой две табличные части в 1С «понимают», что они связаны. В типовых конфигурациях (таких как БП 3.0 или УТ 11) для этого используется специальный технический реквизит — КлючСтроки.

Рассмотрим основные правила работы с ключом:

  1. В верхней (родительской) ТЧ каждая строка имеет уникальный номер в рамках документа (обычно это Число).
  2. В нижней (дочерней) ТЧ каждая строка, относящаяся к конкретной «родительской» записи, должна содержать точно такое же значение в поле КлючСтроки.
  3. Если типы данных или значения ключей не совпадут, при открытии формы документа в базе-приемнике связь не сработает: при выборе строки в верхней таблице нижняя будет оставаться пустой или показывать нерелевантные данные.

Способ 1: Использование обработчика «Перед выгрузкой» ПКО и ВходящихДанных

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

Разберем алгоритм действий в обработчике ПередВыгрузкой правила конвертации объекта (ПКО), который можно адаптировать под перенос данных из 1С:УПП 1.3 в 1С:БП 3.0:


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

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

// 3. Перебираем исходную ТЧ документа-источника
ТЗИсточник = Источник.Товары;
СчетчикКлюча = 0;

Для Каждого СтрокаИсточника Из ТЗИсточник Цикл
    // Здесь должна быть логика поиска или группировки
    // Если это новая уникальная дата/покупатель:
    СчетчикКлюча = СчетчикКлюча + 1;
    
    НоваяСтрокаПок = ТЗПокупатели.Добавить();
    НоваяСтрокаПок.Покупатель = СтрокаИсточника.Контрагент;
    НоваяСтрокаПок.ДатаСФ = СтрокаИсточника.ДатаРеализации;
    НоваяСтрокаПок.КлючСтроки = СчетчикКлюча;
    
    // Заполняем товары, привязывая их к этому же ключу
    НоваяСтрокаТов = ТЗТовары.Добавить();
    НоваяСтрокаТов.Номенклатура = СтрокаИсточника.Номенклатура;
    НоваяСтрокаТов.Количество = СтрокаИсточника.Количество;
    НоваяСтрокаТов.КлючСтроки = СчетчикКлюча;
КонецЦикла;

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

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

Способ 2: Использование Правил выгрузки данных (ПВД)

Если логика выборки требует сложных запросов к базе данных, лучше использовать ПВД. Рассмотрим ситуацию, когда мы программно формируем ВыборкаДанных.

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


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

// Выполняем запрос для получения данных
Запрос = Новый Запрос;
Запрос.Текст = "ВЫБРАТЬ ..."; // Текст запроса с итогами по периодам/покупателям
Результаты = Запрос.ВыполнитьПакет();

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

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

Работа с реквизитами формы (Всего, НДС)

Посмотрим на важный нюанс: часто в верхней табличной части есть колонки Всего и СуммаНДС, которые не являются реквизитами объекта, а вычисляются на форме. Как их заполнить?

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


// Пример кода в обработчике "После загрузки" (на стороне приемника)
Объект.ЗаполнитьСчетаУчета(); // если нужно
Объект.РассчитатьИтоги();     // типовая процедура для пересчета сумм в ТЧ

Подведем итоги

Для успешного разделения одной ТЧ на две в КД 2.1 мы должны:

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

Такой подход гарантирует целостность данных и сохранение визуальной связи между строками таблиц в интерфейсе 1С:Предприятие.

← На главную