Как обрезать часть наименования элемента справочника в запросе 1С

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

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

Ограничения языка запросов 1С при работе со строками

Язык запросов 1С имеет существенные технические ограничения при работе с текстовыми данными. В отличие от встроенного языка платформы или классического SQL, в запросе 1С отсутствуют:

  1. Функции поиска позиции подстроки или символа (аналоги функции СтрНайти()).
  2. Функции замены текста (аналоги функции СтрЗаменить()).
  3. Поддержка регулярных выражений.

Единственной базовой функцией для работы со строками в запросе является ПОДСТРОКА(). Однако она требует четко заданных параметров: исходная строка, начальная позиция и длина. Третий параметр (длина) обязан быть числовой константой или вычисляемым значением, но платформа не позволяет динамически определить точное местоположение искомого символа (например, открывающей скобки "(") без специальных ухищрений.

Теоретический способ: обрезка строки в запросе через таблицу чисел

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

Проанализируем следующий пример запроса:


ВЫБРАТЬ 0 КАК Поле
ПОМЕСТИТЬ Цифры
ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ 1
ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ 2
ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ 3
ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ 4
ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ 5
ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ 6
ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ 7
ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ 8
ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ 9
;

ВЫБРАТЬ ПЕРВЫЕ 100
    Числа1.Поле + 10 * Числа2.Поле КАК ПОЛЕ
ПОМЕСТИТЬ втСотня
ИЗ
    Цифры КАК Числа1,
    Цифры КАК Числа2
УПОРЯДОЧИТЬ ПО
    ПОЛЕ
;

ВЫБРАТЬ
    Номенклатура.Ссылка КАК Ссылка,
    МИНИМУМ(втСотня.ПОЛЕ) КАК Номер
ПОМЕСТИТЬ НомераСкобок
ИЗ
    Справочник.Номенклатура КАК Номенклатура,
    втСотня КАК втСотня
ГДЕ
    ПОДСТРОКА(Номенклатура.Наименование, втСотня.ПОЛЕ, 1) = "("
СГРУППИРОВАТЬ ПО
    Номенклатура.Ссылка
;

ВЫБРАТЬ
    ВЫБОР
        КОГДА ЕСТЬNULL(НомераСкобок.Номер, 0) = 0
            ТОГДА Номенклатура.Наименование
        ИНАЧЕ ПОДСТРОКА(Номенклатура.Наименование, 1, НомераСкобок.Номер - 1)
    КОНЕЦ КАК Наименование
ИЗ
    Справочник.Номенклатура КАК Номенклатура
        ЛЕВОЕ СОЕДИНЕНИЕ НомераСкобок КАК НомераСкобок
        ПО Номенклатура.Ссылка = НомераСкобок.Ссылка

Разберем по шагам, как работает данная конструкция:

  1. ВТ Цифры создает набор из 10 базовых цифр от 0 до 9.
  2. ВТ втСотня путем декартова произведения генерирует последовательность чисел от 0 до 99.
  3. ВТ НомераСкобок соединяет таблицу номенклатуры с таблицей чисел и выбирает по 1 символу через ПОДСТРОКА(), находя минимальную позицию, где встречается знак "(".
  4. Итоговый запрос обрезает наименование от первой позиции до найденного номера скобки минус один.

Важное предупреждение: Использование подобного метода в реальных рабочих базах крайне не рекомендуется. Соединение справочника с таблицей чисел вызывает сплошное сканирование (Table Scan) и создаёт критическую нагрузку на СУБД. На больших объемах данных данный запрос приведет к катастрофическому падению производительности или аварийному завершению сеанса сервера 1С.

Оптимальные практические решения проблемы

Выясним, какие подходы считаются правильными и наиболее эффективными в реальной разработке.

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

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

Посмотрим на пример кода:


ПозицияСкобки = СтрНайти(ИсходноеНаименование, "(");
Если ПозицияСкобки > 0 Тогда
    ОчищенноеНаименование = СокрЛП(Лев(ИсходноеНаименование, ПозицияСкобки - 1));
Иначе
    ОчищенноеНаименование = ИсходноеНаименование;
КонецЕсли;

2. Разделение реквизитов для пользователей и для печати

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

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

3. Использование вычисляемых полей в Схеме компоновки данных (СКД)

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

В вкладке Вычисляемые поля СКД можно добавить новое поле и указать выражение:


ВЫБОР 
    КОГДА СтрНайти(Наименование, "(") > 0 
    ТОГДА СокрЛП(Лев(Наименование, СтрНайти(Наименование, "(") - 1)) 
    ИНАЧЕ Наименование 
КОНЕЦ

Также в выражениях СКД допускается вызов экспортируемых функций общих модулей конфигурации.

4. Каскадная проверка через ВЫБОР КОГДА (для ограниченной длины)

Если требуется выполнить обрезку исключительно в запросе и позиция символа находится в пределах первых нескольких знаков, можно применить каскадную проверку без использования таблиц чисел:


ВЫБОР
    КОГДА ПОДСТРОКА(Номенклатура.Наименование, 1, 1) = "(" ТОГДА ""
    КОГДА ПОДСТРОКА(Номенклатура.Наименование, 2, 1) = "(" ТОГДА ПОДСТРОКА(Номенклатура.Наименование, 1, 1)
    КОГДА ПОДСТРОКА(Номенклатура.Наименование, 3, 1) = "(" ТОГДА ПОДСТРОКА(Номенклатура.Наименование, 1, 2)
    КОГДА ПОДСТРОКА(Номенклатура.Наименование, 4, 1) = "(" ТОГДА ПОДСТРОКА(Номенклатура.Наименование, 1, 3)
    ИНАЧЕ Номенклатура.Наименование
КОНЕЦ КАК НаименованиеДляПечати

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

← На главную