К статье
Практический материал

Разработка и Конфигурация · 10 мин

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

Как вызвать процедуру из модуля формы в 1С: директивы компиляции, обращение из других модулей, ЭтаФорма, типичные ошибки и проверка результата.

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

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

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

Как устроен модуль формы и почему это важно

Модуль формы компилируется в двух контекстах: на клиенте и на сервере. Директивы компиляции &НаКлиенте, &НаСервере, &НаСервереБезКонтекста определяют, где будет выполняться код. Процедура, помеченная &НаКлиенте, недоступна из серверного кода и наоборот — это первое, что нужно проверять при ошибке «Процедура или функция с указанным именем не определена».

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

Вызов процедуры внутри самой формы

Самый простой сценарий — вызов из одной процедуры формы другой процедуры той же формы. Достаточно указать имя и передать параметры:

&НаКлиенте

Процедура КомандаРассчитать(Команда)

РассчитатьИтог(Объект.Сумма);

КонецПроцедуры

&НаКлиенте

Процедура РассчитатьИтог(Сумма)

Сообщить("Итог: " + Сумма);

КонецПроцедуры

Здесь обе процедуры клиентские, поэтому вызов проходит напрямую. Если вызываемая процедура серверная, а вызывающая — клиентская, платформа автоматически выполнит серверный вызов, но это накладная операция: каждый такой переход «клиент → сервер» замедляет работу формы. По возможности группируйте серверные действия в одну процедуру и вызывайте её один раз.

Обратить внимание стоит и на &НаСервереБезКонтекста: такие процедуры не имеют доступа к данным формы (реквизитам, элементам), зато выполняются быстрее, потому что не сериализуют весь объект формы. Если процедуре нужны только переданные параметры — выбирайте именно этот вариант.

Вызов процедуры формы из другой формы

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

  • ЭтаФорма.ВладелецФормы — если форма открыта как подчинённая;
  • параметр, переданный при открытии формы;
  • результат функции ПолучитьФорму() — если форма ещё не открыта или нужен новый экземпляр.

Пример вызова из подчинённой формы процедуры формы-владельца:

&НаКлиенте

Процедура ПередатьДанные(Команда)

ФормаВладелец = ЭтаФорма.ВладелецФормы;

ФормаВладелец.ОбработатьВыбор(ВыбранноеЗначение);

КонецПроцедуры

В модуле формы-владельца процедура ОбработатьВыбор обязательно должна быть объявлена с Экспорт. Без этого слова вызов завершится ошибкой «Метод объекта не обнаружен», хотя процедура в модуле существует.

Как вызвать процедуру другой формы
  1. 1
    В модуле целевой формы объявите процедуру с ключевым словом Экспорт
  2. 2
    Проверьте, что директива компиляции совместима с местом вызова (клиент/сервер)
  3. 3
    В вызывающей форме получите объект формы: ВладелецФормы, параметр или ПолучитьФорму()
  4. 4
    Вызовите процедуру через точку: ОбъектФормы.ИмяПроцедуры(Параметры)
  5. 5
    Проверьте выполнение: поставьте точку останова или выведите сообщение внутри вызываемой процедуры

Вызов через ПолучитьФорму и из внешнего кода

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

&НаКлиенте

Процедура ОткрытьИЗаполнить(Команда)

Форма = ПолучитьФорму("Документ.Заказ.Форма.ФормаДокумента");

Форма.УстановитьПараметрыЗаполнения(Контрагент);

Форма.Открыть();

КонецПроцедуры

Из общего модуля или модуля объекта напрямую обратиться к форме нельзя — у серверного кода нет доступа к клиентским формам. Если бизнес-логика нужна и в форме, и вне её, правильное решение — вынести её в общий модуль или модуль менеджера объекта, а из формы лишь вызывать этот общий код. Дублирование логики между формой и объектом — частый источник расхождений в поведении программы.

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

Если формы слабо связаны между собой или заранее неизвестно, какая форма открыта, вместо прямого вызова используйте Оповестить() и обработчик ОбработкаОповещения. Отправляющая сторона вызывает:

Оповестить("ОбновитьСписокТоваров", ПараметрыДанных, ЭтаФорма);

Принимающая форма объявляет обработчик:

&НаКлиенте

Процедура ОбработкаОповещения(ИмяСобытия, Параметр, Источник)

