Как сопоставить номенклатуру и вывести остатки из другой базы 1С через COM-соединение в Универсальном отчете

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

При работе с разветвленными информационными системами часто возникает задача консолидации данных. Типичный сценарий: основная деятельность ведется в Управлении торговлей 10.3 (платформа 8.2), а специфический учет — в отраслевом решении на платформе 8.1. Рассмотрим, как объединить данные об остатках из этих баз, используя технологию COM-соединения, и внедрить этот функционал в существующий Универсальный отчет, не переписывая его архитектуру полностью.

Постановка задачи и выбор стратегии

Представим ситуацию: нам необходимо дополнить отчет «Анализ доступности товаров на складах» в базе 8.2 данными по остаткам из базы 8.1. Основная сложность заключается в том, что справочники номенклатуры в базах не идентичны (наименования могут различаться), а сопоставление происходит по коду, который в одной базе хранится в карточке товара, а в другой — может быть зафиксирован в регистре сведений НоменклатураКонтрагентов.

Разберем поэтапно, как реализовать этот механизм, обеспечив максимальную производительность и корректность передачи данных.

Шаг 1: Установка COM-соединения и получение данных

Для начала нам необходимо подключиться к внешней базе. Важно использовать объект V81.COMConnector, так как он работает быстрее, чем полноценное приложение Application, поскольку не требует инициализации графического интерфейса.

Проанализируем процесс получения данных из внешней базы:


// Инициализация соединения
Попытка
    COMСоединение = Новый COMОбъект("V81.COMConnector");
    ПараметрыСвязи = "Srvr='ServerName';Ref='BaseName';Usr='Login';Pwd='Password';";
    БД = COMСоединение.Connect(ПараметрыСвязи);
Исключение
    Сообщить("Не удалось установить соединение: " + ОписаниеОшибки());
    Возврат;
КонецПопытки;

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

ТабВнешняя = ЗапросВнешний.Выполнить().Выгрузить();

Важный момент: полученный объект ТабВнешняя является COM-объектом. Мы не можем напрямую передать его в запрос текущей базы (в качестве параметра временной таблицы), так как менеджер временных таблиц 8.2 «не понимает» структуру объектов базы 8.1.

Шаг 2: Перенос данных из COM-объекта в локальную таблицу значений

Чтобы использовать данные из внешней базы в нашем отчете, необходимо «приземлить» их в локальную таблицу значений (ТЗ). Рассмотрим наиболее эффективный способ — ручной перебор строк. Метод ЗначениеВСтрокуВнутр часто дает сбои при переходе между версиями платформ 8.1 и 8.2 из-за различий в сериализации объектов.

Создадим локальную таблицу и заполним ее:


ЛокальнаяТЗ = Новый ТаблицаЗначений;
ЛокальнаяТЗ.Колонки.Добавить("Код", Новый ОписаниеТипов("Строка", , Новый КвалификаторыСтроки(20)));
ЛокальнаяТЗ.Колонки.Добавить("Остаток81", Новый ОписаниеТипов("Число", , Новый КвалификаторыЧисла(15, 3)));

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

Такой подход гарантирует, что все типы данных будут приведены к примитивным (строки, числа), которые корректно обрабатываются в любой версии платформы.

Шаг 3: Внедрение данных во временную таблицу запроса (МВТ)

Теперь, когда у нас есть ЛокальнаяТЗ, мы можем передать ее в запрос Универсального отчета. Универсальный отчет в УТ 10.3 строится на базе объекта ПостроительЗапроса. Нам нужно модифицировать текст запроса так, чтобы он соединялся с нашей временной таблицей.

Проанализируем, как поместить данные во временную таблицу (МВТ):


МенеджерВТ = Новый МенеджерВременныхТаблиц;
Запрос = Новый Запрос;
Запрос.МенеджерВременныхТаблиц = МенеджерВТ;

// Помещаем локальную ТЗ во временную таблицу
Запрос.Текст = 
"ВЫБРАТЬ * ПОМЕСТИТЬ ВТ_ОстаткиВнешние ИЗ &ВнешниеДанные КАК ВнешниеДанные";
Запрос.УстановитьПараметр("ВнешниеДанные", ЛокальнаяТЗ);
Запрос.Выполнить();

Теперь временная таблица ВТ_ОстаткиВнешние доступна в рамках сессии менеджера временных таблиц и может быть использована в основном запросе отчета.

Шаг 4: Модификация Универсального отчета

Универсальный отчет хранит основной текст запроса в модуле объекта (обычно в процедуре УстановитьНачальныеНастройки или СформироватьОтчет). Чтобы добавить остатки из 8.1, выполним следующие действия:

  1. Найдем место формирования запроса: В модуле отчета найдем код, где переменной ТекстЗапроса присваивается значение.
  2. Добавим соединение: Вставим конструкцию ЛЕВОЕ СОЕДИНЕНИЕ с нашей временной таблицей по полю «Код».
  3. Сопоставим объекты: Поскольку в 8.2 мы можем искать код через регистр НоменклатураКонтрагентов или напрямую в справочнике, запрос будет выглядеть примерно так:

ТекстЗапроса = 
"ВЫБРАТЬ
|   ОсновнойЗапрос.Номенклатура КАК Номенклатура,
|   ОсновнойЗапрос.КоличествоОстаток КАК Остаток82,
|   ЕСТЬNULL(ВТ_ОстаткиВнешние.Остаток81, 0) КАК Остаток81
|ИЗ
|   (&ТекстОсновногоЗапроса) КАК ОсновнойЗапрос
|   ЛЕВОЕ СОЕДИНЕНИЕ ВТ_ОстаткиВнешние КАК ВТ_ОстаткиВнешние
|   ПО ОсновнойЗапрос.Номенклатура.Код = ВТ_ОстаткиВнешние.Код";

Оптимизация производительности

Работа через COM — это всегда нагрузка на сеть и память. Разберем, как сделать работу отчета быстрее:

1. Фильтрация на стороне источника. Не стоит выгружать все остатки из базы 8.1. Проанализируем настройки отбора в 8.2, соберем массив кодов номенклатуры, которая попала в отчет, и передадим этот массив в COM-запрос как параметр. Это в разы сократит объем передаваемого трафика.

2. Использование уникальных идентификаторов (GUID). Если есть возможность прописать UID из 8.1 в дополнительный реквизит номенклатуры в 8.2, это будет самым надежным способом связи. Сопоставление по строковому коду может быть нестабильным (например, из-за префиксов).

3. Кэширование соединения. Создание COM-объекта занимает 2-5 секунд. Если пользователь формирует отчет несколько раз подряд с разными настройками, целесообразно хранить открытое соединение в переменной модуля или в параметрах сеанса (если это допустимо архитектурой).

Резюме

Для реализации задачи мы рассмотрели использование V81.COMConnector, выяснили необходимость ручного копирования данных в локальную таблицу значений для преодоления несовместимости типов, и разобрали механизм внедрения внешних данных в ПостроительЗапроса через временные таблицы. Этот метод позволяет расширить функционал стандартных отчетов 1С 8.2, сохраняя их привычный интерфейс и возможности группировок.

← На главную