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