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