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