В разработке на платформе 1С:Предприятие 8.3 (особенно в управляемом приложении) часто возникает задача: сделать определенную ячейку в строке таблицы доступной или недоступной для редактирования в зависимости от некоторого условия. Например, если в строке выбран конкретный вид операции, то колонка с суммой должна быть заблокирована, а для других операций — открыта для ввода.
Разработчики, только начинающие работать с управляемыми формами, часто пытаются решить эту задачу «в лоб» — через обращение к элементам формы в коде: Элементы.ИмяКолонки.Доступность = Ложь. Однако при этом они сталкиваются с тем, что доступность меняется сразу для всей колонки во всех строках таблицы. Это связано с тем, что в управляемом интерфейсе элемент формы представляет собой описание элемента управления для всей колонки целиком, а не для конкретной ячейки в отдельной строке.
В этой статье мы подробно разберем, как правильно реализовать динамическое изменение доступности ячеек для каждой строки отдельно. Мы рассмотрим три различных подхода, проанализируем их плюсы и минусы, а также разберем особенности применения свойств Доступность и ТолькоПросмотр.
---
Прежде чем перейти к правильным решениям, разберем типичные ошибки. Некоторые разработчики пытаются обойти ограничение платформы с помощью события таблицы ПриАктивизацииСтроки. Идея этого метода заключается в следующем: при переходе пользователя на новую строку программно менять доступность всей колонки формы в зависимости от данных текущей строки.
Давайте проанализируем, почему этот подход использовать не рекомендуется:
ПриАктивизацииСтроки может инициировать повторный вызов этого же события. Платформа уходит в бесконечный цикл, что приводит к зависанию сеанса или аварийному завершению работы программы.Единственным архитектурно верным решением в платформе 1С является использование механизма Условного оформления в связке со служебными реквизитами строки.
---
Условное оформление управляемой формы — это мощный встроенный механизм декларативного описания того, как должны выглядеть и вести себя данные при выполнении определенных условий. Платформа сама берет на себя всю работу по отрисовке и блокировке конкретных ячеек «на лету» без постоянных вызовов сервера.
Для того чтобы заблокировать ячейку по сложному условию (например, по результату запроса), нам понадобится вспомогательный служебный реквизит. Давайте разберем этот процесс по шагам.
Если условие блокировки ячейки простое (например, Объект.Товары.Количество > 10), мы можем использовать уже существующие реквизиты. Но если условие зависит от результатов запроса, прав доступа или сторонних данных, необходимо добавить в табличную часть (или в коллекцию формы) специальную колонку-флаг.
Добавим в табличную часть Товары реквизит с именем ТолькоПросмотрСуммы с типом Булево. Выносить этот реквизит на форму в виде видимой колонки не нужно — он будет использоваться исключительно как скрытый служебный флаг.
Хотя условное оформление можно настроить интерактивно в конфигураторе, стандарты разработки 1С рекомендуют делать это программно. Это гарантирует контроль ошибок при переименовании реквизитов и упрощает групповую разработку. Для автоматической генерации готового кода по интерактивным настройкам подойдёт обработка для декомпиляции условного оформления в программный код.
Настройку выполним в обработчике формы ПриСозданииНаСервере:
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
// 1. Создаем новый элемент условного оформления
ЭлементОформления = УсловноеОформление.Элементы.Добавить();
// 2. Определяем действие: устанавливаем режим "Только просмотр" в значение Истина
ЭлементОформления.Оформление.УстановитьЗначениеПараметра("ТолькоПросмотр", Истина);
// 3. Указываем, к какому именно полю (колонке таблицы) применять оформление
ПолеОформления = ЭлементОформления.Поля.Элементы.Добавить();
ПолеОформления.Поле = Новый ПолеКомпоновкиДанных("ТоварыСумма");
// 4. Задаем условие, при котором оформление сработает
ЭлементОтбора = ЭлементОформления.Отбор.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
ЭлементОтбора.ЛевоеЗначение = Новый ПолеКомпоновкиДанных("Объект.Товары.ТолькоПросмотрСуммы");
ЭлементОтбора.ВидСравнения = ВидСравненияКомпоновкиДанных.Равно;
ЭлементОтбора.ПравоеЗначение = Истина;
КонецПроцедуры
В результате этой настройки платформа будет автоматически делать ячейку в колонке Сумма доступной только для чтения в тех строках, где скрытый флаг ТолькоПросмотрСуммы установлен в значение Истина.
---
При настройке условного оформления у вас будет выбор между двумя свойствами: Доступность и ТолькоПросмотр. Крайне важно понимать разницу между ними:
Tab работает стандартно (фокус заходит в ячейку, но редактировать ее нельзя). Это наиболее предпочтительный вариант для большинства бизнес-сценариев.Tab просто перепрыгивает эту ячейку. Данный вариант используется редко, когда необходимо полностью исключить поле из интерфейса строки.---
Иногда логика проверки доступности ячейки настолько динамическая или тяжелая, что хранить готовый флаг в каждой строке нецелесообразно. Например, доступность может зависеть от текущего времени, остатков товаров на складах в реальном времени или прав текущего пользователя.
В таких случаях отлично подходит использование клиентского события таблицы ПриНачалеРедактирования. Мы позволяем пользователю попытаться изменить ячейку, но в момент старта редактирования проверяем условия и при необходимости отменяем действие.
Рассмотрим пример реализации:
&НаКлиенте
Процедура ТоварыПриНачалеРедактирования(Элемент, НоваяСтрока, Копирование, Отказ)
ТекущиеДанные = Элемент.ТекущиеДанные;
Если ТекущиеДанные = Неопределено Тогда
Возврат;
КонецЕсли;
// Проверяем условие. Например, запрещаем редактировать строки с определенным статусом номенклатуры
Если ТекущиеДанные.СтатусНоменклатуры = ПредопределенноеЗначение("Перечисление.Статусы.Архивный") Тогда
// Установка этого параметра в Истина отменяет открытие ячейки для редактирования
Отказ = Истина;
// Информируем пользователя о причине отказа
ПоказатьПредупреждение(, "Редактирование позиций со статусом 'Архивный' запрещено!");
КонецЕсли;
КонецПроцедуры
Преимущества этого способа: вся логика выполняется на клиенте в момент действия пользователя, нет необходимости заранее рассчитывать и хранить значения флагов в памяти сервера для тысяч строк табличной части.
---
Если вы выбрали Способ №1 (Условное оформление + служебный реквизит флага), вам необходимо позаботиться о своевременном расчете и обновлении этого флага. Недостаточно просто заполнить его при открытии формы в методе ПриСозданииНаСервере. Данные могут меняться в процессе работы пользователя.
Рассмотрим сценарии, при которых требуется обязательный пересчет служебного флага:
ПриИзменении или ПередНачаломДобавления.
Давайте посмотрим, как правильно реализовать интерактивный пересчет на клиенте без лишних серверных вызовов:
&НаКлиенте
Процедура ТоварыВидОплатыПриИзменении(Элемент)
СтрокаТаблицы = Элементы.Товары.ТекущиеДанные;
Если СтрокаТаблицы = Неопределено Тогда
Возврат;
КонецЕсли;
// Логика проверки прямо на клиенте
Если СтрокаТаблицы.ВидОплаты = ПредопределенноеЗначение("Перечисление.ВидыОплаты.Наличные") Тогда
// Если оплата наличными - блокируем ячейку суммы для редактирования
СтрокаТаблицы.ТолькоПросмотрСуммы = Истина;
Иначе
СтрокаТаблицы.ТолькоПросмотрСуммы = Ложь;
КонецЕсли;
// Платформа автоматически применит условное оформление сразу после изменения флага!
КонецПроцедуры
Благодаря тому, что условное оформление "слушает" изменение данных формы, визуальное отображение ячейки обновится мгновенно в ту же секунду, когда пользователь сменит вид оплаты. При этом не будет выполнено ни одного серверного вызова, что обеспечивает максимальную отзывчивость интерфейса даже при работе через веб-клиент или слабое интернет-соединение.
---
Для настройки доступности отдельных ячеек в строках управляемых форм 1С:
Элементы.ИмяКолонки.Доступность) для управления конкретными строками.ТолькоПросмотр — это наиболее мягкий и визуально красивый способ блокировки данных.ПриНачалеРедактирования с параметром Отказ = Истина.