Почему при OLE-подключении в 1С 7.7 возникает ошибка «Функция не найдена» в EvalExpr?

Программист 1С v7.7 IT и автоматизация бизнеса
← На главную

Интеграция между двумя информационными базами 1С:Предприятия 7.7 с использованием OLE Automation — распространенный сценарий для обмена данными, синхронизации справочников и выполнения удаленных запросов. Однако нередко разработчики сталкиваются с ситуацией: соединение с удаленной базой формально устанавливается, стандартные объекты и выборки работают, но при попытке вызвать функцию через метод EvalExpr система выдает сообщение об ошибке: «Функция не найдена».

Разберем детально, почему возникает данная ошибка, как правильно формировать строку подключения в методе Initialize при наличии пробелов в путях, а также проанализируем ключевые ограничения платформы при работе через COM/OLE.

Причина 1: Некорректная передача пути к базе данных (пробелы в параметре /D)

Наиболее коварная и распространенная причина, по которой 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-соединение с базой данных!");
    Возврат;
КонецЕсли;

Причина 2: Область видимости и статус функции в подключаемой базе

Метод EvalExpr работает исключительно с глобальным контекстом OLE Automation сервера. Выясним технические требования к вызываемой функции:

  1. Расположение: функция обязана находиться строго в Глобальном модуле той базы, к которой выполняется подключение. Функции из модулей документов, справочников, отчетов или внешних обработок из глобального контекста OLE не видны.
  2. Директива экспорта: в заголовке функции обязательно должно присутствовать ключевое слово Экспорт. Если объявить функцию без экспорта, она останется локальной для Глобального модуля и метод EvalExpr вернет ошибку отсутствия функции:
    
    Функция ПолучитьОстатокТовара(КодТовара, Склад) Экспорт
        // Код вычисления остатка
        Возврат Итог;
    КонецФункции
    
  3. Тип возвращаемого значения: метод EvalExpr предназначен только для вычисления выражений и вызова функций, возвращающих результат. Если требуется выполнить процедуру или набор операторов, не возвращающих значение, следует использовать метод ExecuteBatch.

Причина 3: Особенности вызова функций в условиях OLE-запросов

Рассмотрим частую задачу: вызов функции внутри секции Условие текстового запроса 1С 7.7 через OLE. Пример типичной конструкции:


ТекстЗапроса = "
|Период с ВыбНачПериода по ВыбКонПериода;
|Товар = Регистр.ОстаткиТоваров.Товар;
|Остаток = Регистр.ОстаткиТоваров.Количество;
|Функция КонОст = КонОст(Остаток);
|Условие(МояЭкспортнаяФункция(Товар) = 1);
|";
Запрос = ОЛЕприемник.CreateObject("Запрос");
Если Запрос.Выполнить(ТекстЗапроса) = 0 Тогда
    Сообщить("Ошибка выполнения запроса!");
КонецЕсли;

При выполнении такого кода необходимо учитывать два критически важных правила:

  1. Функция МояЭкспортнаяФункция исполняется целиком в адресном пространстве OLE-сервера. Она должна быть объявлена как экспортная в Глобальном модуле подключаемой базы.
  2. В параметры условия нельзя передавать переменные из модуля базы-источника. Любые внешние фильтры (например, даты, списки или числовые пороги) необходимо либо встраивать в строку текста запроса в виде литералов, либо предварительно передавать в глобальные переменные OLE-сервера.

Причина 4: Права доступа пользователя и модальные окна

Проанализируем две неочевидные системные проблемы, которые могут блокировать доступ к методам OLE Automation:

  1. Права пользователя в конфигураторе: в настройках набора прав пользователя, под которым выполняется OLE-вход, обязательно должен быть установлен флаг «Использование в качестве OLE Automation сервера». Если этот флаг снят, платформа откажет в доступе к внутренним вызовам.
  2. Модальные диалоги и предупреждения: параметр "NO_SPLASH_SHOW" подавляет исключительно отображение стартовой заставки 1С. Если в процедуре ПриНачалеРаботыСистемы подключаемой конфигурации вызывается модальное окно (команда Предупреждение, Вопрос, окно предложения смены пароля или уведомление о невозможности монопольного входа), OLE-поток зависает в ожидании реакции пользователя. В этом случае вызовы EvalExpr будут выдавать системные сбои или ошибки тайм-аута.

Альтернативный подход: вынос логики во внешнюю обработку (.ert)

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

  1. Создаем файл внешней обработки (например, ExportData.ert), в модуле формы которой реализуем все нужные алгоритмы, выборки и запросы.
  2. Открываем обработку через OLE с передачей параметров:
    
    ПараметрыОбмена = СоздатьОбъект("СписокЗначений");
    ПараметрыОбмена.ДобавитьЗначение("СкладОсновной", "ИмяСклада");
    
    // Открываем форму внешней обработки в OLE-базе
    ОЛЕприемник.ОткрытьФорму("Отчет", ПараметрыОбмена, "C:\Bases\Services\ExportData.ert");
    
    // Обработка заполняет список результатами и возвращает их вызывающей стороне
    Результат = ПараметрыОбмена.Получить("Результат");
    

Такой подход исключает конфликт версий в Глобальном модуле и защищает OLE-сессию от ошибок поиска функций при последующих обновлениях конфигурации.

← На главную