При разработке отчетов и обработок в среде 1С часто возникает задача собрать данные из нескольких разных колонок в одну общую строку. Например, когда в справочнике ХарактеристикиНоменклатуры хранятся разные свойства (Пантон 1, Пантон 2), а в печатной форме их нужно вывести единым списком через запятую. В этой статье мы подробно разберем, как решить эту задачу с помощью языка запросов и механизмов Системы компоновки данных (СКД), а также проанализируем типичные ошибки, такие как обработка NULL и работа со ссылочными типами данных.
Самый прямой способ объединить поля — сделать это непосредственно в тексте запроса. Однако здесь программисты часто сталкиваются с тем, что простое сложение полей не работает, если они имеют тип «Ссылка» или если одно из значений не заполнено.
Рассмотрим ситуацию: у нас есть два поля Значение и Значение1. Если это строковые поля, мы можем попытаться сложить их. Но в 1С нельзя складывать ссылки — их нужно предварительно преобразовать в строку. Для этого используется функция ВЫРАЗИТЬ. Проанализируем правильный синтаксис конкатенации:
ВЫБРАТЬ
(ВЫРАЗИТЬ(Первыя.Значение КАК СТРОКА(100))) + ", " + (ВЫРАЗИТЬ(Первыя.Значение1 КАК СТРОКА(100))) КАК ОбъединенноеПоле
ИЗ
Первыя КАК Первыя
Важный нюанс: при использовании ВЫРАЗИТЬ необходимо обязательно указывать длину строки в скобках. Если вы работаете с объектами, имеющими наименования разной длины, выбирайте разумный максимум (например, 100 или 150 символов), чтобы избежать обрезки данных или избыточной нагрузки на СУБД.
Выясним причину, по которой запрос может возвращать пустые строки вместо ожидаемого результата. В языке запросов 1С любая операция со значением NULL (например, "Строка" + NULL) всегда дает в результате NULL. Если в вашем запросе используется ЛЕВОЕ СОЕДИНЕНИЕ и для какого-то объекта не найдено соответствующее свойство, вся итоговая строка станет пустой.
Чтобы избежать этой ситуации, разберем применение функции ЕСТЬNULL. Посмотрим на доработанный пример кода, который гарантирует корректный вывод даже при отсутствии данных:
ВЫБРАТЬ
ЕСТЬNULL(ВЫРАЗИТЬ(Таблица.Поле1 КАК СТРОКА(100)), "")
+ ВЫБОР КОГДА Таблица.Поле1 ЕСТЬ НЕ NULL И Таблица.Поле2 ЕСТЬ НЕ NULL ТОГДА ", " ИНАЧЕ "" КОНЕЦ
+ ЕСТЬNULL(ВЫРАЗИТЬ(Таблица.Поле2 КАК СТРОКА(100)), "") КАК Итог
ИЗ
Таблица КАК Таблица
Здесь мы не только защитились от NULL, но и добавили условие, чтобы запятая не выводилась в начале или в конце строки, если заполнено только одно из полей. Это делает результат профессиональным и удобным для чтения пользователем.
Если вы не хотите перегружать запрос сложными конструкциями ВЫБОР КОГДА, логичнее перенести задачу на уровень Системы компоновки данных. Рассмотрим использование вкладки «Вычисляемые поля». В отличие от запроса, здесь нам доступно больше функций, включая функции общих модулей и более гибкое преобразование типов.
В поле «Выражение» вычисляемого поля мы можем написать:
Представление(Значение1) + ", " + Представление(Значение2)
Функция Представление в СКД работает эффективнее, чем ВЫРАЗИТЬ в запросе, так как она автоматически берет текстовое описание любого объекта (будь то перечисление, ссылка на справочник или число), не требуя ручного указания длины строки.
Важно различать две разные задачи: объединение колонок в одной строке и объединение данных из разных строк в одну. Если ваша задача — собрать все «Пантоны» из разных записей таблицы в одну ячейку, используйте агрегатную функцию СКД СоединитьСтроки.
Перейдем на вкладку «Ресурсы» и для поля, которое должно стать списком, пропишем выражение:
СоединитьСтроки(Значение, ", ", "ПорядокСортировки")
Параметры функции позволяют нам:
Значение).", ").Иногда программное сложение строк в запросе или СКД избыточно, если нам нужно просто отобразить данные красиво. В СКД существует механизм макетов полей. Рассмотрим, как это работает:
[Пантон1], [Пантон2].В этом случае СКД сама сформирует итоговую строку в момент вывода отчета. Это наиболее «чистый» способ с точки зрения архитектуры, так как данные в наборе остаются ссылками (что позволяет использовать расшифровку), а объединение происходит только на уровне представления.
Проанализируем ситуацию с длиной строк. При использовании ВЫРАЗИТЬ(... КАК СТРОКА(X)) помните, что в некоторых СУБД (например, PostgreSQL или старые версии SQL Server) установка слишком большого значения X (более 1000) может привести к неоптимальной работе индексов или планов запросов. Если вам нужно объединять очень длинные текстовые поля (типа «ХранилищеЗначения» или неограниченные строки), делать это в запросе запрещено — такие операции следует выполнять исключительно в коде на встроенном языке или через вычисляемые поля СКД.
Подведем итог: для простого объединения в запросе используйте конкатенацию через + с обязательным ЕСТЬNULL и ВЫРАЗИТЬ. Для сложных отчетов с сохранением интерактивности лучше подходят вычисляемые поля или ресурсы СКД с функцией СоединитьСтроки.