При разработке интерфейсов в конфигурациях на обычных формах часто возникает ситуация, когда привычное событие ПриИзменении не отрабатывает при выборе пользователем значения из списка или через кнопки регулирования. Давайте подробно разберем, почему это происходит и как правильно организовать архитектуру формы, чтобы код пересчета данных выполнялся корректно.
Основная причина заключается в архитектуре обработки событий платформой 1С. Когда вы устанавливаете СтандартнаяОбработка = Ложь в обработчике НачалоВыбораИзСписка, вы берете управление процессом выбора на себя. Платформа понимает, что она больше не контролирует процесс интерактивного заполнения поля, и цепочка стандартных событий, которые обычно следуют за изменением значения, прерывается.
Событие ПриИзменении в элементе управления ПолеВвода генерируется платформой в двух случаях:
Ctrl+V) и завершил ввод нажатием клавиши Enter или переходом на другой элемент.СтандартнаяОбработка не была принудительно отключена.Если же вы используете кнопки выбора или регулирования, которые программно меняют значение элемента, то ПриИзменении не вызывается, так как программное изменение значения поля (например, присвоение Элемент.Значение = НовоеЗначение) не инициирует событие изменения в системе.
Чтобы ваша логика (пересчет табличных полей, изменение заголовков, обновление сумм) срабатывала при любом способе выбора значения, рекомендуем следовать принципу инкапсуляции. Вместо того чтобы полагаться на автоматический вызов ПриИзменении, лучше вынести всю бизнес-логику в отдельную процедуру.
Рассмотрим по шагам, как это реализовать:
ПриИзменении.НачалоВыбораИзСписка (сразу после установки значения).Давайте посмотрим, как это выглядит на практике. Допустим, у нас есть процедура ОбновитьДанныеПериода(), которая выполняет все необходимые пересчеты:
Процедура ПериодРегистрацииПриИзменении(Элемент)
// Эта процедура отработает при ручном вводе
ОбновитьДанныеПериода();
КонецПроцедуры
Процедура ПериодРегистрацииНачалоВыбораИзСписка(Элемент, СтандартнаяОбработка)
СтандартнаяОбработка = Ложь;
// ... ваш код выбора значения из списка ...
// Элемент.Значение = ВыбранноеЗначение;
// Принудительный вызов логики после программного изменения
ОбновитьДанныеПериода();
КонецПроцедуры
Процедура ОбновитьДанныеПериода()
// Здесь размещаем весь код пересчета
ОпределитьДатыПериодаНачисления();
УстановитьЗаголовокФормыДокумента();
ЗаполнитьСоответствиеДоходовИВычетов();
КонецПроцедуры
В типовых решениях (например, в УПП) разработчики часто используют именно такой подход. Вы можете заметить, что процедуры, подобные ПериодРегистрацииПриИзменении, присутствуют в коде формы, но их вызов дублируется в других местах. Это сделано для того, чтобы:
Помните, что для отладки последовательности событий в обычных формах самым надежным инструментом является Отладчик. Установите точку останова в начало обработчика события и используйте Стек вызовов, чтобы увидеть, какая именно процедура инициировала вызов. Это поможет вам лучше понять структуру вызовов в вашей конкретной задаче.
Используя предложенный подход, вы избавите себя от проблем, когда часть данных обновляется, а часть — «забывает» измениться после выбора из списка, и обеспечите стабильную работу интерфейса документа.