При разработке интерфейсов на управляемых формах 1С программисты часто сталкиваются с задачей: необходимо запретить редактирование всех данных в документе или справочнике, но оставить возможность изменять одно конкретное поле или колонку в табличной части. Стандартный подход с использованием свойства ТолькоПросмотр для всей формы в данном случае не работает. Давайте подробно разберем, почему это происходит и какими способами можно добиться желаемого результата.
Рассмотрим ситуацию, которую описывает автор темы. При установке ЭтаФорма.ТолькоПросмотр = Истина платформа 1С включает глобальный режим защиты данных формы. В этом режиме приоритет настройки формы выше, чем настройки любого дочернего элемента. Даже если вы программно обратитесь к конкретному полю и установите ему ТолькоПросмотр = Ложь или Доступность = Истина, визуально и функционально элемент останется заблокированным. Платформа просто игнорирует частные настройки, если общее правило формы диктует запрет на редактирование.
Проанализируем архитектуру управления доступностью. Чтобы разблокировать хотя бы один элемент, свойство ТолькоПросмотр всей формы обязательно должно быть установлено в значение Ложь. Только после этого мы получаем возможность точечно управлять каждым элементом интерфейса.
Наиболее современным и производительным методом управления доступностью полей является механизм Условного оформления. Вместо того чтобы перебирать все элементы формы в цикле, мы можем создать правило, которое будет действовать на всю форму, за исключением нужного нам поля. Это особенно полезно, когда условие блокировки зависит от данных (например, если документ проведен).
Разберем реализацию этого метода в процедуре ПриСозданииНаСервере:
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
// 1. Оставляем форму доступной для редактирования на общем уровне
ЭтаФорма.ТолькоПросмотр = Ложь;
// 2. Настраиваем условное оформление для блокировки полей
ЭлементОформления = УсловноеОформление.Элементы.Добавить();
// Определяем поле, которое будет заблокировано (например, вся группа или конкретные реквизиты)
// Чтобы заблокировать почти всё, нужно добавить все поля, кроме исключения
Для Каждого ЭлементФормы Из Элементы Цикл
Если ЭлементФормы.Имя = "ДокументацияПутьКДокументу" Тогда
Продолжить; // Пропускаем наш исключительный реквизит
КонецЕсли;
ПолеОформления = ЭлементОформления.Поля.Элементы.Добавить();
ПолеОформления.Поле = Новый ПолеКомпоновкиДанных(ЭлементФормы.Имя);
КонецЦикла;
// Устанавливаем само оформление
ЭлементОформления.Оформить.УстановитьЗначениеПараметра("ТолькоПросмотр", Истина);
// Можно добавить условие, когда эта блокировка действует (например, всегда)
ЭлементУсловия = ЭлементОформления.Отбор.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
ЭлементУсловия.ЛевоеЗначение = Новый ПолеКомпоновкиДанных("Объект.Проведен");
ЭлементУсловия.ВидСравнения = ВидСравненияКомпоновкиДанных.Равно;
ЭлементУсловия.ПравоеЗначение = Истина;
КонецПроцедуры
Если логика формы сложная и условное оформление не подходит, можно воспользоваться методом "от обратного". Мы оставляем форму в режиме редактирования, но программно обходим все её элементы и выключаем их доступность, минуя нужный нам реквизит. Посмотрим на доработанный код из примера автора темы.
Важно помнить: если мы работаем с табличной частью, то для редактирования колонки сама таблица также должна иметь ТолькоПросмотр = Ложь. Иначе вы не сможете даже активировать строку.
&НаСервере
Процедура УстановитьДоступностьИсключаяРеквизит(ИмяИсключения)
ЭтаФорма.ТолькоПросмотр = Ложь;
Для Каждого Элемент Из ЭтаФорма.Элементы Цикл
// Проверяем, не является ли элемент нашим исключением
Если Элемент.Имя = ИмяИсключения Тогда
Элемент.ТолькоПросмотр = Ложь;
Элемент.Доступность = Истина;
Продолжить;
КонецЕсли;
// Для таблиц нужно особое внимание
Если ТипЗнч(Элемент) = Тип("ТаблицаФормы") Тогда
// Если в таблице есть колонка-исключение, саму таблицу НЕЛЬЗЯ делать ТолькоПросмотр
// Мы должны заблокировать все её остальные колонки
Элемент.ТолькоПросмотр = Ложь;
Продолжить;
КонецЕсли;
// Блокируем остальные элементы (кроме групп и кнопок, если нужно)
Попытка
Элемент.ТолькоПросмотр = Истина;
Исключение
// Для кнопок или групп используем Доступность
Элемент.Доступность = Ложь;
КонецПопытки;
КонецЦикла;
КонецПроцедуры
Рассмотрим еще один практичный вариант, который часто используют опытные разработчики для упрощения кода. Вместо того чтобы программно искать и перебирать элементы, мы можем подготовить структуру формы заранее в конфигураторе.
ГруппаФормы), назовем её, например, ГруппаВсеРеквизиты.Элементы.ГруппаВсеРеквизиты.Доступность = Ложь;.При таком подходе форма остается доступной, кнопка "Записать" работает, а вся основная часть интерфейса становится неактивной ("серой"), за исключением нашего выделенного поля. Это самый надежный способ с точки зрения производительности.
Проанализируем нюанс, возникший у автора: почему таблица остается заблокированной, даже если для неё прописан код? В 1С ТаблицаФормы имеет несколько уровней блокировки:
Выясним причину неудачи автора: если форма открыта для чтения (например, объект заблокирован платформой), то даже при ЭтаФорма.ТолькоПросмотр = Ложь данные могут быть недоступны для редактирования на уровне самого объекта. В этом случае проверьте свойство РазрешитьРедактированиеДанных или используйте параметры формы при открытии.
Разберем по шагам правильный алгоритм действий для решения задачи:
ЭтаФорма.ТолькоПросмотр установлено в Ложь.ТолькоПросмотр = Ложь.Записать() для сохранения изменений в этом единственном поле.Помните, что безопасность данных должна стоять на первом месте. Разблокируя поле в режиме "Только просмотр", вы берете на себя ответственность за то, что пользователь сможет изменить данные в объекте, который по бизнес-логике должен быть защищен.