При разработке отчетов с использованием Системы Компоновки Данных (СКД) разработчики часто сталкиваются с необходимостью объединить (выполнить конкатенацию) ссылочное поле (например, документ) и строковый реквизит. Давайте подробно проанализируем ситуацию, когда вместо ожидаемой строки в отчете выводится пустое значение, и разберем по шагам, как грамотно решать эту задачу с учетом всех технических нюансов платформы 1С.
Рассмотрим пример из практики. Допустим, мы пытаемся создать в отчете СКД строку вида "Наряд на внутренние работы (обучение стажера)". У нас есть поле ТипДокумента (содержащее ссылку на документ) и поле ОписаниеРаботы (строка). Первоначальное выражение в вычисляемом поле выглядит так:
ВЫБОР
КОГДА ТИПЗНАЧЕНИЯ(ТипДокумента) = ТИП("Документ.НарядНаВнутренниеРаботы")
ТОГДА ТипДокумента + " (" + ОписаниеРаботы + ")"
КОНЕЦ
В результате выполнения этого кода мы получаем пустоту. Выясним причину такого поведения. Дело в том, что выражение ТипДокумента + " (" + ОписаниеРаботы + ")" представляет собой попытку сложить ДокументСсылка и строку. В отличие от встроенного языка 1С, где платформа часто "прощает" такие вещи и выполняет неявное преобразование типов, СКД не выполняет неявное приведение типов при конкатенации. Выражение возвращает ошибку вычисления, и в отчет выводится пустая ячейка.
Чтобы код заработал, рассмотрим главное правило конкатенации в СКД: перед сложением со строкой мы обязаны явно привести все значения к типу "Строка". Для этого в СКД существует функция Строка(). Посмотрим на исправленный вариант кода:
ВЫБОР
КОГДА ТИПЗНАЧЕНИЯ(ТипДокумента) = ТИП("Документ.НарядНаВнутренниеРаботы")
ТОГДА Строка(ТипДокумента) + " (" + ОписаниеРаботы + ")"
КОНЕЦ
Теперь система понимает, что мы складываем три строковых значения, и корректно выводит результат в отчет.
Если в ветке ТОГДА мы точно знаем, что тип документа — это "Наряд на внутренние работы", и нам не обязательно выводить его стандартное представление (включающее номер и дату), мы можем сразу написать нужный текст. Разберем этот пример:
ВЫБОР
КОГДА ТИПЗНАЧЕНИЯ(ТипДокумента) = ТИП("Документ.НарядНаВнутренниеРаботы")
ТОГДА "Документ Наряд на внутренние работы (" + ОписаниеРаботы + ")"
КОНЕЦ
Такой подход работает быстрее, так как платформе не нужно обращаться к базе данных для получения строкового представления ссылки документа.
Проанализируем ситуацию глубже. Чтобы вычисляемое поле работало надежно и без сбоев на любых данных, необходимо учесть ряд важных особенностей платформы.
При использовании оператора + в СКД есть коварная особенность: если хотя бы один из операндов равен NULL (например, поле ОписаниеРаботы не заполнено и получено через левое соединение), результатом всего сложения станет NULL, и вся строка исчезнет. Защитим наше выражение с помощью функции ЕстьNull():
ВЫБОР
КОГДА ТИПЗНАЧЕНИЯ(ТипДокумента) = ТИП("Документ.НарядНаВнутренниеРаботы")
ТОГДА Строка(ТипДокумента) + " (" + ЕстьNull(ОписаниеРаботы, "") + ")"
КОНЕЦ
Вместо громоздкой конструкции ТИПЗНАЧЕНИЯ(Поле) = ТИП("...") рассмотрим более элегантный и рекомендуемый 1С способ проверки типа — оператор ССЫЛКА. Он делает код лаконичнее:
ВЫБОР
КОГДА ТипДокумента ССЫЛКА Документ.НарядНаВнутренниеРаботы
ТОГДА Строка(ТипДокумента) + " (" + ЕстьNull(ОписаниеРаботы, "") + ")"
КОНЕЦ
Для получения текста ссылки можно использовать не только Строка(), но и функцию ПРЕДСТАВЛЕНИЕ(). На практике ПРЕДСТАВЛЕНИЕ(ТипДокумента) часто отрабатывает эффективнее при массовом выводе строк, так как СКД умеет оптимизировать получение представлений.
Если конфигурация рассчитана на работу с несколькими языками, жестко вшивать текст не рекомендуется. Разберем использование функции НСтр() для мультиязычности:
ВЫБОР
КОГДА ТипДокумента ССЫЛКА Документ.НарядНаВнутренниеРаботы
ТОГДА НСтр("ru='Наряд на работы'") + " (" + ЕстьNull(ОписаниеРаботы, "") + ")"
КОНЕЦ
Посмотрим на еще одну потенциальную ошибку. Даже если тип совпал (это действительно документ нужного вида), ссылка может быть пустой (например, битая ссылка или незаполненный реквизит). Если мы попробуем получить от нее строковое представление, отчет может выглядеть некрасиво. Добавим проверку:
ВЫБОР
КОГДА ТипДокумента ССЫЛКА Документ.НарядНаВнутренниеРаботы И ТипДокумента.Ссылка ЕСТЬ НЕ NULL
ТОГДА ПРЕДСТАВЛЕНИЕ(ТипДокумента) + " (" + ЕстьNull(ОписаниеРаботы, "") + ")"
КОНЕЦ
В завершение проанализируем производительность. Вычисляемые поля СКД рассчитываются процессором уже после того, как данные получены из СУБД. Если в вашем отчете сотни тысяч строк, сложная склейка строк через условия ВЫБОР КОГДА в вычисляемых полях может существенно замедлить формирование отчета.
Рекомендация: по возможности переносите сложную логику и конкатенацию строковых полей на уровень запроса SQL (в текст основного набора данных). Используйте оператор объединения строк ПОДСТРОКА() и функции работы с NULL непосредственно в тексте запроса. Это позволит СУБД выполнить тяжелую работу, а СКД останется лишь вывести готовые данные.