Программный запуск обработок 1С 8.3: от Создать() до фонового задания

· 9 мин

Содержание

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

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

Способы запустить обработку из кода: что выбрать

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

ЗадачаМетодГде выполняется
Выполнить алгоритм встроенной обработкиОбработки.Имя.Создать() + вызов экспортной процедурыСервер
Открыть форму встроенной обработкиОткрытьФорму("Обработка.Имя.Форма", Параметры)Клиент
Выполнить внешнюю обработку (.epf)ВнешниеОбработки.Подключить() → ВнешниеОбработки.Создать()Сервер
Открыть форму внешней обработкиОткрытьФорму("ВнешняяОбработка." + Имя + ".Форма")Клиент, после подключения
Долгая операция без зависания интерфейсаФоновыеЗадания.Выполнить()Сервер, отдельный сеанс
Запуск по времениРегламентное задание или команда дополнительной обработкиСервер
Запуск при старте 1СПараметр командной строки /ExecuteКлиент

Объект обработки в тонком клиенте и веб-клиенте на клиенте не создать. Код с Создать() всегда кладите в процедуру с директивой &НаСервере или в серверный общий модуль.

Встроенная обработка: создать объект или открыть форму

Выполнить без формы

В модуле объекта обработки опишите процедуру с ключевым словом Экспорт. Без него вызов извне упадёт с ошибкой Метод объекта не обнаружен.

// Модуль объекта обработки «ЗакрытиеЗаказов»
Перем Протокол Экспорт;

Процедура ЗакрытьПросроченные(ДатаОтсечки) Экспорт
	Протокол = Новый Массив;
	// ... алгоритм обработки
	Протокол.Добавить("Обработано до " + Формат(ДатаОтсечки, "ДЛФ=D"));
КонецПроцедуры

Вызов из другого места конфигурации (серверный контекст):

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

Реквизиты обработки доступны как свойства объекта: Обработка.Организация = Организация;. Табличные части заполняются так же, как у документа: Обработка.Товары.Добавить().

Открыть форму

С клиента форма открывается по полному имени. Если имя формы не указано, откроется основная:

&НаКлиенте
Процедура ОткрытьЗакрытиеЗаказов(Команда)
	ОткрытьФорму("Обработка.ЗакрытиеЗаказов.Форма");
	// конкретная форма: "Обработка.ЗакрытиеЗаказов.Форма.ФормаНастроек"
КонецПроцедуры

Пользователь увидит форму, только если у его роли есть права на эту обработку («Использование» и «Просмотр»). Иначе получит Нарушение прав доступа.

Внешняя обработка .epf из кода

Внешний файл нельзя просто создать по пути из тонкого клиента : сервер не видит диск пользователя. Порядок такой:

  1. Двоичные данные файла кладут во временное хранилище.
  2. На сервере вызывают ВнешниеОбработки.Подключить() — метод возвращает имя обработки в сеансе.
  3. По этому имени создают объект или открывают форму.

Файл лежит на сервере 1С

&НаСервереБезКонтекста
Функция ПодключитьВнешнююОбработку(ПутьНаСервере)
	Адрес = ПоместитьВоВременноеХранилище(Новый ДвоичныеДанные(ПутьНаСервере));
	// третий параметр — безопасный режим; Ложь снимает ограничения
	Возврат ВнешниеОбработки.Подключить(Адрес, , Ложь);
КонецФункции

&НаСервереБезКонтекста
Процедура ВыполнитьВнешнююНаСервере(ПутьНаСервере)
	Имя = ПодключитьВнешнююОбработку(ПутьНаСервере);
	Обработка = ВнешниеОбработки.Создать(Имя);
	Обработка.ЗакрытьПросроченные(ТекущаяДатаСеанса());
КонецПроцедуры

Файл выбирает пользователь

Файл с компьютера пользователя передаётся асинхронно, через НачатьПомещениеФайла:

&НаКлиенте
Процедура ВыбратьИЗапустить(Команда)
	Оповещение = Новый ОписаниеОповещения("ПослеПомещенияФайла", ЭтотОбъект);
	НачатьПомещениеФайла(Оповещение, , "", Истина, УникальныйИдентификатор);
КонецПроцедуры

&НаКлиенте
Процедура ПослеПомещенияФайла(Результат, Адрес, ИмяФайла, ДопПараметры) Экспорт
	Если Не Результат Тогда
		Возврат;
	КонецЕсли;
	Имя = ПодключитьНаСервере(Адрес);
	ОткрытьФорму("ВнешняяОбработка." + Имя + ".Форма");
