Как запретить удаление определенных строк в табличной части, добавленных программно?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

В практике разработки на платформе 1С:Предприятие часто возникают задачи, связанные с тонкой настройкой взаимодействия пользователя с табличными частями (используя приемы построения эффективных интерфейсов) — для этого подойдёт универсальная настройка интерфейса и логики форм 1С. Одна из таких ситуаций — гибридное заполнение таблицы. Это когда часть строк пользователь добавляет вручную, а часть заполняется автоматически по нажатию какой-либо кнопки (например, «Заполнить по остаткам» или «Подбор по спецификации»).

Возникает логичное требование: строки, добавленные пользователем вручную, он может удалять свободно. А вот «системные» строки, добавленные автоматическим алгоритмом, должны быть защищены от случайного удаления — для этой задачи есть модуль автоматической проверки и запрета действий в 1С. Давайте разберем подробно, как реализовать такой механизм, сделав его надежным и понятным для пользователя.

Постановка задачи и выбор стратегии

Проблема заключается в том, что стандартные права доступа или настройки элемента формы (например, свойство ТолькоПросмотр) действуют либо на всю таблицу целиком, либо на конкретные колонки, но не на отдельные строки в зависимости от их происхождения — для более детального контроля подойдёт инструмент гибкой настройки ограничений доступа к объектам.

Чтобы реализовать выборочный запрет (удобно через настройка запретов редактирования и удаления без программирования), нам необходимо выполнить два условия:

  1. Научить систему отличать «ручные» строки от «автоматических».
  2. Перехватить событие удаления строки и проверить это отличие.

Рассмотрим пошагово реализацию этого функционала, ориентируясь на современные стандарты разработки (управляемое приложение), тем более что добавление реквизитов и элементов на управляемые формы сейчас значительно упростилось.

Шаг 1. Маркировка строк

Как правильно заметили участники обсуждения, системе нужно где-то хранить информацию о том, как появилась строка. Самый надежный способ — добавить специальный реквизит в саму табличную часть.

Давайте добавим в нашу табличную часть (назовем её для примера Товары) новый реквизит (колонку):

Этот реквизит будет служить флагом. Если значение Истина — строку удалять нельзя.

Шаг 2. Заполнение признака при создании строк

Теперь нам нужно обеспечить правильное заполнение этого флага. У нас есть два сценария появления строк:

Сценарий А: Пользователь добавляет строку вручную (кнопка Ins или «Добавить»).
В этом случае наш флаг АвтоматическиСоздана по умолчанию будет равен Ложь (так как это значение типа Булево по умолчанию). Это нам и нужно — такие строки удалять можно.

Сценарий Б: Строки добавляются программно по кнопке «К».
В обработчике команды, которая заполняет таблицу, мы должны явно установить этот флаг в значение Истина. Рассмотрим пример кода заполнения:


&НаКлиенте
Процедура ЗаполнитьТовары(Команда)
    // Вызываем серверную процедуру для заполнения
    ЗаполнитьТоварыНаСервере();
КонецПроцедуры

&НаСервере
Процедура ЗаполнитьТоварыНаСервере()
    
    // Очищаем или дополняем таблицу - зависит от логики.
    // Допустим, мы добавляем новые строки из какого-то источника данных
    ТаблицаДанных = ПолучитьДанныеДляЗаполнения(); // Функция возвращает таблицу значений
    
    Для Каждого СтрДанных Из ТаблицаДанных Цикл
        
        НоваяСтрока = Объект.Товары.Добавить();
        ЗаполнитьЗначенияСвойств(НоваяСтрока, СтрДанных);
        
        // ВАЖНО: Устанавливаем признак, что строка создана автоматически
        НоваяСтрока.АвтоматическиСоздана = Истина;
        
    КонецЦикла;
    
КонецПроцедуры

Теперь все строки, созданные этой кнопкой, имеют «метку», отличающую их от ручных записей.

Шаг 3. Реализация запрета удаления (Событие «ПередУдалением»)

Самый важный этап — перехват действия пользователя. Для этого у элемента формы (Таблицы) существует событие ПередУдалением. В этом событии есть параметр Отказ, установив который в Истина, мы отменяем действие.

