При разработке отчетов на Системе компоновки данных (СКД) в 1С программисты часто сталкиваются с проблемой избыточности данных. Представим ситуацию: в вашем отчете должно выводиться 10 колонок. По 9 колонкам информация абсолютно идентична, но в десятой колонке (например, «Номер акта» или «Сертификат») содержатся разные значения. В результате на уровне базы данных мы получаем несколько строк, которые при выводе отчета дублируют всю основную информацию ради одного различающегося поля.
Попытки решить эту проблему «в лоб» через агрегатные функции или выражение ВычислитьВыражениеСГруппировкойМассив непосредственно в детальных записях обычно заканчиваются неудачей. В этой статье мы подробно разберем, почему так происходит, и рассмотрим три эффективных способа получить плоскую таблицу без дублирования строк, где все уникальные значения будут красиво склеены в одной ячейке.
Для начала проанализируем причину проблемы. Когда в настройках структуры отчета СКД мы используем элемент Детальные записи, система выводит строки в том виде, в котором они приходят из источника данных (запроса). Если в результате SQL-запроса вернулось 5 строк (так как у одного заказа может быть 5 разных актов), СКД послушно выведет все 5 строк.
Попытка написать в ресурсах выражение вида Массив(Различные НомерАкта) не схлопывает строки сами по себе. Ресурсы рассчитываются только для группировок. На уровне детальной записи (которая группировкой не является) контекст вычисления выражения равен текущей строке. В результате для каждой строки мы получаем массив из одного единственного элемента — значения текущей строки, а дублирование информации по остальным колонкам сохраняется.
Выражение ВычислитьВыражениеСГруппировкойМассив предназначено для совершенно других целей — для так называемого двойного агрегирования. Например, когда нам нужно на уровне номенклатуры рассчитать максимальные продажи, а затем на уровне группы сложить эти максимумы. Свернуть детальные записи в одну строку эта функция не поможет.
Ниже мы подробно разберем три рабочих сценария решения этой задачи.
Это самый изящный способ получить линейный отчет без дублирования строк и без написания кода в общем модуле. Суть метода заключается в разделении запроса на «сворачиваемую» часть и «детализирующую» часть с последующим связыванием на уровне СКД.
Рассмотрим этот алгоритм по шагам:
РАЗЛИЧНЫЕ или сгруппируем данные в самом запросе. Колонка «Номер акта» в этом запросе присутствовать не должна. Основным связующим полем будет, например, Заказ.Заказ) и поле, которое необходимо собрать в массив (НомерАкта).Заказ = ЗаказНомерАкта в список ресурсов. В качестве выражения укажем:
СоединитьСтроки(Массив(Различные НомерАкта), "; ")
НомерАкта.Как это работает: СКД сформирует плоскую таблицу по первому набору данных. Для каждой строки система автоматически обратится ко второму набору по ключу связи, соберет все номера актов в массив, исключит дубли благодаря функции Различные, объединит их через точку с запятой в одну строку и выведет в ячейку. При этом исходные строки дублироваться не будут.
Если мы не хотим разделять один простой запрос на два набора данных, мы можем использовать агрегатные функции СКД, правильно настроив саму структуру вывода отчета.
Разберем данный подход:
НомерАкта как ресурс с выражением:
СоединитьСтроки(Массив(Различные НомерАкта), "; ")
Организация, Контрагент, Заказ, Договор и т.д.).НомерАкта.В результате СКД сгруппирует строки на уровне самой компоновки, а благодаря отключению расположения группировок пользователь увидит привычную плоскую таблицу, где в одной из колонок будет находиться склеенный список значений.
Иногда требования к форматированию результирующей строки слишком сложны для встроенных функций СКД, либо выгрузка данных должна производиться строго через детальные записи без перенастройки структуры компоновки. В этом случае мы можем прибегнуть к помощи программного кода.
Для реализации этого метода нам потребуется создать экспортную функцию в общем модуле. Обратите внимание, что у этого общего модуля должны быть установлены флажки «Клиент (управляемое приложение)», «Сервер» и «Внешнее соединение».
Пример кода функции общего модуля (назовем его УправлениеОтчетами):
Функция СклеитьЗначенияПоля(ТаблицаДанных, КлючевоеПоле, ЗначениеКлюча, ИмяПоляАгрегации) Экспорт
// Фильтруем таблицу по ключевому полю
ПараметрыОтбора = Новый Структура(КлючевоеПоле, ЗначениеКлюча);
СтрокиТаблицы = ТаблицаДанных.НайтиСтроки(ПараметрыОтбора);
МассивЗначений = Новый Массив;
Для Каждого СтрокаДанных Из СтрокиТаблицы Цикл
Если ЗначениеЗаполнено(СтрокаДанных[ИмяПоляАгрегации]) Тогда
// Исключаем дублирование значений в результирующем массиве
Если МассивЗначений.Найти(СтрокаДанных[ИмяПоляАгрегации]) = Неопределено Тогда
МассивЗначений.Добавить(СтрокаДанных[ИмяПоляАгрегации]);
EndIf;
EndIf;
КонецЦикла;
Возврат СтрСоединить(МассивЗначений, "; ");
КонецФункции
В самой схеме компоновки данных мы можем добавить Вычисляемое поле. Назовем его АктыСтрокой. В выражении этого поля вызовем нашу функцию, передав туда необходимые параметры:
УправлениеОтчетами.СклеитьЗначенияПоля(НаборДанных, "Заказ", Заказ, "НомерАкта")
Этот метод дает максимальную гибкость, однако у него есть существенный недостаток: скорость работы отчета может снизиться, так как вызов функций общего модуля для каждой детальной строки при больших объемах данных создает дополнительную нагрузку на сервер.
Разработчикам полезно знать, что штатная функция СКД СоединитьСтроки способна работать не только с простыми плоскими массивами, но и с целыми таблицами значений. Это позволяет красиво форматировать вывод нескольких связанных реквизитов.
Например, если нам нужно вывести не просто список номеров актов, а связать каждый номер с его датой, мы можем использовать конструкцию:
СоединитьСтроки(ТаблицаЗначений(НомерАкта, ДатаАкта), "; ", " от ")
При использовании такого выражения на выходе мы получим отформатированную строку следующего вида:
«Акт №123 от 10.05.2026; Акт №124 от 12.05.2026»
Также внутри агрегатных функций СКД поддерживается упорядочивание данных. Если вам принципиально, чтобы номера документов выводились по возрастанию или по дате, вы можете применить конструкцию упорядочивания непосредственно внутри выражения ресурса.
Мы проанализировали причины возникновения избыточных строк в детальных записях отчетов СКД и разобрали эффективные методы борьбы с ними. Выбор конкретного метода зависит от архитектуры вашей конфигурации и требований к производительности системы. В большинстве стандартных случаев использование первого или второго способа позволяет решить задачу быстро, красиво и исключительно штатными инструментами компоновки без написания кода.