Как реализовать получение данных из внешней базы 1С и сопоставить объекты по коду

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

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

В данной статье мы подробно разберем, как организовать этот процесс, используя COM-соединение, и как правильно сопоставить объекты, если их уникальные идентификаторы не совпадают, но коды идентичны.

Шаг 1: Установка COM-соединения и выполнение запроса во внешней базе

Для начала нам необходимо инициировать подключение к внешней базе. Мы используем V83.COMConnector для создания сессии. После успешного подключения мы можем создавать объекты во внешней базе так же, как и в локальной, но обращаясь к ним через переменную COM-объекта.

Рассмотрим пример кода для инициализации подключения и выполнения запроса. Обратите внимание, что текст запроса пишется на языке запросов 1С, но сам объект запроса создается через внешнее соединение.


// Устанавливаем соединение
ПараметрыСоединения = "Srvr=""ServerName"";Ref=""TradeBase"";Usr=""Admin"";Pwd=""Password"";";
Connector = Новый COMОбъект("V83.COMConnector");

Попытка
    ВнешняяБаза = Connector.Connect(ПараметрыСоединения);
Исключение
    Сообщить("Не удалось подключиться: " + ОписаниеОшибки());
    Возврат;
КонецПопытки;

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

ЗапросВнешний.УстановитьПараметр("Артикул", "ТОВ-001");
РезультатЗапроса = ЗапросВнешний.Выполнить().Выгрузить();

Важный момент: Мы выбираем не саму ссылку Счет.Контрагент, а его Код (или УникальныйИдентификатор в строковом виде). Это критически важно, так как ссылка из внешней базы не будет иметь смысла в локальной — поиск по ней ничего не даст.

Шаг 2: Обработка данных и сопоставление объектов

Проанализируем ситуацию: мы получили таблицу с кодами контрагентов из внешней базы. Теперь нам нужно найти этих контрагентов в нашей локальной базе. Самая распространенная ошибка новичков — искать контрагента в цикле. Это создает избыточную нагрузку на систему.

Правильный подход заключается в использовании временных таблиц или пакетных запросов в локальной базе. Разберем, как это сделать эффективно:

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

Рассмотрим реализацию этого алгоритма:


// 1. Формируем локальную таблицу из COM-результата
ЛокальнаяТЗ = Новый ТаблицаЗначений;
ЛокальнаяТЗ.Колонки.Добавить("КонтрагентКод", Новый ОписаниеТипов("Строка"));
ЛокальнаяТЗ.Колонки.Добавить("Сумма", Новый ОписаниеТипов("Число"));

Для Каждого СтрокаВнешняя Из РезультатЗапроса Цикл
    НоваяСтрока = ЛокальнаяТЗ.Добавить();
    НоваяСтрока.КонтрагентКод = СтрокаВнешняя.КонтрагентКод;
    НоваяСтрока.Сумма = СтрокаВнешняя.Сумма;
КонецЦикла;

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

ЗапросЛокальный.УстановитьПараметр("ЛокальнаяТЗ", ЛокальнаяТЗ);
Выборка = ЗапросЛокальный.Выполнить().Выбрать();

Пока Выборка.Следующий() Цикл
    // Здесь мы уже имеем и локальную ссылку на контрагента, и менеджера из РС
    // Добавляем запись в документ или ТЧ
КонецЦикла;

Шаг 3: Оптимизация производительности и безопасность

При работе с внешними соединениями необходимо учитывать несколько технических нюансов. Выясним основные причины возможных проблем и способы их решения:

Управление ресурсами: После завершения работы с внешней базой обязательно нужно обнулять переменную COM-объекта. В противном случае сессия на сервере может «зависнуть», потребляя лицензию и оперативную память. Используйте конструкцию ВнешняяБаза = Неопределено;.

Лицензирование: Каждое COM-подключение — это отдельный сеанс, который требует клиентскую лицензию. Если ваша задача выполняется регламентным заданием каждые 5 минут, убедитесь, что у вас достаточно свободных лицензий, чтобы не блокировать работу пользователей.

Альтернативные методы: Рассмотрим использование современных HTTP-сервисов. В отличие от COM, HTTP-сервисы работают быстрее, не зависят от разрядности операционной системы (32/64 бит) и более стабильны при обрывах связи. Если вы планируете долгосрочную поддержку интеграции, рекомендуем настроить в «НеОсновной» базе простейший REST API (OData) или собственный HTTP-сервис, который будет отдавать данные в формате JSON.

Безопасность: Никогда не храните пароли к базам в открытом виде внутри кода. Проанализируем ситуацию: если злоумышленник получит доступ к конфигурации, он узнает доступы ко всем смежным системам. Используйте БезопасноеХранилищеДанных или хотя бы закрытые константы с ограниченными правами доступа.

Резюме

Для успешного решения задачи нам потребовалось:

  1. Подключиться к базе через V83.COMConnector.
  2. Получить данные с помощью Запроса во внешней базе, обязательно извлекая строковые идентификаторы (Код или GUID).
  3. Передать данные в локальную базу и выполнить сопоставление через временные таблицы в одном запросе.
  4. Связать полученные ссылки с данными локального Регистра Сведений.

Такой подход обеспечивает высокую скорость работы и надежность сопоставления объектов между независимыми информационными системами.

← На главную