При работе с Системой Компоновки Данных (СКД) в 1С часто возникает задача, когда необходимо вывести в отчете агрегированные данные, причем не в отдельной колонке, а непосредственно в ячейке группировки, рядом с основным полем группировки. Особенно это актуально, когда требуется собрать список связанных значений (например, наименований документов) и отобразить их через разделитель в одной строке с элементом основной группировки. Давайте рассмотрим подробнее, как решить эту задачу, используя стандартные возможности СКД.
Представим типовую ситуацию: у нас есть данные по поступлениям номенклатуры, и мы хотим видеть список всех поступлений для каждой номенклатуры в одной ячейке с названием самой номенклатуры, а затем в отдельных колонках - цены по годам.
Исходные данные, которые мы получаем из запроса, выглядят примерно так:
Номенклатура | Поступление | Год поступления | Цена из поступления
Ном 1 | Поступление 12 от 2020 | 2020 | 100
Ном 1 | Поступление 34 от 2021 | 2021 | 150
Ном 2 | Поступление 56 от 2020 | 2020 | 200
Ном 2 | Поступление 78 от 2021 | 2021 | 180
Целевой вид отчета, к которому мы стремимся:
Номенклатура | Поступление | 2020 | 2021
Ном 1 | Поступление 12 от 2020; Поступление 34 от 2021 | 100 | 150
Ном 2 | Поступление 56 от 2020; Поступление 78 от 2021 | 200 | 180
Мы видим, что в целевом отчете для каждой номенклатуры в одной ячейке объединены её наименование и список всех связанных поступлений, а затем идут колонки с ценами по годам. Мы разберем по шагам, как добиться такого результата в СКД.
Прежде всего, нам необходимо убедиться, что наш запрос СКД возвращает все необходимые поля. В нашем случае это:
НоменклатураПоступление (представление документа поступления, например, "Поступление 12 от 2020")ГодПоступления (или просто Год, извлеченный из даты поступления)ЦенаЗапрос может выглядеть примерно так:
ВЫБРАТЬ
ТаблицаПоступлений.Номенклатура КАК Номенклатура,
ТаблицаПоступлений.Поступление.Представление КАК Поступление,
ГОД(ТаблицаПоступлений.ДатаПоступления) КАК ГодПоступления,
ТаблицаПоступлений.Цена КАК Цена
ИЗ
РегистрНакопления.ПоступленияТоваров.Обороты КАК ТаблицаПоступлений
Убедитесь, что в списке доступных полей на вкладке "Наборы данных" присутствуют все эти поля.
Ключевым моментом для сбора нескольких значений в одну ячейку является использование ресурсов СКД. Мы создадим новый ресурс, который будет собирать все представления документов поступления для каждой номенклатуры.
СписокПоступлений.Массив(Поступление).Номенклатура. Это означает, что массив поступлений будет собираться для каждого уникального значения поля Номенклатура.Использование функции Массив() в выражении ресурса имеет существенное преимущество: СКД соберет все значения поля Поступление в массив для каждой группировки. При выводе в отчет этот массив по умолчанию будет преобразован в строку, элементы которой будут перечислены через запятую. Более того, как отметил автор темы, такой массив сохраняет возможность детализации: по правой кнопке мыши на ячейке можно будет открыть список значений и, возможно, перейти к конкретному документу, если для поля Поступление настроен соответствующий параметр расшифровки.
Альтернативный вариант, если детализация не требуется, и вы хотите полностью контролировать разделитель, это использовать функцию СоединитьСтроки():
СоединитьСтроки(Массив(Поступление), "; ")
Это выражение сразу вернет строку с поступлениями, разделенными точкой с запятой. Однако в нашем примере мы остановимся на Массив(Поступление), так как это дает больше гибкости и соответствует опыту автора темы. Наглядные практические отчеты с этими функциями можно изучить в примерах использования функций СКД Массив и СоединитьСтроки.
Теперь, когда у нас есть необходимый ресурс, приступим к построению структуры отчета:
Номенклатура.ГодПоступления.Цена.На этом этапе ваш отчет будет выводить номенклатуру по строкам, годы по колонкам и цены на пересечениях. Но ресурс СписокПоступлений пока не будет отображаться так, как нам нужно.
Чтобы ресурс СписокПоступлений появился рядом с Номенклатурой в строке группировки, необходимо добавить его в "Выбранные поля" для самой группировки Номенклатура. Это может показаться нелогичным, так как ресурс обычно ассоциируется с ячейками данных, но СКД позволяет выводить ресурсы и в заголовках группировок.
Номенклатура в разделе "Строки".НоменклатураСписокПоступлений (наш только что созданный ресурс)Важный нюанс: После этих действий, если вы сформируете отчет, вы, скорее всего, увидите, что Номенклатура и СписокПоступлений отображаются в разных колонках в рамках заголовка группировки по строкам. Это не то, что нам нужно. СКД по умолчанию стремится размещать каждое поле в своей колонке. Для того чтобы они оказались в одной ячейке, нам потребуется настроить пользовательский макет.
Чтобы объединить несколько полей в одной ячейке заголовка группировки, мы должны использовать функциональность пользовательских макетов СКД. Это позволяет нам полностью контролировать внешний вид заголовков и подвалов группировок. Практический порядок создания таких настроек показан в примере использования собственных макетов в СКД.
Номенклатура
[Номенклатура] ([СписокПоступлений])
Здесь [Номенклатура] и [СписокПоступлений] – это ссылки на поля. СКД автоматически подставит значения этих полей в шаблон. Круглые скобки и пробел между ними – это обычный текст, который будет отображаться.
Номенклатура и СписокПоступлений установлен как "Поле".Теперь, когда вы сформируете отчет, СКД будет использовать этот пользовательский макет для отображения заголовка группировки Номенклатура. В одной ячейке вы увидите наименование номенклатуры и через пробел список всех поступлений, собранных в массив, который СКД автоматически преобразует в строку для вывода.
Мы выяснили, что основной подход заключается в создании ресурса типа Массив() и его выводе через пользовательский макет группировки. Давайте проанализируем некоторые важные аспекты и дополнительные возможности:
Использование Массив(Поступление) как выражения ресурса не только позволяет отобразить объединенную строку, но и сохраняет ссылку на исходные данные. Как было отмечено в исходной теме, это дает возможность по правой кнопке мыши на ячейке с объединенными поступлениями открыть список значений и, при наличии соответствующих настроек, перейти к просмотру конкретного документа поступления. Это очень мощная функция, которая значительно повышает интерактивность отчета.
Для корректной работы детализации убедитесь, что поле Поступление в вашем запросе является ссылочным типом данных (например, ДокументСсылка.ПоступлениеТоваровУслуг). СКД автоматически свяжет эти ссылки с возможностью их открытия.
В макете группировки вы имеете полный контроль над форматированием ячейки: шрифт, размер, цвет, выравнивание. Вы можете сделать заголовок более читабельным, выделив его жирным или изменив цвет фона.
Если вам нужно изменить разделитель по умолчанию для массива (который обычно является запятой с пробелом), вы можете использовать функцию СоединитьСтроки(Массив(Поступление), "; ") вместо просто Массив(Поступление). Это даст вам точный контроль над тем, как элементы массива будут объединены в строку.
Если для какой-то номенклатуры поступлений не будет, Массив() вернет пустой массив. При выводе в шаблоне ([СписокПоступлений]) это может привести к выводу пустых скобок. Если это нежелательно, вы можете использовать более сложное выражение в шаблоне макета, или, что чаще, изменить само выражение ресурса:
ВЫБОР КОГДА ЕСТЬNULL(Количество(Поступление), 0) > 0 ТОГДА СоединитьСтроки(Массив(Поступление), "; ") ИНАЧЕ "" КОНЕЦ
Такое выражение ресурса будет возвращать пустую строку, если поступлений нет, что предотвратит вывод пустых скобок в отчете.
В некоторых случаях, если функционал Массив() или СоединитьСтроки(Массив()) в СКД не подходит или вызывает сложности с производительностью на очень больших объемах данных, можно агрегировать строки непосредственно в запросе. Для этого используются специфичные для СУБД функции. Например, в PostgreSQL это STRING_AGG(), в MS SQL Server STRING_AGG() или FOR XML PATH(''), в Oracle LISTAGG().
Пример для SQL Server (псевдокод, может отличаться от синтаксиса 1С):
ВЫБРАТЬ
Номенклатура,
(
ВЫБРАТЬ STRING_AGG(Поступление.Представление, '; ')
ИЗ ТаблицаПоступлений AS Внутренняя
ГДЕ Внутренняя.Номенклатура = Основная.Номенклатура
) КАК СписокПоступлений,
ГодПоступления,
Цена
ИЗ
РегистрНакопления.ПоступленияТоваров.Обороты КАК Основная
Однако такой подход сложнее в реализации через конструктор запросов 1С и часто требует программного формирования текста запроса. Кроме того, он лишает возможности детализации, которую дает ресурс Массив() в СКД. Поэтому, для большинства задач, решение через ресурсы и макеты СКД является предпочтительным.
Мы рассмотрели, как эффективно настроить вывод объединенного списка значений в одной ячейке с полем группировки в таблице СКД. Основные шаги включают создание ресурса типа Массив(), добавление его в выбранные поля группировки и, что самое главное, настройку пользовательского макета для заголовка группировки с использованием шаблона. Этот метод позволяет не только достичь желаемого визуального представления, но и сохранить мощные функции детализации, присущие СКД.
Используя эти инструкции, вы сможете создавать более информативные и удобные для анализа отчеты в 1С, гибко управляя расположением и агрегацией данных в группировках.