При переходе на управляемое приложение многие разработчики сталкиваются с ситуацией, когда привычный вызов процедур модуля объекта из формы перестает работать. В обычном приложении мы могли напрямую обратиться к методу через ЭтотОбъект.ИмяПроцедуры(), но в управляемых формах 1С 8.3 архитектура взаимодействия клиента и сервера изменилась. Давайте подробно разберем, почему возникает ошибка «Метод не обнаружен» и как правильно реализовать такой вызов. При необходимости можно воспользоваться руководством по управлению контекстом выполнения в управляемых формах для более глубокого понимания теории.
Проанализируем архитектуру управляемой формы. В контексте модуля формы основной реквизит Объект (например, документ или справочник) имеет тип ДанныеФормыСтруктура. Это «легковесная» копия объекта, которая содержит только данные, необходимые для отображения в интерфейсе. Она не является полноценным прикладным объектом и не имеет доступа к методам модуля объекта.
Важно понимать: модуль объекта живет только на сервере и доступен только для «настоящих» объектов (типа ДокументОбъект, СправочникОбъект и т.д.). Чтобы достучаться до его процедур, нам нужно выполнить преобразование данных формы в реальный объект базы данных.
Рассмотрим самый распространенный случай. У нас есть экспортная процедура в модуле объекта документа. Чтобы вызвать ее из формы, нам необходимо выполнить три условия:
Экспорт.&НаСервере).Разберем пример кода в модуле управляемой формы:
&НаКлиенте
Процедура ВыполнитьДействие(Команда)
// Вызываем серверную процедуру, так как конвертация возможна только там
ВыполнитьДействиеНаСервере();
КонецПроцедуры
&НаСервере
Процедура ВыполнитьДействиеНаСервере()
// 1. Преобразуем данные формы в полноценный объект
ДокОбъект = РеквизитФормыВЗначение("Объект");
// 2. Теперь нам доступны все экспортные методы модуля объекта
ДокОбъект.МояЭкспортнаяПроцедура();
// 3. Если процедура изменила данные объекта (например, заполнила ТЧ),
// необходимо вернуть изменения обратно в форму
ЗначениеВРеквизитФормы(ДокОбъект, "Объект");
КонецПроцедуры
Ситуация с внешними обработками часто вводит в заблуждение, так как у них нет модуля менеджера, а работа с типами имеет свои нюансы. Посмотрим на пример, как вызвать процедуру ЗаполнитьДанные из модуля объекта внешней обработки:
&НаСервере
Процедура ВызватьМетодОбработкиНаСервере()
// Для внешних обработок типизация происходит автоматически
ОбъектВЗначение = РеквизитФормыВЗначение("Объект");
ОбъектВЗначение.ЗаполнитьДанные();
// Возвращаем результат в реквизиты формы
ЗначениеВРеквизитФормы(ОбъектВЗначение, "Объект");
КонецПроцедуры
Если вы сталкиваетесь с ошибкой «Тип не определен» при работе с внешними объектами, попробуйте не указывать второй параметр в функции РеквизитФормыВЗначение или использовать экспресс-отладку дополнительных обработок (поможет отладчик кода 1С в режиме Предприятия), платформа 1С обычно сама корректно определяет тип реквизита Объект.
Для отчетов принцип остается тем же, однако важно правильно указать имя реквизита. В формах отчетов основной реквизит обычно называется Отчет, а не Объект.
&НаСервере
Процедура ВыполнитьЛогикуОтчета()
ОтчетОбъект = РеквизитФормыВЗначение("Отчет");
ОтчетОбъект.СформироватьСпецифическиеДанные();
ЗначениеВРеквизитФормы(ОтчетОбъект, "Отчет");
КонецПроцедуры
Проанализируем ситуацию: если ваша процедура не использует данные конкретного экземпляра (текущие значения реквизитов документа), а выполняет общую логику, то перенос ее в Модуль менеджера будет более правильным решением. При необходимости можно воспользоваться инструментом для автоматического анализа вызовов экспортных процедур, который поможет избежать ошибок при переносе кода.
Преимущества модуля менеджера:
РеквизитФормыВЗначение.Пример вызова из модуля менеджера (для быстрого нахождения таких мест используйте поиск вызовов в коде):
// В модуле менеджера документа
Процедура РассчитатьСкидку(СсылкаНаДокумент) Экспорт
// Логика расчета
КонецПроцедуры
// В модуле формы
&НаСервере
Процедура ВызовМенеджера()
Документы.РеализацияТоваровУслуг.РассчитатьСкидку(Объект.Ссылка);
КонецПроцедуры
Метод РеквизитФормыВЗначение является довольно ресурсоемким, так как он передает все данные формы на сервер и создает объект в памяти. Если вам нужно просто получить какой-то результат из модуля объекта, не меняя данные на форме, используйте &НаСервереБезКонтекста.
Однако помните, что внутри внеконтекстной процедуры реквизит Объект недоступен. Вам придется передать его как параметр:
&НаСервереБезКонтекста
Функция ПолучитьРасчетИзМодуляОбъекта(ДанныеОбъекта)
// ДанныеОбъекта здесь имеют тип ДанныеФормыСтруктура
МойОбъект = ДанныеФормыВЗначение(ДанныеОбъекта, Тип("ДокументОбъект.ИмяДокумента"));
Возврат МойОбъект.ВычислитьЗначение();
КонецФункции
1. Можно ли вызвать процедуру формы из модуля объекта?
Нет. Модуль объекта — это серверная сущность, она ничего не знает об интерфейсе (форме). Сервер не может инициировать вызов клиента. Единственный способ взаимодействия — это возврат значений из функций модуля объекта обратно в вызывающую процедуру формы.
2. Нужно ли использовать ЗначениеВРеквизитФормы, если я только читаю данные?
Нет. Если ваша экспортная процедура не меняет реквизиты объекта и не заполняет табличные части, использовать обратную конвертацию не нужно. Более того, вызов ЗначениеВРеквизитФормы всегда устанавливает флаг модифицированности формы (звездочку), и программа предложит сохранить изменения при закрытии, даже если их не было.
3. Директивы компиляции в модуле объекта.
Помните, что в модуле объекта директивы типа &НаСервере или &НаКлиенте не действуют. Весь код модуля объекта всегда исполняется на сервере.
Выяснив эти особенности, мы можем сделать вывод: для успешного вызова метода модуля объекта необходимо четко разделять контексты и использовать механизмы платформы для преобразования данных формы в прикладные объекты. Это обеспечит стабильную работу вашего кода в управляемом приложении.