Почему не всегда срабатывает событие ПередОкончаниемРедактирования в таблице управляемой формы 1С?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

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

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

Суть технической проблемы

Представим рабочую ситуацию: на форме программно или интерактивно создана таблица (например, список долей распределения заработной платы по статьям калькуляции и судам). В таблице реализовано требование уникальности — нельзя добавлять строки с одинаковой комбинацией ключевых полей (в данном случае это колонки СтатьяКалькуляции и Судно). Третья колонка — числовая (доля распределения).

Для проверки уникальности разработчик использует событие таблицы ПередОкончаниемРедактирования. Однако при тестировании выявляется странная закономерность:

  1. Если пользователь редактирует только ключевые ссылочные поля (колонки 1 и 2) и пытается завершить ввод, проверка отрабатывает корректно — система выдает предупреждение и не позволяет выйти из режима редактирования.
  2. Если пользователь меняет числовое значение в третьей колонке, то при попытке завершить редактирование строки (нажатием клавиши Enter или кликом мыши вне строки) событие ПередОкончаниемРедактирования попросту не вызывается. Строка успешно сохраняется в памяти формы, приводя к появлению дубликатов.

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

Причина 1. Неявные вызовы сервера и перестроение формы (Особенность платформы)

Основная и наиболее частая причина «исчезновения» клиентских событий завершения редактирования строки кроется во взаимодействии клиента и сервера при изменении данных. В управляемом приложении 1С действует жесткое правило: если во время изменения значения в ячейке происходит серверный вызов, который приводит к обновлению структуры или данных формы, режим интерактивного редактирования строки аварийно завершается на стороне платформы.

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

Причина 2. Ошибка в приоритете логических операторов

Обратим внимание на условие, которое разработчики часто используют в обработчике события:


Если Не НоваяСтрока Или НоваяСтрока И Не ОтменаРедактирования Тогда
    // Код проверки уникальности
КонецЕсли;

В языке программирования 1С оператор И имеет более высокий приоритет, чем оператор ИЛИ. Из-за этого платформа вычисляет данное выражение следующим образом:

(Не НоваяСтрока) Или (НоваяСтрока И (Не ОтменаРедактирования))

Рассмотрим, как вычисляется это условие в различных сценариях:

Для предотвращения логических ошибок всегда явно расставляйте скобки, даже если вы уверены в приоритетах по умолчанию:


Если (Не НоваяСтрока) Или (НоваяСтрока И Не ОтменаРедактирования) Тогда
    // Код проверки
КонецЕсли;

Причина 3. Особенности программного создания элементов формы

Если таблица формы и её колонки создаются программно в коде модуля формы (например, в процедуре ПриСозданииНаСервере), важно помнить о правильной привязке путей к данным и типах элементов управления.

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

Также проверьте свойство таблицы РежимРедактирования. Оно должно быть установлено в значение ВходПриВводе или Непосредственно. При определенных сочетаниях свойств колонок изменение числового значения может интерпретироваться платформой как завершение интерактивного ввода с автоматическим сохранением без вызова клиентских проверок.

Рекомендуемые архитектурные решения

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

Рассмотрим два надежных способа организации валидации данных в таблицах.

Вариант 1. Интерактивная проверка в событиях колонок (На стороне клиента)

Поскольку уникальность строки определяется ключевыми полями (СтатьяКалькуляции и Судно), логично выполнять проверку сразу при их изменении, а не дожидаться, пока пользователь заполнит всю строку и попытается выйти из нее.

Добавим обработчик события ПриИзменении для элементов управления ключевых колонок:


&НаКлиенте
Процедура ДолиПоСтатьямЗаработнойПлатыСтатьяКалькуляцииПриИзменении(Элемент)
    
    ТекущиеДанные = Элементы.ДолиПоСтатьямЗаработнойПлаты.ТекущиеДанные;
    Если ТекущиеДанные = Неопределено Тогда
        Возврат;
    КонецЕсли;
    
    // Выполняем проверку дубликатов в таблице
    ПараметрыОтбора = Новый Структура;
    ПараметрыОтбора.Вставить("СтатьяКалькуляции", ТекущиеДанные.СтатьяКалькуляции);
    ПараметрыОтбора.Вставить("Судно",             ТекущиеДанные.Судно);
    
    НайденныеСтроки = ДолиПоСтатьямЗаработнойПлаты.НайтиСтроки(ПараметрыОтбора);
    
    // Если найдено более одной строки (с учетом текущей редактируемой)
    Если НайденныеСтроки.Количество() > 1 Тогда
        
        ТекстОшибки = "Строка с такой статьей калькуляции и судном уже существует в таблице!";
        ОбщегоНазначенияКлиентСервер.СообщитьПользователю(ТекстОшибки, , "ДолиПоСтатьямЗаработнойПлаты.СтатьяКалькуляции");
        
        // Очищаем некорректно заполненное поле
        ТекущиеДанные.СтатьяКалькуляции = ПредопределенноеЗначение("Справочник.СтатьиКалькуляции.ПустаяСсылка");
        
    КонецЕсли;
    
КонецПроцедуры

Вариант 2. Гарантированная серверная проверка перед записью (Золотой стандарт)

Для обеспечения 100% защиты от дублирования данных (в том числе при программном заполнении таблицы или копировании строк) обязательно реализуйте проверку на сервере в событии формы ПередЗаписьюНаСервере или в модуле объекта в событии ПередЗаписью.

Проанализируем пример серверной проверки с использованием свертки таблицы значений для быстрого поиска дубликатов:


&НаСервере
Функция ПроверитьТабличнуюЧастьНаСервере() Экспорт
    
    // Выгружаем данные табличной части во временную Таблицу Значений
    ТаблицаПроверки = ДолиПоСтатьямЗаработнойПлаты.Выгрузить();
    
    // Запоминаем исходное количество строк
    ИсходноеКоличество = ТаблицаПроверки.Количество();
    
    // Сворачиваем по уникальным ключевым полям
    ТаблицаПроверки.Свернуть("СтатьяКалькуляции, Судно");
    
    // Если количество строк уменьшилось, значит были дубли
    Если ТаблицаПроверки.Количество() <> ИсходноеКоличество Тогда
        Возврат Ложь;
    КонецЕсли;
    
    Возврат Истина;
    
КонецФункции

&НаСервере
Процедура ПередЗаписьюНаСервере(Отказ, ТекущийОбъект, ПараметрыЗаписи)
    
    Если Не ПроверитьТабличнуюЧастьНаСервере() Тогда
        Отказ = Истина;
        Сообщение = Новый СообщениеПользователю;
        Сообщение.Текст = "Запись невозможна: таблица распределения содержит дублирующиеся строки по статьям калькуляции и судам!";
        Сообщение.Сообщить();
    КонецЕсли;
    
КонецПроцедуры

Резюме

Если в вашей форме перестает работать событие ПередОкончаниемРедактирования, выполните следующие шаги:

  1. Проверьте наличие обработчиков ПриИзменении у колонок таблицы и связанных реквизитов, которые могут вызывать сервер.
  2. Убедитесь в корректности расстановки скобок в логических условиях проверки параметров НоваяСтрока и ОтменаРедактирования.
  3. При программном создании колонок тщательно проверяйте пути к данным, типы создаваемых полей и свойства режима редактирования таблицы.
  4. Перенесите логику интерактивной валидации на события изменения конкретных ячеек, а окончательный контроль уникальности обязательно зафиксируйте на сервере в процедурах записи объекта.
← На главную