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