Как отследить изменение и окончание редактирования реквизитов формы в 1С 7.7?

Программист 1С v7.7 IT и автоматизация бизнеса
← На главную

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

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

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

Вариант 1. Использование невидимого элемента «Текст» с кэшированием значений (Штатный метод)

Платформа 1С 7.7 пересчитывает формулы текстовых элементов диалога при любом обновлении или перерисовывании формы. Если поместить на форму невидимый текстовый элемент и прописать в его поле «Формула» специальную функцию, она будет вызываться регулярно. Чтобы предотвратить лишние срабатывания при открытии и избежать зацикливания при пересчете, реализуем механизм сравнения с кэшем прошлых значений.

Рассмотрим пошаговый алгоритм реализации:

  1. В модуле формы объявляем глобальные переменные для хранения кэша реквизитов и флагов состояния.
  2. В процедуре ПриОткрытии() заполняем список значений текущими реквизитами формы и устанавливаем флаг завершения инициализации.
  3. На форму добавляем элемент «Текст» (его можно сделать невидимым или разместить за пределами видимой области диалога) и в поле «Формула» указываем вызов функции, например: ФлОтследитьИзменения().
  4. В самой функции ФлОтследитьИзменения() сравниваем текущие значения реквизитов со значениями из кэша. При обнаружении изменений обновляем кэш и вызываем процедуру обработки.

Проанализируем пример кода для модуля формы:


Перем мКэшРеквизитов;
Перем ФлИнициализацияПрошла;
Перем ФлПересчетВыполняется;

Функция ФлОтследитьИзменения()
    // Предотвращаем выполнение функции до окончания процедуры ПриОткрытии()
    Если ФлИнициализацияПрошла <> 1 Тогда
        Возврат "";
    КонецЕсли;
    
    // Защита от рекурсивного зацикливания при программном изменении реквизитов
    Если ФлПересчетВыполняется = 1 Тогда
        Возврат "";
    КонецЕсли;
    
    // Перебираем сохраненные реквизиты
    Для Сч = 1 По мКэшРеквизитов.РазмерСписка() Цикл
        ИмяРеквизита = "";
        СтароеЗначение = мКэшРеквизитов.ПолучитьЗначение(Сч, ИмяРеквизита);
        ТекущееЗначение = Вычислить(ИмяРеквизита);
        
        Если ТекущееЗначение <> СтароеЗначение Тогда
            // Обновляем значение в кэше
            мКэшРеквизитов.УстановитьЗначение(Сч, ТекущееЗначение, ИмяРеквизита);
            
            // Включаем флаг блокировки и вызываем обработчик
            ФлПересчетВыполняется = 1;
            ОбработатьИзменениеРеквизита(ИмяРеквизита, ТекущееЗначение);
            ФлПересчетВыполняется = 0;
        КонецЕсли;
    КонецЦикла;
    
    Возврат "";
КонецФункция

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

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

Вариант 2. Использование внешней компоненты FormEx

Если в базе разрешено использование внешних компонент, эффективным решением является применение FormEx.dll. Данная библиотека расширяет возможности работы с интерфесом 1С 7.7 и позволяет программно управлять элементами диалога.

С помощью объекта РасширениеФормы можно программно обойти все элементы диалога при открытии формы и назначить им единую формулу обработки без необходимости редактировать свойства каждого элемента вручную в Конфигураторе.

Выясним, как это реализовать на практике:


Перем Сервис, РасшФормы;

Процедура ПриИзмененииЛюбогоРеквизита(ИдентификаторЭлемента)
    Сообщить("Изменен реквизит: " + ИдентификаторЭлемента);
    // Выполняем требуемый пересчет
КонецПроцедуры

Процедура ПриОткрытии()
    Если ЗагрузитьВнешнююКомпоненту("formex.dll") = 1 Тогда
        Сервис = СоздатьОбъект("Сервис");
        РасшФормы = СоздатьОбъект("РасширениеФормы");
        РасшФормы.УстановитьФорму(Форма);
        
        // Обходим элементы формы и программно назначаем формулу
        Для Сч = 1 По Форма.КоличествоЭлементов() Цикл
            Элемент = Форма.ПолучитьЭлемент(Сч);
            ИмяЭлемента = Элемент.Идентификатор;
            
            Если ПустаяСтрока(ИмяЭлемента) = 0 Тогда
                // Назначаем вызов процедуры с передачей идентификатора
                Элемент.Формула = "ПриИзмененииЛюбогоРеквизита(""" + ИмяЭлемента + """)";
            КонецЕсли;
        КонецЦикла;
    КонецЕсли;
КонецПроцедуры

Вариант 3. Перехват событий интерфейса (1С++ / Перехватчик)

При использовании внешней компоненты 1С++ или классов перехватчиков доступен механизм перехвата низкоуровневых событий формы. Это позволяет отлавливать события потери фокуса элементом ввода (OnKillFocus) или непосредственного редактирования текста.

Преимущество этого метода заключается в том, что событие срабатывает ровно в момент, когда пользователь завершил ввод данных в поле и переместил фокус на другой элемент (клавишами Enter, Tab или мышью).

Сравнение подходов и рекомендации

  1. Штатный метод (Текст с формулой + кэш): Не требует подключения внешних DLL, работает в любых конфигурациях и на любых серверах. Подходит для ситуаций, когда список контролируемых реквизитов заранее известен или динамически собирается из состава метаданных.
  2. Использование FormEx: Наиболее удобный вариант с точки зрения чистоты кода. Позволяет не менять форму в Конфигураторе и автоматически обрабатывать появление новых полей.
  3. Табличная часть: Для отслеживания изменений в строках табличной части всегда рекомендуется использовать штатную предопределенную процедуру ПриОкончанииРедактированияСтроки().
← На главную