При разработке в среде 1С:Предприятие 8.3, особенно при работе с расширениями в типовых конфигурациях вроде УТ 11.5, программисты часто сталкиваются с ситуацией, когда обработчики событий ведут себя непредсказуемо. Одной из таких загадок является выборочное "игнорирование" платформой события ОбработкаВыбора (или его расширений Перед и После) для определенных реквизитов формы. Рассмотрим подробнее, почему для номенклатуры код отрабатывает идеально, а на количестве упаковок "молчит", и как обеспечить стабильную работу логики.
Проанализируем ситуацию, описанную разработчиком. В документе "Заказ клиента" создано расширение, которое должно перехватывать выбор в строковой части. Для реквизитов Номенклатура и Упаковка всё работает корректно, но для поля КоличествоУпаковок обработчик не вызывается. Выясним причину этого поведения, обратив внимание на типы данных.
Реквизиты Номенклатура и Упаковка имеют ссылочный тип. Когда пользователь взаимодействует с таким полем, он почти всегда совершает акт выбора: либо из формы списка, либо через выпадающий список автоподбора. Платформа интерпретирует это как событие ОбработкаВыбора.
Реквизит КоличествоУпаковок имеет тип Число. Здесь и кроется корень проблемы. Для примитивных типов данных (число, строка, дата) ввод значения с клавиатуры — это прямое редактирование, а не выбор из источника. Платформа 1С не генерирует событие выбора, если вы просто набрали "10" и нажали Enter.
Посмотрим на интересный нюанс: если в числовом поле нажать на кнопку выбора (иконка калькулятора) и подтвердить введенное значение там, событие ОбработкаВыбора внезапно сработает. Это подтверждает, что сам обработчик в расширении написан верно, но он "ждет" именно интерактивного действия выбора из вспомогательного окна (которым технически является калькулятор).
Вывод: использовать ОбработкаВыбора для контроля ввода чисел — архитектурно неверное решение, так как 99% пользователей будут вводить данные вручную, минуя калькулятор.
Для надежного перехвата любых изменений в числовых полях (будь то ручной ввод или использование калькулятора) мы должны использовать событие ПриИзменении (OnChange). Рассмотрим, как правильно реализовать это в расширении для УТ 11.5.
Предположим, нам нужно выполнить код после того, как типовые механизмы пересчета УТ завершили свою работу. Используем аннотацию &После:
&НаКлиенте
Процедура Расш1_КоличествоУпаковокПриИзмененииПосле(Элемент)
// Получаем текущую строку, чтобы работать с данными
ТекущаяСтрока = Элементы.Товары.ТекущиеДанные;
Если ТекущаяСтрока <> Неопределено Тогда
// Наша логика обработки
РассчитатьДополнительныеПоказатели(ТекущаяСтрока);
КонецЕсли;
КонецПроцедуры
Этот метод гарантированно сработает в любом сценарии изменения значения. Это наиболее универсальный и рекомендуемый подход для примитивных типов данных.
Разберем ситуацию, когда нам принципиально нужно вклиниться в процесс выбора. Если мы используем &Перед для события ОбработкаВыбора, мы можем даже отменить стандартную обработку. Однако помните, что для числовых полей это сработает только при открытии калькулятора.
Проанализируем, почему в некоторых случаях расширения "не подцепляются". В платформе 8.3.22 и выше существует оптимизация: если у элемента формы свойство КнопкаВыбора установлено в значение Нет, платформа может игнорировать наличие обработчиков выбора в расширении для оптимизации производительности. Проверьте свойства элемента формы в конфигураторе: если вы хотите перехватывать выбор, кнопка выбора должна быть активна.
В конфигурации "Управление торговлей" поле КоличествоУпаковок сильно завязано на серверные пересчеты (цены, суммы, скидки). Посмотрим, как это влияет на наши обработчики:
ПриИзменении в УТ часто вызывает процедуру ТоварыКоличествоУпаковокПриИзменении на сервере.&После, ваш код выполнится только после того, как сервер вернет управление клиенту.Оповестить), что может привести к потере фокуса или перерисовке элементов до того, как ваша логика успеет завершиться.Для тяжелых вычислений, которые должны следовать за изменением количества, иногда полезно использовать обработчик ожидания. Это позволяет платформе "успокоиться" после типовых процедур и выполнить ваш код в чистом контексте:
&НаКлиенте
Процедура Расш1_КоличествоУпаковокПриИзмененииПосле(Элемент)
// Откладываем выполнение на 0.1 секунды
ПодключитьОбработчикОжидания("ВыполнитьМоюЛогикуПослеПересчета", 0.1, Истина);
КонецПроцедуры
&НаКлиенте
Процедура ВыполнитьМоюЛогикуПослеПересчета()
// Здесь код, который выполнится после всех типовых пересчетов УТ
Сообщить("Пересчет завершен успешно!");
КонецПроцедуры
Подведем итог нашего анализа. Если вы столкнулись с тем, что обработчик события не срабатывает выборочно:
Во-первых, проверьте тип данных. Помните, что ОбработкаВыбора — это про выбор из другого окна, а не про ввод текста или цифр. Для чисел, строк и дат всегда используйте ПриИзменении.
Во-вторых, убедитесь, что в расширении вы правильно указали имя элемента формы. Ошибка в одной букве не вызовет падения системы (так как расширения подключаются динамически), но обработчик просто не будет вызван.
В-третьих, учитывайте специфику платформы 8.3.22+. Если логика расширения не срабатывает, попробуйте явно включить кнопку выбора в свойствах элемента или проверить, не перекрывается ли событие другим расширением с более высоким приоритетом.
Используя предложенные методы, вы сможете создавать стабильные и предсказуемые кастомизации для любых документов в 1С.