КонецПроцедуры

&НаСервереБезКонтекста
Функция ПодключитьНаСервере(Адрес)
	Возврат ВнешниеОбработки.Подключить(Адрес, , Ложь);
КонецФункции

Для внешних отчётов (.erf) схема та же, только менеджер другой: ВнешниеОтчеты.Подключить(), ВнешниеОтчеты.Создать(), а форма открывается по имени "ВнешнийОтчет." + Имя + ".Форма".

Безопасный режим

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

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

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

В объект

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

В форму

Параметры формы передают структурой. В форме обработки объявите параметр на вкладке «Параметры» с тем же именем и прочитайте его при создании:

// Вызывающий код
&НаКлиенте
Процедура ОткрытьСПараметрами(Команда)
	П = Новый Структура("Организация, Период", Организация, Период);
	Оповещение = Новый ОписаниеОповещения("ПослеЗакрытия", ЭтотОбъект);
	ОткрытьФорму("Обработка.ЗакрытиеЗаказов.Форма", П, ЭтаФорма, , , , Оповещение,
		РежимОткрытияОкнаФормы.БлокироватьОкноВладельца);
КонецПроцедуры

&НаКлиенте
Процедура ПослеЗакрытия(Результат, ДопПараметры) Экспорт
	Если Результат <> Неопределено Тогда
		Сообщить("Закрыто заказов: " + Формат(Результат, "ЧН=0; ЧГ=0"));
	КонецЕсли;
КонецПроцедуры
// Модуль формы обработки
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
	Объект.Организация = Параметры.Организация;
	Объект.Период = Параметры.Период;
КонецПроцедуры

// при завершении работы формы
// Закрыть(КоличествоЗакрытых);

Значение, переданное в Закрыть(), приходит в процедуру оповещения первым параметром. Если пользователь закрыл окно крестиком, туда придёт Неопределено — проверяйте это.

Запомнить настройки между запусками

Для внешних обработок часто нужно хранить настройки: путь к файлу обмена, флаги. Используйте ХранилищеОбщихНастроек.Сохранить() и ХранилищеОбщихНастроек.Загрузить() с ключом объекта, например "МояОбработка.Настройки". Значение сохраняется для текущего пользователя.

Фоновый запуск обработки

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

Ключевое ограничение: ФоновыеЗадания.Выполнить() принимает имя экспортной процедуры серверного общего модуля, а не метод обработки. Поэтому нужна обёртка.

// Общий модуль «ФоновыеОбработки», флажок «Сервер», не глобальный
Процедура ЗакрытьЗаказыВФоне(ДатаОтсечки) Экспорт
	Обработка = Обработки.ЗакрытиеЗаказов.Создать();
	Обработка.ЗакрытьПросроченные(ДатаОтсечки);
КонецПроцедуры
&НаСервере
Процедура ЗапуститьФоновоеНаСервере()
	П = Новый Массив;
	П.Добавить(НачалоДня(ТекущаяДатаСеанса()));
	Задание = ФоновыеЗадания.Выполнить("ФоновыеОбработки.ЗакрытьЗаказыВФоне", П,
		"ЗакрытиеЗаказов", "Закрытие просроченных заказов");
	ИдентификаторЗадания = Задание.УникальныйИдентификатор;
КонецПроцедуры

Третий параметр — ключ. Второе задание с тем же ключом не запустится, пока первое активно: так вы не получите двойной прогон по нажатию кнопки дважды.

Состояние проверяйте через ФоновыеЗадания.НайтиПоУникальномуИдентификатору() и свойство Состояние (СостояниеФоновогоЗадания.Активно, Завершено, ЗавершеноАварийно). Текст ошибки аварийного завершения лежит в ИнформацияОбОшибке.

Внешняя обработка в фоне

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

Процедура ВыполнитьВнешнююВФоне(ДанныеФайла) Экспорт
	Адрес = ПоместитьВоВременноеХранилище(ДанныеФайла);
	Имя = ВнешниеОбработки.Подключить(Адрес, , Ложь);
	ВнешниеОбработки.Создать(Имя).ЗакрытьПросроченные(ТекущаяДатаСеанса());
КонецПроцедуры

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

Обработка по расписанию: три варианта

Регламентное задание в конфигурации

В конфигураторе добавьте объект «Регламентное задание», в поле «Имя метода» выберите процедуру серверного общего модуля (ту же обёртку). Расписание задаётся в свойствах объекта или кодом:

