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