При разработке в среде 1С:Предприятие 8.3 программисты часто сталкиваются с задачей автоматизации действий, которые ранее выполнялись пользователем вручную через форму. Типичный пример: обработка создает документы по нажатию кнопки, и теперь необходимо, чтобы этот процесс запускался автоматически по расписанию. Однако здесь возникает серьезное архитектурное препятствие: регламентные задания работают на сервере в фоновом режиме и «не знают» о существовании форм.
В данной статье мы разберем, почему нельзя напрямую обратиться к модулю формы из модуля объекта, и как правильно реорганизовать код, чтобы ваша обработка успешно работала по расписанию.
Для начала проанализируем ситуацию. Модуль формы предназначен исключительно для управления интерфейсом и взаимодействия с пользователем. Он существует только тогда, когда у пользователя открыто окно программы. Регламентное (фоновое) задание выполняется сервером автономно, без участия клиента и без создания интерфейсного контекста. Следовательно, любая попытка программно «открыть форму» или «обратиться к процедуре формы» в фоновом задании обречена на ошибку.
Важное правило: Если логика должна работать автоматически, она должна быть полностью отделена от формы и перенесена в модуль объекта или общий модуль.
Рассмотрим первый и самый важный шаг — рефакторинг кода. Нам необходимо переместить основную процедуру выполнения задачи (например, создание документов) из модуля формы в модуль объекта. При этом процедуру нужно пометить ключевым словом Экспорт, чтобы она была доступна извне.
Допустим, в модуле формы у нас была процедура СоздатьДокументы(). Мы переносим ее в модуль объекта:
// В модуле ОБЪЕКТА обработки
Процедура ВыполнитьСозданиеДокументов() Экспорт
// Здесь размещается логика создания документов
// ВАЖНО: Не используйте здесь Сообщить(), Вопрос() или Предупреждение()
ЗаписьЖурналаРегистрации("Обработка.СозданиеДокументов",
УровеньЖурналаРегистрации.Информация, , , "Запуск формирования документов");
// Тело вашей обработки...
КонецПроцедуры
Теперь, чтобы запустить эту логику из регламентного задания или из другого места в коде, нам достаточно создать экземпляр объекта обработки и вызвать этот метод:
ОбработкаОбъект = Обработки.ИмяВашейОбработки.Создать();
ОбработкаОбъект.ВыполнитьСозданиеДокументов();
Если ваша конфигурация построена на базе Библиотеки стандартных подсистем (БСП), наиболее правильным и современным способом будет регистрация обработки как «Дополнительной». Это позволит настраивать расписание прямо в пользовательском режиме, не внося изменений в конфигуратор для создания нового регламентного задания.
Для этого в модуле объекта необходимо реализовать стандартную функцию СведенияОВнешнейОбработке и экспортную процедуру ВыполнитьКоманду. Разберем пример реализации:
// В модуле объекта внешней обработки
Функция СведенияОВнешнейОбработке() Экспорт
ПараметрыРегистрации = ДополнительныеОтчетыИОбработки.СведенияОВнешнейОбработке("2.2.2.1");
ПараметрыРегистрации.Вид = ДополнительныеОтчетыИОбработкиКлиентСервер.ВидОбработкиДополнительнаяОбработка();
ПараметрыРегистрации.Наименование = "Автоматическое создание документов";
ПараметрыРегистрации.БезопасныйРежим = Ложь; // Если нужны права на запись документов
НоваяКоманда = ПараметрыРегистрации.Команды.Добавить();
НоваяКоманда.Представление = "Запустить создание документов";
НоваяКоманда.Идентификатор = "СоздатьДокументыПоРасписанию";
НоваяКоманда.Использование = ДополнительныеОтчетыИОбработкиКлиентСервер.ТипКомандыВызовСерверногоМетода();
Возврат ПараметрыРегистрации;
КонецФункции
Процедура ВыполнитьКоманду(ИдентификаторКоманды, ПараметрыВыполненияКоманды) Экспорт
Если ИдентификаторКоманды = "СоздатьДокументыПоРасписанию" Тогда
ВыполнитьСозданиеДокументов(); // Вызов нашей основной логики
КонецЕсли;
КонецПроцедуры
После того как вы загрузите такую обработку в справочник «Дополнительные отчеты и обработки», система позволит вам в карточке этой обработки нажать на ссылку «Настроить расписание». БСП сама создаст фоновое задание, которое будет вызывать вашу процедуру ВыполнитьКоманду в указанное время.
Проанализируем важные нюансы, которые могут привести к сбоям при выполнении кода без участия пользователя:
Вопрос(), Предупреждение() или ОткрытьФорму(). Код просто «упадет» с ошибкой. Для логирования используйте ЗаписьЖурналаРегистрации().Чтобы убедиться, что вы правильно перенесли код в модуль объекта, не дожидаясь срабатывания регламентного задания, вы можете изменить код кнопки в модуле формы. Теперь кнопка должна не сама выполнять работу, а обращаться к методу объекта:
&НаСервере
Процедура ВыполнитьНаСервере()
// Преобразуем данные формы (реквизит "Объект") в реальный объект обработки
ОбработкаОбъект = РеквизитФормыВЗначение("Объект");
// Вызываем экспортный метод модуля объекта
ОбработкаОбъект.ВыполнитьСозданиеДокументов();
// Если объект изменил свои реквизиты и их нужно вернуть на форму
ЗначениеВРеквизитФормы(ОбработкаОбъект, "Объект");
КонецПроцедуры
Таким образом, мы добиваемся единства кода: одна и та же процедура ВыполнитьСозданиеДокументов используется и при ручном запуске из формы, и при автоматическом запуске по расписанию. Это гарантирует идентичность результата и упрощает дальнейшую поддержку программы.