Где и как подключить свою процедуру к событию формы, объекта или всей программы в 1С 8.3
Содержание
Чтобы добавить обработчик события в 1С, откройте объект в Конфигураторе, выделите форму или её элемент, в палитре свойств найдите группу «События» и нажмите кнопку с лупой рядом с нужным событием. Платформа сама создаст процедуру в модуле формы и свяжет её с событием. Для событий документа или справочника процедуру пишут в модуле объекта, а для реакции сразу на много объектов — создают подписку на события.
Место для кода выбирают по тому, где должна срабатывать логика. Реакция интерфейса — в модуле формы. Правило для данных, которое должно работать при любой записи, — в модуле объекта или в подписке. Действия при входе в программу — в модуле управляемого приложения. В типовых конфигурациях всё это лучше делать через расширение.
Как устроена событийная модель 1С
Платформа сама вызывает процедуры с заранее известными именами или процедуры, которые вы явно привязали к событию. Отсюда два способа связи:
- 🔗 По привязке — в свойствах формы или элемента указано имя процедуры. Так работают все события форм, элементов и команд. Имя может быть любым.
- 📛 По имени — процедура в модуле называется ровно как событие:
ПередЗаписью,ОбработкаПроведения,ПриНачалеРаботыСистемы. Так работают модули объектов, менеджеров, приложения и сеанса. - 📣 Через подписку — объект метаданных «Подписка на событие» связывает событие многих объектов с одной экспортной процедурой общего модуля.
Второе, что надо держать в голове, — где выполняется код. Форма живёт на клиенте, а данные базы доступны только на сервере. Поэтому у процедур формы есть директивы компиляции:
| Директива | Где выполняется | Доступ к данным формы | Когда брать |
|---|---|---|---|
&НаКлиенте | клиент | да | реакция интерфейса, вопросы пользователю |
&НаСервере | сервер | да, форма передаётся на сервер | запросы к базе с использованием реквизитов формы |
&НаСервереБезКонтекста | сервер | нет | быстрый серверный вызов, данные передаются параметрами |
Модули объектов, менеджеров и серверные общие модули исполняются на сервере, директивы там не нужны.
Если серверной процедуре нужны два-три значения с формы, выбирайте &НаСервереБезКонтекста и передавайте их параметрами. Вызов без контекста не гоняет всю форму между клиентом и сервером и заметно быстрее на медленных каналах.
Обработчик события формы: создаём через палитру свойств
События самой формы — открытие, создание, закрытие, запись, оповещения — подключаются так:
- В дереве конфигурации раскройте объект, ветку «Формы» и откройте нужную форму двойным щелчком.
- В верхнем левом дереве элементов выделите корневой элемент «Форма».
- Откройте палитру свойств (
Alt+Enterили правая кнопка → «Свойства»). - Пролистайте до группы «События».
- Щёлкните по строке события, например
ПриОткрытии, и нажмите кнопку с лупой справа. - Для событий, у которых есть выбор, платформа спросит, где создать обработчик: на клиенте, на клиенте с серверной процедурой или на клиенте с серверной процедурой без контекста. Выберите вариант по таблице выше.
Конфигуратор добавит в модуль формы процедуру с правильными параметрами и откроет её. Имя по умолчанию совпадает с событием, а в свойстве появится ссылка на неё.
Самые ходовые события формы:
| Событие | Где | Для чего |
|---|---|---|
ПриСозданииНаСервере(Отказ, СтандартнаяОбработка) | сервер | установить начальные значения, скрыть элементы по правам |
ПриОткрытии(Отказ) | клиент | действия после показа формы |
ПриЧтенииНаСервере(ТекущийОбъект) | сервер | дочитать данные при открытии существующего объекта |
ПередЗаписьюНаСервере(Отказ, ТекущийОбъект, ПараметрыЗаписи) | сервер | перенести данные формы в объект перед записью |
ПослеЗаписи(ПараметрыЗаписи) | клиент | оповестить другие формы, обновить интерфейс |
ОбработкаОповещения(ИмяСобытия, Параметр, Источник) | клиент | реагировать на Оповестить() из других форм |
ПередЗакрытием(...) | клиент | предупредить о несохранённых данных |
Пример: при создании нового документа подставляем текущего пользователя в реквизит «Ответственный».
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
Если Объект.Ссылка.Пустая() Тогда
Объект.Ответственный = Пользователи.ТекущийПользователь();
КонецЕсли;
КонецПроцедуры
Пользователи.ТекущийПользователь() есть в конфигурациях на БСП (БП 3.0, ЗУП 3.1, УТ 11). В самописной конфигурации без БСП берите ПользователиИнформационнойБазы.ТекущийПользователь() и ищите элемент справочника сами.
События реквизитов и элементов формы
У каждого поля, таблицы и кнопки на форме свой набор событий. Порядок тот же: выделите элемент в дереве элементов, откройте свойства, группа «События», кнопка с лупой.
Поле ввода: ПриИзменении и НачалоВыбора
Чаще всего пересчитывают что-то при смене значения. Обработчик поля «Контрагент» получит имя КонтрагентПриИзменении:
&НаКлиенте
Процедура КонтрагентПриИзменении(Элемент)
КонтрагентПриИзмененииНаСервере();
КонецПроцедуры
&НаСервере
Процедура КонтрагентПриИзмененииНаСервере()
Объект.Договор = Справочники.ДоговорыКонтрагентов.ПустаяСсылка();
КонецПроцедуры
Событие НачалоВыбора(Элемент, ДанныеВыбора, СтандартнаяОбработка) срабатывает при нажатии кнопки выбора. Поставьте СтандартнаяОбработка = Ложь, и стандартная форма выбора не откроется — можно показать свой список.
Колонка табличной части
Обработчики колонок называются по схеме «ИмяТаблицыИмяКолонкиСобытие». Текущую строку берите через ТекущиеДанные:
&НаКлиенте
Процедура ТоварыКоличествоПриИзменении(Элемент)
СтрокаТЧ = Элементы.Товары.ТекущиеДанные;
Если СтрокаТЧ = Неопределено Тогда
Возврат;
КонецЕсли;
СтрокаТЧ.Сумма = СтрокаТЧ.Количество * СтрокаТЧ.Цена;
КонецПроцедуры
У самой таблицы формы есть свои события: ПриАктивизацииСтроки, ПередНачаломДобавления, ПередУдалением, ПриОкончанииРедактирования, Выбор.
Подключение из кода
Иногда элемент создают программно — тогда событие привязывают методом УстановитьДействие:
&НаСервере
Процедура ДобавитьПолеКомментарий()
Поле = Элементы.Добавить("ПолеКомментарий", Тип("ПолеФормы"), Элементы.ГруппаШапка);
Поле.Вид = ВидПоляФормы.ПолеВвода;
Поле.ПутьКДанным = "Объект.Комментарий";
Поле.УстановитьДействие("ПриИзменении", "ПолеКомментарийПриИзменении");
КонецПроцедуры
Процедура ПолеКомментарийПриИзменении должна уже существовать в модуле формы с директивой &НаКлиенте.
Обработчики команд формы
Кнопка на форме — это обычно команда:
- В редакторе формы откройте вкладку «Команды» (верхняя правая панель), подвкладку «Команды формы».
- Добавьте команду кнопкой «Добавить», задайте имя, например
ЗаполнитьЦены. - В свойстве «Действие» нажмите лупу — создастся процедура
ЗаполнитьЦены(Команда). - Перетащите команду мышью в дерево элементов формы — появится кнопка.
Если кнопка есть, а при нажатии ничего не происходит, первым делом проверьте свойство «Действие» у команды: оно не должно быть пустым.
Обработчики в модуле объекта: документы и справочники
Логика, которая должна срабатывать при любой записи — из формы, из обработки, из обмена, — пишется не в форме, а в модуле объекта. Форма открыта не всегда, модуль объекта работает всегда.
Как открыть модуль : двойной щелчок по документу или справочнику в дереве конфигурации → вкладка «Прочее» → кнопка «Модуль объекта». Или правая кнопка по объекту в дереве → «Открыть модуль объекта».
Обработчики пишутся вручную по имени события, с точной сигнатурой:
| Событие | Объекты | Назначение |
|---|---|---|
ОбработкаЗаполнения(ДанныеЗаполнения, ТекстЗаполнения, СтандартнаяОбработка) | все | заполнение нового и ввод на основании |
ОбработкаПроверкиЗаполнения(Отказ, ПроверяемыеРеквизиты) | все | своя проверка обязательных полей |
ПередЗаписью(Отказ, РежимЗаписи, РежимПроведения) | документы | проверки и доработка данных до записи |
ПередЗаписью(Отказ) | справочники, планы видов характеристик | то же для справочника |
ПриЗаписи(Отказ) | все | действия в той же транзакции после записи |
ОбработкаПроведения(Отказ, РежимПроведения) | документы | формирование движений |
ОбработкаУдаленияПроведения(Отказ) | документы | действия при отмене проведения |
ПриКопировании(ОбъектКопирования) | все | очистить поля, которые не должны копироваться |
ПередУдалением(Отказ) | все | запрет удаления по условию |
Пример: запрещаем записывать поступление без номера входящего документа, кроме загрузки из обмена.
Процедура ПередЗаписью(Отказ, РежимЗаписи, РежимПроведения)
Если ОбменДанными.Загрузка Тогда
Возврат;
КонецЕсли;
Если РежимЗаписи = РежимЗаписиДокумента.Проведение
И ПустаяСтрока(НомерВходящегоДокумента) Тогда
ОбщегоНазначения.СообщитьПользователю("Не указан номер входящего документа", ЭтотОбъект, "НомерВходящегоДокумента", , Отказ);
КонецЕсли;
КонецПроцедуры
Проверка ОбменДанными.Загрузка в начале обработчика — привычка опытных разработчиков. При загрузке из обмена объект приходит уже готовым, и ваши проверки там только мешают.
ОбщегоНазначения.СообщитьПользователю — процедура БСП. Без БСП создайте Новый СообщениеПользователю, заполните Текст и вызовите Сообщить(), а Отказ = Истина установите отдельной строкой.
Подписки на события и общие модули
Подписка нужна, когда одно и то же действие должно происходить у многих объектов: записать историю изменений у всех справочников, проверить дату запрета у всех документов.
Шаг 1. Общий модуль
- В дереве конфигурации:
Общие → Общие модули→ «Добавить». - Имя, например
ПодпискиНаСобытияСклад. - В свойствах поставьте флажок «Сервер». Флажки «Клиент» и «Вызов сервера» не нужны.
- Напишите экспортную процедуру. Первый параметр —
Источник(сам объект), дальше — параметры события:
Процедура ПроверитьСкладПередЗаписью(Источник, Отказ, РежимЗаписи, РежимПроведения) Экспорт
Если Источник.ОбменДанными.Загрузка Тогда
Возврат;
КонецЕсли;
Если Не ЗначениеЗаполнено(Источник.Склад) Тогда
Отказ = Истина;
Сообщение = Новый СообщениеПользователю;
Сообщение.Текст = "Не заполнен склад";
Сообщение.Сообщить();
КонецЕсли;
КонецПроцедуры
Шаг 2. Подписка
Общие → Подписки на события→ «Добавить».- В свойстве «Источник» отметьте типы объектов, например
ДокументОбъект.ПоступлениеТоваровУслугиДокументОбъект.РеализацияТоваровУслуг. Обратите внимание: тип именно...Объект, а не ссылка. - В свойстве «Событие» выберите
ПередЗаписью. - В свойстве «Обработчик» выберите процедуру из общего модуля.
Порядок вызова нескольких подписок на одно событие платформа не гарантирует. Если одна подписка зависит от результата другой, объедините их в одну процедуру.
Модули приложения и сеанса — глобальные события
События уровня всей программы находятся в модулях конфигурации. Откройте их через правую кнопку по корню дерева конфигурации:
- 🖥 Модуль управляемого приложения — клиентские события
ПередНачаломРаботыСистемы(Отказ),ПриНачалеРаботыСистемы(),ПередЗавершениемРаботыСистемы(Отказ, ТекстПредупреждения),ПриЗавершенииРаботыСистемы(). - 🔐 Модуль сеанса — серверное событие
УстановкаПараметровСеанса(ТребуемыеПараметры): здесь заполняют параметры сеанса. - 🔌 Модуль внешнего соединения — те же события начала и завершения, но для COM-подключений.
Для периодических действий на клиенте есть обработчик ожидания. Его подключают из кода, процедура должна быть в модуле формы или в клиентском общем модуле:
&НаКлиенте
Процедура ПриОткрытии(Отказ)
ПодключитьОбработчикОжидания("ОбновитьСтатус", 60);
КонецПроцедуры
&НаКлиенте
Процедура ОбновитьСтатус() Экспорт
// обновление раз в 60 секунд
КонецПроцедуры
Отключают его через ОтключитьОбработчикОжидания("ОбновитьСтатус"). Третий параметр Истина в ПодключитьОбработчикОжидания делает вызов однократным.
Как добавить обработчик в типовую конфигурацию через расширение
В БП 3.0, ЗУП 3.1, УТ 11 правка основной конфигурации снимает её с полной поддержки и усложняет обновления. Добавлять обработчики в типовые лучше расширением (механизм появился в 8.3.6).
Конфигурация → Расширения конфигурации→ «Добавить».- В дереве основной конфигурации найдите объект, правая кнопка → «Добавить в расширение».
- Для формы: добавьте форму в расширение, откройте её там, выделите элемент, в событии нажмите лупу. Конфигуратор спросит, как вызывать вашу процедуру относительно типовой: перед ней, после неё или вместо неё.
- Для модуля объекта: откройте модуль объекта в расширении и пометьте процедуру аннотацией.
&После("ПередЗаписью")
Процедура Расш1_ПередЗаписью(Отказ, РежимЗаписи, РежимПроведения)
// ваш код выполняется после типового обработчика
КонецПроцедуры
Доступные аннотации: &Перед, &После, &Вместо. С платформы 8.3.11 добавлена &ИзменениеИКонтроль — она позволяет поменять кусок типовой процедуры и предупредит, если после обновления типовой код изменится.
Префикс в имени процедур расширения (здесь Расш1_) задаётся в свойствах расширения. Он защищает от конфликта имён с типовыми процедурами.
После загрузки или правки расширения выполните «Обновить конфигурацию базы данных» в окне расширений, затем перезапустите сеанс пользователя.
Отладка обработчиков и частые ошибки
Проверить, вызывается ли обработчик, проще всего точкой останова:
- Поставьте курсор на первую строку процедуры, нажмите
F9. - Запустите отладку
F5. - Выполните действие, которое должно вызвать событие.
Если отладчик не останавливается на серверном коде в клиент-серверной базе, проверьте, включена ли отладка на сервере 1С и подключён ли отладчик к серверным предметам отладки: меню Отладка → Подключение.
Ещё две ошибки, которые не видны сразу:
- 🐢 Тяжёлый код в клиентском обработчике. Запросы к базе внутри цикла по строкам на клиенте дают десятки серверных вызовов. Соберите данные и сделайте один вызов на сервер.
- 🔁 Логика только в форме. Проверка в
ПередЗаписьюНаСервереформы не сработает, если документ записывает обработка или обмен. Обязательные проверки держите в модуле объекта.