Передача данных между базами 1С через COM-соединение — это классическая задача, с которой сталкиваются разработчики при интеграции систем. Если передача простых типов (строка, число, дата) не вызывает затруднений, то работа со ссылочными типами, такими как Справочники или Перечисления, часто ставит новичков в тупик. Разберем подробно, как правильно организовать этот процесс, на примере обмена между «Бухгалтерией предприятия 3.0» и «Управлением торговлей 11».
Прежде всего, проанализируем важный нюанс: когда мы создаем COM-соединение, мы получаем доступ к объектам другой базы, но эти объекты не являются «родными» для нашей текущей базы. Это так называемые «прокси-объекты». Мы не можем просто присвоить реквизиту ВидНоменклатуры в базе-приемнике ссылку из базы-источника. Нам необходимо найти соответствующий объект в базе-приемнике или создать его там.
Это самый простой и интуитивно понятный способ. Рассмотрим ситуацию, когда нам нужно передать номенклатуру и заполнить её вид. Мы будем использовать метод НайтиПоНаименованию через объект Соединение.
Разберем алгоритм действий по шагам:
Посмотрим на пример кода:
// Предположим, Соединение уже установлено
НаименованиеВида = ОбъектИсточник.ВидНоменклатуры.Наименование;
// Ищем вид номенклатуры в базе-приемнике (УТ)
ВидНоменклатурыУТ = Соединение.Справочники.ВидыНоменклатуры.НайтиПоНаименованию(НаименованиеВида);
// Проверяем, нашли ли мы что-нибудь
Если Соединение.XMLСтрока(ВидНоменклатурыУТ) = Соединение.XMLСтрока(Соединение.Справочники.ВидыНоменклатуры.ПустаяСсылка()) Тогда
// Если не нашли, можем создать новый элемент
НовыйВид = Соединение.Справочники.ВидыНоменклатуры.СоздатьЭлемент();
НовыйВид.Наименование = НаименованиеВида;
// Заполняем другие обязательные реквизиты для УТ 11
НовыйВид.ТипНоменклатуры = Соединение.Перечисления.ТипыНоменклатуры.Товар;
НовыйВид.Записать();
ВидНоменклатурыУТ = НовыйВид.Ссылка;
КонецЕсли;
// Теперь подставляем найденную или созданную ссылку в объект номенклатуры
НоменклатураОбъектУТ.ВидНоменклатуры = ВидНоменклатурыУТ;
Поиск по наименованию часто подводит: пользователи могут изменить название, или в базе могут оказаться дубли. Проанализируем более профессиональный подход — использование UUID (уникального идентификатора). Каждый объект в 1С имеет свой уникальный ключ, который остается неизменным.
Рассмотрим, как передать ссылку через GUID:
// В базе-источнике получаем строковое представление GUID
СтрокаGUID = Строка(ОбъектИсточник.УникальныйИдентификатор());
// В базе-приемнике через COM создаем объект GUID и ищем по нему ссылку
СсылкаПриемник = Соединение.Справочники.Номенклатура.ПолучитьСсылку(Соединение.NewObject("Guid", СтрокаGUID));
// Проверяем существование объекта в приемнике
ОбъектСуществует = Соединение.Справочники.Номенклатура.Выбрать(СсылкаПриемник).Следующий();
Если Не ОбъектСуществует Тогда
// Логика создания нового объекта, если по GUID ничего не найдено
КонецЕсли;
С Перечислениями ситуация иная: их нельзя создать программно, они жестко заданы в конфигурации. Чтобы передать значение перечисления (например, СтавкаНДС), мы должны сопоставить их по имени значения.
Выясним, как это сделать правильно:
// Получаем имя значения перечисления в источнике (например, "НДС20")
ИмяЗначения = ОбъектИсточник.СтавкаНДС.Метаданные().Имя;
// Находим аналогичное значение в базе-приемнике
СтавкаНДСПриемник = Соединение.Перечисления.СтавкиНДС[ИмяЗначения];
// Присваиваем
НовыйОбъектУТ.СтавкаНДС = СтавкаНДСПриемник;
Важно: Если имена значений перечислений в разных конфигурациях (БП и УТ) различаются, вам придется написать таблицу соответствия (например, через оператор Если ... ИначеЕсли или используя Соответствие).
Проанализируем ситуацию: если вы загружаете 1000 товаров, и для каждого товара вызываете НайтиПоНаименованию через COM, ваш обмен будет работать крайне медленно. Каждое обращение через точку в COM-объекте — это длительный сетевой вызов.
Для ускорения работы рекомендуем использовать объект Соответствие для кэширования уже найденных ссылок:
КэшВидов = Новый Соответствие;
Для Каждого СтрокаТовара Из ТаблицаТоваров Цикл
СсылкаИсточник = СтрокаТовара.ВидНоменклатуры;
// Ищем в локальном кэше, чтобы не дергать COM-соединение лишний раз
ВидПриемник = КэшВидов.Получить(СсылкаИсточник);
Если ВидПриемник = Неопределено Тогда
// Только если в кэше нет, идем в COM
ВидПриемник = Соединение.Справочники.ВидыНоменклатуры.НайтиПоНаименованию(СсылкаИсточник.Наименование);
КэшВидов.Вставить(СсылкаИсточник, ВидПриемник);
КонецЕсли;
// Используем ВидПриемник для записи товара
КонецЦикла;
При реализации обмена часто возникают следующие проблемы, которые стоит учитывать:
comcntr.dll.Если Ссылка = Справочники.Номенклатура.ПустаяСсылка(). Используйте метод Соединение.XMLСтрока(Ссылка) для сравнения строковых представлений пустых ссылок.Номенклатуры обязательно нужно заполнить ВидНоменклатуры, иначе объект не запишется или будет работать некорректно.Таким образом, мы рассмотрели основные механизмы передачи сложных реквизитов. Главное правило — всегда помнить, что в базе-приемнике вы работаете с «чужими» объектами, которые требуют предварительного поиска или создания перед присваиванием в реквизиты.