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

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

В практике разработчика 1С часто возникает задача получения данных из одной информационной базы в другую в режиме реального времени. Это может быть сверка остатков между УПП и Бухгалтерией, получение данных о складских запасах или формирование консолидированной отчетности. Одним из наиболее гибких инструментов для решения этой задачи является COM-соединение. В этой статье мы подробно разберем, как правильно настроить подключение, выполнить запрос и корректно передать результаты между базами.

Способ 1: Использование объекта «Запрос» через COM-соединение

Рассмотрим наиболее прямой способ — создание объекта Запрос непосредственно в контексте внешней базы. Этот метод удобен тем, что нам не нужно вносить изменения в конфигурацию базы-источника. Мы создаем соединение, инициализируем объект Запрос через COM и передаем в него текст запроса.

Проанализируем пример кода, который позволяет выполнить запрос в базе Бухгалтерии из базы УПП:


// 1. Создаем объект коннектора
Коннектор = Новый COMОбъект("V83.COMConnector");

// 2. Устанавливаем соединение с базой
// СтрокаСоединения содержит путь к базе, логин и пароль
БазаCOM = Коннектор.Connect("File=""C:\Base\Accounting"";Usr=""Admin"";Pwd=""123"";");

// 3. Создаем объект запроса во внешней базе
ЗапросCOM = БазаCOM.NewObject("Запрос");

// 4. Задаем текст запроса (используем синтаксис внешней базы)
ЗапросCOM.Текст = 
"ВЫБРАТЬ
|	ХозрасчетныйОстаткиИОбороты.Субконто1 КАК Номенклатура,
|	ХозрасчетныйОстаткиИОбороты.КоличествоКонечныйОстаток КАК Остаток
|ИЗ
|	РегистрБухгалтерии.Хозрасчетный.ОстаткиИОбороты(&НачалоПериода, &ОкончаниеПериода, , , Счет.Код = &Счет, , ) КАК ХозрасчетныйОстаткиИОбороты";

// 5. Устанавливаем параметры (ВАЖНО: только примитивные типы)
ЗапросCOM.УстановитьПараметр("НачалоПериода", НачалоДня(ДатаНачала));
ЗапросCOM.УстановитьПараметр("ОкончаниеПериода", КонецДня(ДатаОкончания));
ЗапросCOM.УстановитьПараметр("Счет", "41.01"); // Передаем код счета как строку

// 6. Выполняем запрос и выгружаем результат
РезультатCOM = ЗапросCOM.Выполнить().Выгрузить();

Важный нюанс: Обратите внимание, что при установке параметров через COM-соединение мы можем использовать только примитивные типы данных (числа, строки, даты, булево). Если вы попытаетесь передать ссылку СправочникСсылка из текущей базы в параметр запроса ЗапросCOM, система выдаст ошибку, так как типы данных в разных базах несовместимы, даже если конфигурации идентичны.

Способ 2: Вызов экспортной функции из общего модуля

Если задача подразумевает регулярное получение данных или сложную логику обработки, которую неудобно описывать в тексте запроса, рассмотрим подход с использованием экспортных функций. Для этого в базе-источнике (например, в Бухгалтерии) создается общий модуль с признаком «Внешнее соединение».

Разберем алгоритм действий:

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

Пример функции в базе-источнике:


Функция ПолучитьОстаткиПоСчету(КодСчета, ДатаОстатков) Экспорт
    Запрос = Новый Запрос;
    Запрос.Текст = "ВЫБРАТЬ ..."; // Текст запроса
    Запрос.УстановитьПараметр("Счет", ПланыСчетов.Хозрасчетный.НайтиПоКоду(КодСчета));
    Возврат Запрос.Выполнить().Выгрузить();
КонецФункции

Вызов в базе-приемнике будет выглядеть максимально просто:


ТзРезультатCOM = БазаCOM.ИмяОбщегоМодуля.ПолучитьОстаткиПоСчету("10.01", ТекущаяДата());

Как обработать результат запроса (Проблема COM-объектов)

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

Для того чтобы превратить внешнюю таблицу значений в локальную, разберем метод обхода:


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

Для Каждого СтрокаCOM Из ТзРезультатCOM Цикл
    НоваяСтрока = ЛокальнаяТЗ.Добавить();
    // Обращаемся к свойствам COM-объекта
    НоваяСтрока.Номенклатура = Строка(СтрокаCOM.Номенклатура); 
    НоваяСтрока.Остаток = СтрокаCOM.Остаток;
КонецЦикла;

Совет: При передаче ссылочных типов (например, Номенклатуры) лучше передавать их Наименование или УникальныйИдентификатор (GUID) в виде строки, чтобы потом найти соответствующий объект в текущей базе.

Оптимизация скорости: Сериализация данных

Построчный обход таблицы через COM — это самый медленный способ получения данных. Каждое обращение к СтрокаCOM.ИмяПоля инициирует вызов через границу процессов, что создает значительные задержки на больших объемах данных. Чтобы ускорить процесс в десятки раз, проанализируем метод сериализации в XML или JSON.

Суть метода заключается в том, чтобы упаковать всю таблицу в одну длинную строку на стороне источника и передать её одним «пакетом». В базе-источнике используем ЗначениеВСтрокуВнутреннее() или СериализаторXDTO, а в базе-приемнике выполняем обратное преобразование. Это позволяет избежать тысяч мелких COM-вызовов.

Технические нюансы и подводные камни

При работе с COM-соединением мы часто сталкиваемся со специфическими проблемами, которые стоит рассмотреть заранее:

  1. Проблема разрядности (32 vs 64 бита): Если сервер 1С работает в 64-битном режиме, а библиотека comcntr.dll зарегистрирована только для 32 бит, соединение не установится. В этом случае необходимо настроить COM+ в Windows (Службы компонентов), создав отдельное приложение для работы V83.COMConnector под конкретным пользователем.
  2. Потеря точности чисел: При передаче числовых данных через COM возможна неявная конвертация в тип double, что иногда приводит к потере копеек (например, 100.20 превращается в 100.1999999). Если точность критична, передавайте суммы в виде строк и преобразуйте их обратно в число в локальной базе.
  3. Утечки памяти: COM-объекты не всегда оперативно удаляются из памяти. После завершения работы обязательно обнуляйте переменные: БазаCOM = Неопределено;.
  4. Лицензирование: Помните, что каждое COM-подключение потребляет одну клиентскую лицензию 1С. Если вы вызываете соединение из сеанса пользователя, будет занята вторая лицензия.

Альтернативные варианты

Если ваша база-источник — это «Бухгалтерия предприятия 3.0» на управляемых формах, посмотрим в сторону современных протоколов. Использование OData, HTTP-сервисов или Web-сервисов часто оказывается более производительным и надежным решением, так как не требует настройки COM-компонентов на сервере и не зависит от разрядности операционной системы.

Тем не менее, для классических задач интеграции старых систем (таких как УПП или Бухгалтерия 2.0) COM-соединение остается мощным и проверенным инструментом, позволяющим получить доступ к любым данным через механизм запросов.

← На главную