Как передать контекст управляемой формы на сервер и вызвать логику формы программно

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

В процессе разработки на платформе 1С:Предприятие 8.3 программисты часто сталкиваются с ситуацией, когда необходимая бизнес-логика (например, расчет налогов, заполнение строк документа или пересчет итогов) реализована непосредственно в модуле управляемой формы. Это создает серьезные препятствия при попытке программного создания объектов или выполнения задач в фоновом режиме, так как форма является клиентской сущностью. Разберем подробно, почему возникает эта проблема и какими методами ее можно решить.

Природа управляемой формы и контекстная передача

Прежде всего, проанализируем, почему нельзя просто вызвать ПолучитьФорму() на сервере и передать ее в общий модуль. Управляемая форма в 1С существует в двух ипостасях: на клиенте (как визуальный объект) и на сервере (как временная структура данных в памяти сеанса). Когда мы вызываем процедуру с директивой &НаСервере, платформа выполняет сериализацию: она берет данные из реквизитов формы, упаковывает их в специальный транспортный формат и передает на сервер. Там создается объект типа ДанныеФормыСтруктура, который имитирует состав реквизитов формы.

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

Решение 1. Использование «структуры-заглушки» (Mock-объекта)

Многие типовые процедуры в общих модулях (особенно в конфигурациях ЗУП или ERP) принимают в качестве параметра ПараметрыДействия или ДанныеФормы. Выясним причину: это сделано для того, чтобы код мог работать с данными, которые еще не записаны в базу. Если нам нужно вызвать такой метод программно, мы можем эмулировать форму с помощью обычной структуры.

Рассмотрим пример создания структуры, которая будет «прикидываться» данными формы для серверного метода:


// Создаем структуру, повторяющую состав реквизитов формы
ДанныеЭмуляции = Новый Структура;
ДанныеЭмуляции.Вставить("Дата", ТекущаяДата());
ДанныеЭмуляции.Вставить("Организация", СсылкаНаОрганизацию);
ДанныеЭмуляции.Вставить("Сотрудник", СсылкаНаСотрудника);

// Если в форме есть табличная часть, эмулируем ее массивом структур
ТЧ_Состав = Новый Массив;
СтрокаТЧ = Новый Структура("Номенклатура, Количество", СсылкаТовар, 10);
ТЧ_Состав.Добавить(СтрокаТЧ);
ДанныеЭмуляции.Вставить("Товары", ТЧ_Состав);

// Передаем эмуляцию в типовой метод
ОбщийМодульРасчета.РассчитатьПоказатели(ДанныеЭмуляции);

Важный нюанс: тип ДанныеФормыСтруктура поддерживает метод Свойство(), как и обычная структура. Однако, если внутри типового кода используются специфические методы платформы (например, ПроверитьЗаполнение()), этот метод выдаст ошибку, так как у структуры его нет. В таких случаях придется «подсматривать» в код и обходить проблемные места.

Решение 2. Преобразование данных формы в объект и обратно

Если нам все же удалось получить доступ к контексту формы (например, через расширение), самым правильным способом работы с бизнес-логикой на сервере будет преобразование данных формы в реальный прикладной объект. Для этого используются методы РеквизитФормыВЗначение и ЗначениеВДанныеФормы.

Посмотрим на алгоритм действий внутри серверного модуля формы:


&НаСервере
Процедура ВыполнитьРасчетНаСервере()
    // 1. Превращаем данные формы в полноценный объект документа
    ДокОбъект = РеквизитФормыВЗначение("Объект");
    
    // 2. Теперь нам доступны все экспортные методы модуля объекта
    ДокОбъект.РассчитатьЦеныИСуммы();
    
    // 3. Возвращаем изменения обратно в контекст формы, чтобы пользователь их увидел
    ЗначениеВДанныеФормы(ДокОбъект, Объект);
КонецПроцедуры

Этот подход позволяет использовать всю мощь объектной модели 1С, не ограничиваясь интерфейсными данными. Однако он работает только тогда, когда вызов инициирован из самой формы.

Решение 3. Вынос логики в модуль менеджера или общий модуль

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

Правильный алгоритм рефакторинга выглядит так:

  1. Проанализируем код в форме и выделим те части, которые не обращаются к элементам управления (Элементы.ИмяКнопки.Доступность и т.д.).
  2. Перенесем этот код в Модуль менеджера соответствующего объекта или в Общий модуль с установленным флагом «Сервер».
  3. В качестве параметров метода будем передавать либо ДокументОбъект, либо Структуру.
  4. В модуле формы заменим старый код вызовом этого нового метода.

Пример универсального метода в модуле менеджера:


// В модуле менеджера документа
Процедура ЗаполнитьДокументПоДанным(ОбъектДанных, ДополнительныеПараметры) Экспорт
    // ОбъектДанных может быть как ДокументОбъект, так и Структура
    ОбъектДанных.Дата = ТекущаяДата();
    // Логика заполнения...
КонецПроцедуры

Решение 4. Использование расширений для «раскрытия» контекста

Если вы работаете с типовой конфигурацией и не можете менять код оригинальной формы, воспользуйтесь расширениями. Рассмотрим, как сделать процедуру формы доступной извне. Для этого в расширении нужно добавить процедуру с аннотацией &НаСервере и сделать ее Экспортной.

Хотя форма все еще требует клиентского запуска для инициализации, экспортные процедуры позволяют «подключиться» к контексту, если форма уже открыта. Однако для фоновых заданий этот метод не подходит. В фоновых заданиях единственным выходом остается полное дублирование логики или (что предпочтительнее) вызов тех же серверных процедур общих модулей, которые использует форма, передавая им подготовленные данные в виде структур или объектов.

Подведение итогов

Подведем итог нашему анализу. Невозможность прямой передачи формы на сервер как объекта — это не недоработка платформы, а следствие архитектуры клиент-серверного взаимодействия. Для эффективного решения задачи программного создания документов «как в форме», мы должны:

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

← На главную