В процессе разработки в среде «1С:Предприятие» программисты часто сталкиваются с задачей автоматизации действий пользователя. Один из популярных сценариев — необходимость автоматически, по определенному расписанию, открыть перед пользователем форму внешней обработки (например, отчет по продажам за день, форму сверки данных или интерактивный помощник).
Однако при попытке реализовать это напрямую через стандартные регламентные задания разработчики упираются в жесткое архитектурное ограничение платформы: регламентные задания выполняются в фоновом режиме на сервере, где интерфейса (клиентского контекста) просто не существует. Сервер не может самостоятельно «вытолкнуть» форму на экран конкретного пользователя.
В этой статье мы подробно разберем, почему возникает эта проблема, и рассмотрим 5 проверенных практических способов обхода данного ограничения, которые успешно применяются в реальных проектах.
Давайте проанализируем архитектуру клиент-серверного взаимодействия в 1С. Любое регламентное задание запускается планировщиком платформы на стороне сервера 1С:Предприятия. Оно выполняется в изолированном фоновом сеансе, у которого:
ОткрытьФорму, Предупреждение или ПоказатьВопрос.Как справедливо заметили участники обсуждения на форуме, даже если бы платформа позволяла это сделать, возник бы логический тупик: на чей именно монитор выводить форму, если в системе одновременно работают сто пользователей? А что делать, если нужный пользователь вообще выключил компьютер или закрыл программу? Именно поэтому попытка открыть форму непосредственно из кода регламентного задания на сервере гарантированно приведет к ошибке выполнения.
Тем не менее решение этой задачи существует. Все обходные пути строятся на одном принципе: сервер должен оставить «сигнал» о необходимости открытия, а клиентское приложение должно этот сигнал считать и запустить форму на клиенте. Разобьем эти варианты по шагам.
Это классический, наиболее надежный и часто используемый архитектурный паттерн в 1С. Мы будем использовать промежуточное хранилище в базе данных — служебный регистр сведений.
Шаг 1. Создание вспомогательного регистра сведений
Создадим простой регистр сведений ОчередьОткрытияФорм (непериодический, независимый). В качестве измерений добавим:
Пользователь (Тип: СправочникСсылка.Пользователи) — указывает, кому именно нужно открыть форму.ИмяОбработки (Тип: Строка) — имя или путь к внешней обработке.Шаг 2. Запись сигнала на сервере (Регламентное задание)
Наше регламентное задание по своему расписанию выполняет необходимые проверки. Когда условия сошлись и нужно показать форму пользователю, серверный код делает запись в наш регистр:
НоваяЗапись = РегистрыСведений.ОчередьОткрытияФорм.СоздатьМенеджерЗаписи();
НоваяЗапись.Пользователь = НужныйПользователь;
НоваяЗапись.ИмяОбработки = "ВыгрузкаДанныхВБанк";
НоваяЗапись.Записать(Истина);
Шаг 3. Чтение сигнала на клиенте (Обработчик ожидания)
Теперь перейдем на сторону клиента. Нам нужно заставить клиентский сеанс пользователя периодически проверять этот регистр. Для этого используем метод ПодключитьОбработчикОжидания.
В модуле управляемого приложения в процедуре ПриНачалеРаботыСистемы пропишем подключение обработчика, который будет срабатывать, например, каждые 60 секунд:
Процедура ПриНачалеРаботыСистемы()
#Если Клиент Тогда
ПодключитьОбработчикОжидания("ПроверитьОчередьОткрытияФорм", 60);
#КонецЕсли
КонецПроцедуры
В глобальном клиентском общем модуле (например, КлиентскиеПроцедурыВсеобщегоВызова) опишем саму процедуру проверки. Обратите внимание: чтобы не перегружать СУБД постоянными тяжелыми запросами, проверка должна быть максимально быстрой и легкой.
Процедура ПроверитьОчередьОткрытияФорм() Экспорт
ТекущийПользовательСистемы = Пользователи.ТекущийПользователь();
// Вызываем серверную функцию для проверки наличия записи в регистре
ПараметрыОбработки = ПроверитьЗаписьВРегистреНаСервере(ТекущийПользовательСистемы);
Если ПараметрыОбработки <> Неопределено Тогда
// Обязательно сначала удаляем запись из регистра на сервере,
// чтобы избежать бесконечного зацикленного открытия формы!
УдалитьЗаписьИзОчередиНаСервере(ТекущийПользовательСистемы);
// Открываем форму внешней обработки
// (предполагается, что обработка предварительно сохранена в справочнике ДополнительныеОтчетыИОбработки)
ПараметрыФормы = Новый Структура;
ОткрытьФорму("ВнешняяОбработка." + ПараметрыОбработки.ИмяОбработки + ".Форма.Форма", ПараметрыФормы);
КонецЕсли;
КонецПроцедуры
Предыдущий способ имеет один существенный недостаток: форма открывается внезапно. Если пользователь в этот момент активно вводил многострочный документ или заполнял сложную таблицу, внезапно всплывшее окно обработки может перехватить фокус ввода, сбить пользователя или привести к потере не сохраненных им данных. Это считается плохим тоном в UI/UX разработке.
Более изящное решение — использование метода ПоказатьОповещениеПользователя. Схема взаимодействия с регистром сведений остается прежней, но меняется поведение на клиенте при обнаружении записи:
Процедура ПроверитьОчередьОткрытияФорм() Экспорт
ТекущийПользовательСистемы = Пользователи.ТекущийПользователь();
ПараметрыОбработки = ПроверитьЗаписьВРегистреНаСервере(ТекущийПользовательСистемы);
Если ПараметрыОбработки <> Неопределено Тогда
УдалитьЗаписьИзОчередиНаСервере(ТекущийПользовательСистемы);
// Описываем действие при нажатии на оповещение
ОписаниеОповещения = Новый ОписаниеОповещения("ВыполнитьОткрытиеФормыПослеКлика", ЭтотОбъект, ПараметрыОбработки);
// Выводим аккуратное всплывающее окошко в правом нижнем углу экрана
ПоказатьОповещениеПользователя(
"Требуется ваше внимание",
"Кликните здесь, чтобы запустить обработку выгрузки данных",
ОписаниеОповещения,
БиблиотекаКартинок.ВажнаяИнформация
);
КонецЕсли;
КонецПроцедуры
Процедура ВыполнитьОткрытиеФормыПослеКлика(ДополнительныеПараметры) Экспорт
ОткрытьФорму("ВнешняяОбработка." + ДополнительныеПараметры.ИмяОбработки + ".Форма.Форма");
КонецПроцедуры
Такой подход делает работу пользователя комфортной: программа ненавязчиво сообщает о необходимости запустить процесс, а пользователь открывает его тогда, когда завершит текущую операцию.
Если в вашей организации развернута и настроена Система взаимодействия (встроенный в 1С чат и механизм обмена сообщениями), вы можете отказаться от периодических запросов к базе данных (обработчиков ожидания), которые создают лишнюю паразитную нагрузку на сервер СУБД.
Система взаимодействия работает по протоколу WebSockets, поддерживая постоянное открытое соединение между клиентом и сервером. Это позволяет передавать сообщения мгновенно.
Алгоритм выглядит следующим образом:
Этот способ является наиболее прогрессивным и технологичным для современных версий платформы 1С v8.3.
Рассмотрим другую жизненную ситуацию: форму внешней обработки необходимо открыть строго по времени на конкретном компьютере, но при этом сама программа 1С в этот момент может быть вообще закрыта пользователем.
В этом случае механизмы внутри самой 1С нам не помогут, так как сеанс отсутствует. Решением станет интеграция со средствами операционной системы.
Шаг 1. Настройка планировщика ОС
Мы используем встроенный Планировщик задач Windows (Task Scheduler) на компьютере пользователя, настроив его запуск по требуемому расписанию.
Шаг 2. Создание исполняемого BAT-файла
Планировщик будет запускать специально подготовленный командный файл (например, start_1c_task.bat), содержащий инструкции для запуска платформы 1С под определенным пользователем и автоматического выполнения внешней обработки через ключ запуска /Execute:
"C:\Program Files\1cv8\8.3.22.1709\bin\1cv8.exe" ENTERPRISE /F "C:\1C_Bases\Accounting" /N "РоботРасписания" /P "StrongPassword123" /Execute "C:\ExternalProcessings\DailyReport.epf"
При таком запуске платформа 1С стартует, автоматически находит файл обработки по указанному пути и открывает его форму. Чтобы сеанс после выполнения обработки не висел в системе вечно тратя лицензию, в модуле самой обработки (в событии ПриОткрытии или после выполнения основного алгоритма) обязательно пропишите команду закрытия программы:
Процедура ПриОткрытии(Отказ)
// Выполняем полезную работу...
ВыгрузитьДанные();
// Завершаем работу сеанса 1С
ЗавершитьРаботуСистемы(Ложь);
КонецПроцедуры
Давайте зададимся важным вопросом: а действительно ли пользователю нужно видеть саму форму визуально? Очень часто форму хотят открыть только ради того, чтобы в ее модуле сработал какой-то код (например, нажалась виртуальная кнопка «Выполнить обмен»).
Если конфигурация вашей базы данных построена на основе БСП (Библиотеки стандартных подсистем), что справедливо для подавляющего большинства современных конфигураций (1С:ERP, Комплексная автоматизация, Управление торговлей, Бухгалтерия предприятия), то вы можете полностью автоматизировать этот процесс без открытия окон:
СведенияОВнешнейОбработке().ВызовСерверногоМетода (вместо ОткрытиеФормы).В этом случае вся тяжелая работа выполнится на сервере в фоновом режиме по расписанию, абсолютно незаметно для пользователей и без необходимости держать открытым клиентский сеанс.
Резюмируем: Прямого способа открыть форму на клиенте из регламентного задания в 1С не существует из-за особенностей клиент-серверной архитектуры. Однако, используя связку из регистров сведений и обработчиков ожидания, интерактивные оповещения, Систему взаимодействия или внешние BAT-файлы, вы легко решите эту задачу наиболее оптимальным для вашей системы способом.