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

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

При работе с Системой компоновки данных (СКД) программисты часто сталкиваются с необходимостью объединить несколько строковых полей в одну строку с использованием определенного разделителя. Для этого в языке выражений СКД предусмотрена функция СоединитьСтроки. Однако стандартное поведение этой функции иногда преподносит сюрпризы: если одно из объединяемых полей оказывается пустым или содержит NULL, в итоговой строке могут появиться «лишние» разделители, например, "; ;" или ", ,". Это портит внешний вид отчета и делает данные трудночитаемыми.

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

Разберем причину возникновения пустых значений

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

  1. Вкладка «Ресурсы»: Здесь функция работает как классический агрегат. Если вы указываете СоединитьСтроки(Наименование), СКД перебирает записи в группировке. Если поле Наименование в какой-то записи равно NULL, функция просто игнорирует эту строку и не добавляет лишний разделитель.
  2. Вкладка «Вычисляемые поля»: Здесь часто используется конструкция ТаблицаЗначений(Поле1, Поле2, Поле3). В этом случае вы принудительно создаете коллекцию элементов. Если Поле2 пустое, оно все равно попадает в коллекцию как элемент. Функция СоединитьСтроки видит три элемента и честно ставит разделители между ними, даже если второй элемент — пустая строка.

Рассмотрим основные способы борьбы с этой проблемой.

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

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

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


СтрЗаменить(
    СоединитьСтроки(
        ТаблицаЗначений(Сотрудник, ПричинаЗаписи, Комментарий), 
        ";", 
        "; "
    ),
    "; ;", 
    ";"
)

В данном случае мы сначала собираем строку, а затем ищем комбинации пустых значений, разделенных точкой с запятой, и заменяем их на одиночный разделитель. Однако этот метод имеет изъян: если пустое значение окажется в самом начале или в самом конце, СтрЗаменить может не справиться с краевыми разделителями. Поэтому рассмотрим более надежные варианты.

Способ 2. Приведение пустых значений к NULL в запросе

Выясним важную техническую деталь: функция СоединитьСтроки во многих случаях лучше обрабатывает NULL, чем пустые строки "". Если ваши данные приходят из запроса, мы можем на лету трансформировать пустые строки в NULL. Это позволит агрегатным механизмам СКД «отфильтровать» их автоматически.

Рассмотрим пример реализации в тексте запроса или в выражении поля:


ВЫБОР 
    КОГДА ФОТ1Категорию = "" ТОГДА NULL 
    ИНАЧЕ ФОТ1Категорию 
КОНЕЦ

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

Способ 3. Использование общего модуля (Универсальный подход)

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

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


Функция СоединитьСтрокиБезПустых(Знач МассивСтрок, Разделитель = "; ") Экспорт
    Результат = "";
    Для Каждого Стр Из МассивСтрок Цикл
        ТекущееЗначение = СокрЛП(Строка(Стр));
        Если ПустаяСтрока(ТекущееЗначение) Тогда
            Продолжить;
        КонецЕсли;
        
        Результат = Результат + ?(ПустаяСтрока(Результат), "", Разделитель) + ТекущееЗначение;
    КонецЦикла;
    Возврат Результат;
КонецФункции

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

Посмотрим на пример вызова:

СерверныеФункцииОтчетов.СоединитьСтрокиБезПустых(ТаблицаЗначений(Характер, Категория, Воздух))

Способ 4. Трансформация данных в запросе (UNPIVOT)

Рассмотрим ситуацию, когда нам нужно соединить значения из разных колонок одной строки. Вместо того чтобы мучиться с разделителями в вычисляемом поле, мы можем «развернуть» эти колонки в строки прямо в запросе с помощью оператора ОБЪЕДИНИТЬ ВСЕ.

Проанализируем пример структуры запроса:


ВЫБРАТЬ Ссылка, Характер КАК Значение ИЗ Справочник.Объекты ГДЕ Характер <> ""
ОБЪЕДИНИТЬ ВСЕ
ВЫБРАТЬ Ссылка, Категория ИЗ Справочник.Объекты ГДЕ Категория <> ""
ОБЪЕДИНИТЬ ВСЕ
ВЫБРАТЬ Ссылка, ОткрытыйВоздух ИЗ Справочник.Объекты ГДЕ ОткрытыйВоздух <> ""

После такой подготовки данных в СКД появится поле Значение. Теперь достаточно в Ресурсах написать СоединитьСтроки(Значение, "; ") с группировкой по Ссылка. Поскольку пустые значения мы отсекли еще на этапе запроса условием ГДЕ, результат будет идеально чистым.

Способ 5. Использование функции СтрСоединить (Платформа 8.3.10+)

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

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

Подведем итоги

Выясним, какой метод выбрать в зависимости от ситуации:

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

← На главную