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

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

Как вызвать обработчик события формы в 1С

Как программно вызвать обработчик события формы в 1С: ПриОткрытии, ПриИзменении, команды. Примеры кода, типичные ошибки и проверка результата.

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

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

Как устроены обработчики событий формы

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

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

События делятся на события самой формы, события элементов формы (полей, таблиц, кнопок) и события реквизита объекта. У каждой группы свой набор параметров и свой контекст исполнения.

Вызов обработчика внутри модуля формы

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

Здесь важно помнить о параметрах. Если обработчик ПолеКонтрагентПриИзменении(Элемент) ожидает ссылку на элемент формы, при ручном вызове нужно передать либо реальный элемент (Элементы.Контрагент), либо Неопределено — но тогда внутри обработчика должна быть проверка, иначе код упадёт с ошибкой обращения к свойствам.

Также учитывайте директивы компиляции. Процедура с директивой &НаКлиенте не может вызвать процедуру &НаСервере напрямую без серверного вызова — точнее, вызов возможен, но он пойдёт через сервер, что накладно в циклах. А процедура &НаСервере вообще не видит клиентские методы.

bsl
&НаКлиенте
Процедура ОбновитьДанные(Команда)
	// Вручную вызываем обработчик изменения поля
	КонтрагентПриИзменении(Элементы.Контрагент);
КонецПроцедуры

Вызов обработчика из другой формы

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

Второй способ — механизм оповещений. Форма-источник вызывает Оповестить("ИмяСобытия", Параметры, Источник), а форма-приёмник обрабатывает это событие в обработчике ОбработкаОповещения(ИмяСобытия, Параметр, Источник). Это стандартный и самый безопасный путь, когда формы не знают друг о друге напрямую.

Третий вариант — ОписаниеОповещения. При открытии формы через ОткрытьФорму() можно передать описание оповещения, которое выполнится после закрытия формы. Так родительская форма получает результат и запускает нужный обработчик у себя.

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

Контекст клиента и сервера

Главный источник ошибок при ручном вызове обработчиков — несовпадение контекстов. Директивы &НаКлиенте, &НаСервере, &НаСервереБезКонтекста определяют, где выполняется код и что ему доступно. Клиентский обработчик не имеет доступа к запросам и объектным данным напрямую, а серверный без контекста — к данным формы.

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

Для вызова серверной процедуры из общего модуля используйте общие модули с флагом «Сервер» или «Вызов сервера». Из клиентского кода доступны только общие модули с установленным свойством «Вызов сервера».

Правильный приём: вынос логики в отдельную процедуру

Лучшая практика вместо ручного вызова обработчика — вынести его содержимое в отдельную процедуру с говорящим именем, а обработчик оставить тонкой обёрткой. Например, обработчик КонтрагентПриИзменении вызывает ЗаполнитьДанныеПоКонтрагенту(), и эту же процедуру можно вызвать из любого другого места без подделки параметров события.

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

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

Проверка результата и типичные ошибки

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

Частые ошибки: вызов клиентской процедуры из серверного контекста (ошибка компиляции или выполнения), передача Неопределено вместо Элемент без проверки внутри обработчика, обращение к закрытой форме извне, вызов обработчика до завершения создания формы. Ещё одна типичная проблема — рекурсия: обработчик изменения поля вызывает код, который снова меняет это поле и снова запускает обработчик.

Типичные ошибки
01
Вызов обработчика с фиктивными параметрами без проверки внутри — падение при обращении к свойствам Неопределено
02
Вызов клиентского метода из серверного контекста — ошибка компиляции или выполнения
03
Обращение к экспортному методу уже закрытой формы — исключение времени выполнения
04
Рекурсивный вызов: обработчик изменения поля изменяет то же поле и запускает сам себя
05
Повторный вызов ПриОткрытии или ПриСозданииНаСервере — дублирование инициализации
Контрольные точки

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

Данные на форме
Норма

Реквизиты и связанные поля обновились после вызова

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

Поля остались пустыми или содержат старые значения

Ошибки выполнения
Норма

Нет сообщений об ошибках, журнал регистрации чист

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

Исключения о недопустимом контексте или обращении к Неопределено

Поведение при повторном вызове
Норма

Результат идентичен первому вызову

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

Данные дублируются или форма ведёт себя непредсказуемо

FAQ

Можно ли вызвать обработчик ПриОткрытии повторно?

Технически можно — это обычная процедура, вызов ПриОткрытии(Ложь) сработает. Но делать так не рекомендуется: обработчик часто содержит одноразовую инициализацию. Правильнее вынести логику в отдельную процедуру и вызывать её и из обработчика, и из нужного места.

Как вызвать обработчик события элемента формы без параметра Элемент?

Передайте реальный элемент: Элементы.ИмяПоля. Если обработчик не использует параметр, можно передать Неопределено, но убедитесь, что внутри нет обращений к свойствам элемента. Лучший вариант — вынести логику в процедуру без параметров.

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

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

Почему серверная процедура не видна из клиентского обработчика?

Проверьте директивы компиляции. Процедура &НаСервере в модуле формы доступна из клиентского кода, но вызов идёт через сервер. Если процедура в общем модуле — у модуля должен быть установлен флаг «Вызов сервера», иначе клиент её не увидит.

Как избежать рекурсии при вызове обработчиков изменения?

Введите признак-флаг в реквизит формы или переменную модуля: перед программным изменением поля устанавливайте флаг, а в начале обработчика проверяйте его и выходите. После обработки сбрасывайте флаг. Это стандартный приём защиты от циклических вызовов.

Можно ли вызвать обработчик команды формы программно?

Да, обработчик команды — обычная процедура с параметром Команда. Вызовите её по имени, передав Команды.ИмяКоманды или Неопределено, если параметр не используется. Если нужно выполнить стандартную команду, используйте ВыполнитьКоманду() или методы работы со списком.

Итог

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

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