В практике разработчика 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, система выдаст ошибку, так как типы данных в разных базах несовместимы, даже если конфигурации идентичны.
Если задача подразумевает регулярное получение данных или сложную логику обработки, которую неудобно описывать в тексте запроса, рассмотрим подход с использованием экспортных функций. Для этого в базе-источнике (например, в Бухгалтерии) создается общий модуль с признаком «Внешнее соединение».
Разберем алгоритм действий:
БазаCOM.Пример функции в базе-источнике:
Функция ПолучитьОстаткиПоСчету(КодСчета, ДатаОстатков) Экспорт
Запрос = Новый Запрос;
Запрос.Текст = "ВЫБРАТЬ ..."; // Текст запроса
Запрос.УстановитьПараметр("Счет", ПланыСчетов.Хозрасчетный.НайтиПоКоду(КодСчета));
Возврат Запрос.Выполнить().Выгрузить();
КонецФункции
Вызов в базе-приемнике будет выглядеть максимально просто:
ТзРезультатCOM = БазаCOM.ИмяОбщегоМодуля.ПолучитьОстаткиПоСчету("10.01", ТекущаяДата());
Выясним причину, по которой метод Выгрузить() не сразу дает нам готовую к использованию таблицу. Результатом выполнения запроса через COM является COM-объект. Мы не можем просто так привязать его к табличному полю на форме или использовать в локальном запросе.
Для того чтобы превратить внешнюю таблицу значений в локальную, разберем метод обхода:
ЛокальнаяТЗ = Новый ТаблицаЗначений;
ЛокальнаяТЗ.Колонки.Добавить("Номенклатура", Новый ОписаниеТипов("Строка"));
ЛокальнаяТЗ.Колонки.Добавить("Остаток", Новый ОписаниеТипов("Число"));
Для Каждого СтрокаCOM Из ТзРезультатCOM Цикл
НоваяСтрока = ЛокальнаяТЗ.Добавить();
// Обращаемся к свойствам COM-объекта
НоваяСтрока.Номенклатура = Строка(СтрокаCOM.Номенклатура);
НоваяСтрока.Остаток = СтрокаCOM.Остаток;
КонецЦикла;
Совет: При передаче ссылочных типов (например, Номенклатуры) лучше передавать их Наименование или УникальныйИдентификатор (GUID) в виде строки, чтобы потом найти соответствующий объект в текущей базе.
Построчный обход таблицы через COM — это самый медленный способ получения данных. Каждое обращение к СтрокаCOM.ИмяПоля инициирует вызов через границу процессов, что создает значительные задержки на больших объемах данных. Чтобы ускорить процесс в десятки раз, проанализируем метод сериализации в XML или JSON.
Суть метода заключается в том, чтобы упаковать всю таблицу в одну длинную строку на стороне источника и передать её одним «пакетом». В базе-источнике используем ЗначениеВСтрокуВнутреннее() или СериализаторXDTO, а в базе-приемнике выполняем обратное преобразование. Это позволяет избежать тысяч мелких COM-вызовов.
При работе с COM-соединением мы часто сталкиваемся со специфическими проблемами, которые стоит рассмотреть заранее:
comcntr.dll зарегистрирована только для 32 бит, соединение не установится. В этом случае необходимо настроить COM+ в Windows (Службы компонентов), создав отдельное приложение для работы V83.COMConnector под конкретным пользователем.double, что иногда приводит к потере копеек (например, 100.20 превращается в 100.1999999). Если точность критична, передавайте суммы в виде строк и преобразуйте их обратно в число в локальной базе.БазаCOM = Неопределено;.Если ваша база-источник — это «Бухгалтерия предприятия 3.0» на управляемых формах, посмотрим в сторону современных протоколов. Использование OData, HTTP-сервисов или Web-сервисов часто оказывается более производительным и надежным решением, так как не требует настройки COM-компонентов на сервере и не зависит от разрядности операционной системы.
Тем не менее, для классических задач интеграции старых систем (таких как УПП или Бухгалтерия 2.0) COM-соединение остается мощным и проверенным инструментом, позволяющим получить доступ к любым данным через механизм запросов.