Перенос данных между двумя информационными базами 1С — это классическая задача, с которой сталкивается почти каждый разработчик. Использование COM-соединения (V83.COMConnector) остается популярным методом благодаря его прямому доступу к объектам другой базы. Однако при реализации таких механизмов часто возникает вопрос: как избежать избыточных циклов и сделать процесс создания документов максимально быстрым и структурированным? Разберем подробно, как уйти от плоских таблиц и оптимизировать работу с данными.
Самый эффективный способ избежать ручной группировки данных в таблице значений на стороне базы-приемника — это использование предложения ИТОГИ в тексте запроса. Проанализируем, как это работает. Вместо того чтобы получать линейный список строк, где данные шапки (контрагент, дата, склад) дублируются для каждой строки номенклатуры, мы заставляем платформу подготовить данные в виде дерева.
Рассмотрим пример запроса, который следует выполнить в базе-источнике:
ТекстЗапроса =
"ВЫБРАТЬ
| РеализацияТоваровУслуг.Ссылка КАК Ссылка,
| РеализацияТоваровУслуг.Агент КАК Агент,
| РеализацияТоваровУслуг.Товары.(
| Номенклатура КАК Номенклатура,
| Количество КАК Количество,
| Коэффициент КАК Коэффициент
| )
|ИЗ
| Документ.РеализацияТоваровУслуг КАК РеализацияТоваровУслуг
|ГДЕ
| РеализацияТоваровУслуг.Дата МЕЖДУ &НачалоПериода И &КонецПериода
|ИТОГИ ПО
| Ссылка";
Выясним, в чем преимущество такого подхода. Когда мы используем ИТОГИ ПО Ссылка, результат запроса приобретает иерархическую структуру. Теперь мы можем применить метод Выбрать с параметром ОбходРезультатаЗапроса.ПоГруппировкам. Это позволяет нам организовать два вложенных цикла, которые идеально ложатся на структуру документа.
Проанализируем пример кода для обхода такого результата:
ВыборкаДокументов = РезультатЗапроса.Выбрать(ОбходРезультатаЗапроса.ПоГруппировкам);
Пока ВыборкаДокументов.Следующий() Цикл
// В этом цикле мы находимся на уровне "Шапки" документа
// Создаем новый документ в базе-приемнике
НовыйДок = БазаПриемник.Документы.РеализацияТоваровУслуг.СоздатьДокумент();
НовыйДок.Дата = ВыборкаДокументов.Ссылка.Дата;
НовыйДок.Агент = НайтиСоответствие(ВыборкаДокументов.Агент); // Функция поиска ссылки в другой базе
// Теперь выбираем подчиненные записи (строки табличной части)
ВыборкаСтрок = ВыборкаДокументов.Выбрать();
Пока ВыборкаСтрок.Следующий() Цикл
// Здесь мы заполняем табличную часть
НоваяСтрока = НовыйДок.Товары.Добавить();
НоваяСтрока.Номенклатура = НайтиНоменклатуру(ВыборкаСтрок.Номенклатура);
НоваяСтрока.Количество = ВыборкаСтрок.Количество;
КонецЦикла;
НовыйДок.Записать();
КонецЦикла;
Этот метод избавляет нас от необходимости предварительно создавать ТаблицуЗначений и вручную искать в ней строки, относящиеся к конкретному документу. Мы работаем напрямую с результатом запроса, что экономит память и время.
Рассмотрим технический нюанс, который часто упускают из виду. При каждом обращении через COM (например, Выборка.Номенклатура.Наименование) происходит сетевой вызов между процессами. Если у вас 1000 документов по 50 строк, количество таких микро-вызовов может исчисляться десятками тысяч, что катастрофически замедляет перенос.
Чтобы ускорить процесс, проанализируем вариант с выгрузкой данных в Таблицу Значений на стороне источника и передачей её целиком. Однако стоит помнить, что типы данных 1С (Ссылки, Перечисления) нельзя передать напрямую «как есть». Посмотрим, как это оптимизировать:
ТаблицуЗначений.УникальныйИдентификатор или Код).Такой подход позволяет выполнить один «тяжелый» запрос и получить массив данных, с которым база-приемник будет работать локально, не обращаясь постоянно к источнику через COM-шлюз.
При переносе данных крайне важно обеспечить идемпотентность (возможность повторного запуска без создания дублей). Разберем, как это сделать правильно. Использование поиска по наименованию или коду ненадежно. Рекомендуется использовать УникальныйИдентификатор (GUID).
Посмотрим на пример логики поиска:
ИдентификаторИсточника = Строка(Выборка.Ссылка.УникальныйИдентификатор());
GUID = БазаПриемник.NewObject("UUID", ИдентификаторИсточника);
СсылкаНаДокумент = БазаПриемник.Документы.РеализацияТоваровУслуг.ПолучитьСсылку(GUID);
ДокументОбъект = СсылкаНаДокумент.ПолучитьОбъект();
Если ДокументОбъект = Неопределено Тогда
ДокументОбъект = БазаПриемник.Документы.РеализацияТоваровУслуг.СоздатьДокумент();
ДокументОбъект.УстановитьСсылкуНового(СсылкаНаДокумент);
КонецЕсли;
Таким образом, мы сначала проверяем существование объекта по его уникальному ключу. Если документ уже был перенесен ранее, мы просто обновляем его, а не создаем копию.
Хотя тема посвящена COM, проанализируем ситуацию, когда этот метод может стать «узким местом». COM требует установленной платформы на сервере, активной лицензии и стабильного Windows-окружения. Если объем данных растет, рассмотрим следующие варианты:
XDTO позволяет настроить правила обмена, которые будут работать асинхронно. Это современный стандарт для интеграции систем.Выясним причину, по которой перенос может прерваться на середине. Если в процессе записи возникнет ошибка (например, не заполнено обязательное поле), часть документов будет создана, а часть — нет. При работе с большими объемами данных через COM рекомендуется использовать Транзакции.
Разберем алгоритм пакетной записи:
БазаПриемник.НачатьТранзакцию();
Попытка
// Цикл создания документов (например, по 50 штук)
// ...
БазаПриемник.ЗафиксироватьТранзакцию();
Исключение
БазаПриемник.ОтменитьТранзакцию();
ЗаписьЖурналаРегистрации("Ошибка переноса: " + ОписаниеОшибки());
КонецПопытки;
Важный момент: не стоит пытаться записать все 10 000 документов в одной транзакции, так как это может привести к блокировкам базы и переполнению лога транзакций. Оптимальный размер порции — от 50 до 200 документов.
Мы рассмотрели основной способ оптимизации переноса данных — использование иерархических запросов с итогами. Этот метод позволяет структурировать код, сделать его читаемым и избежать лишних операций поиска в таблицах значений. Дополнительно мы проанализировали важность синхронизации по GUID и преимущества пакетной обработки данных. Следуя этим рекомендациям, вы сможете построить надежный и быстрый механизм обмена между информационными базами 1С.