Как запретить редактирование строки табличной части по условию в 1С (обычные формы)?

Программист 1С v8.3 (Обычные формы) 1С:Управление торговлей Торговля и дистрибуция
← На главную

Часто при разработке и доработке конфигураций на платформе 1С возникает задача ограничить права пользователя на изменение определенных данных. Разберем типичную техническую ситуацию: в документе Заказ покупателя (в конфигурации 1С:Управление торговлей 10.3, использующей интерфейс обычных форм) необходимо программно запретить редактировать конкретные строки табличной части в зависимости от выполнения определенного условия. Проанализируем несколько способов решения этой задачи, от самых очевидных до наиболее оптимальных и правильных с точки зрения архитектуры приложения.

Использование события ПриАктивизацииСтроки

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

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


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

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

Оптимальное решение: событие ПередНачаломИзменения

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

Разберем по шагам, как реализовать этот метод. В обработчике события нам достаточно получить данные текущей выделенной строки через свойство Элемент.ТекущиеДанные. Если наше условие блокировки выполняется, мы просто устанавливаем системный параметр Отказ в значение Истина. Это моментально прервет действие пользователя и не позволит интерфейсу переключиться в режим ввода.


Процедура ТоварыПередНачаломИзменения(Элемент, Отказ)
    ТекущиеДанные = Элемент.ТекущиеДанные;
    
    // Проверяем наличие данных и срабатывание условия
    Если ТекущиеДанные <> Неопределено И ТекущиеДанные.НашПризнакЗапрета = Истина Тогда
        Отказ = Истина; // Блокируем попытку редактирования
    КонецЕсли;
КонецПроцедуры

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

Запрет на добавление, удаление и перемещение строк

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

Для реализации этого требования мы можем программно воздействовать на общие свойства табличного поля:

  1. Чтобы запретить пользователю удалять существующие или добавлять новые строки (кнопками Insert/Delete или через панель), используем свойство ИзменятьСоставСтрок.
  2. Для запрета изменения позиций строк (кнопками перемещения «вверх» и «вниз») используем свойство ИзменятьПорядокСтрок.

Пример применения при открытии формы или изменении статуса документа:


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

Визуальное информирование пользователя

Проанализируем итоговый результат с точки зрения пользовательского опыта (UX). Если пользователь кликает по строке, пытается ввести текст, нажимает кнопки, а программа никак не реагирует (из-за срабатывания Отказ = Истина), это вызывает недоумение и часто воспринимается как зависание 1С. Чтобы избежать шквала обращений в техническую поддержку, скомбинируем технический запрет редактирования с интуитивно понятным визуальным выделением недоступных строк.

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


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

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

← На главную