Как передать таблицу значений со ссылочными данными между базами 1С и создать недостающие справочники

Программист IT и автоматизация бизнеса
← На главную

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

В данной статье мы подробно разберем несколько стратегий решения этой задачи: от использования универсальных механизмов платформы до гибкой настройки правил обмена. Мы проанализируем преимущества каждого метода и выясним, как правильно обрабатывать ссылочные данные, чтобы избежать появления "битых" ссылок или объекта "Объект не обнаружен".

Метод 1. Сериализация в JSON и использование уникальных идентификаторов (GUID)

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

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


// Пример подготовки ТЗ к выгрузке в JSON
ЗаписьJSON = Новый ЗаписьJSON;
ЗаписьJSON.ОткрытьФайл(ПутьКФайлу);

ЗаписьJSON.ЗаписатьНачалоМассива();
Для Каждого СтрокаТЗ Из ТаблицаДанных Цикл
    ЗаписьJSON.ЗаписатьНачалоОбъекта();
    
    // Примитивный тип
    ЗаписьJSON.ЗаписатьИмяСвойства("Наименование");
    ЗаписьJSON.ЗаписатьЗначение(СтрокаТЗ.Наименование);
    
    // Ссылочный тип - передаем GUID
    ЗаписьJSON.ЗаписатьИмяСвойства("Товар_GUID");
    ЗаписьJSON.ЗаписатьЗначение(СтрокаТЗ.Товар.УникальныйИдентификатор());
    
    ЗаписьJSON.ЗаписатьКонецОбъекта();
КонецЦикла;
ЗаписьJSON.ЗаписатьКонецМассива();
ЗаписьJSON.Закрыть();

Проанализируем ситуацию на стороне приемника. При чтении JSON мы получаем GUID. Нам нужно проверить, есть ли в текущей базе объект с таким идентификатором. Если его нет — создаем новый и присваиваем ему переданный GUID. Это критически важно для сохранения идентичности данных между базами.


// Пример загрузки в базе-приемнике
ЧтениеJSON = Новый ЧтениеJSON;
ЧтениеJSON.ОткрытьФайл(ПутьКФайлу);
Данные = ПрочитатьJSON(ЧтениеJSON);

Для Каждого ЭлементДанных Из Данные Цикл
    СсылкаНаОбъект = Справочники.Номенклатура.ПолучитьСсылку(Новый УникальныйИдентификатор(ЭлементДанных.Товар_GUID));
    
    // Проверяем, существует ли объект
    Если СсылкаНаОбъект.ПолучитьОбъект() = Неопределено Тогда
        // Создаем новый, если не нашли
        НовыйОбъект = Справочники.Номенклатура.СоздатьЭлемент();
        НовыйОбъект.УстановитьСсылкуНового(СсылкаНаОбъект);
        НовыйОбъект.Наименование = ЭлементДанных.Наименование;
        // Заполняем остальные реквизиты...
        НовыйОбъект.Записать();
    КонецЕсли;
КонецЦикла;

Метод 2. Использование универсального механизма XDTO и XML

Если структуры метаданных в базах схожи, можно использовать СериализаторXDTO. Этот метод позволяет выгружать объекты целиком со всеми их реквизитами. Как было отмечено в обсуждении, XML умеет выгружать объект со всеми значениями реквизитов, но требует определенной аккуратности при сопоставлении схем.

Разберем пример использования СериализаторXDTO для выгрузки ссылки:


ЗаписьXML = Новый ЗаписьXML;
ЗаписьXML.ОткрытьФайл(ПутьКПапкеОбмена + ИмяФайла + ".xml");

// Используем фабрику XDTO для записи
Сериализатор = Новый СериализаторXDTO(ФабрикаXDTO);
Сериализатор.ЗаписатьXML(ЗаписьXML, СсылкаВыгрузки);
ЗаписьXML.Закрыть();

Важный нюанс: при загрузке через XML в базе-приемнике платформа попытается сопоставить типы. Если в приемнике отсутствуют какие-то реквизиты, которые есть в источнике, может возникнуть ошибка. Поэтому данный метод лучше всего подходит для баз с идентичной или очень близкой структурой (например, обмен между УТ и БП в рамках стандартных узлов).

