Как в СКД сгруппировать данные по уникальному составу строк документа?

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

В практике разработки на платформе 1С:Предприятие 8.3 часто возникает задача, когда необходимо сгруппировать документы не по их реквизитам («шапке»), а по уникальному набору строк в табличной части. Например, нужно понять, сколько раз в системе встречается определенная комбинация товаров (набор) и какими документами она была продана. Стандартная группировка Системы компоновки данных (СКД) работает построчно, поэтому для решения задачи «схлопывания» одинаковых составов требуются дополнительные технические приемы.

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

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

Представим, что у нас есть таблица с данными: Регистратор, Тип и Номенклатура. В одном документе может быть несколько строк с разной номенклатурой. Нам необходимо получить отчет, где верхним уровнем будет Тип, а вторым уровнем — уникальное сочетание товаров (состав), которое встречается в документах. При этом важно правильно рассчитать количество: на уровне типа — общее количество уникальных документов, на уровне состава — количество документов, имеющих именно такой набор строк.

Основная сложность заключается в том, что СКД не может сравнивать массивы строк напрямую. Чтобы система поняла, что «Товар1 + Товар2» в одном документе — это то же самое, что и «Товар1 + Товар2» в другом, нам нужно привести этот набор к единому значению (строковому представлению).

Метод 1: Использование вычисляемых полей и функции СоединитьСтроки

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

Шаг 1. Создание вычисляемого поля

Перейдем на закладку «Вычисляемые поля» и добавим новое поле Состав. В выражении этого поля нам нужно собрать все наименования номенклатуры, относящиеся к одному регистратору. Однако, если мы просто напишем СоединитьСтроки(Номенклатура), система не поймет контекст группировки. Поэтому мы будем использовать ресурсы.

Шаг 2. Настройка ресурсов

На закладке «Ресурсы» определим правила расчета для нашего поля Состав и поля Количество:

  1. Для поля Состав укажем выражение:
    
    СоединитьСтроки(Упорядочить(ВычислитьВыражениеСГруппировкойТаблица("Номенклатура.Наименование", "Номенклатура"), "Наименование"), " \ ")
    
    Здесь функция Упорядочить критически важна: если в одном документе порядок будет «Товар1, Товар2», а в другом «Товар2, Товар1», без сортировки СКД посчитает их разными составами.
  2. Для поля Количество используем выражение: Количество(Различные Регистратор) Это позволит нам корректно посчитать количество уникальных документов (наборов) в каждой группировке.

Метод 2: Подготовка данных во временных таблицах запроса

Если данных очень много, расчет строкового состава «на лету» в выражении ресурса может замедлить отчет. Рассмотрим, как подготовить данные более эффективно на уровне запроса.

В обычном запросе 1С нет функции конкатенации строк из разных записей таблицы. Поэтому мы можем пойти по пути создания «контрольной суммы» или идентификатора состава. Разберем алгоритм:

  1. Выгрузим данные во временную таблицу: Регистратор, Номенклатура.
  2. В коде на языке 1С (перед формированием отчета) выгрузим эту таблицу в ТаблицуЗначений.
  3. Свернем таблицу по регистраторам, программно перебрав строки и создав текстовую колонку Состав, где номенклатура перечислена через разделитель в алфавитном порядке.
  4. Передадим полученную таблицу обратно в СКД как «Внешний набор данных».

Посмотрим на пример кода обработки данных перед выводом:


// Предположим, ТЗ_Данные получена из запроса
ТЗ_Результат = ТЗ_Данные.Скопировать();
ТЗ_Результат.Свернуть("Регистратор, Тип", "Номенклатура"); // Номенклатура здесь для примера, нам нужна агрегация

Для Каждого СтрокаДок Из ТЗ_Результат Цикл
    Отбор = Новый Структура("Регистратор", СтрокаДок.Регистратор);
    СтрокиСостава = ТЗ_Данные.НайтиСтроки(Отбор);
    
    // Сортируем массив для идентичности составов
    СписокТоваров = Новый СписокЗначений;
    Для Каждого СтрСостава Из СтрокиСостава Цикл
        СписокТоваров.Добавить(СтрСостава.Номенклатура.Наименование);
    КонецЦикла;
    СписокТоваров.СортироватьПоЗначению();
    
    // Собираем строку
    СтрокаСоставаТекст = "";
    Для Каждого ЭлементСписка Из СписокТоваров Цикл
        СтрокаСоставаТекст = СтрокаСоставаТекст + ЭлементСписка.Значение + " \ ";
    КонецЦикла;
    
    СтрокаДок.Состав = СтрокаСоставаТекст;
КонецЦикла;

Метод 3: Иерархическая группировка в настройках СКД

Теперь выясним, как правильно настроить структуру отчета на закладке «Настройки», чтобы получить вид, требуемый в условии задачи. Нам нужно реализовать вложенность:

  1. Группировка по полю Тип: В колонках выводится Тип и Количество. В данном случае Количество покажет сумму всех уникальных документов этого типа.
  2. Вложенная группировка по полю Состав: Это то самое поле, которое мы вычислили или подготовили заранее. В этой строке будет выведен перечень товаров и количество документов, имеющих именно такой состав.

Важно помнить: чтобы в группировке по Тип не выводилось пустое поле состава, в настройках выбранных полей для каждой группировки нужно указывать только соответствующие поля. Для группировки «Тип» — только поле «Тип» и «Количество», для вложенной — «Состав» и «Количество».

Особенности подсчета ресурсов

Проанализируем ситуацию с расчетом итогов. Если один и тот же регистратор содержит несколько строк номенклатуры, обычная функция Сумма(Количество) выдаст неверный результат (количество строк вместо количества документов).

Именно поэтому мы используем Количество(Различные Регистратор). Рассмотрим, как это работает на примере автора темы:

При группировке по составу «Товар1 \ Товар2» система увидит два различных регистратора (Документ1 и Документ3) и выведет цифру 2. При группировке по «Товар4 \ Товар3» — только Документ2, выведет цифру 1. На уровне итогов по «Тип1» система насчитает 3 уникальных регистратора.

Заключение

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

← На главную