Запуск процедур обработок в 1С: все рабочие способы

· 9 мин

Содержание

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

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

Что считать «процедурой обработки» и где у неё вход

Обработка в 1С — это объект метаданных с собственным модулем. Процедуры и функции живут в двух местах:

  • 📄 Модуль объекта — методы самой обработки как сущности. Их вызывают у экземпляра, полученного через Создать().
  • 🖥 Модуль формы — обработчики команд и событий конкретной формы. Снаружи, из другого кода, к ним напрямую не обращаются.
  • ⚙️ Модуль менеджера — методы, которые вызывают без создания экземпляра, прямо у менеджера: Обработки.ИмяОбработки.МетодМенеджера().

Ключевое правило: процедуру модуля объекта видно снаружи, только если она помечена Экспорт.

// Модуль объекта обработки
Процедура ВыполнитьЗагрузку(ИмяФайла) Экспорт
    // код загрузки
КонецПроцедуры

Без Экспорт вызов Объект.ВыполнитьЗагрузку(...) упадёт с «Метод объекта не обнаружен ». Это не баг — это область видимости.

Коротко, от какого объекта что вызывают:

Что вызываемОткудаКак получить
Метод модуля объектаэкземпляр обработкиОбработки.Имя.Создать() или ВнешниеОбработки.Создать(путь)
Метод модуля менеджераменеджер, без экземпляраОбработки.Имя.Метод()
Обработчик модуля формытолько сама формаснаружи недоступен

Как создать и запустить внешнюю обработку из файла .epf

Внешняя обработка лежит отдельным файлом и не входит в конфигурацию. Запускают её через глобальный менеджер ВнешниеОбработки.

Способ 1 — создать объект и вызвать метод. Подходит, когда нужно отработать программно, без открытия формы:

Обработка = ВнешниеОбработки.Создать("C:\Обработки\Загрузка.epf", Ложь);
Обработка.ВыполнитьЗагрузку("C:\Данные\прайс.xlsx");

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

Способ 2 — подключить и открыть форму. Когда у обработки есть интерфейс и её запускает пользователь:

ИмяОбработки = ВнешниеОбработки.Подключить("C:\Обработки\Загрузка.epf");
Форма = ВнешниеОбработки.ПолучитьФорму(ИмяОбработки);
Форма.Открыть();

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

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

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

Как обратиться к встроенной обработке конфигурации

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

Создать экземпляр и вызвать экспортную процедуру модуля объекта:

Обработка = Обработки.ЗакрытиеМесяца.Создать();
Обработка.ВыполнитьЗакрытие(ТекущаяДата());

Открыть форму встроенной обработки на клиенте — через ОткрытьФорму:

ОткрытьФорму("Обработка.ЗакрытиеМесяца.Форма.Форма");

Третий сегмент — имя формы в метаданных. Если у обработки назначена основная форма, хватает "Обработка.ЗакрытиеМесяца.ФормаОбъекта" или просто пути до нужной формы.

Метод модуля менеджера вызывают вообще без Создать():

Результат = Обработки.ЗакрытиеМесяца.ПроверитьГотовность();

💡 Разделение по назначению: тяжёлую бизнес-логику держите в модуле объекта (экспортные процедуры), а то, что нужно дёргать из разных мест без создания экземпляра, — в модуле менеджера.

Как вызвать обработку динамически через объект метаданных

Иногда имя обработки заранее неизвестно — например, нужно перебрать все обработки конфигурации или выбрать одну по строке из настроек. Тогда идут через коллекцию метаданных.

Перебор всех обработок:

Для Каждого ОписаниеОбработки Из Метаданные.Обработки Цикл
    Сообщить(ОписаниеОбработки.Имя + " — " + ОписаниеОбработки.Синоним);
КонецЦикла;

Метаданные.Обработки даёт объекты описания (имя, синоним, комментарий), но не экземпляры. Чтобы получить рабочий объект по имени-строке, обращайтесь к менеджеру через квадратные скобки:

ИмяОбработки = "ЗакрытиеМесяца"; // пришло из настройки
МенеджерОбработки = Обработки[ИмяОбработки];
Объект = МенеджерОбработки.Создать();
Объект.ВыполнитьЗакрытие(ТекущаяДата());

Запись Обработки[ИмяОбработки] возвращает тот же менеджер, что и Обработки.ЗакрытиеМесяца, только имя задаётся строкой. Это и есть «вызов через объект метаданных»: метаданные дают список имён, а менеджер по имени — рабочий экземпляр.

Если нужного имени в конфигурации нет, Обработки[ИмяОбработки] вызовет исключение. Проверяйте вход заранее — например, собрав допустимые имена в один проход по Метаданные.Обработки.

Как передать параметры в процедуру и забрать результат

Чаще всего обработку зовут не просто «запустись», а «отработай вот эти данные и верни, что получилось». Здесь важны две вещи: как параметры передаются и чем процедура отличается от функции.

По умолчанию параметр передаётся по ссылке: если процедура меняет его внутри, изменение видно в вызывающем коде. Чтобы запретить это и передать по значению — ставят Знач перед именем параметра.

// Модуль объекта обработки
Процедура ЗаполнитьТаблицу(Знач Период, ТаблицаРезультата) Экспорт
    // Период менять нельзя — он пришёл по значению (Знач)
    // ТаблицаРезультата заполняется здесь и возвращается вызывающему по ссылке
КонецПроцедуры

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

Обработка = Обработки.АнализПродаж.Создать();
Итог = Новый ТаблицаЗначений;
Обработка.ЗаполнитьТаблицу(КонецМесяца(ТекущаяДата()), Итог);
// Итог заполнен внутри процедуры

Если из вызова нужно именно значение — делайте не процедуру, а функцию с Возврат:

Функция ПосчитатьИтог(Знач Данные) Экспорт
    Сумма = 0;
    Для Каждого Строка Из Данные Цикл
        Сумма = Сумма + Строка.Сумма;
    КонецЦикла;
    Возврат Сумма;
КонецФункции

💡 Практичный приём для необязательных параметров — значение по умолчанию прямо в объявлении: Процедура Выполнить(РежимОтладки = Ложь) Экспорт. Тогда старый код, который зовёт Выполнить() без аргумента, продолжит работать после того, как вы добавите параметр.

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

Когда код процедуры хранится как текст (в реквизите, в настройке, в макете), его исполняют операторами Выполнить и Вычислить.

  • Выполнить(СтрокаКода) — исполняет строку как операторы, ничего не возвращает.
  • Вычислить(Выражение) — вычисляет выражение и возвращает результат.
Выполнить("Сообщить('Обработка запущена');");

НалоговаяБаза = 100000;
Ставка = Вычислить("НалоговаяБаза * 0.2");

Вычислить видит локальные переменные того метода, где вызван, — в примере выше НалоговаяБаза доступна. Это удобно для настраиваемых формул: храните выражение строкой, подставляйте значения переменными, считайте Вычислить.

Выполнить и Вычислить — дыра в безопасности, если строка приходит от пользователя или из обмена. Исполняется произвольный код с правами сеанса. На сервере и в безопасном режиме эти операторы ограничены. Не пускайте в них внешние данные без жёсткой проверки, а лучше замените явным разбором допустимых формул.

Отдельно: эти операторы не умеют объявлять процедуры. Строка "Процедура Тест() ... КонецПроцедуры" в Выполнить не скомпилируется — исполняются только операторы, а не определения методов.

Как перехватить ошибку при вызове

Любой из способов выше может упасть: нет файла, метод не экспортный, внутри обработки необработанное исключение. Оборачивайте вызов в Попытка.

Попытка
    Обработка = ВнешниеОбработки.Создать("C:\Обработки\Загрузка.epf", Ложь);
    Обработка.ВыполнитьЗагрузку("C:\Данные\прайс.xlsx");