Если ИмяСобытия = "ОбновитьСписокТоваров" Тогда

ОбновитьДанные(Параметр);

КонецЕсли;

КонецПроцедуры

Такой подход не требует экспорта процедур и не ломается, если форма-получатель закрыта — оповещение просто никто не обработает. Минус: связь между формами становится неявной, её сложнее отследить при отладке, поэтому имена событий стоит делать осмысленными и уникальными.

Способы вызова между формами

Прямой вызов через объект формы

Подходит для жёстко связанных форм (владелец — подчинённая). Требует Экспорт и гарантии, что форма открыта.

Оповестить + ОбработкаОповещения

Подходит для слабосвязанных форм и широковещательных событий. Не требует Экспорт, но усложняет отладку.

Вынос логики в общий модуль

Подходит, когда код нужен и форме, и другим объектам. Самый надёжный вариант для переиспользуемой логики.

Типичные ошибки и их диагностика

Большинство проблем при вызове процедур формы сводится к нескольким повторяющимся ситуациям:

Типичные ошибки
01
Ошибка «Процедура не определена» — чаще всего отсутствует слово Экспорт или несовпадение директив компиляции (вызов серверной процедуры из клиентской без учёта контекста)
02
Ошибка «Метод объекта не обнаружен» при вызове через ПолучитьФорму — процедура объявлена без Экспорт либо опечатка в имени
03
Обращение к закрытой форме — объект формы получен раньше, форма уже закрыта, вызов приводит к исключению
04
Вызов клиентской процедуры из серверного контекста — платформа не может выполнить такой переход, код падает или не компилируется
05
Изменение данных формы в процедуре &НаСервереБезКонтекста — реквизиты формы там недоступны, изменения «теряются»

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

Контрольные точки

Как проверить результат

Компиляция модуля формы
Норма

Конфигуратор не выдаёт ошибок при проверке модуля

Тревожный признак

Сообщение «Процедура или функция с указанным именем не определена»

Фактический вызов
Норма

Точка останова в вызываемой процедуре срабатывает

Тревожный признак

Отладчик не входит в процедуру — объект формы не получен или имя неверно

Изменение данных
Норма

Реквизиты формы обновились и отобразились на экране

Тревожный признак

Код выполнился, но на форме ничего не изменилось — вероятно, изменения сделаны в другом контексте

FAQ

Можно ли вызвать процедуру формы из общего модуля?

Напрямую — нет: общий модуль выполняется на сервере и не имеет доступа к клиентским формам. Правильный путь — вынести нужную логику в сам общий модуль и вызывать её из формы, а не наоборот. Если нужно уведомить открытые формы, серверный код может вернуть результат клиенту, а клиентская процедура — вызвать Оповестить.

Чем отличается &НаСервере от &НаСервереБезКонтекста?

Контекстная серверная процедура (&НаСервере) имеет доступ к реквизитам и элементам формы, но требует передачи всего состояния формы на сервер. Процедура без контекста работает быстрее, но видит только переданные параметры — данные формы в ней нужно получать отдельно через РеквизитФормыВЗначение.

Почему вызов через ВладелецФормы выдаёт ошибку?

Чаще всего две причины: форма открыта не как подчинённая (тогда ВладелецФормы равен Неопределено) или вызываемая процедура объявлена без Экспорт. Проверьте способ открытия формы и добавьте Экспорт в объявление процедуры.

Как вызвать процедуру формы после закрытия другой формы?

Используйте ОписаниеОповещения: при открытии формы через ОткрытьФорму укажите описание оповещения с именем экспортной клиентской процедуры текущей формы. После закрытия открытой формы платформа сама вызовет указанную процедуру и передаст результат закрытия.

Нужно ли слово Экспорт для обработчиков событий формы?

Нет. Обработчики событий (ПриОткрытии, ПередЗаписью и т.п.) и обработчики команд вызываются платформой внутри модуля формы, поэтому Экспорт им не требуется. Экспорт нужен только для процедур, которые вызываются извне — из других форм или через объект формы.

Можно ли вызвать процедуру формы другого пользователя?

Нет, форма существует только в сеансе пользователя, который её открыл. Для обмена данными между сеансами используются другие механизмы: запись в базу данных, регистры сведений, фоновые задания или система взаимодействия.

Итог

Что важно запомнить

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