Задание = РегламентныеЗадания.НайтиПредопределенное(Метаданные.РегламентныеЗадания.ЗакрытиеЗаказов);
Расписание = Новый РасписаниеРегламентногоЗадания;
Расписание.ПериодПовтораДней = 1;
Расписание.ВремяНачала = Дата(1, 1, 1, 2, 0, 0); // каждый день в 02:00
Задание.Расписание = Расписание;
Задание.Использование = Истина;
Задание.Записать();

Способ требует правки конфигурации. Для типовой на поддержке это лишняя работа при каждом обновлении — удобнее следующий вариант.

Дополнительная обработка БСП

В типовых базах внешнюю обработку регистрируют в справочнике по пути Администрирование → Печатные формы, отчеты и обработки → Дополнительные отчеты и обработки. Чтобы её можно было поставить на расписание, в модуле объекта нужны две функции:

Функция СведенияОВнешнейОбработке() Экспорт
	Сведения = ДополнительныеОтчетыИОбработки.СведенияОВнешнейОбработке("2.2.2.1");
	Сведения.Вид = ДополнительныеОтчетыИОбработкиКлиентСервер.ВидОбработкиДополнительнаяОбработка();
	Сведения.Версия = "1.0";
	Команда = Сведения.Команды.Добавить();
	Команда.Представление = "Закрыть просроченные заказы";
	Команда.Идентификатор = "ЗакрытьЗаказы";
	Команда.Использование = ДополнительныеОтчетыИОбработкиКлиентСервер.ТипКомандыВызовСерверногоМетода();
	Возврат Сведения;
КонецФункции

Процедура ВыполнитьКоманду(ИдентификаторКоманды, ПараметрыВыполнения) Экспорт
	Если ИдентификаторКоманды = "ЗакрытьЗаказы" Тогда
		ЗакрытьПросроченные(ТекущаяДатаСеанса());
	КонецЕсли;
КонецПроцедуры

После загрузки файла в справочник в карточке обработки, на списке команд, можно задать расписание для команды с типом «Вызов серверного метода». Платформа будет выполнять её регламентным заданием БСП.

Запуск 1С с ключом /Execute

Без доработки конфигурации внешнюю обработку можно открыть сразу при старте клиента:

"C:\Program Files\1cv8\common\1cestart.exe" ENTERPRISE /S"srv1c\buh" /N"Робот" /P"пароль" /Execute"D:\Scripts\ZakrytieZakazov.epf"

Для файловой базы вместо /S укажите /F"D:\Bases\Buh". Такую строку ставят в планировщик Windows. Код в форме обработки (ПриОткрытии) выполняет работу и в конце вызывает ЗавершитьРаботуСистемы(Ложь).

ВариантПлюсыМинусы
Регламентное заданиеРаботает на сервере без клиентаПравка конфигурации
Команда доп. обработки БСПБез снятия с поддержкиТолько для конфигураций на БСП
/Execute + планировщик WindowsНе трогает базуНужна лицензия на сеанс, пароль в командной строке

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

Динамический вызов и запуск из других программ

Имя обработки в переменной

Когда имя приходит из настроек, не собирайте код строкой для Выполнить(). Менеджер Обработки поддерживает обращение по имени:

Если Метаданные.Обработки.Найти(ИмяОбработки) <> Неопределено Тогда
	Обработка = Обработки[ИмяОбработки].Создать();
	Обработка.ЗакрытьПросроченные(ТекущаяДатаСеанса());
КонецЕсли;

Проверка через Метаданные.Обработки.Найти() защищает от падения, если обработку переименовали или удалили.

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

Выполнить() со строкой кода оставьте на крайний случай. Ошибку в такой строке не поймает синтаксический контроль, а подстановка значений из настроек открывает дорогу к выполнению чужого кода.

Через COM-соединение

Внешняя программа (скрипт, другая база 1С) подключается через V83.COMConnector и вызывает обработку так же, как код внутри базы:

Коннектор = Новый COMОбъект("V83.COMConnector");
База = Коннектор.Connect("Srvr=""srv1c"";Ref=""buh"";Usr=""Робот"";Pwd=""пароль"";");
Обработка = База.Обработки.ЗакрытиеЗаказов.Создать();
Обработка.ЗакрытьПросроченные(ТекущаяДата());

COM-соединение работает только в Windows, и разрядность компоненты должна совпадать с разрядностью вызывающего процесса. Для обмена между разными серверами надёжнее HTTP-сервис: опубликуйте его на веб-сервере и вызывайте из модуля сервиса ту же обёртку общего модуля.

Ошибки при программном запуске обработки

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

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

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