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