Как установить пометку удаления на все подчиненные элементы иерархического справочника в 1С?

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

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

Разберем подробнее, как реализовать данную задачу программно с помощью встроенного языка 1С, а также как быстро решить ее пользователю с помощью типовых инструментов платформы.

Способ 1. Программная установка пометки через запрос с условием иерархии

Проанализируем частую ошибку начинающих разработчиков: при попытке отобрать элементы по условию Родитель = &Родитель в выборку попадают только объекты первого уровня вложенности. Если внутри выбранной папки содержатся подпапки со своими позициями, они будут пропущены. Кроме того, вызов метода Удалить() приводит к необратимому физическому удалению записи из базы данных вместо штатной установки пометки удаления.

Чтобы выбрать абсолютно все вложенные элементы и группы на всех уровнях вложенности, используем конструкцию языка запросов В ИЕРАРХИИ. Чтобы сама группа-родитель не была помечена на удаление, обязательно исключим ее условием Ссылка <> &Родитель.

Посмотрим на пример оптимального кода с обходом выборки:


Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ
    |	Номенклатура.Ссылка КАК Ссылка
    |ИЗ
    |	Справочник.Номенклатура КАК Номенклатура
    |ГДЕ
    |	Номенклатура.Ссылка В ИЕРАРХИИ(&Родитель)
    |	И Номенклатура.Ссылка <> &Родитель";

Запрос.УстановитьПараметр("Родитель", ВыбраннаяПапка);

Результат = Запрос.Выполнить();
Выборка = Результат.Выбрать();

Пока Выборка.Следующий() Цикл
	Объект = Выборка.Ссылка.ПолучитьОбъект();
	Если Объект <> Неопределено Тогда
		// Устанавливаем пометку удаления
		Объект.УстановитьПометкуУдаления(Истина);
	КонецЕсли;
КонецЦикла;

Обратим внимание на метод УстановитьПометкуУдаления(). Он принимает параметры установки признака и при вызове сразу выполняет неявную запись объекта в базу данных. Если требуется пометить исключительно конечные позиции, не затрагивая структуру подпапок, в запрос достаточно добавить условие И Номенклатура.ЭтоГруппа = Ложь.

Оптимизация производительности и обход проверок

Когда подчиненных элементов тысячи, последовательная запись каждого объекта в цикле открывает отдельную транзакцию, что существенно замедляет выполнение обработки. Кроме того, в модуле объекта при записи могут срабатывать строгие прикладные проверки заполнения реквизитов.

Рассмотрим, как оптимизировать этот процесс:

  1. Использование явных транзакций: оборачиваем пакеты записей в транзакции с помощью НачатьТранзакцию() и ЗафиксироватьТранзакцию().
  2. Отключение прикладных проверок: для административных обработок свойство ОбменДанными.Загрузка = Истина позволяет пропустить проверки в событии ПередЗаписью.

Посмотрим на практическую реализацию пакетной обработки:


Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ
    |	Номенклатура.Ссылка КАК Ссылка
    |ИЗ
    |	Справочник.Номенклатура КАК Номенклатура
    |ГДЕ
    |	Номенклатура.Ссылка В ИЕРАРХИИ(&Родитель)
    |	И Номенклатура.Ссылка <> &Родитель";

Запрос.УстановитьПараметр("Родитель", ВыбраннаяПапка);
Выборка = Запрос.Выполнить().Выбрать();

Счетчик = 0;
НачатьТранзакцию();

Пока Выборка.Следующий() Цикл
	Объект = Выборка.Ссылка.ПолучитьОбъект();
	Если Объект <> Неопределено Тогда
		Объект.ОбменДанными.Загрузка = Истина;
		Объект.ПометкаУдаления = Истина;
		Объект.Записать();
		
		Счетчик = Счетчик + 1;
		Если Счетчик % 500 = 0 Тогда
			ЗафиксироватьТранзакцию();
			НачатьТранзакцию();
		КонецЕсли;
	КонецЕсли;
КонецЦикла;

Если Счетчик % 500 <> 0 Тогда
	ЗафиксироватьТранзакцию();
КонецЕсли;

Способ 2. Использование метода родителя с параметром подчиненных

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

СправочникОбъект.УстановитьПометкуУдаления(ПометкаУдаления, ПомечатьПодчиненные)

Если вызвать этот метод у объекта группы-родителя со значениями ОбъектРодитель.УстановитьПометкуУдаления(Истина, Истина), платформа автоматически пометит как саму группу, так и все вложенные элементы и подчиненные справочники. Важный нюанс: этот способ подходит только тогда, когда саму исходную папку тоже необходимо пометить на удаление. Если папка должна остаться непомеченной, необходимо использовать пообъектную обработку через запрос, описанную в первом способе.

Способ 3. Интерактивная обработка штатными средствами 1С

Для пользователей и администраторов нет необходимости писать собственный код для разовой задачи. В типовых конфигурациях предусмотрены стандартные инструменты:

  1. Групповое изменение реквизитов (для конфигураций на Управляемых формах):

    Открываем обработку «Групповое изменение реквизитов» (раздел «НСИ и администрирование» — «Обслуживание» — «Корректировка данных»). Выбираем нужный справочник и нажимаем ссылку добавления условий отбора. В условии указываем: Ссылка В иерархии [Выбранная группа] и дополнительно Ссылка Не равно [Выбранная группа]. Переходим в «Дополнительные параметры», включаем видимость служебных реквизитов, в списке полей находим ПометкаУдаления, выставляем значение Да и нажимаем кнопку «Изменить выделенные».

  2. Групповая обработка справочников и документов (для Обычных форм):

    Открываем обработку через меню «Операции» — «Обработки». В типе объекта выбираем справочники, добавляем нужный справочник. В табличной части отбора задаем поле Ссылка с условием В группе (или В иерархии) и выбираем родителя. Нажимаем кнопку «Отобрать», выбираем действие «Установить пометку удаления» и нажимаем «Выполнить».

При выполнении любых массовых операций с базой данных рекомендуется предварительно создавать резервную копию.

← На главную