Как в 1С отрезать часть наименования до определенной запятой в запросе или при обработке данных?

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

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

Почему реализовать обрезку строки в самом запросе крайне сложно?

Язык запросов 1С ориентирован на работу с данными в СУБД и имеет ограниченный набор функций для работы со строками. В нем отсутствуют такие привычные функции, как СтрНайти или СтрРазделить. Единственный инструмент, который у нас есть — это функция ПОДСТРОКА.

Проанализируем ситуацию: чтобы найти позицию третьей запятой в запросе, нам пришлось бы создавать громоздкие конструкции. Нам бы потребовалось посимвольно проверять строку, выделять части текста до первой запятой во временную таблицу, затем из оставшейся части искать вторую запятую и так далее. Как верно замечено в обсуждении, такой запрос выглядел бы «ужасающе» и работал бы крайне медленно из-за огромного количества операций ВЫБОР и соединений временных таблиц.

Пример «устрашающей» логики (фрагмент), который наглядно показывает, почему так делать не стоит:


// Это пример того, как НЕ рекомендуется делать в реальных задачах
ВЫБОР 
    Когда ПОДСТРОКА(Наименование, 1, 1) = "," Тогда ...
    Когда ПОДСТРОКА(Наименование, 2, 1) = "," Тогда ...
    // И так для каждого символа...
Конец

Поэтому в 99% случаев задачу обрезки строк следует выносить на этап постобработки или использовать специальные механизмы платформы.

Решение 1: Постобработка результата запроса (Рекомендуемый способ)

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

Разберем по шагам программный код:

  1. Выполняем запрос и получаем выборку.
  2. В цикле обхода используем функцию СтрНайти, передавая в нее номер вхождения (в нашем случае — 3).
  3. Если запятая найдена, обрезаем строку функцией Лев.

Запрос = Новый Запрос;
Запрос.Текст = "ВЫБРАТЬ Номенклатура.Наименование КАК Наименование ИЗ Справочник.Номенклатура КАК Номенклатура";
Выборка = Запрос.Выполнить().Выбрать();

Пока Выборка.Следующий() Цикл
    // Ищем позицию именно 3-й запятой
    ПозицияЗапятой = СтрНайти(Выборка.Наименование, ",", , 3); 
    
    Если ПозицияЗапятой > 0 Тогда
        // Отрезаем всё, что идет после 3-й запятой (не включая её саму)
        ЧистоеНаименование = Лев(Выборка.Наименование, ПозицияЗапятой - 1);
    Иначе
        // Если запятых меньше трех, оставляем как есть
        ЧистоеНаименование = Выборка.Наименование;
    КонецЕсли;
    
    // Далее используем ЧистоеНаименование для вывода в отчет или обработки
КонецЦикла;

Этот метод работает быстро, код остается читаемым и его легко отладить.

Решение 2: Использование функции СтрРазделить (Современный подход)

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

Рассмотрим пример реализации:


ИсходнаяСтрока = "Туфли, 22 размера, красные, для мужчин, летние";
ЧастиСтроки = СтрРазделить(ИсходнаяСтрока, ",");

Если ЧастиСтроки.Количество() >= 3 Тогда
    // Собираем обратно только первые три элемента
    Результат = ЧастиСтроки[0] + "," + ЧастиСтроки[1] + "," + ЧастиСтроки[2];
Иначе
    Результат = ИсходнаяСтрока;
КонецЕсли;

Важный момент: обратите внимание, что индексы массива в 1С начинаются с нуля. Поэтому элементы с 0 по 2 — это как раз то, что находится до третьей запятой (считая саму третью запятую разделителем).

Решение 3: Использование Системы компоновки данных (СКД)

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

Выполним следующие действия:

  1. Создадим в общем модуле функцию, например, ОбрезатьНаименованиеДоЗапятой(Строка, НомерЗапятой).
  2. Обязательно добавим ключевое слово Экспорт и убедимся, что модуль доступен на сервере.
  3. В настройках СКД на закладке «Вычисляемые поля» добавим новое поле.
  4. В колонке «Выражение» вызовем нашу функцию: ОбщийМодульСтроковыеФункции.ОбрезатьНаименованиеДоЗапятой(Наименование, 3).

Этот метод позволяет оставить запрос «чистым» и переложить логику форматирования на уровень представления отчета.

Решение 4: Переопределение представления в модуле менеджера

Если обрезать наименование нужно глобально во всей программе (в ссылках на товар, в списках), стоит рассмотреть обработчик ОбработкаПолученияПредставления. Он находится в модуле менеджера соответствующего объекта (например, справочника Номенклатура).

Посмотрим на пример кода в модуле менеджера:


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

Внимание: этот метод кардинально меняет отображение объекта во всей системе. Используйте его только в том случае, если вы уверены, что пользователям никогда не понадобится видеть полное наименование в ссылочных полях.

Архитектурный совет

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

Если бы эти данные хранились в разных колонках, ваш запрос выглядел бы максимально просто:


ВЫБРАТЬ
    Номенклатура.Наименование,
    Номенклатура.Размер,
    Номенклатура.Цвет
ИЗ
    Справочник.Номенклатура КАК Номенклатура

В этом случае задача «отрезания» лишнего вообще бы не возникла, а производительность системы была бы значительно выше.

← На главную