Как вызвать процедуру из модуля объекта в модуле управляемой формы 1С

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

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

Почему нельзя вызвать процедуру напрямую?

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

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

Базовый алгоритм вызова (для документов и справочников)

Рассмотрим самый распространенный случай. У нас есть экспортная процедура в модуле объекта документа. Чтобы вызвать ее из формы, нам необходимо выполнить три условия:

  1. Процедура в модуле объекта должна быть объявлена с ключевым словом Экспорт.
  2. Вызов должен происходить в серверном контексте модуля формы (директива &НаСервере).
  3. Необходимо выполнить программную конвертацию типов.

Разберем пример кода в модуле управляемой формы:


&НаКлиенте
Процедура ВыполнитьДействие(Команда)
    // Вызываем серверную процедуру, так как конвертация возможна только там
    ВыполнитьДействиеНаСервере();
КонецПроцедуры

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

Особенности работы с внешними обработками

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


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

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

Работа с отчетами

Для отчетов принцип остается тем же, однако важно правильно указать имя реквизита. В формах отчетов основной реквизит обычно называется Отчет, а не Объект.


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

Альтернативный подход: использование модуля менеджера

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

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

Пример вызова из модуля менеджера (для быстрого нахождения таких мест используйте поиск вызовов в коде):


// В модуле менеджера документа
Процедура РассчитатьСкидку(СсылкаНаДокумент) Экспорт
    // Логика расчета
КонецПроцедуры

// В модуле формы
&НаСервере
Процедура ВызовМенеджера()
    Документы.РеализацияТоваровУслуг.РассчитатьСкидку(Объект.Ссылка);
КонецПроцедуры

Оптимизация производительности: внеконтекстные вызовы

Метод РеквизитФормыВЗначение является довольно ресурсоемким, так как он передает все данные формы на сервер и создает объект в памяти. Если вам нужно просто получить какой-то результат из модуля объекта, не меняя данные на форме, используйте &НаСервереБезКонтекста.

Однако помните, что внутри внеконтекстной процедуры реквизит Объект недоступен. Вам придется передать его как параметр:


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

Типичные ошибки и вопросы

1. Можно ли вызвать процедуру формы из модуля объекта?
Нет. Модуль объекта — это серверная сущность, она ничего не знает об интерфейсе (форме). Сервер не может инициировать вызов клиента. Единственный способ взаимодействия — это возврат значений из функций модуля объекта обратно в вызывающую процедуру формы.

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

3. Директивы компиляции в модуле объекта.
Помните, что в модуле объекта директивы типа &НаСервере или &НаКлиенте не действуют. Весь код модуля объекта всегда исполняется на сервере.

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

← На главную