Как отключить доступность или редактирование ячейки табличного поля в обычных формах 1С

Программист 1С v8.3 (Обычные формы) IT и автоматизация бизнеса
← На главную

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

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

Почему возникает ошибка при обращении через ТекущиеДанные

Проанализируем распространенную ошибку, с которой сталкиваются разработчики при попытке отключить поле:


Если НЕ ЭлементыФормы.ПЛ_ПлановаяСтоимостьСкорректированный.ТекущиеДанные.Статья = Перечисления.ПЛ_СтатьиИнвестпрограммы.СМР Тогда 
    ЭлементыФормы.ПЛ_ПлановаяСтоимостьСкорректированный.ТекущиеДанные.ДлинаЛинии.ТолькоПросмотр = Истина; // Ошибка!
КонецЕсли;

При выполнении этого кода платформа выдает ошибку: «Значение не является значением объектного типа (ТолькоПросмотр)». Выясним причину такого поведения:

  1. Свойства ТекущиеДанные, ТекущаяСтрока и ДанныеСтроки возвращают ссылку на строку источника данных (строку табличной части или набора записей регистра сведений). Поля в них являются строго типизированными значениями (число, строка, ссылка), у которых физически нет визуальных свойств ТолькоПросмотр или Доступность.
  2. Свойство ТекущиеДанные может возвращать Неопределено (например, если в таблице нет ни одной строки или курсор не спозиционирован), что приведет к исключительной ситуации при попытке прочитать реквизит через точку.
  3. Свойство Доступность отсутствует у объекта ОформлениеЯчейки. Для запрета ввода на уровне отдельной ячейки строки используется только свойство ТолькоПросмотр = Истина (или Видимость = Ложь, если ячейку требуется полностью спрятать).

Способ 1. Использование события ПриПолученииДанных (рекомендуемый)

Обработчик ПриПолученииДанных является наиболее производительным и оптимальным способом для динамического оформления ячеек в табличных полях обычных форм, так как обрабатывает видимые строки пакетом.

Разберем по шагам подключение и реализацию обработчика:

  1. Откроем форму в конфигураторе и выделим элемент управления Табличное поле.
  2. Нажмем правой кнопкой мыши, выберем Палитра свойств и перейдем на вкладку События.
  3. Найдем событие ПриПолученииДанных и нажмем кнопку с лупой для генерации процедуры в модуле формы.
  4. Напишем код обхода коллекции оформлений строк:

Процедура ПЛ_ПлановаяСтоимостьПервоначальныйПриПолученииДанных(Элемент, ОформленияСтрок)
    
    Для Каждого Оформление Из ОформленияСтрок Цикл
        // Проверяем значение в данных строки
        Если Оформление.ДанныеСтроки.Статья = Перечисления.ПЛ_СтатьиИнвестпрограммы.СМР Тогда
            Оформление.Ячейки.ДлинаЛинии.ТолькоПросмотр = Ложь;
        Иначе
            Оформление.Ячейки.ДлинаЛинии.ТолькоПросмотр = Истина;
        КонецЕсли;
    КонецЦикла;
    
КонецПроцедуры

Способ 2. Использование события ПриВыводеСтроки

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

Посмотрим на пример реализации данного обработчика:


Процедура ПЛ_ПлановаяСтоимостьПервоначальныйПриВыводеСтроки(Элемент, ОформлениеСтроки, ДанныеСтроки)
    
    Если ДанныеСтроки = Неопределено Тогда
        Возврат;
    КонецЕсли;
    
    Если ДанныеСтроки.Статья = Перечисления.ПЛ_СтатьиИнвестпрограммы.СМР Тогда
        ОформлениеСтроки.Ячейки.ДлинаЛинии.ТолькоПросмотр = Ложь;
    Иначе
        ОформлениеСтроки.Ячейки.ДлинаЛинии.ТолькоПросмотр = Истина;
    КонецЕсли;
    
КонецПроцедуры

Нюансы интерактивного обновления и очистки данных

Рассмотрим важные детали, которые необходимо учесть при интерактивном изменении данных пользователем:

  1. Обновление отображения при редактировании: события ПриВыводеСтроки и ПриПолученииДанных срабатывают при перерисовке списка. Если пользователь меняет значение колонки «Статья», оформление текущей строки может не пересчитаться мгновенно. Чтобы принудительно обновить ячейки, в событии ПриИзменении колонки «Статья» следует вызвать метод: ЭлементыФормы.ПЛ_ПлановаяСтоимостьПервоначальный.ОбновитьСтроки();
  2. Очистка заблокированных значений: установка ТолькоПросмотр = Истина блокирует интерактивное изменение, но сохраняет уже записанное ранее значение. Если при смене статьи на отличную от «СМР» значение длины линии должно сбрасываться, его необходимо явно очищать в обработчике ПриИзменении:
    
    Процедура ПЛ_ПлановаяСтоимостьПервоначальныйСтатьяПриИзменении(Элемент)
        
        ТекДанные = ЭлементыФормы.ПЛ_ПлановаяСтоимостьПервоначальный.ТекущиеДанные;
        Если ТекДанные <> Неопределено Тогда
            Если ТекДанные.Статья <> Перечисления.ПЛ_СтатьиИнвестпрограммы.СМР Тогда
                ТекДанные.ДлинаЛинии = 0;
            КонецЕсли;
            ЭлементыФормы.ПЛ_ПлановаяСтоимостьПервоначальный.ОбновитьСтроки();
        КонецЕсли;
        
    КонецПроцедуры
    

Альтернативные способы блокировки редактирования

Помимо оформления ячеек, существуют и другие способы управления редактированием строк табличного поля:

  1. Переключение свойства колонки в событии ПриАктивизацииСтроки:
    
    Процедура ПЛ_ПлановаяСтоимостьПервоначальныйПриАктивизацииСтроки(Элемент)
        
        ТекДанные = Элемент.ТекущиеДанные;
        Если ТекДанные <> Неопределено Тогда
            ЗапретитьРедактирование = (ТекДанные.Статья <> Перечисления.ПЛ_СтатьиИнвестпрограммы.СМР);
            ЭлементыФормы.ПЛ_ПлановаяСтоимостьПервоначальный.Колонки.ДлинаЛинии.ТолькоПросмотр = ЗапретитьРедактирование;
        КонецЕсли;
        
    КонецПроцедуры
    
  2. Запрет через событие ПередНачаломИзменения: позволяет полностью отменить вход в режим редактирования ячейки при определенных условиях:
    
    Процедура ПЛ_ПлановаяСтоимостьПервоначальныйПередНачаломИзменения(Элемент, Отказ)
        
        ТекДанные = Элемент.ТекущиеДанные;
        Если ТекДанные <> Неопределено И Элемент.ТекущаяКолонка.Имя = "ДлинаЛинии" Тогда
            Если ТекДанные.Статья <> Перечисления.ПЛ_СтатьиИнвестпрограммы.СМР Тогда
                Отказ = Истина;
            КонецЕсли;
        КонецЕсли;
        
    КонецПроцедуры
    

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

← На главную