Как разрешить редактирование отдельных реквизитов табличной части, если форма закрыта на просмотр

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

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

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

Разбираем основную проблему: иерархия ограничений

Рассмотрим типичную ситуацию, с которой столкнулся автор темы. При попытке программно включить доступность колонки в цикле ничего не происходит. Причина кроется в свойстве ТолькоПросмотр самой формы.

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

Шаг 1. Снятие блокировки с формы и инверсия логики

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

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


Если РольДоступна("Менеджер") И Стадия = Перечисления.Стадия.Завершен Тогда
    // 1. Разрешаем редактирование формы в целом
    ЭтаФорма.ТолькоПросмотр = Ложь;
    
    // 2. Блокируем все элементы формы по умолчанию
    Для каждого Элемент Из ЭтаФорма.ЭлементыФормы Цикл
        Элемент.Доступность = Ложь;
    КонецЦикла;
    
    // 3. Теперь точечно включаем нужные элементы
    ЭлементыФормы.Товары.Доступность = Истина;
    ЭлементыФормы.ОсновныеДействияФормы.Доступность = Истина;
КонецЕсли;

Шаг 2. Доступ к колонкам табличной части

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

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

Оптимальный способ настройки колонок

Вместо того чтобы перебирать все колонки в цикле и сравнивать их имена, мы можем обратиться к ним напрямую через коллекцию ЭлементыФормы.Товары.Колонки. Это делает код чище и быстрее.


// Включаем возможность редактирования конкретных колонок
ЭлементыФормы.Товары.Колонки.Цена.ТолькоПросмотр = Ложь;
ЭлементыФормы.Товары.Колонки.Оплата.ТолькоПросмотр = Ложь;

// Если нужно, чтобы остальные колонки были только для чтения
Для каждого Колонка Из ЭлементыФормы.Товары.Колонки Цикл
    Если Колонка.Имя <> "Цена" И Колонка.Имя <> "Оплата" Тогда
        Колонка.ТолькоПросмотр = Истина;
    КонецЕсли;
КонецЦикла;

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

Разбор типичных ошибок при работе с циклами

В процессе обсуждения на форуме была замечена классическая ошибка программиста — использование переменной с одним и тем же именем во вложенных циклах:


Для каждого Элемент Из ЭтаФорма.ЭлементыФормы цикл 
    // ... какой-то код ...
    Для каждого Элемент Из ЭтаФорма.ЭлементыФормы.Товары.Колонки цикл // ОШИБКА! Переменная 'Элемент' перезаписывается
        // ...
    КонецЦикла;
КонецЦикла;

При таком подходе внешний цикл ломается сразу после завершения внутреннего, так как переменная Элемент больше не указывает на объект из коллекции элементов формы. Всегда используйте уникальные имена итераторов, например, ТекЭлемент и ТекКолонка.

Где разместить код управления доступом?

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

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

Влияние прав доступа на уровне метаданных

Выясним причину, почему даже при идеально написанном коде колонки могут оставаться недоступными. Если в конфигураторе для роли «Менеджер» сняты права на «Редактирование» конкретного реквизита объекта, то никакие программные манипуляции с ЭтаФорма.ТолькоПросмотр не помогут. Платформа всегда отдает приоритет правам доступа (Roles) и ограничениям доступа на уровне записей (RLS).

Перед написанием кода обязательно убедитесь, что:

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

← На главную