Как из модуля объекта получить доступ к элементам формы или ее реквизитам?

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

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

Метод 1. Получение формы через «ЭтотОбъект» (для обычных форм)

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


Форма = ЭтотОбъект.ПолучитьФорму("ОсновнаяФормаОтчета");
Если Форма.Открыта() Тогда
    ЗначениеПоля = Форма.ЭлементыФормы.ТекущиеДО.Значение;
    Форма.ЭлементыФормы.ТекущиеДО.Значение = "Новое значение";
КонецЕсли;

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

Метод 2. Передача формы как параметра процедуры

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

Рассмотрим пример реализации. В модуле объекта пишем:


Процедура ВыполнитьРасчетНаФорме(КонтекстФормы) Экспорт
    // Читаем данные из элементов формы
    ТекЗначение = КонтекстФормы.ЭлементыФормы.ИмяРеквизита.Значение;
    
    // Выполняем логику
    НовоеЗначение = ТекЗначение * 1.18;
    
    // Обновляем визуальный элемент
    КонтекстФормы.ЭлементыФормы.ИмяРеквизита.Значение = НовоеЗначение;
КонецПроцедуры

В модуле формы вызываем эту процедуру следующим образом:


Процедура КнопкаРассчитатьНажатие(Элемент)
    ЭтотОбъект.ВыполнитьРасчетНаФорме(ЭтаФорма);
КонецПроцедуры

Этот способ позволяет четко контролировать, с какой именно формой работает объект. Мы передаем ссылку ЭтаФорма, и объект получает полный доступ ко всем ее свойствам и элементам управления.

Метод 3. Использование реквизитов объекта как «моста» данных

Выясним причину, по которой многие разработчики стараются избегать прямого обращения к элементам формы. Главная проблема — это жесткая зависимость кода от интерфейса. Если завтра вы переименуете поле ТекущиеДО на форме, код в модуле объекта «сломается».

Правильнее всего связать элемент формы с реквизитом объекта. Разберем этот алгоритм по шагам:

  1. В дереве конфигурации добавляем новый реквизит в сам Объект (Документ, Отчет или Обработку).
  2. На форме у соответствующего элемента управления (например, поля ввода) в свойстве «Данные» указываем этот реквизит объекта.
  3. В модуле объекта мы теперь можем обращаться к этому значению просто по имени, как к любой переменной модуля: ИмяРеквизита = "Значение";.

Этот метод является стандартным для платформы «1С:Предприятие». Когда пользователь меняет что-то в поле на форме, значение автоматически попадает в реквизит объекта, и наоборот. Для реализации подобного механизма с динамическими данными подойдёт пример программного создания колонок и сохранения их значений в документе.

Метод 4. Особенности управляемого приложения (Сервер и Клиент)

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

Для взаимодействия в управляемом приложении используем механизм ДополнительныеСвойства. Это специальная структура, которая есть у каждого объекта и предназначена именно для передачи параметров «извне» в модуль объекта.

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


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

В модуле объекта анализируем переданные данные:


Процедура ВыполнитьДействие() Экспорт
    Если ДополнительныеСвойства.Свойство("ВажныйПараметрИнтерфейса") Тогда
        Параметр = ДополнительныеСвойства.ВажныйПараметрИнтерфейса;
        // Используем параметр в логике проведения или заполнения
    КонецЕсли;
КонецПроцедуры

Метод 5. Использование экспортных переменных модуля объекта

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

Перем МояФорма Экспорт;

В модуле формы, в обработчике ПередОткрытием, мы можем присвоить этой переменной ссылку на форму:


Процедура ПередОткрытием(Отказ, СтандартнаяОбработка)
    ЭтотОбъект.МояФорма = ЭтаФорма;
КонецПроцедуры

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

Резюме и рекомендации

Подводя итог, можно выстроить иерархию правильности решений:

Помните, что код модуля объекта должен быть максимально автономным. Представьте, что ваш объект будет записываться не пользователем через кнопку, а программно через COM-соединение или мобильное приложение. Если код внутри объекта будет требовать «наличия формы», такая интеграция просто не заработает.

← На главную