При интеграции или переносе данных из конфигурации «1С:Управление торговлей 11» через COM-соединение разработчики часто сталкиваются с ситуацией, когда стандартный реквизит Код у справочников Контрагенты или Номенклатура возвращает пустую строку. В результате привычный поиск методом НайтиПоКоду() не дает результатов и приводит к дублированию записей в базе-приемнике. Разберем по шагам, почему так происходит и как правильно организовать сопоставление и перенос объектов.
Проанализируем архитектуру конфигурации «Управление торговлей 11» и выясним причины, по которым обращение к реквизиту Код возвращает пустое значение:
Код установлена равной нулю (он отключен в метаданных). В УТ 11 разделен управленческий и регламентированный контур: управленческий учет ведется в разрезе справочника Партнеры (у которого есть код), а юридические лица хранятся в справочнике Контрагенты. Для контрагентов ключевыми идентификаторами являются реквизиты ИНН и КПП, либо связь с партнером через реквизит Партнер.Код в метаданных присутствует, однако он может оставаться незаполненным, если позиции ранее загружались из внешних источников или создавались программно без явного вызова метода УстановитьНовыйКод(). Платформа 1С не генерирует код автоматически при программной записи, если автонумерация не вызывается разработчиком явно.Если для номенклатуры в базе-источнике требуется восстановить коды, можно выполнить групповую перенумерацию с помощью обработки «Групповое изменение реквизитов» или вызвать перенумерацию программно:
Выборка = Справочники.Номенклатура.Выбрать();
Пока Выборка.Следующий() Цикл
Если ПустаяСтрока(Выборка.Код) Тогда
Объект = Выборка.ПолучитьОбъект();
Объект.УстановитьНовыйКод();
Объект.Записать();
КонецЕсли;
КонецЦикла;
Поскольку код или наименование могут быть неуникальными либо незаполненными, наиболее надежным способом сопоставления объектов между базами является синхронизация по уникальному идентификатору (GUID). Рассмотрим, как правильно получить GUID объекта через COM-соединение и применить его в базе-приемнике.
При обращении через COM-объект вызов метода УникальныйИдентификатор() возвращает внешний COM-объект, который нельзя напрямую преобразовать в строку стандартными функциями текущей базы. Для безопасного извлечения строкового представления GUID используем метод менеджера XML базы-источника XMLСтрока().
Посмотрим на пример получения строкового GUID из COM-соединения:
// Получаем строковое представление GUID объекта базы-источника
СтрокаGUID = COMСоединение.XMLСтрока(ТоварCOM.Ссылка);
Разберем процесс поиска существующего элемента в базе-приемнике и создания нового элемента с тем же идентификатором, что и в источнике. Для этого используем методы ПолучитьСсылку() и УстановитьСсылкуНового().
Важное ограничение: метод УстановитьСсылкуНового() можно вызывать только для нового, еще не записанного в базу объекта (когда ЭтоНовый() = Истина). Если элемент с таким GUID уже существует, попытка записать новый объект с той же ссылкой вызовет ошибку нарушения уникальности.
// 1. Преобразуем строку в тип УникальныйИдентификатор базы-приемника
Идентификатор = Новый УникальныйИдентификатор(СтрокаGUID);
// 2. Получаем ссылку по идентификатору
СсылкаПриемника = Справочники.Номенклатура.ПолучитьСсылку(Идентификатор);
// 3. Проверяем, существует ли уже элемент в базе
НайденныйОбъект = СсылкаПриемника.ПолучитьОбъект();
Если НайденныйОбъект = Неопределено Тогда
// Элемент не найден, создаем новый с предопределенным GUID
НовыйЭлемент = Справочники.Номенклатура.СоздатьЭлемент();
НовыйЭлемент.УстановитьСсылкуНового(СсылкаПриемника);
НовыйЭлемент.Наименование = COMСоединение.XMLСтрока(ТоварCOM.Наименование);
// Заполнение остальных реквизитов...
НовыйЭлемент.Записать();
Иначе
// Элемент найден, при необходимости обновляем его реквизиты
НайденныйОбъект.Наименование = COMСоединение.XMLСтрока(ТоварCOM.Наименование);
// Обновление остальных реквизитов...
НайденныйОбъект.Записать();
КонецЕсли;
Если требуется сопоставлять контрагентов не по GUID, а по бизнес-ключам, разберем корректный алгоритм поиска по реквизитам ИНН и КПП, который учитывает как юридических, так и физических лиц:
Функция НайтиКонтрагентаПоРеквизитам(ИНН, КПП, Наименование)
Если ЗначениеЗаполнено(ИНН) Тогда
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Контрагенты.Ссылка КАК Ссылка
|ИЗ
| Справочник.Контрагенты КАК Контрагенты
|ГДЕ
| Контрагенты.ИНН = &ИНН
| И (&ПроверятьКПП = ЛОЖЬ ИЛИ Контрагенты.КПП = &КПП)";
Запрос.УстановитьПараметр("ИНН", ИНН);
Запрос.УстановитьПараметр("КПП", КПП);
Запрос.УстановитьПараметр("ПроверятьКПП", ЗначениеЗаполнено(КПП));
Результат = Запрос.Выполнить();
Если Не Результат.Пустой() Тогда
Выборка = Результат.Выбрать();
Выборка.Следующий();
Возврат Выборка.Ссылка;
КонецЕсли;
КонецЕсли;
// Если по ИНН/КПП не нашли, ищем по точному наименованию
Возврат Справочники.Контрагенты.НайтиПоНаименованию(Наименование, Истина);
КонецФункции
Построчное чтение свойств через точку (например, Товар.Родитель.Код) выполняет отдельный удаленный вызов на каждое обращение, что существенно снижает скорость выгрузки. Для ускорения обмена рекомендуется:
COMСоединение.NewObject("Запрос"), выбирать все необходимые поля пакетом и обходить готовую выборку или таблицу значений.comcntr.dll должна соответствовать разрядности запускаемого клиента 1С. При несовпадении разрядностей COM-компоненту настраивают через службу компонентов Windows (COM+ приложение).EnterpriseData, что исключает зависимость от платформенного COM-соединения.