Метод 3. Конвертация данных (КД 2.0 или 3.0)

Проанализировав советы опытных разработчиков, мы видим, что использование конфигурации "Конвертация данных" — это наиболее надежный и гибкий путь. Если в вашей таблице значений много ссылочных полей, и у этих полей есть свои вложенные ссылки (например, в справочнике "Номенклатура" есть ссылка на "ЕдиницыИзмерения"), то ручное описание всех связей в JSON станет трудоемким.

Выясним преимущества КД для данной задачи:

  1. Автоматическое создание объектов: В правилах обмена (ПКО) можно установить флаг "Искать объект по внутреннему идентификатору" и "Продолжить поиск по полям поиска". Если объект не найден, КД сама его создаст.
  2. Обработка таблиц значений: В КД можно передать ТЗ как входящие данные (через Параметры или как источник данных для выгрузки коллекции) и сопоставить ее с объектом приемника.
  3. Минимизация кода: Вам не нужно писать сложные циклы обхода и проверки на Неопределено. Платформа берет на себя сопоставление типов.

Если метаданные баз различаются значительно, рекомендуем использовать Конвертацию данных 3.0. Она работает через формат EnterpriseData (XDTO), что позволяет базе-источнику вообще "не знать" о структуре приемника, передавая данные в универсальном формате.

Метод 4. COM-соединение для прямой передачи

Если обе базы находятся в одной локальной сети и платформа позволяет использовать COM-соединение, это может быть самым быстрым способом реализации. Рассмотрим, как это работает программно:

Сначала мы создаем подключение к базе-приемнику, затем передаем данные из ТЗ построчно, вызывая методы поиска и создания объектов непосредственно в контексте второй базы.


// Подключение к базе-приемнику
COMСоединение = Новый COMОбъект("V83.COMConnector");
БазаПриемник = COMСоединение.Connect("Srvr='ServerName';Ref='BaseName';Usr='Login';Pwd='Password';");

Для Каждого СтрокаТЗ Из ИсточникТЗ Цикл
    // Поиск объекта в приемнике по GUID из источника
    GUIDСтрокой = Строка(СтрокаТЗ.СсылкаНаОбъект.УникальныйИдентификатор());
    СсылкаВПриемнике = БазаПриемник.Справочники.Номенклатура.ПолучитьСсылку(БазаПриемник.NewObject("UUID", GUIDСтрокой));
    
    ОбъектВПриемнике = СсылкаВПриемнике.GetObject();
    Если ОбъектВПриемнике = Неопределено Тогда
        // Если объекта нет, создаем его прямо через COM
        НовыйЭлемент = БазаПриемник.Справочники.Номенклатура.CreateItem();
        НовыйЭлемент.SetNewObjectRef(СсылкаВПриемнике);
        НовыйЭлемент.Description = СтрокаТЗ.Наименование;
        НовыйЭлемент.Write();
    КонецЕсли;
КонецЦикла;

Важно: помните, что COM-соединение недоступно в некоторых средах (например, при использовании Linux-серверов 1С) и требует установленных идентичных версий платформы для стабильной работы.

Практические советы по обработке "пустых" ссылок

Разберем ситуацию, которая часто ставит в тупик новичков: вы передали GUID, создали ссылку в приемнике, но не успели заполнить реквизиты объекта. В интерфейсе пользователя это выглядит как "Объект не обнаружен".

Чтобы избежать этой проблемы, рекомендуем использовать двухэтапный подход:

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

Выводы

Для простых задач и небольшого количества типов метаданных оптимальным будет JSON-сериализация с передачей GUID. Если же задача предполагает регулярный обмен сложными структурами данных, то изучение и применение Конвертации данных окупится стократно, так как этот инструмент специально спроектирован для решения проблем сопоставления и создания объектов "на лету".

Рассмотренные методы позволяют гибко подходить к интеграции баз 1С, обеспечивая целостность ссылочных данных и автоматизацию создания необходимых справочников в базе-приемнике.

← На главную