При формировании аналитических отчетов разработчики часто сталкиваются с ситуацией, когда критически важные характеристики товара (например, объем фасовки «1л», «4л», «5л») хранятся не в виде отдельных реквизитов или дополнительных свойств, а непосредственно в текстовом наименовании номенклатуры. Рассмотрим, какими способами можно выделить эти данные для использования в отчетах на СКД или стандартных выборках.
Язык запросов платформы 1С:Предприятие имеет существенные ограничения при работе со строками: в нем отсутствуют встроенные функции динамического поиска подстрок с конца, регулярные выражения или аналоги метода СтрРазделить(). Поэтому в зависимости от архитектуры задачи применяются различные подходы.
Если набор возможных значений объемов заранее известен и ограничен (например, стандартная тара масел: 1л, 4л, 5л, 10л, 20л, 200л), задачу можно решить непосредственно на уровне СУБД в тексте запроса. Разберем по шагам, как построить условие с оператором ПОДОБНО:
ВЫБОР
КОГДА Номенклатура.Наименование ПОДОБНО "% 1л" ТОГДА 1
КОГДА Номенклатура.Наименование ПОДОБНО "% 4л" ТОГДА 4
КОГДА Номенклатура.Наименование ПОДОБНО "% 5л" ТОГДА 5
КОГДА Номенклатура.Наименование ПОДОБНО "% 6л" ТОГДА 6
КОГДА Номенклатура.Наименование ПОДОБНО "% 10л" ТОГДА 10
КОГДА Номенклатура.Наименование ПОДОБНО "% 20л" ТОГДА 20
ИНАЧЕ 0
КОНЕЦ КАК Литров
Обратите внимание: использование шаблона вида "% 1л" с пробелом перед числом позволяет избежать ложных срабатываний, если в середине названия встретится похожая комбинация символов.
Если отчет строится с помощью Системы компоновки данных (СКД), наиболее элегантным и гибким решением будет использование вычисляемого поля, вызывающего функцию парсинга на встроенном языке. Разберем алгоритм настройки:
СтроковыеФункцииКлиентСервер или используем существующий серверный модуль). Убедимся, что у модуля включены флаги Сервер и Внешнее соединение.
Функция ПолучитьОбъемИзНаименования(Знач Наименование) Экспорт
Если ПустаяСтрока(Наименование) Тогда
Возврат 0;
КонецЕсли;
МассивСлов = СтрРазделить(СокрЛП(Наименование), " ");
Если МассивСлов.Количество() = 0 Тогда
Возврат 0;
КонецЕсли;
ПоследнееСлово = ВРег(МассивСлов[МассивСлов.ВГраница()]);
// Удаляем обозначения единиц измерения
ОчищенноеЗначение = СтрЗаменить(ПоследнееСлово, "Л", "");
ОчищенноеЗначение = СтрЗаменить(ОчищенноеЗначение, "ЛИТР", "");
ОчищенноеЗначение = СтрЗаменить(ОчищенноеЗначение, "Л.", "");
ОчищенноеЗначение = СтрЗаменить(ОчищенноеЗначение, ",", ".");
Попытка
Возврат Число(ОчищенноеЗначение);
Исключение
Возврат 0;
КонецПопытки;
КонецФункции
Литров, а в колонке Выражение пропишем вызов функции: ИмяОбщегоМодуля.ПолучитьОбъемИзНаименования(Номенклатура.Наименование).Такой способ позволяет вычислять значения динамически без необходимости модификации табличной части отчета вручную.
Если отчет формируется программно или требуется сложный предварительный анализ массива номенклатуры, можно сначала выполнить базовый запрос, обработать строки в коде и передать результирующую ТаблицуЗначений в качестве внешнего набора данных СКД. Проанализируем пример кода постобработки:
// 1. Получаем данные запросом
РезультатЗапроса = Запрос.Выполнить();
ТаблицаДанных = РезультатЗапроса.Выгрузить();
// 2. Добавляем колонку для вычисленного значения
ТаблицаДанных.Колонки.Добавить("Литров", Новый ОписаниеТипов("Число", Новый КвалификаторыЧисла(10, 2)));
// 3. Обрабатываем каждую строку
Для Каждого СтрокаТЗ Из ТаблицаДанных Цикл
МассивСлов = СтрРазделить(СокрЛП(СтрокаТЗ.Номенклатура), " ");
Если МассивСлов.Количество() > 0 Тогда
ПоследнееСлово = ВРег(МассивСлов[МассивСлов.ВГраница()]);
СтрокаЛитры = СтрЗаменить(ПоследнееСлово, "Л", "");
СтрокаЛитры = СтрЗаменить(СтрокаЛитры, ",", ".");
Попытка
СтрокаТЗ.Литров = Число(СтрокаЛитры);
Исключение
СтрокаТЗ.Литров = 0;
КонецПопытки;
КонецЕсли;
КонецЦикла;
// 4. Передаем ТаблицуЗначений в СКД как внешний источник
ВнешниеНаборыДанных = Новый Структура;
ВнешниеНаборыДанных.Вставить("ТаблицаТоваров", ТаблицаДанных);
СхемаКомпоновки = ЭтотОбъект.ПолучитьМакет("ОсновнаяСхемаКомпоновкиДанных");
Настройки = СхемаКомпоновки.НастройкиПоУмолчанию;
КомпоновщикМакета = Новый КомпоновщикМакетаКомпоновкиДанных;
МакетКомпоновки = КомпоновщикМакета.Выполнить(СхемаКомпоновки, Настройки);
ПроцессорКомпоновки = Новый ПроцессорКомпоновкиДанных;
ПроцессорКомпоновки.Инициализировать(МакетКомпоновки, ВнешниеНаборыДанных);
ПроцессорВывода = Новый ПроцессорВыводаРезультатаКомпоновкиДанныхВТабличныйДокумент;
ПроцессорВывода.УстановитьДокумент(Элементы.Результат);
ПроцессорВывода.Вывести(ПроцессорКомпоновки);
Выделение характеристик из текстового наименования через запросы и программные функции является временным решением. Для построения надежного и быстродействующего учета рекомендуется нормализовать данные справочника Номенклатура: