Как реализовать разделение строки по разделителю в отчете СКД

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

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

Способ 1. Использование строковых функций в языке запросов

Если мы заранее знаем, что строка содержит только два значения, разделенных одним символом (например, "Новый, 123"), самым простым и производительным решением будет использование стандартных функций языка запросов: ЛЕВ, ПРАВ и СТРНАЙТИ. Рассмотрим, как это реализовать.

Предположим, у нас есть поле ЭтоСтрока. Нам нужно выделить часть до запятой и часть после нее. Проанализируем логику: сначала мы находим позицию разделителя, а затем отсекаем нужные фрагменты.


ВЫБРАТЬ
    ЛЕВ(Источник.ЭтоСтрока, СТРНАЙТИ(Источник.ЭтоСтрока, ",") - 1) КАК Колонка1,
    ПРАВ(Источник.ЭтоСтрока, ДЛИНАСТРОКИ(Источник.ЭтоСтрока) - СТРНАЙТИ(Источник.ЭтоСтрока, ",")) КАК Колонка2
ИЗ
    Справочник.Номенклатура КАК Источник

Важные нюансы этого подхода:

  1. Функция СТРНАЙТИ доступна в платформе 1С, начиная с версии 8.3.6. Если ваша конфигурация работает в режиме совместимости с более старыми версиями, этот метод в запросе может не сработать. Чтобы избежать подобных проблем, полезно проводить анализ конфигурации и отчетов на наличие ошибок, связанных с совместимостью функций.
  2. Необходимо обрабатывать ситуацию, когда разделитель отсутствует. В противном случае функции могут вернуть пустую строку или вызвать ошибку на стороне СУБД.
  3. Для повышения надежности рекомендуется использовать ВЫРАЗИТЬ(Поле КАК СТРОКА(100)), чтобы СУБД четко понимала длину обрабатываемых данных.

Способ 2. Разделение строки с неопределенным количеством элементов (через таблицу чисел)

Ситуация усложняется, когда строка содержит множество фрагментов. Подобные задачи часто встречаются, когда требуется разобрать текст на отдельные слова или извлечь список кодов. В этом случае обычными функциями ЛЕВ и ПРАВ не обойтись. Разберем продвинутый метод парсинга строки прямо в запросе СКД с помощью вспомогательной таблицы чисел.

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

Сначала подготовим исходные данные и таблицу цифр для генерации номеров:


ВЫБРАТЬ
    ПриходнаяНакладная.Ссылка КАК Ссылка,
    (ВЫРАЗИТЬ(ПриходнаяНакладная.Комментарий КАК СТРОКА(1000))) + "|" КАК Текст
ПОМЕСТИТЬ ВТ_Строка
ИЗ
    Документ.ПриходнаяНакладная КАК ПриходнаяНакладная;

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

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
    Н1.Номер * 100 + Н2.Номер * 10 + Н3.Номер КАК Номер
ПОМЕСТИТЬ Номера
ИЗ
    Цифры КАК Н1, Цифры КАК Н2, Цифры КАК Н3;

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


ВЫБРАТЬ
    ПОДСТРОКА(ВЗ.Текст, ВЗ.Н + 1, ВЗ.К - ВЗ.Н - 1) КАК Фрагмент,
    ВЗ.Ссылка КАК Ссылка
ИЗ
    (ВЫБРАТЬ
        Номера.Номер КАК Н,
        МИНИМУМ(Н_След.Номер) КАК К,
        Строка.Текст КАК Текст,
        Строка.Ссылка КАК Ссылка
    ИЗ
        Номера КАК Номера
        ВНУТРЕННЕЕ СОЕДИНЕНИЕ ВТ_Строка КАК Строка
            ПО (ПОДСТРОКА(Строка.Текст, Номера.Номер, 1) = "|" ИЛИ Номера.Номер = 0)
        ВНУТРЕННЕЕ СОЕДИНЕНИЕ Номера КАК Н_След
            ПО (ПОДСТРОКА(Строка.Текст, Н_След.Номер, 1) = "|") И (Н_След.Номер > Номера.Номер)
    СГРУППИРОВАТЬ ПО
        Номера.Номер, Строка.Текст, Строка.Ссылка) КАК ВЗ

Этот метод превращает одну строку с разделителями в несколько полноценных записей (строк) в результате запроса, что позволяет использовать их в группировках СКД.

Способ 3. Вычисляемые поля и функции общего модуля

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

Выясним причину, почему это удобно: вы пишете привычный код на языке 1С, используете СтрРазделить, массивы и циклы, а СКД просто выводит результат. Для этого:

  1. Создайте в общем модуле (например, РаботаСоСтроками) функцию с признаком "Сервер, Внешнее соединение".
  2. Функция должна принимать строку и индекс нужной части.

Функция ПолучитьЧастьСтроки(Знач ИсходнаяСтрока, Знач Разделитель, Знач Индекс) Экспорт
    МассивРезультата = СтрРазделить(ИсходнаяСтрока, Разделитель, Ложь);
    Если Индекс < МассивРезультата.Количество() Тогда
        Возврат МассивРезультата[Индекс];
    КонецЕсли;
    Возврат "";
КонецФункции

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

РаботаСоСтроками.ПолучитьЧастьСтроки(Комментарий, ";", 0)

Способ 4. Использование СтрРазделить в выражениях СКД (Платформа 8.3.15+)

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

Проанализируем пример. Если в вычисляемом поле написать СтрРазделить(МоеПоле, ",")[0], система вернет первый элемент массива. Важно помнить: такая возможность доступна именно в вычисляемых полях или в ресурсах, но не в тексте самого запроса к базе данных.

Рекомендации по выбору метода

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

← На главную