Как убрать лишние пробелы и разделители в функции СоединитьСтроки() в СКД?

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

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

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

Выясним причину: почему функция СоединитьСтроки() не игнорирует "пустоту"?

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

Рассмотрим по шагам основные способы исправления этой ситуации.

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

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

Предположим, у нас есть поля КодНеявки и Часы. Если часов нет, мы не хотим видеть пробел после кода. Посмотрим на пример выражения в поле "Ресурс":


СоединитьСтроки(
    ТаблицаЗначений(
        КодНеявки, 
        ВЫБОР КОГДА Часы = 0 ИЛИ Часы = "" ТОГДА NULL ИНАЧЕ Часы КОНЕЦ
    ), 
    "; ", 
    " "
)

В данном случае, если поле Часы равно нулю, оно превращается в NULL. Вторая часть составного элемента (внутри одной строки) исчезает, и лишний пробел (третий параметр функции — разделитель колонок) не добавляется.

Способ 2. Настройка роли поля в наборе данных

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

Хотя эта галка в первую очередь влияет на соединение наборов, ее правильная настройка помогает системе корректно интерпретировать отсутствие данных. Однако помните, что для строковых полей, где в БД записана именно пустая строка, а не NULL, этот метод может не сработать без предварительного преобразования в запросе через ЕСТЬNULL или ВЫБОР КОГДА.

Способ 3. Подготовка данных в Вычисляемых полях

Часто программисты пытаются написать всю логику сразу в ресурсах, что делает выражение нечитаемым. Мы рекомендуем вынести логику склейки конкретной строки в "Вычисляемые поля".

Создадим вычисляемое поле, например, ПредставлениеСтрокиНеявки. В выражении напишем:


КодНеявки + ВЫБОР КОГДА ЗначениеЗаполнено(Часы) ТОГДА " (" + Строка(Часы) + ")" ИНАЧЕ "" КОНЕЦ

Теперь в ресурсах нам достаточно использовать простую конструкцию:

СоединитьСтроки(Массив(ПредставлениеСтрокиНеявки), "; ")

Важный нюанс: использование функции Массив() вместо ТаблицаЗначений() внутри СоединитьСтроки() часто работает быстрее и избавляет от проблем с разделителями колонок, так как мы оперируем уже готовой строкой.

Способ 4. Использование функции СтрЗаменить() для очистки результата

Если структура данных сложная и NULL по каким-то причинам не помогают, можно прибегнуть к "грубой силе" — обрезать лишние разделители в итоговой строке. Рассмотрим пример из практики, когда нужно убрать лишние точки с запятой и двойные пробелы:


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

Здесь мы сначала сворачиваем таблицу (чтобы убрать дубликаты), соединяем всё в строку, а затем последовательно удаляем артефакты. Метод не самый изящный, но крайне надежный в сложных отчетах.

Способ 5. Работа с макетами полей

Рассмотрим еще один вариант решения задачи. В СКД на закладке "Макеты" можно создать макет для конкретного поля. Если в параметрах макета прописать выражение с условием, мы сможем визуально скрыть ненужные данные.

В поле выражения макета можно написать:

ВЫБОР КОГДА ПараметрПоле = "" ТОГДА "" ИНАЧЕ ПараметрПоле КОНЕЦ

Это заставит систему пересчитать представление поля непосредственно перед выводом в табличный документ.

Способ 6. Программная обработка схемы компоновки

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

Разберем пример кода, который перебирает поля итога и оборачивает их в функцию СтрЗаменить():


Процедура ЗаполнитьПоляИтогаСхемыКомпоновкиДанных(ИсполняемаяСхема)
    Для Каждого ПолеИтога Из ИсполняемаяСхема.ПоляИтога Цикл
        // Проверяем, используется ли в ресурсе соединение строк
        Если Не СтрНачинаетсяС(ВРег(СокрЛ(ПолеИтога.Выражение)), "СОЕДИНИТЬСТРОКИ(") Тогда
            Продолжить;
        КонецЕсли;

        Выражение = ПолеИтога.Выражение;
        // Заменяем пустые представления дат и пустые строки на "пусто"
        Выражение = СтрШаблон("СтрЗаменить(%1, ""01.01.0001 0:00:00"", """")", Выражение);
        Выражение = СтрШаблон("СтрЗаменить(%1, "" , "", """")", Выражение);
        
        ПолеИтога.Выражение = Выражение;
    КонецЦикла;
КонецПроцедуры

Этот подход позволяет автоматизировать "чистку" данных, не внося изменения в каждое поле вручную в конструкторе СКД.

Способ 7. Разделение наборов данных

Проанализируем ситуацию, когда нужно собрать реквизиты разных объектов. Если стандартная связь наборов выдает пустые строки, которые мешают агрегации, можно пойти на хитрость: создать под каждый специфический реквизит отдельный набор данных с условием ГДЕ Поле <> "". При соединении по ключу (например, по Контрагенту) в итоговую таблицу попадут только реально заполненные значения, и функция СоединитьСтроки() отработает идеально.

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

Проблема лишних разделителей в СоединитьСтроки() решается на разных уровнях:

  1. На уровне запроса/ресурса: приведение пустых значений к NULL — это "золотой стандарт".
  2. На уровне структуры СКД: вынос логики в вычисляемые поля с использованием ЗначениеЗаполнено().
  3. На уровне визуализации: использование СтрЗаменить() прямо в выражении итога.

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

← На главную