К статье
Практический материал

Разработка и Конфигурация · 12 мин

1С: как обратиться к процедуре внешней обработки

Как вызвать процедуру или функцию внешней обработки в 1С: методы Создать(), ПолучитьФорму(), вызов клиентских и серверных процедур, типичные ошибки и безопасный подход.

Обращение к процедуре внешней обработки — частая задача при доработке конфигураций 1С без изменения типового кода. Внешняя обработка (файл .epf) содержит собственный модуль объекта, модули форм и экспортные процедуры, которые можно вызвать из другой обработки, отчёта или из кода конфигурации. Ключевая сложность в том, что обращаться к процедурам напрямую «по имени файла» нельзя — сначала нужно создать объект обработки или получить её форму.

Способ вызова зависит от того, где лежит процедура: в модуле объекта обработки, в модуле формы или в общем модуле, а также от контекста исполнения — на клиенте или на сервере. Неправильный выбор контекста приводит к ошибкам вида «Процедура или функция с указанным именем не определена» или «Метод объекта не обнаружен», даже если сам код процедуры написан верно.

Ниже разобраны рабочие способы вызова: через ВнешниеОбработки.Создать(), через ПолучитьФорму(), вызов серверных процедур из клиентского кода, а также ограничения управляемого приложения и типичные ошибки с диагностикой.

Как устроена внешняя обработка и где могут лежать процедуры

Внешняя обработка состоит из нескольких модулей, и место размещения процедуры определяет способ обращения к ней. Модуль объекта — аналог модуля объекта справочника или документа: его экспортные процедуры вызываются через созданный объект обработки. Модуль формы содержит обработчики событий формы и экспортные процедуры, доступные только после получения формы. Реквизиты формы и данные объекта — разные сущности, путать их нельзя.

Процедура становится доступной извне только если в её заголовке указано ключевое слово Экспорт и (в управляемом приложении) директива компиляции, соответствующая нужному контексту: &НаСервере, &НаКлиенте или &НаСервереБезКонтекста. Процедура без Экспорт видна только внутри своего модуля.

Вызов процедуры модуля объекта через ВнешниеОбработки.Создать()

Основной способ обратиться к процедуре модуля объекта — создать объект обработки методом ВнешниеОбработки.Создать(), передав полный путь к файлу .epf. После этого экспортные процедуры вызываются как методы полученного объекта.

&НаСервере

Процедура ВыполнитьОбработкуНаСервере()

ОбъектОбработки = ВнешниеОбработки.Создать("C:\Обработки\МояОбработка.epf");

Результат = ОбъектОбработки.РассчитатьДанные(Параметр1, Параметр2);

КонецПроцедуры

В модуле объекта самой внешней обработки вызываемая процедура должна выглядеть так:

Функция РассчитатьДанные(Парам1, Парам2) Экспорт

// логика

Возврат Результат;

КонецФункции

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

Обращение к процедуре модуля формы через ПолучитьФорму()

Если нужная процедура находится в модуле формы внешней обработки, создавать объект не нужно — вместо этого получают форму методом ПолучитьФорму(). В управляемом приложении путь к форме строится от файла обработки:

&НаКлиенте

Процедура ВызватьПроцедуруФормы(Команда)

ФормаОбработки = ПолучитьФорму("ВнешняяОбработка.МояОбработка.Форма.ФормаОбработки");

ФормаОбработки.ЗаполнитьТаблицу(Параметр);

КонецПроцедуры

Такой вызов работает, если обработка подключена к информационной базе (например, через справочник «Дополнительные отчеты и обработки») и известна под именем «МояОбработка». Для файловой обработки, не зарегистрированной в базе, путь формируется иначе — через ВнешняяОбработка с указанием, как она была открыта, поэтому надёжнее передавать в форму параметры при открытии через ОткрытьФорму() и выполнять логику в обработчике ПриСозданииНаСервере или ПриОткрытии.

Важное ограничение: обращение к форме возможно только на клиенте. Серверные процедуры формы вызываются из её же клиентских процедур, но не извне — чужой модуль не может вызвать серверную процедуру чужой формы напрямую.

