Почему при переносе данных из УТ 11 через COM-соединение пустые коды и как синхронизировать объекты?

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

При интеграции или переносе данных из конфигурации «1С:Управление торговлей 11» через COM-соединение разработчики часто сталкиваются с ситуацией, когда стандартный реквизит Код у справочников Контрагенты или Номенклатура возвращает пустую строку. В результате привычный поиск методом НайтиПоКоду() не дает результатов и приводит к дублированию записей в базе-приемнике. Разберем по шагам, почему так происходит и как правильно организовать сопоставление и перенос объектов.

Причины отсутствия кодов в справочниках УТ 11

Проанализируем архитектуру конфигурации «Управление торговлей 11» и выясним причины, по которым обращение к реквизиту Код возвращает пустое значение:

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

Если для номенклатуры в базе-источнике требуется восстановить коды, можно выполнить групповую перенумерацию с помощью обработки «Групповое изменение реквизитов» или вызвать перенумерацию программно:


Выборка = Справочники.Номенклатура.Выбрать();
Пока Выборка.Следующий() Цикл
    Если ПустаяСтрока(Выборка.Код) Тогда
        Объект = Выборка.ПолучитьОбъект();
        Объект.УстановитьНовыйКод();
        Объект.Записать();
    КонецЕсли;
КонецЦикла;

Синхронизация объектов через уникальный идентификатор (GUID)

Поскольку код или наименование могут быть неуникальными либо незаполненными, наиболее надежным способом сопоставления объектов между базами является синхронизация по уникальному идентификатору (GUID). Рассмотрим, как правильно получить GUID объекта через COM-соединение и применить его в базе-приемнике.

При обращении через COM-объект вызов метода УникальныйИдентификатор() возвращает внешний COM-объект, который нельзя напрямую преобразовать в строку стандартными функциями текущей базы. Для безопасного извлечения строкового представления GUID используем метод менеджера XML базы-источника XMLСтрока().

Посмотрим на пример получения строкового GUID из COM-соединения:


// Получаем строковое представление GUID объекта базы-источника
СтрокаGUID = COMСоединение.XMLСтрока(ТоварCOM.Ссылка);

Поиск и создание нового элемента с сохранением GUID

Разберем процесс поиска существующего элемента в базе-приемнике и создания нового элемента с тем же идентификатором, что и в источнике. Для этого используем методы ПолучитьСсылку() и УстановитьСсылкуНового().

Важное ограничение: метод УстановитьСсылкуНового() можно вызывать только для нового, еще не записанного в базу объекта (когда ЭтоНовый() = Истина). Если элемент с таким GUID уже существует, попытка записать новый объект с той же ссылкой вызовет ошибку нарушения уникальности.


// 1. Преобразуем строку в тип УникальныйИдентификатор базы-приемника
Идентификатор = Новый УникальныйИдентификатор(СтрокаGUID);

// 2. Получаем ссылку по идентификатору
СсылкаПриемника = Справочники.Номенклатура.ПолучитьСсылку(Идентификатор);

// 3. Проверяем, существует ли уже элемент в базе
НайденныйОбъект = СсылкаПриемника.ПолучитьОбъект();

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

Сопоставление контрагентов по ИНН и КПП

Если требуется сопоставлять контрагентов не по GUID, а по бизнес-ключам, разберем корректный алгоритм поиска по реквизитам ИНН и КПП, который учитывает как юридических, так и физических лиц:


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

Рекомендации по оптимизации обмена через COM-соединение

Построчное чтение свойств через точку (например, Товар.Родитель.Код) выполняет отдельный удаленный вызов на каждое обращение, что существенно снижает скорость выгрузки. Для ускорения обмена рекомендуется:

  1. Использовать запросы на стороне источника: формировать COMСоединение.NewObject("Запрос"), выбирать все необходимые поля пакетом и обходить готовую выборку или таблицу значений.
  2. Учитывать разрядность клиента: библиотека comcntr.dll должна соответствовать разрядности запускаемого клиента 1С. При несовпадении разрядностей COM-компоненту настраивают через службу компонентов Windows (COM+ приложение).
  3. Переходить на современные форматы обмена: для регулярной синхронизации данных между конфигурациями эффективнее использовать HTTP-сервисы, протокол OData или формат обмена EnterpriseData, что исключает зависимость от платформенного COM-соединения.
← На главную