Как правильно перенести данные из регистра сведений в документы при помощи Конвертации данных 2.0

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

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

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

Шаг 1. Формирование данных в ПВД (Произвольный алгоритм)

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

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


// В обработчике "Перед обработкой" ПВД
ДатаРеорганизации = Константы.ДатаРеорганизации.Получить();

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

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

Запрос.УстановитьПараметр("НаДату", КонецДня(ДатаРеорганизации));
Запрос.УстановитьПараметр("Организация", Параметры.Организация);

РезультатЗапроса = Запрос.Выполнить();

// Подготовим шаблоны таблиц для ТЧ документа
ТаблицаОсновные = РезультатЗапроса.Выгрузить().СкопироватьКолонки();

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

Шаг 2. Обход результатов и вложенные табличные части

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


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

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

Шаг 3. Настройка ПКО и решение проблемы поиска объектов

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

Когда вы создаете документы программно через Конвертацию данных, у них в источнике (в нашей ТЗ) нет уникального идентификатора (GUID) и нет номера (он присваивается при записи в приемнике). Если в ПКО настроен поиск по Дате и Номеру, происходит следующее:

  1. Загружается первый документ. Ему присваивается дата. Номер пока пустой или заполнится после записи.
  2. Загружается второй документ. Система ищет в базе объект с такой же датой и таким же (пустым) номером.
  3. Система находит первый документ и вместо создания нового просто обновляет его данными второго.
  4. В итоге после загрузки 100 строк из регистра мы видим в базе только 1 документ (данные последней итерации).

Как решить проблему поиска:

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

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

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


// Если объект не найден по GUID, не пытаемся искать по полям, а сразу создаем новый
Если НомерВариантаПоиска = 1 Тогда
    // Здесь можно принудительно заставить систему создавать новый объект,
    // если не переданы уникальные признаки
    // ПрекратитьПоиск = Истина; 
КонецЕсли;

Итоги и рекомендации

Проанализируем ключевые моменты, которые обеспечивают успешную конвертацию из регистра в документ:

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

← На главную