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