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