При разработке сложных интерфейсов на управляемых формах 1С часто возникает необходимость работать с таблицами, которые создаются или модифицируются программно. Одной из ключевых задач в этом процессе является перехват действий пользователя: добавление новой строки, изменение существующих данных или удаление элементов. В этой статье мы подробно разберем, как правильно назначить обработчики этих событий, на что обратить внимание при написании процедур и какие нюансы платформы могут привести к ошибкам.
Когда мы работаем с элементами формы, созданными в конфигураторе, мы привыкли назначать события через палитру свойств. Однако для динамически созданных элементов (или при необходимости динамически менять логику) используется метод УстановитьДействие. Рассмотрим, как это выглядит в коде на примере таблицы ТаблПолейВыбора.
Для того чтобы система поняла, какую процедуру вызвать при наступлении события, мы должны передать имя события и имя процедуры в виде строки:
// Назначаем обработчики для интерактивных действий с таблицей
ТаблПолейВыбора.УстановитьДействие("ПередНачаломДобавления", "ПроцедураПередНачаломДобавления");
ТаблПолейВыбора.УстановитьДействие("ПередУдалением", "ПроцедураПередУдалением");
ТаблПолейВыбора.УстановитьДействие("ПослеУдаления", "ПроцедураПослеУдаления");
ТаблПолейВыбора.УстановитьДействие("ПриИзменении", "ПроцедураПриИзмененииДанных");
Важный момент: процедура, имя которой мы указываем (например, "ПроцедураПередУдалением"), должна обязательно существовать в модуле формы и иметь соответствующую директиву компиляции (обычно &НаКлиенте).
Проанализируем критически важную особенность: обработчики, установленные через УстановитьДействие для элемента формы "Таблица", срабатывают только при интерактивных действиях пользователя. Если пользователь нажал кнопку "Добавить" на командной панели или клавишу Del, событие сработает.
Однако, если вы решите удалить строку программно непосредственно из реквизита формы, например так:
// Это действие НЕ вызовет событие "ПередУдалением" элемента формы
Индекс = 0;
Объект.Товары.Удалить(Индекс);
В этом случае события элемента формы ПередУдалением или ПослеУдаления проигнорируются. Для отслеживания таких "тихих" изменений данных на уровне реквизита следует использовать событие ПриИзменении самого реквизита или пересчитывать логику сразу после программного вызова метода Удалить().
Выясним, чем полезно событие ПослеУдаления, которое часто упускают из виду. В отличие от ПередУдалением, этот обработчик выполняется уже после того, как строка физически исчезла из коллекции строк на форме. У него нет параметра Отказ, так как действие уже совершено.
Мы рекомендуем использовать этот обработчик для следующих задач:
ПослеУдаления — идеальное место для вызова функции пересчета.Пример сигнатуры процедуры:
&НаКлиенте
Процедура ПроцедураПослеУдаления(Элемент)
// Элемент — это наша таблица формы
ОбновитьОбщиеИтогиПоДокументу();
КонецПроцедуры
Рассмотрим ситуацию, когда пользователь нажимает кнопку "Скопировать". В этом случае также срабатывает событие ПередНачаломДобавления. Нам важно уметь отличать создание пустой строки от копирования существующей. Разберем параметры этого события:
Элемент — ссылка на таблицу.Отказ — если установить в Истина, добавление будет прервано.Копирование — Булево. Если Истина, значит, происходит копирование текущей строки.Родитель и Группа — используются для иерархических списков.Проанализируем пример кода, который очищает уникальные идентификаторы при копировании строки, чтобы данные не дублировались некорректно:
&НаКлиенте
Процедура ПроцедураПередНачаломДобавления(Элемент, Отказ, Копирование, Родитель, Группа, ПараметрыОсновногоДействия)
Если Копирование Тогда
// Логика при копировании: например, очистка полей, которые не должны дублироваться
Сообщить("Выполняется копирование строки...");
КонецЕсли;
КонецПроцедуры
Посмотрим на ситуацию шире: иногда нам не важно, добавлена строка или изменена, нам нужно зафиксировать результат, когда пользователь закончил ввод. Для этого отлично подходит событие ПриОкончанииРедактирования. Оно обладает параметром НоваяСтрока.
Если НоваяСтрока = Истина, значит, пользователь только что завершил создание элемента. Это гораздо удобнее, чем пытаться поймать момент "фиксации" данных через ПередНачаломДобавления, где строка еще фактически не наполнена данными.
Крайне важно соблюдать количество параметров в процедурах. Если вы используете УстановитьДействие, а в модуле форма описана процедура с неверным количеством аргументов, 1С выдаст ошибку во время выполнения в тот момент, когда пользователь совершит действие (например, нажмет "Удалить").
Вспомним стандартные наборы параметров:
ПередУдалением: (Элемент, Отказ)ПослеУдаления: (Элемент)Выбор: (Элемент, ВыбраннаяСтрока, Поле, СтандартнаяОбработка)Все перечисленные выше события являются клиентскими. Если в процессе удаления или добавления строки вам требуется выполнить запрос к базе данных (например, проверить остатки на складе или получить цену номенклатуры), вам необходимо создать дополнительную серверную процедуру или функцию. Вызов должен выглядеть так:
&НаКлиенте
Процедура ПроцедураПередУдалением(Элемент, Отказ)
// Проверим права пользователя на сервере
Если Не ПроверитьПравоНаУдалениеНаСервере() Тогда
Отказ = Истина;
ПоказатьПредупреждение(, "У вас недостаточно прав для удаления этой строки!");
КонецЕсли;
КонецПроцедуры
&НаСервере
Функция ПроверитьПравоНаУдалениеНаСервере()
// Проверка через роли или параметры сеанса
Возврат РольДоступна("ПолныеПрава");
КонецФункции
Подводя итог, можно сказать, что программная работа с событиями таблицы требует внимательности к контексту (интерактивное или программное изменение) и строгого соблюдения структуры процедур-обработчиков. Использование связки событий ПередУдалением и ПослеУдаления позволяет полностью контролировать жизненный цикл данных в динамических формах 1С.