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

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

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

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

Где найти глобальный обработчик «После загрузки данных»

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

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

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

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

Почему создание связанных документов внутри ПКО «После загрузки» работает некорректно

Посмотрим на пример кода, который часто пытаются использовать начинающие разработчики непосредственно внутри ПКО документа-источника в обработчике «После загрузки»:


Если Не Отказ Тогда
    Док = Документы._ПоступлениеТоваров.СоздатьДокумент();
    GUID = Ссылка.УникальныйИдентификатор(); 
    РезСсылка = Документы._ПоступлениеТоваров.ПолучитьСсылку(GUID);
    Док.УстановитьСсылкуНового(РезСсылка);
                        
    Док.Дата = Ссылка.Дата;
    Док.ОбработкаЗаполнения(Текстрока.ПоступлениеБУ, ИСТИНА);
    Попытка
        Док.Записать(РежимЗаписиДокумента.Запись);
    Исключение
        // обработка ошибки
    КонецПопытки;
КонецЕсли;

Проанализируем эту ситуацию и выделим три критические ошибки, из-за которых данный код не будет работать:

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

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

Рассмотрим надежный и рекомендуемый паттерн решения этой задачи. Мы разделим процесс на три шага: инициализация коллекции в начале загрузки, сбор ссылок на загруженные документы в процессе работы ПКО и итоговая обработка в глобальном событии после окончания загрузки всего файла.

Шаг 1. Инициализация таблицы в событии «Перед загрузкой данных»

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


СписокДок = Новый ТаблицаЗначений;
СписокДок.Колонки.Добавить("Ссылка");
СписокДок.Колонки.Добавить("Дата");

Параметры.Вставить("СписокЗагруженныхБУ", СписокДок);

Шаг 2. Наполнение коллекции в ПКО «После загрузки»

Теперь в ПКО нашего исходного документа (например, Поступление товаров БУ) в обработчике После загрузки мы будем фиксировать каждый успешно обработанный объект. Чтобы гарантировать наличие ссылки в базе данных, мы принудительно запишем новый объект, если он еще не был сохранен:


Если Не Отказ Тогда
    // Если объект новый, записываем его принудительно для получения физической ссылки в БД
    Если Не ОбъектНайден Тогда
        Объект.Записать();
        ОбъектМодифицирован = Ложь; // Указываем КД, что повторная запись платформой не требуется
    КонецЕсли;

    // Добавляем информацию в наш глобальный параметр
    НоваяСтрока = Параметры.СписокЗагруженныхБУ.Добавить();
    НоваяСтрока.Ссылка = Объект.Ссылка;
    НоваяСтрока.Дата = Объект.Дата;
КонецЕсли;

Шаг 3. Обработка коллекции в «После загрузки данных»

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


Если Параметры.Свойство("СписокЗагруженныхБУ") И Параметры.СписокЗагруженныхБУ.Количество() > 0 Тогда

    Для Каждого СтрокаДок Из Параметры.СписокЗагруженныхБУ Цикл
        
        // Создаем новый документ №2 (управленческий)
        ДокУпр = Документы._ПоступлениеТоваров.СоздатьДокумент();
        
        // Связываем GUID документов для однозначного сопоставления при последующих обменах
        GUID = СтрокаДок.Ссылка.УникальныйИдентификатор();
        РезСсылка = Документы._ПоступлениеТоваров.ПолучитьСсылку(GUID);
        ДокУпр.УстановитьСсылкуНового(РезСсылка);
        
        ДокУпр.Дата = СтрокаДок.Дата;
        
        // Заполняем документ на основании уже записанного документа №1
        ДокУпр.Заполнить(СтрокаДок.Ссылка);
        
        Попытка
            ДокУпр.Записать(РежимЗаписиДокумента.Запись);
        Исключение
            ЗаписьЖурналаРегистрации("ОбменДанными.ПослеЗагрузки", 
                                     УровеньЖурналаРегистрации.Ошибка, 
                                     , , 
                                     "Ошибка создания связанного документа: " + ОписаниеОшибки());
        КонецПопытки;
        
    КонецЦикла;

КонецЕсли;

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

← На главную