Как запретить редактирование ячейки в конкретной строке табличной части 1С

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

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

Метод 1. Использование механизма «Условное оформление» (рекомендуемый способ)

Для управляемых форм (платформа 8.2 и 8.3) использование Условного оформления является «золотым стандартом». Это позволяет избежать написания сложного кода в обработчиках событий и минимизировать количество серверных вызовов. Основное преимущество этого метода заключается в том, что платформа самостоятельно отслеживает изменение данных и обновляет интерфейс.

Проанализируем ситуацию: нам нужно запретить редактирование колонки Размещение, если Номенклатура принадлежит определенной группе. Мы можем настроить это правило программно в процедуре ПриСозданииНаСервере или непосредственно в конфигураторе.

Рассмотрим пример программной настройки условного оформления (кстати, получить его код поможет декомпиляция условного оформления):


ЭлементОформления = УсловноеОформление.Элементы.Добавить();

// 1. Указываем, какое поле мы хотим оформить
ПолеОформления = ЭлементОформления.Поля.Элементы.Добавить();
ПолеОформления.Поле = Новый ПолеКомпоновкиДанных("Объект.Товары.Размещение");

// 2. Устанавливаем условие (например, Номенклатура входит в группу "Услуги")
ЭлементУсловия = ЭлементОформления.Отбор.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
ЭлементУсловия.ЛевоеЗначение = Новый ПолеКомпоновкиДанных("Объект.Товары.Номенклатура");
ЭлементУсловия.ВидСравнения = ВидСравненияКомпоновкиДанных.ВИерархии;
ЭлементУсловия.ПравоеЗначение = ГруппаЗапрета; // Ссылка на группу номенклатуры

// 3. Устанавливаем свойство оформления
ЭлементОформления.Оформить.УстановитьЗначениеПараметра("ТолькоПросмотр", Истина);

Этот способ позволяет системе автоматически блокировать ячейку сразу после выбора номенклатуры, не требуя от пользователя никаких дополнительных действий.

Метод 2. Обработка события «ПриАктивизацииЯчейки»

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

Посмотрим на пример реализации для управляемой формы, где мы блокируем колонку ТоварыГоденДо, если Количество в строке больше нуля:


&НаКлиенте
Процедура ТоварыПриАктивизацииЯчейки(Элемент)
    ТекущиеДанные = Элемент.ТекущиеДанные;
    Если ТекущиеДанные = Неопределено Тогда
        Возврат;
    КонецЕсли;

    Количество = ТекущиеДанные.Количество;
    
    // Если условие выполняется и мы стоим в нужной колонке
    Если Количество > 0 И Элемент.ТекущийЭлемент.Имя = "ТоварыГоденДо" Тогда
        Элемент.ТекущийЭлемент.ТолькоПросмотр = Истина;
    Иначе
        // Обязательно возвращаем доступность для других строк
        Элементы.ТоварыГоденДо.ТолькоПросмотр = Ложь;
    КонецЕсли;
КонецПроцедуры

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

Метод 3. Запрет через «ПередНачаломИзменения»

Если ваша задача — просто запретить ввод данных в определенных условиях, не меняя визуальный стиль ячейки заранее, можно воспользоваться событием ПередНачаломИзменения. Это событие срабатывает в момент, когда пользователь пытается войти в режим редактирования (нажать Enter или начать печатать).

Рассмотрим пример кода:


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

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

Метод 4. Различия между «ТолькоПросмотр» и «Доступность»

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

  1. Доступность = Ложь: Ячейка становится серой, в нее нельзя кликнуть мышкой, в нее невозможно установить курсор и скопировать текст. Это часто раздражает пользователей, если им нужно прочитать длинный текст или скопировать артикул.
  2. ТолькоПросмотр = Истина: Пользователь может зайти в ячейку, выделить данные и скопировать их в буфер обмена, но не может изменить содержимое. Для табличных частей документов это обычно более предпочтительный вариант.

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

Метод 5. Контроль на уровне модуля объекта

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

Рассмотрим пример в процедуре ПередЗаписью:


Процедура ПередЗаписью(Отказ, РежимЗаписи, РежимПроведения)
    Для Каждого СтрокаТовары Из Товары Цикл
        Если СтрокаТовары.Номенклатура.ПринадлежитЭлементу(Справочники.Номенклатура.НайтиПоНаименованию("Услуги")) 
             И ЗначениеЗаполнено(СтрокаТовары.Размещение) Тогда
            
            ТекстСообщения = "Для услуг поле 'Размещение' должно быть пустым в строке №" + СтрокаТовары.НомерСтроки;
            ОбщегоНазначенияКлиентСервер.СообщитьПользователю(ТекстСообщения, , , , Отказ);
            
        КонецЕсли;
    КонецЦикла;
КонецПроцедуры

Таким образом, мы обеспечиваем комплексную защиту данных: Условное оформление создает комфортную среду для пользователя, а проверка в Модуле объекта гарантирует целостность данных в базе.

Итоги и рекомендации

Подведем итог нашему анализу:

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

← На главную