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