Почему не срабатывает событие ПриИзменении при использовании кнопки выбора из списка в 1С (ОФ)?

Программист 1С v8.3 (Обычные формы) 1С:Зарплата и Управление Персоналом Управленческий учет Промышленность, строительство и АПК
← На главную

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

Разбор причин поведения платформы

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

Событие ПриИзменении в элементе управления ПолеВвода генерируется платформой в двух случаях:

  1. Пользователь ввел данные вручную с клавиатуры (включая Ctrl+V) и завершил ввод нажатием клавиши Enter или переходом на другой элемент.
  2. Значение было изменено через стандартные интерактивные механизмы, где СтандартнаяОбработка не была принудительно отключена.

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

Как правильно организовать логику пересчета

Чтобы ваша логика (пересчет табличных полей, изменение заголовков, обновление сумм) срабатывала при любом способе выбора значения, рекомендуем следовать принципу инкапсуляции. Вместо того чтобы полагаться на автоматический вызов ПриИзменении, лучше вынести всю бизнес-логику в отдельную процедуру.

Рассмотрим по шагам, как это реализовать:

  1. Создайте общую процедуру в модуле формы, которая содержит весь необходимый код для обновления интерфейса и данных.
  2. Вызывайте эту процедуру из обработчика ПриИзменении.
  3. Вызывайте эту же процедуру принудительно в конце обработчика НачалоВыбораИзСписка (сразу после установки значения).

Пример программной реализации

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


Процедура ПериодРегистрацииПриИзменении(Элемент)
    // Эта процедура отработает при ручном вводе
    ОбновитьДанныеПериода();
КонецПроцедуры

Процедура ПериодРегистрацииНачалоВыбораИзСписка(Элемент, СтандартнаяОбработка)
    СтандартнаяОбработка = Ложь;
    // ... ваш код выбора значения из списка ...
    // Элемент.Значение = ВыбранноеЗначение;
    
    // Принудительный вызов логики после программного изменения
    ОбновитьДанныеПериода();
КонецПроцедуры

Процедура ОбновитьДанныеПериода()
    // Здесь размещаем весь код пересчета
    ОпределитьДатыПериодаНачисления();
    УстановитьЗаголовокФормыДокумента();
    ЗаполнитьСоответствиеДоходовИВычетов();
КонецПроцедуры

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

В типовых решениях (например, в УПП) разработчики часто используют именно такой подход. Вы можете заметить, что процедуры, подобные ПериодРегистрацииПриИзменении, присутствуют в коде формы, но их вызов дублируется в других местах. Это сделано для того, чтобы:

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

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

← На главную