Вызов серверной процедуры из клиентского кода

Самый частый практический сценарий: пользователь нажимает кнопку в форме, а логика должна выполниться на сервере — например, обратиться к данным информационной базы или создать объект внешней обработки. Прямой вызов невозможен, поэтому используется цепочка: клиентская процедура вызывает серверную процедуру той же формы, а та уже работает с внешней обработкой.

Порядок действий
  1. 1
    В форме создайте серверную процедуру с директивой &НаСервере или &НаСервереБезКонтекста
  2. 2
    Внутри неё вызовите ВнешниеОбработки.Создать(Путь) и нужную экспортную процедуру
  3. 3
    В клиентском обработчике команды вызовите эту серверную процедуру по имени
  4. 4
    Проверьте, что все передаваемые параметры сериализуемы (примитивы, структуры, таблицы значений — не COM-объекты и не элементы формы)
  5. 5
    Запустите и убедитесь, что результат возвращается на клиент без ошибок
&НаКлиенте

Процедура Выполнить(Команда)

Результат = ВыполнитьНаСервере(ПутьКФайлу);

Сообщить(Результат);

КонецПроцедуры

&НаСервереБезКонтекста

Функция ВыполнитьНаСервере(Путь)

ОбъектОбработки = ВнешниеОбработки.Создать(Путь);

Возврат ОбъектОбработки.ПолучитьСводку();

КонецФункции

Если серверной процедуре нужны реквизиты текущей формы, используйте &НаСервере (с контекстом) — тогда внутри доступны реквизиты формы. Если контекст не нужен, предпочтительнее &НаСервереБезКонтекста: вызов выполняется быстрее, потому что состояние формы не передаётся на сервер и обратно.

Подключение обработки через дополнительные отчеты и обработки

Когда обработка зарегистрирована в подсистеме «Дополнительные отчеты и обработки» (БСП), обращаться к ней по файловому пути не нужно и небезопасно — путь может меняться. Вместо этого используется программный интерфейс подсистемы: обработка подключается по имени, а команды вызываются через её форму или через экспортные процедуры модуля объекта после подключения.

Типовой приём — получить ссылку на элемент справочника дополнительных обработок и через методы БСП (например, ДополнительныеОтчетыИОбработки.ПодключитьВнешнююОбработку() в версиях БСП, где он доступен) получить имя подключённой обработки, после чего работать с ней через ВнешниеОбработки.Создать(ИмяПодключеннойОбработки). Точный состав методов зависит от версии библиотеки стандартных подсистем, поэтому сверяйтесь с документацией вашей версии БСП.

Способы вызова процедур внешней обработки

ВнешниеОбработки.Создать(путь)

Подходит для процедур модуля объекта; только на сервере; требует известного пути к файлу

ПолучитьФорму()

Для процедур модуля формы; только на клиенте; форма должна быть доступна по имени

Через БСП (доп. отчеты и обработки)

Для обработок, зарегистрированных в базе; устойчиво к смене пути; зависит от версии БСП

ОткрытьФорму() с параметрами

Когда нужно передать данные и выполнить логику при открытии; не возвращает значение напрямую

Передача параметров и возврат результата

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

Если процедура внешней обработки должна вернуть сложный результат, оформляйте его как структуру с понятными ключами и проверяйте наличие ключей на стороне вызова. Это защитит от ошибок при доработке обработки, когда состав возвращаемых данных меняется.

Результат = ОбъектОбработки.СформироватьОтчет(ДатаНачала, ДатаОкончания);

Если ТипЗнч(Результат) = Тип("Структура") И Результат.Свойство("ТаблицаДанных") Тогда

// работаем с результатом

КонецЕсли;

Храните путь к внешней обработке не константой в коде, а в константе, регистре сведений или параметре сеанса. Иначе при переносе файла обработки придётся искать и править все места вызова.
ПЗ
Практическое замечание

Типичные ошибки и их диагностика

