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

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

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

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

Вариант 1. Использование конструкции ВЫБОР и оператора ПОДОБНО в запросе

Если набор возможных значений объемов заранее известен и ограничен (например, стандартная тара масел: 1л, 4л, 5л, 10л, 20л, 200л), задачу можно решить непосредственно на уровне СУБД в тексте запроса. Разберем по шагам, как построить условие с оператором ПОДОБНО:


ВЫБОР
    КОГДА Номенклатура.Наименование ПОДОБНО "% 1л" ТОГДА 1
    КОГДА Номенклатура.Наименование ПОДОБНО "% 4л" ТОГДА 4
    КОГДА Номенклатура.Наименование ПОДОБНО "% 5л" ТОГДА 5
    КОГДА Номенклатура.Наименование ПОДОБНО "% 6л" ТОГДА 6
    КОГДА Номенклатура.Наименование ПОДОБНО "% 10л" ТОГДА 10
    КОГДА Номенклатура.Наименование ПОДОБНО "% 20л" ТОГДА 20
    ИНАЧЕ 0
КОНЕЦ КАК Литров

Обратите внимание: использование шаблона вида "% 1л" с пробелом перед числом позволяет избежать ложных срабатываний, если в середине названия встретится похожая комбинация символов.

Вариант 2. Вызов функции общего модуля из вычисляемого поля СКД

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

  1. Создадим в конфигурации общий модуль (например, СтроковыеФункцииКлиентСервер или используем существующий серверный модуль). Убедимся, что у модуля включены флаги Сервер и Внешнее соединение.
  2. Опишем функцию, которая извлекает последнее слово из строки и преобразует его в число:

Функция ПолучитьОбъемИзНаименования(Знач Наименование) Экспорт
    
    Если ПустаяСтрока(Наименование) Тогда
        Возврат 0;
    КонецЕсли;
    
    МассивСлов = СтрРазделить(СокрЛП(Наименование), " ");
    Если МассивСлов.Количество() = 0 Тогда
        Возврат 0;
    КонецЕсли;
    
    ПоследнееСлово = ВРег(МассивСлов[МассивСлов.ВГраница()]);
    
    // Удаляем обозначения единиц измерения
    ОчищенноеЗначение = СтрЗаменить(ПоследнееСлово, "Л", "");
    ОчищенноеЗначение = СтрЗаменить(ОчищенноеЗначение, "ЛИТР", "");
    ОчищенноеЗначение = СтрЗаменить(ОчищенноеЗначение, "Л.", "");
    ОчищенноеЗначение = СтрЗаменить(ОчищенноеЗначение, ",", ".");
    
    Попытка
        Возврат Число(ОчищенноеЗначение);
    Исключение
        Возврат 0;
    КонецПопытки;
    
КонецФункции
  1. В схеме компоновки данных (СКД) перейдем на вкладку Вычисляемые поля.
  2. Добавим новое поле с путем к данным Литров, а в колонке Выражение пропишем вызов функции: ИмяОбщегоМодуля.ПолучитьОбъемИзНаименования(Номенклатура.Наименование).

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

Вариант 3. Постобработка выборки и передача Таблицы значений в СКД

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


// 1. Получаем данные запросом
РезультатЗапроса = Запрос.Выполнить();
ТаблицаДанных = РезультатЗапроса.Выгрузить();

// 2. Добавляем колонку для вычисленного значения
ТаблицаДанных.Колонки.Добавить("Литров", Новый ОписаниеТипов("Число", Новый КвалификаторыЧисла(10, 2)));

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

// 4. Передаем ТаблицуЗначений в СКД как внешний источник
ВнешниеНаборыДанных = Новый Структура;
ВнешниеНаборыДанных.Вставить("ТаблицаТоваров", ТаблицаДанных);

СхемаКомпоновки = ЭтотОбъект.ПолучитьМакет("ОсновнаяСхемаКомпоновкиДанных");
Настройки = СхемаКомпоновки.НастройкиПоУмолчанию;

КомпоновщикМакета = Новый КомпоновщикМакетаКомпоновкиДанных;
МакетКомпоновки = КомпоновщикМакета.Выполнить(СхемаКомпоновки, Настройки);

ПроцессорКомпоновки = Новый ПроцессорКомпоновкиДанных;
ПроцессорКомпоновки.Инициализировать(МакетКомпоновки, ВнешниеНаборыДанных);

ПроцессорВывода = Новый ПроцессорВыводаРезультатаКомпоновкиДанныхВТабличныйДокумент;
ПроцессорВывода.УстановитьДокумент(Элементы.Результат);
ПроцессорВывода.Вывести(ПроцессорКомпоновки);

Рекомендация по нормализации нормативно-справочной информации (НСИ)

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

  1. Использовать типовой механизм Дополнительных реквизитов (в конфигурациях на базе БСП: 1С:ERP, 1С:КА, 1С:УТ, 1С:УНФ), добавив числовой реквизит «Объем (л)». Это позволит связывать и фильтровать данные в запросе через стандартное левое соединение.
  2. Использовать механизмы упаковок или единиц измерения с заданным коэффициентом пересчета в базовые единицы.
← На главную