Интеграция между двумя информационными базами 1С:Предприятия 7.7 с использованием OLE Automation — распространенный сценарий для обмена данными, синхронизации справочников и выполнения удаленных запросов. Однако нередко разработчики сталкиваются с ситуацией: соединение с удаленной базой формально устанавливается, стандартные объекты и выборки работают, но при попытке вызвать функцию через метод EvalExpr система выдает сообщение об ошибке: «Функция не найдена».
Разберем детально, почему возникает данная ошибка, как правильно формировать строку подключения в методе Initialize при наличии пробелов в путях, а также проанализируем ключевые ограничения платформы при работе через COM/OLE.
Наиболее коварная и распространенная причина, по которой OLE-сервер не видит добавленные функции, кроется в параметрах инициализации. Если путь к целевой информационной базе содержит пробелы (например, C:\Bases\Base 1C\), парсер командной строки 1С воспринимает строку только до первого пробела.
В результате платформа либо аварийно завершает попытку соединения, либо — что случается чаще — не переходит в указанный каталог и подключается к каталогу по умолчанию (к текущей рабочей базе, из которой запускается обработка). Разработчик добавляет экспортную функцию в Глобальный модуль удаленной базы-приемника, а OLE-объект на самом деле ссылается на базу-источник, где этой функции нет.
Посмотрим на ошибочный вариант инициализации:
ОЛЕприемник = СоздатьОбъект("V77.Application");
// Ошибка: путь с пробелами передается без кавычек внутри строки параметров
Открыта = ОЛЕприемник.Initialize(ОЛЕприемник.RMTrade, "/N" + СокрЛП(ИмяПользователя) + " /D" + СокрЛП(ПутьКБазе), "NO_SPLASH_SHOW");
Чтобы платформа восприняла путь как единую строку, его обязательно необходимо экранировать двойными кавычками. Разберем правильный синтаксис формирования параметров:
ОЛЕприемник = СоздатьОбъект("V77.Application");
// Оборачиваем путь к базе и имя пользователя в дополнительные кавычки
ПараметрыЗапуска = "/D""" + СокрЛП(ПутьКБазе) + """ /N""" + СокрЛП(ИмяПользователя) + """";
// При необходимости монопольного входа добавляем ключ /M
// ПараметрыЗапуска = ПараметрыЗапуска + " /M";
// При наличии пароля добавляем ключ /P
// ПараметрыЗапуска = ПараметрыЗапуска + " /P""" + СокрЛП(ПарольПользователя) + """";
Открыта = ОЛЕприемник.Initialize(ОЛЕприемник.RMTrade, ПараметрыЗапуска, "NO_SPLASH_SHOW");
Если Открыта = 0 Тогда
Предупреждение("Не удалось инициализировать OLE-соединение с базой данных!");
Возврат;
КонецЕсли;
Метод EvalExpr работает исключительно с глобальным контекстом OLE Automation сервера. Выясним технические требования к вызываемой функции:
Экспорт. Если объявить функцию без экспорта, она останется локальной для Глобального модуля и метод EvalExpr вернет ошибку отсутствия функции:
Функция ПолучитьОстатокТовара(КодТовара, Склад) Экспорт
// Код вычисления остатка
Возврат Итог;
КонецФункции
EvalExpr предназначен только для вычисления выражений и вызова функций, возвращающих результат. Если требуется выполнить процедуру или набор операторов, не возвращающих значение, следует использовать метод ExecuteBatch.Рассмотрим частую задачу: вызов функции внутри секции Условие текстового запроса 1С 7.7 через OLE. Пример типичной конструкции:
ТекстЗапроса = "
|Период с ВыбНачПериода по ВыбКонПериода;
|Товар = Регистр.ОстаткиТоваров.Товар;
|Остаток = Регистр.ОстаткиТоваров.Количество;
|Функция КонОст = КонОст(Остаток);
|Условие(МояЭкспортнаяФункция(Товар) = 1);
|";
Запрос = ОЛЕприемник.CreateObject("Запрос");
Если Запрос.Выполнить(ТекстЗапроса) = 0 Тогда
Сообщить("Ошибка выполнения запроса!");
КонецЕсли;
При выполнении такого кода необходимо учитывать два критически важных правила:
МояЭкспортнаяФункция исполняется целиком в адресном пространстве OLE-сервера. Она должна быть объявлена как экспортная в Глобальном модуле подключаемой базы.Проанализируем две неочевидные системные проблемы, которые могут блокировать доступ к методам OLE Automation:
"NO_SPLASH_SHOW" подавляет исключительно отображение стартовой заставки 1С. Если в процедуре ПриНачалеРаботыСистемы подключаемой конфигурации вызывается модальное окно (команда Предупреждение, Вопрос, окно предложения смены пароля или уведомление о невозможности монопольного входа), OLE-поток зависает в ожидании реакции пользователя. В этом случае вызовы EvalExpr будут выдавать системные сбои или ошибки тайм-аута.Чтобы не изменять типовой Глобальный модуль подключаемой конфигурации ради добавления нескольких экспортных функций, рекомендуется использовать внешнюю обработку:
ExportData.ert), в модуле формы которой реализуем все нужные алгоритмы, выборки и запросы.
ПараметрыОбмена = СоздатьОбъект("СписокЗначений");
ПараметрыОбмена.ДобавитьЗначение("СкладОсновной", "ИмяСклада");
// Открываем форму внешней обработки в OLE-базе
ОЛЕприемник.ОткрытьФорму("Отчет", ПараметрыОбмена, "C:\Bases\Services\ExportData.ert");
// Обработка заполняет список результатами и возвращает их вызывающей стороне
Результат = ПараметрыОбмена.Получить("Результат");
Такой подход исключает конфликт версий в Глобальном модуле и защищает OLE-сессию от ошибок поиска функций при последующих обновлениях конфигурации.