Исключение
    Инфо = ИнформацияОбОшибке();
    ЗаписьЖурналаРегистрации("ВнешняяОбработка.Запуск",
        УровеньЖурналаРегистрации.Ошибка, , ,
        ПодробноеОписаниеОшибки(Инфо));
    Сообщить("Не удалось выполнить обработку: " + ОписаниеОшибки());
КонецПопытки;

Что использовать внутри Исключение:

МетодЧто даёт
ОписаниеОшибки()короткий текст ошибки — показать пользователю
ИнформацияОбОшибке()объект с причиной, модулем, строкой — для разбора
ПодробноеОписаниеОшибки(Инфо)полный стек — в журнал регистрации

Свою ошибку с понятным текстом бросают через ВызватьИсключение:

Если НЕ ЗначениеЗаполнено(ИмяФайла) Тогда
    ВызватьИсключение "Не указан файл для загрузки";
КонецЕсли;

Типовые ошибки запуска и причины:

Диагностика: выберите симптом

Клиент или сервер: где физически выполняется код

Это чаще всего ломает запуск в тонком и веб-клиенте. Место выполнения задают директивы компиляции:

  • &НаКлиенте — код идёт на компьютере пользователя, есть доступ к его файловой системе и формам.
  • &НаСервере / &НаСервереБезКонтекста — код идёт на сервере 1С, доступа к диску пользователя нет.

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

Рабочая схема для тонкого/веб-клиента, когда файл у пользователя:

  1. На клиенте выбрать файл (НачатьПомещениеФайла / диалог выбора) и положить его во временное хранилище.
  2. Передать адрес хранилища в серверную процедуру.
  3. На сервере получить двоичные данные из хранилища, записать во временный файл сервера и создать обработку оттуда.
&НаСервере
Процедура ЗапуститьОбработкуНаСервере(АдресВХранилище)
    ВременныйФайл = ПолучитьИмяВременногоФайла("epf");
    ДвоичныеДанные = ПолучитьИзВременногоХранилища(АдресВХранилище);
    ДвоичныеДанные.Записать(ВременныйФайл);

    Обработка = ВнешниеОбработки.Создать(ВременныйФайл, Ложь);
    Обработка.ВыполнитьЗагрузку();

    УдалитьФайлы(ВременныйФайл);
КонецПроцедуры

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

Параметры = Новый Массив;
Параметры.Добавить(КонецМесяца(ТекущаяДата()));
ФоновыеЗадания.Выполнить("РегламентныеОперации.ВыполнитьЗакрытие",
    Параметры, , "Фоновое закрытие месяца");

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

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

Перед запуском внешней обработки стоит пройтись по короткому чек-листу:

Перед запуском внешней обработки
Выполнено: 0 / 5

Частые вопросы

Чем `Выполнить` отличается от `Вычислить`?
Выполнить исполняет строку как операторы и ничего не возвращает. Вычислить вычисляет выражение и возвращает значение. Для формулы-строки нужен Вычислить.
Почему процедура обработки не видна из другого модуля?
В модуле объекта процедура видна снаружи, только если помечена Экспорт. Обработчики модуля формы снаружи недоступны в принципе — их вызывает только сама форма.
Можно ли вызвать обработку по имени-строке?
Да: Обработки[ИмяОбработки].Создать(). Имя можно взять из настройки или собрать перебором Метаданные.Обработки.
Внешняя обработка не находит файл, хотя путь верный. В чём дело?
Код скорее всего выполняется на сервере, а файл лежит на компьютере пользователя. В клиент-серверной базе путь всегда локален для стороны выполнения — передайте файл на сервер через временное хранилище.
Безопасно ли пускать в `Выполнить` строку из реквизита, который заполняет пользователь?
Нет. Исполняется произвольный код с правами сеанса. Либо жёстко ограничьте допустимые выражения, либо разбирайте формулу вручную, не передавая её целиком в Выполнить.