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