Ошибка «Процедура или функция с указанным именем не определена» почти всегда означает одно из трёх: у процедуры нет ключевого слова Экспорт, неверная директива компиляции (клиент пытается вызвать серверную процедуру напрямую) или вызов идёт не к тому модулю — например, процедура лежит в модуле формы, а обращение идёт к объекту. Проверяйте заголовок процедуры в первую очередь.

Ошибка «Метод объекта не обнаружен» при вызове через ВнешниеОбработки.Создать() указывает, что в модуле объекта обработки процедуры с таким именем нет либо она не экспортная. Ошибка «Операции с внешними обработками запрещены в безопасном режиме» возникает при работе в безопасном режиме — например, при вызове из регламентного задания с установленным безопасным режимом.

Типичные ошибки
01
Вызов ВнешниеОбработки.Создать() в клиентской процедуре — метод доступен только на сервере
02
Пропущено слово Экспорт — процедура невидима извне, ошибка при вызове
03
Обращение к процедуре формы через объект обработки — модуль формы и модуль объекта не связаны
04
Передача несериализуемых параметров между клиентом и сервером — падение вызова
05
Жёстко прописанный путь к файлу — вызов ломается после переноса обработки
06
Отсутствие проверки существования файла — непонятная ошибка вместо понятного сообщения
Контрольные точки

Как проверить результат

Заголовок процедуры
Норма

Есть Экспорт и подходящая директива (&НаСервере / &НаКлиенте)

Тревожный признак

Экспорт отсутствует или директива не соответствует контексту вызова

Файл обработки
Норма

Файл существует по указанному пути, открывается в конфигураторе

Тревожный признак

Файл не найден или повреждён

Вызов
Норма

Процедура выполняется, результат возвращается ожидаемого типа

Тревожный признак

Ошибка о неопределённой процедуре или о безопасном режиме

FAQ

Можно ли вызвать процедуру внешней обработки из модуля документа конфигурации?

Да, если код выполняется на сервере. В модуле объекта документа вызовите ВнешниеОбработки.Создать(Путь) и далее экспортную процедуру. Учтите, что это создаёт зависимость конфигурации от внешнего файла: при его отсутствии проведение документа будет падать, поэтому оборачивайте вызов в попытку-исключение.

Как вызвать процедуру внешней обработки из другой внешней обработки?

Точно так же: в модуле объекта первой обработки на сервере создайте объект второй через ВнешниеОбработки.Создать() и вызовите её экспортную процедуру. Если обе обработки открыты интерактивно, программное создание объекта всё равно выполняется на сервере.

Почему ВнешниеОбработки.Создать() недоступен в тонком клиенте?

Менеджер внешних обработок работает только на сервере — это ограничение платформы, а не ошибка в коде. Решение стандартное: вызывайте создание объекта внутри серверной процедуры формы или общего модуля с признаком «Сервер».

Как передать таблицу значений в процедуру внешней обработки?

Таблица значений сериализуема, поэтому её можно передать параметром между клиентом и сервером и далее в процедуру обработки. Если таблица лежит в реквизите формы типа «ДанныеФормыКоллекция», сначала преобразуйте её в таблицу значений через РеквизитФормыВЗначение() на сервере.

Что делать, если обработка должна работать и в обычном, и в управляемом приложении?

Разделяйте код по директивам компиляции и инструкциям препроцессора #Если ТолстыйКлиентОбычноеПриложение. В обычном приложении ВнешниеОбработки.Создать() доступен и на клиенте, в управляемом — только на сервере, поэтому единый код без разделения контекстов работать не будет.

Можно ли вызвать процедуру обработки, открытой интерактивно пользователем?

Напрямую — нет: у открытой обработки нет глобально доступного имени. Если нужно взаимодействие между открытыми формами, используйте оповещения (Оповестить / ОбработкаОповещения) или передавайте в форму при открытии уникальный ключ, по которому её можно найти.

Итог

Что важно запомнить

Процедуры модуля объекта вызываются через ВнешниеОбработки.Создать(путь) — только на сервере; процедуры формы — через ПолучитьФорму() на клиенте. Процедура должна быть экспортной и иметь правильную директиву компиляции. Путь к файлу лучше хранить в настройках, а вызовы оборачивать в обработку ошибок.