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

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

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

Разработчики, только начинающие работать с управляемыми формами, часто пытаются решить эту задачу «в лоб» — через обращение к элементам формы в коде: Элементы.ИмяКолонки.Доступность = Ложь. Однако при этом они сталкиваются с тем, что доступность меняется сразу для всей колонки во всех строках таблицы. Это связано с тем, что в управляемом интерфейсе элемент формы представляет собой описание элемента управления для всей колонки целиком, а не для конкретной ячейки в отдельной строке.

В этой статье мы подробно разберем, как правильно реализовать динамическое изменение доступности ячеек для каждой строки отдельно. Мы рассмотрим три различных подхода, проанализируем их плюсы и минусы, а также разберем особенности применения свойств Доступность и ТолькоПросмотр.

---

Почему не работают стандартные методы и в чем опасность «костылей»?

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

Давайте проанализируем, почему этот подход использовать не рекомендуется:

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

Единственным архитектурно верным решением в платформе 1С является использование механизма Условного оформления в связке со служебными реквизитами строки.

---

Способ №1: Использование Условного оформления (Рекомендуемый способ)

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

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

Шаг 1. Создание служебного реквизита

Если условие блокировки ячейки простое (например, Объект.Товары.Количество > 10), мы можем использовать уже существующие реквизиты. Но если условие зависит от результатов запроса, прав доступа или сторонних данных, необходимо добавить в табличную часть (или в коллекцию формы) специальную колонку-флаг.

Добавим в табличную часть Товары реквизит с именем ТолькоПросмотрСуммы с типом Булево. Выносить этот реквизит на форму в виде видимой колонки не нужно — он будет использоваться исключительно как скрытый служебный флаг.

Шаг 2. Программная настройка Условного оформления

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

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


&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)

    // 1. Создаем новый элемент условного оформления
    ЭлементОформления = УсловноеОформление.Элементы.Добавить();

    // 2. Определяем действие: устанавливаем режим "Только просмотр" в значение Истина
    ЭлементОформления.Оформление.УстановитьЗначениеПараметра("ТолькоПросмотр", Истина);

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

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

КонецПроцедуры

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

---

Важное различие: «Доступность» против «ТолькоПросмотр»

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

---

Способ №2: Обработчик события «ПриНачалеРедактирования»

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

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

Рассмотрим пример реализации:


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

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

---

Жизненный цикл служебного реквизита: как избежать рассинхронизации данных?

Если вы выбрали Способ №1 (Условное оформление + служебный реквизит флага), вам необходимо позаботиться о своевременном расчете и обновлении этого флага. Недостаточно просто заполнить его при открытии формы в методе ПриСозданииНаСервере. Данные могут меняться в процессе работы пользователя.

Рассмотрим сценарии, при которых требуется обязательный пересчет служебного флага:

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

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


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

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

---

Резюме

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

← На главную