Как сделать реквизит табличной части «Только просмотр» для конкретной строки при определенных условиях?

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

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

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

Способ 1. Интерактивная настройка условного оформления в конфигураторе

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

  1. Откройте нужную управляемую форму в конфигураторе.
  2. В правом верхнем углу (окно свойств и реквизитов формы) перейдите на вкладку «Свойства» самой формы (кликните по корневой строке «Форма» в левом дереве).
  3. Найдите свойство «Условное оформление» в группе «Оформление» и нажмите кнопку «Открыть» (с тремя точками).
  4. В открывшемся окне нажмите кнопку «Добавить» для создания нового элемента оформления.
  5. На вкладке «Оформление» найдите свойство ТолькоПросмотр, установите напротив него галочку и присвойте значение Истина.
  6. Перейдите на вкладку «Условие». Здесь добавьте новое условие. Например: поле Объект.Товары.Статус равно ПредопределенноеЗначение("Перечисление.Статусы.Заблокирован").
  7. Перейдите на вкладку «Оформляемые поля». Нажмите «Добавить» и выберите именно ту колонку (поле) табличной части, которую вы хотите заблокировать для редактирования при выполнении указанного условия.
  8. Нажмите «ОК» и сохраните форму.

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

Способ 2. Программная настройка условного оформления (Рекомендация фирмы «1С»)

Несмотря на удобство интерактивного метода, стандарт разработки фирмы «1С» настоятельно рекомендует настраивать условное оформление программным способом в модуле управляемой формы. Давайте разберем, почему это важно.

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

Проанализируем пример кода, который необходимо разместить в обработчике события формы ПриСозданииНаСервере:


&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
    
    // 1. Создаем новый элемент условного оформления формы
    ЭлементОформления = УсловноеОформление.Элементы.Добавить();
    
    // 2. Определяем свойство, которое мы хотим изменить (делаем ячейку доступной только для чтения)
    ЭлементОформления.Оформление.УстановитьЗначениеПараметра("ТолькоПросмотр", Истина);
    
    // 3. Задаем условие срабатывания правила
    // Допустим, мы блокируем колонку "Количество", если "Статус" равен значению "Блокирован"
    ЭлементОтбора = ЭлементОформления.Отбор.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
    ЭлементОтбора.ЛевоеЗначение  = Новый ПолеКомпоновкиДанных("Объект.Товары.Статус");
    ЭлементОтбора.ВидСравнения   = ВидСравненияКомпоновкиДанных.Равно;
    ЭлементОтбора.ПравоеЗначение = ПредопределенноеЗначение("Перечисление.СтатусыСтрок.Блокирован");
    
    // 4. Указываем конкретное оформляемое поле (колонку табличной части на форме)
    ПолеОформления = ЭлементОформления.Поля.Элементы.Добавить();
    ПолеОформления.Поле = Новый ПолеКомпоновкиДанных("ТоварыКоличество"); // Обратите внимание: пишется имя элемента формы!
    
КонецПроцедуры

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

Нюанс использования параметров «ТолькоПросмотр» и «Доступность» в УО

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

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

Способ 3. Использование события «ПриНачалеРедактирования» (Альтернативный вариант)

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

В таких неординарных ситуациях мы можем использовать обработчик события табличной части ПриНачалеРедактирования на стороне клиента.

Давайте посмотрим на практический пример реализации такого алгоритма:


&НаКлиенте
Процедура ТоварыПриНачалеРедактирования(Элемент, НоваяСтрока, Копирование)
    
    ТекущиеДанные = Элемент.ТекущиеДанные;
    Если ТекущиеДанные = Неопределено Тогда 
        Возврат;
    КонецЕсли;
    
    // Проверяем наше сложное условие для текущей строки
    Если ТекущиеДанные.Номенклатура.Услуга Тогда
        // Если это услуга, запрещаем редактировать колонку "Склад"
        Элементы.ТоварыСклад.ТолькоПросмотр = Истина;
    Иначе
        // КРИТИЧЕСКИ ВАЖНО: обязательно возвращаем доступность обратно для других строк!
        Элементы.ТоварыСклад.ТолькоПросмотр = Ложь;
    КонецЕсли;
    
КонецПроцедуры

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

Критически важный нюанс: Безопасность данных на уровне сервера

Помните важное правило разработки в 1С: Условное оформление — это элемент визуализации интерфейса, а не средство защиты данных.

Если блокировка редактирования реквизита критически важна для бизнес-логики (например, недопущение изменения цен задним числом, проведение документов менеджерами без прав и т.д.), одного лишь условного оформления или отключения доступности кнопок на форме недостаточно!

Продвинутый пользователь или внешняя обработка могут легко изменить значение заблокированной колонки программным путем в обход вашей красивой формы. Поэтому всегда дублируйте ключевые бизнес-проверки на уровне сервера в модуле объекта (в обработчике события ПередЗаписью).

Рассмотрим пример такой защиты в модуле объекта документа:


Процедура ПередЗаписью(Отказ, РежимЗаписи, РежимПроведения)
    
    // Защита данных: проверяем, что никто не обошел ограничения интерфейса
    Для Каждого СтрокаТЧ Из Товары Цикл
        Если СтрокаТЧ.Статус = Перечисления.СтатусыСтрок.Блокирован Тогда
            // Проверяем, пытался ли кто-то изменить защищаемое поле "Количество"
            // Сравниваем с версией данных в базе (если объект не новый)
            СсылкаНаБД = ОбщегоНазначения.ЗначениеРеквизитаОбъекта(Ссылка, "Товары");
            Если ЗначениеЗаполнено(Ссылка) Тогда
                // Здесь должна быть логика сравнения текущей строки с исходной строкой из БД
                // Если обнаружено несанкционированное изменение:
                // Отказ = Истина;
                // Сообщение = Новый СообщениеПользователю; ...
            КонецЕсли;
        КонецЕсли;
    КонецЦикла;
    
КонецПроцедуры

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

← На главную