Программный запуск обработок 1С 8.3: от Создать() до фонового задания
Содержание
Чтобы запустить обработку в 1С программно, на сервере создайте её объект: Обработки.ИмяОбработки.Создать() для встроенной или ВнешниеОбработки.Создать(Имя) для внешней, а затем вызовите экспортную процедуру модуля объекта. Если нужен интерфейс, откройте форму с клиента: ОткрытьФорму("Обработка.ИмяОбработки.Форма").
Всё ниже относится к платформе 8.3 и управляемым формам. Механизм общий для платформы, поэтому код работает в любой конфигурации: Бухгалтерии, ЗУП, УТ или самописной базе. Отличие только одно — в типовых есть подсистема «Дополнительные отчёты и обработки», и для внешних файлов удобнее идти через неё.
Способы запустить обработку из кода: что выбрать
Сначала определите, что именно нужно: выполнить алгоритм без окна или показать форму пользователю. От этого зависит контекст (клиент или сервер) и метод.
| Задача | Метод | Где выполняется |
|---|---|---|
| Выполнить алгоритм встроенной обработки | Обработки.Имя.Создать() + вызов экспортной процедуры | Сервер |
| Открыть форму встроенной обработки | ОткрытьФорму("Обработка.Имя.Форма", Параметры) | Клиент |
| Выполнить внешнюю обработку (.epf) | ВнешниеОбработки.Подключить() → ВнешниеОбработки.Создать() | Сервер |
| Открыть форму внешней обработки | ОткрытьФорму("ВнешняяОбработка." + Имя + ".Форма") | Клиент, после подключения |
| Долгая операция без зависания интерфейса | ФоновыеЗадания.Выполнить() | Сервер, отдельный сеанс |
| Запуск по времени | Регламентное задание или команда дополнительной обработки | Сервер |
| Запуск при старте 1С | Параметр командной строки /Execute | Клиент |
Объект обработки в тонком клиенте и веб-клиенте на клиенте не создать. Код с Создать() всегда кладите в процедуру с директивой &НаСервере или в серверный общий модуль.
Встроенная обработка: создать объект или открыть форму
Выполнить без формы
В модуле объекта обработки опишите процедуру с ключевым словом Экспорт. Без него вызов извне упадёт с ошибкой Метод объекта не обнаружен.
// Модуль объекта обработки «ЗакрытиеЗаказов»
Перем Протокол Экспорт;
Процедура ЗакрытьПросроченные(ДатаОтсечки) Экспорт
Протокол = Новый Массив;
// ... алгоритм обработки
Протокол.Добавить("Обработано до " + Формат(ДатаОтсечки, "ДЛФ=D"));
КонецПроцедуры
Вызов из другого места конфигурации (серверный контекст):
&НаСервереБезКонтекста
Процедура ЗапуститьЗакрытиеНаСервере()
Обработка = Обработки.ЗакрытиеЗаказов.Создать();
Обработка.ЗакрытьПросроченные(НачалоДня(ТекущаяДатаСеанса()));
Для Каждого Строка Из Обработка.Протокол Цикл
Сообщить(Строка);
КонецЦикла;
КонецПроцедуры
Реквизиты обработки доступны как свойства объекта: Обработка.Организация = Организация;. Табличные части заполняются так же, как у документа: Обработка.Товары.Добавить().
Открыть форму
С клиента форма открывается по полному имени. Если имя формы не указано, откроется основная:
&НаКлиенте
Процедура ОткрытьЗакрытиеЗаказов(Команда)
ОткрытьФорму("Обработка.ЗакрытиеЗаказов.Форма");
// конкретная форма: "Обработка.ЗакрытиеЗаказов.Форма.ФормаНастроек"
КонецПроцедуры
Пользователь увидит форму, только если у его роли есть права на эту обработку («Использование» и «Просмотр»). Иначе получит Нарушение прав доступа.
Внешняя обработка .epf из кода
Внешний файл нельзя просто создать по пути из тонкого клиента : сервер не видит диск пользователя. Порядок такой:
- Двоичные данные файла кладут во временное хранилище.
- На сервере вызывают
ВнешниеОбработки.Подключить()— метод возвращает имя обработки в сеансе. - По этому имени создают объект или открывают форму.
Файл лежит на сервере 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С?
Как передать в обработку ссылку на текущий документ?
Объект.Ссылка в структуре параметров формы или аргументом экспортной процедуры. Документ перед этим должен быть записан, иначе ссылка будет пустой.