Как эффективно перенести документы Реализация между базами 1С через COM-соединение?

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

Перенос данных между двумя информационными базами 1С — это классическая задача, с которой сталкивается почти каждый разработчик. Использование COM-соединения (V83.COMConnector) остается популярным методом благодаря его прямому доступу к объектам другой базы. Однако при реализации таких механизмов часто возникает вопрос: как избежать избыточных циклов и сделать процесс создания документов максимально быстрым и структурированным? Разберем подробно, как уйти от плоских таблиц и оптимизировать работу с данными.

Метод 1. Использование запросов с итогами и иерархического обхода

Самый эффективный способ избежать ручной группировки данных в таблице значений на стороне базы-приемника — это использование предложения ИТОГИ в тексте запроса. Проанализируем, как это работает. Вместо того чтобы получать линейный список строк, где данные шапки (контрагент, дата, склад) дублируются для каждой строки номенклатуры, мы заставляем платформу подготовить данные в виде дерева.

Рассмотрим пример запроса, который следует выполнить в базе-источнике:


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

Выясним, в чем преимущество такого подхода. Когда мы используем ИТОГИ ПО Ссылка, результат запроса приобретает иерархическую структуру. Теперь мы можем применить метод Выбрать с параметром ОбходРезультатаЗапроса.ПоГруппировкам. Это позволяет нам организовать два вложенных цикла, которые идеально ложатся на структуру документа.

Проанализируем пример кода для обхода такого результата:


ВыборкаДокументов = РезультатЗапроса.Выбрать(ОбходРезультатаЗапроса.ПоГруппировкам);

Пока ВыборкаДокументов.Следующий() Цикл
    // В этом цикле мы находимся на уровне "Шапки" документа
    // Создаем новый документ в базе-приемнике
    НовыйДок = БазаПриемник.Документы.РеализацияТоваровУслуг.СоздатьДокумент();
    НовыйДок.Дата = ВыборкаДокументов.Ссылка.Дата;
    НовыйДок.Агент = НайтиСоответствие(ВыборкаДокументов.Агент); // Функция поиска ссылки в другой базе
    
    // Теперь выбираем подчиненные записи (строки табличной части)
    ВыборкаСтрок = ВыборкаДокументов.Выбрать();
    
    Пока ВыборкаСтрок.Следующий() Цикл
        // Здесь мы заполняем табличную часть
        НоваяСтрока = НовыйДок.Товары.Добавить();
        НоваяСтрока.Номенклатура = НайтиНоменклатуру(ВыборкаСтрок.Номенклатура);
        НоваяСтрока.Количество = ВыборкаСтрок.Количество;
    КонецЦикла;
    
    НовыйДок.Записать();
КонецЦикла;

Этот метод избавляет нас от необходимости предварительно создавать ТаблицуЗначений и вручную искать в ней строки, относящиеся к конкретному документу. Мы работаем напрямую с результатом запроса, что экономит память и время.

Метод 2. Минимизация «маршалинга» через пакетную передачу данных

Рассмотрим технический нюанс, который часто упускают из виду. При каждом обращении через COM (например, Выборка.Номенклатура.Наименование) происходит сетевой вызов между процессами. Если у вас 1000 документов по 50 строк, количество таких микро-вызовов может исчисляться десятками тысяч, что катастрофически замедляет перенос.

Чтобы ускорить процесс, проанализируем вариант с выгрузкой данных в Таблицу Значений на стороне источника и передачей её целиком. Однако стоит помнить, что типы данных 1С (Ссылки, Перечисления) нельзя передать напрямую «как есть». Посмотрим, как это оптимизировать:

  1. Выполним запрос в базе-источнике и выгрузим его в ТаблицуЗначений.
  2. Приведем все ссылочные типы к строковому представлению (например, УникальныйИдентификатор или Код).
  3. Передадим эту таблицу в базу-приемник (через COM или сериализацию).

Такой подход позволяет выполнить один «тяжелый» запрос и получить массив данных, с которым база-приемник будет работать локально, не обращаясь постоянно к источнику через COM-шлюз.

Важные аспекты синхронизации объектов

При переносе данных крайне важно обеспечить идемпотентность (возможность повторного запуска без создания дублей). Разберем, как это сделать правильно. Использование поиска по наименованию или коду ненадежно. Рекомендуется использовать УникальныйИдентификатор (GUID).

Посмотрим на пример логики поиска:


ИдентификаторИсточника = Строка(Выборка.Ссылка.УникальныйИдентификатор());
GUID = БазаПриемник.NewObject("UUID", ИдентификаторИсточника);
СсылкаНаДокумент = БазаПриемник.Документы.РеализацияТоваровУслуг.ПолучитьСсылку(GUID);

ДокументОбъект = СсылкаНаДокумент.ПолучитьОбъект();
Если ДокументОбъект = Неопределено Тогда
    ДокументОбъект = БазаПриемник.Документы.РеализацияТоваровУслуг.СоздатьДокумент();
    ДокументОбъект.УстановитьСсылкуНового(СсылкаНаДокумент);
КонецЕсли;

Таким образом, мы сначала проверяем существование объекта по его уникальному ключу. Если документ уже был перенесен ранее, мы просто обновляем его, а не создаем копию.

Современные альтернативы COM-соединению

Хотя тема посвящена COM, проанализируем ситуацию, когда этот метод может стать «узким местом». COM требует установленной платформы на сервере, активной лицензии и стабильного Windows-окружения. Если объем данных растет, рассмотрим следующие варианты:

  1. HTTP-сервисы и JSON: База-источник формирует JSON-пакет и отправляет его в базу-приемник через HTTP-запрос. Это работает в разы быстрее, так как платформа 1С нативно и очень быстро обрабатывает JSON.
  2. Конвертация данных 3.0: Использование формата XDTO позволяет настроить правила обмена, которые будут работать асинхронно. Это современный стандарт для интеграции систем.
  3. OData: Встроенный REST-интерфейс 1С позволяет получать данные из таблиц базы-источника с помощью простых HTTP-запросов без написания кода на стороне источника.

Использование транзакций для надежности

Выясним причину, по которой перенос может прерваться на середине. Если в процессе записи возникнет ошибка (например, не заполнено обязательное поле), часть документов будет создана, а часть — нет. При работе с большими объемами данных через COM рекомендуется использовать Транзакции.

Разберем алгоритм пакетной записи:


БазаПриемник.НачатьТранзакцию();
Попытка
    // Цикл создания документов (например, по 50 штук)
    // ...
    БазаПриемник.ЗафиксироватьТранзакцию();
Исключение
    БазаПриемник.ОтменитьТранзакцию();
    ЗаписьЖурналаРегистрации("Ошибка переноса: " + ОписаниеОшибки());
КонецПопытки;

Важный момент: не стоит пытаться записать все 10 000 документов в одной транзакции, так как это может привести к блокировкам базы и переполнению лога транзакций. Оптимальный размер порции — от 50 до 200 документов.

Заключение

Мы рассмотрели основной способ оптимизации переноса данных — использование иерархических запросов с итогами. Этот метод позволяет структурировать код, сделать его читаемым и избежать лишних операций поиска в таблицах значений. Дополнительно мы проанализировали важность синхронизации по GUID и преимущества пакетной обработки данных. Следуя этим рекомендациям, вы сможете построить надежный и быстрый механизм обмена между информационными базами 1С.

← На главную