Как вызвать команду формы из модуля объекта или регламентного задания в 1С?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

При разработке в среде 1С:Предприятие 8 начинающие программисты часто сталкиваются с необходимостью выполнить код, который уже написан и отлажен в модуле управляемой формы, но вызвать его нужно из модуля объекта или регламентного задания. На первый взгляд кажется удобным просто «нажать кнопку» программно, однако здесь мы упираемся в архитектурные ограничения платформы. Разберем подробно, почему прямой вызов невозможен и как правильно организовать архитектуру вашего решения.

Почему нельзя просто вызвать команду формы?

Проанализируем ситуацию: когда выполняется регламентное задание, оно запускается в отдельном сеансе на сервере. В этом сеансе отсутствует пользовательский интерфейс. Платформа просто не инициализирует формы, так как их некому показывать. Модуль управляемой формы и его команды существуют только тогда, когда у конкретного пользователя открыто окно в тонком или толстом клиенте.

Серверный код (включая модуль объекта и фоновые задания) ничего не знает о том, что происходит на стороне клиента. Рассмотрим основные причины ограничений:

  1. Разные сеансы: Регламентное задание выполняется в своем закрытом окружении.
  2. Отсутствие контекста: Даже если форма открыта у пользователя «Иван», регламентное задание, запущенное от имени «Администратор», не имеет доступа к оперативной памяти сеанса Ивана.
  3. Директивы компиляции: Команды формы обычно имеют директиву &НаКлиенте, а серверный код физически не может исполнять клиентские процедуры.

Правильное решение: Вынос бизнес-логики на сервер

Выясним причину, по которой код оказался в модуле формы. Чаще всего это происходит из-за удобства обращения к реквизитам формы. Однако правильный архитектурный подход по стандартам «1С» требует отделения логики манипуляции данными от интерфейса.

Рассмотрим по шагам, как перенести код для обеспечения его доступности отовсюду:

Шаг 1. Перенос кода в модуль объекта. Выделим алгоритм в отдельную экспортную процедуру в модуле объекта. Это позволит вызывать её и из формы, и из регламентного задания.


// В модуле объекта
Процедура ВыполнитьВажноеДействиеНаСервере() Экспорт
    // Здесь размещаем бизнес-логику, которая раньше была в команде формы
    ЭтотОбъект.Статус = Справочники.Статусы.Выполнено;
    ЭтотОбъект.Записать();
КонецПроцедуры

Шаг 2. Вызов из формы. Теперь в модуле формы мы просто вызываем эту серверную процедуру объекта.


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

Шаг 3. Вызов из регламентного задания. Теперь наше фоновое задание может легко выполнить ту же логику:


// В модуле объекта или общем модуле (регламентное задание)
Выборка = Документы.НашДокумент.Выбрать();
Пока Выборка.Следующий() Цикл
    ОбъектДокумент = Выборка.Ссылка.ПолучитьОбъект();
    ОбъектДокумент.ВыполнитьВажноеДействиеНаСервере();
КонецЦикла;

Использование Системы взаимодействия для оповещения клиента

Иногда задача стоит иначе: регламентное задание что-то сделало, и нужно, чтобы у пользователя в уже открытой форме обновились данные или сработал какой-то визуальный эффект. Рассмотрим, как это реализовать через «Систему взаимодействия».

Посмотрим на пример отправки сообщения с сервера:


// Код на сервере (регламентное задание)
ВыбранныйПользователь = ПользователиИнформационнойБазы.НайтиПоИмени("Иван");
ПараметрыСообщения = Новый Структура("Действие", "ОбновитьФорму");

СистемаВзаимодействия.ОтправитьСообщение(ТекстСообщения, ВыбранныйПользователь, ПараметрыСообщения);

На стороне клиента в модуле формы должен быть настроен обработчик, который при получении сообщения выполнит команду &НаКлиенте. Это единственный способ «дотянуться» с сервера до живого интерфейса пользователя в реальном времени.

Метод передачи формы как параметра

В обсуждениях часто упоминается возможность передачи формы в качестве параметра в серверные процедуры. Разберем этот нюанс. Это работает только в рамках одного сеанса. Если вы из формы вызываете серверную процедуру общего модуля, вы можете передать туда объект формы:


// В модуле формы
&НаКлиенте
Процедура ВыполнитьДействие()
    МойОбщийМодуль.ОбработатьФорму(ЭтаФорма);
КонецПроцедуры

// В общем модуле
Процедура ОбработатьФорму(ФормаОбъекта) Экспорт
    // Здесь мы можем обратиться к экспортным методам формы
    ФормаОбъекта.ОбновитьДанныеНаКлиенте(); 
КонецПроцедуры

Важно: Для этого процедура ОбновитьДанныеНаКлиенте в модуле формы должна быть помечена как Экспорт. Однако помните, что для регламентного задания этот метод бесполезен, так как никакой «ФормыОбъекта» в его сеансе не существует.

Альтернатива: Обработчик ожидания

Проанализируем ситуацию, когда Система взаимодействия не подключена. Мы можем использовать механизм опроса (polling). Форма будет периодически «спрашивать» базу данных: «Не сделало ли регламентное задание что-то важное для меня?».

Для этого используем метод ПодключитьОбработчикОжидания:

  1. В процедуре ПриОткрытии на клиенте подключаем обработчик (например, раз в 30 секунд).
  2. В обработчике проверяем статус документа или запись в специальном регистре сведений.
  3. Если условие выполнено — вызываем нужную команду формы.

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

← На главную