Однако здесь есть нюанс, связанный с множественным выделением строк в управляемых формах. Пользователь может выделить сразу 5 строк (через Ctrl или Shift), среди которых могут быть и разрешенные, и запрещенные к удалению. Если мы проверим только Элементы.Товары.ТекущиеДанные, мы проверим только ту строку, на которой стоит фокус, но не все удаляемые.

Правильный алгоритм проверки выглядит следующим образом:


&НаКлиенте
Процедура ТоварыПередУдалением(Элемент, Отказ)
    
    // Получаем массив идентификаторов выделенных строк
    ВыделенныеСтроки = Элемент.ВыделенныеСтроки;
    
    Для Каждого ИдентификаторСтроки Из ВыделенныеСтроки Цикл
        
        // Получаем данные строки по идентификатору
        // В управляемых формах данные строки получаются через метод ДанныеСтроки
        ДанныеСтроки = Элемент.ДанныеСтроки(ИдентификаторСтроки);
        
        Если ДанныеСтроки <> Неопределено Тогда
            
            // Проверяем наш флаг
            Если ДанныеСтроки.АвтоматическиСоздана Тогда
                
                Отказ = Истина;
                
                // Выводим понятное сообщение пользователю
                Сообщение = Новый СообщениеПользователю;
                Сообщение.Текст = "Строка №" + ДанныеСтроки.НомерСтроки + " добавлена автоматически. Удаление запрещено!";
                Сообщение.Сообщить();
                
                // Если мы нашли хотя бы одну запрещенную строку, 
                // прерываем цикл и отменяем всё удаление целиком.
                Прервать;
                
            КонецЕсли;
            
        КонецЕсли;
        
    КонецЦикла;
    
КонецПроцедуры

Такой подход гарантирует, что даже при групповом удалении ни одна защищенная строка не исчезнет.

Шаг 4. Настройка интерфейса (UI/UX)

Технически мы решили проблему, но для пользователя это может выглядеть неочевидно. Он нажимает Delete, ничего не происходит (или вылезает ошибка). Хорошим тоном считается визуальное разделение строк, чтобы пользователь заранее понимал, с чем работает.

1. Скрытие служебной колонки
Колонка АвтоматическиСоздана пользователю не нужна, она может его смутить. К тому же, если он снимет галочку вручную, защита перестанет работать. Поэтому в настройках формы находим этот элемент и ставим ему свойство Видимость = Ложь. Если по какой-то причине нужно видеть этот признак, обязательно установите ТолькоПросмотр = Истина.

2. Условное оформление
Давайте выделим защищенные строки цветом. В конфигураторе откройте форму, перейдите на вкладку «Условное оформление» (внизу). Добавьте новый элемент:

Теперь строки, которые нельзя удалять, будут визуально отличаться, что снизит количество ошибочных действий пользователя.

Шаг 5. Запрет редактирования ключевых полей

Часто, если строку запрещено удалять, ее также запрещено и редактировать (или редактировать ключевые колонки, например «Номенклатура»). Для этого используем событие таблицы ПриНачалеРедактирования.


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

КонецПроцедуры

Примечание по блокировке полей: Самый изящный способ запретить редактирование полей в зависимости от значения в строке — это опять же использовать Условное оформление — для этого также подойдёт управление логикой заполнения и контроля реквизитов 1С. В настройках условного оформления можно установить параметр ТолькоПросмотр в значение Истина при условии АвтоматическиСоздана = Истина. Это работает на уровне платформы без написания кода в обработчиках событий.

Заключение

Мы рассмотрели комплексный подход к защите строк табличной части. Давайте подведем итог:

  1. Мы добавили булево поле в таблицу для идентификации типа строки.
  2. Заполнили это поле программно при нажатии кнопки заполнения.
  3. Использовали событие ПередУдалением и перебор ВыделенныеСтроки для надежной защиты от удаления.
  4. Использовали УсловноеОформление для визуальной индикации и блокировки редактирования полей.

Такое решение является надежным, понятным для пользователя и соответствует стандартам разработки на платформе 1С.

← На главную