Как в СКД убрать дублирующиеся значения в плоском отчете при соединении наборов данных?

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

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

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

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

Решение 1: Использование условного оформления

Это самый простой и рекомендуемый способ для решения подобных визуальных задач. Он не меняет сами данные в отчете, а лишь скрывает их отображение, что полностью соответствует требованию. Суть метода в том, чтобы задать правило: если строка не первая в группе одинаковых записей, сделать текст в нужных ячейках невидимым.

Разберем по шагам, как это настроить:

  1. Откройте настройки отчета СКД в режиме конфигуратора или в режиме предприятия (Еще -> Прочее -> Изменить вариант отчета).
  2. Перейдите на вкладку "Условное оформление" и нажмите "Добавить".
  3. На вкладке "Оформление" установите параметр, который скроет значение. Самый надежный способ — установить свойство Формат в пустую строку "". Альтернативный вариант — задать цвет текста, совпадающий с цветом фона (например, белый).
  4. На вкладке "Условие" задайте условие, при котором будет срабатывать оформление. Нажмите "Добавить" и в левой части выберите поле Номер по порядку в группировке. Это специальная функция СКД, которая нумерует строки внутри группировки. В качестве условия укажите: Больше 1.

    Выражение будет выглядеть так: НомерПоПорядкуВГруппировке() > 1

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

  5. На вкладке "Оформляемые поля" выберите те колонки, в которых нужно скрыть дубли. В нашем примере это "Количество", "Цена за штуку", "Сумма без НДС".
  6. Сохраните настройки. Теперь при формировании отчета значения в указанных колонках будут отображаться только для первой строки каждой группы связанных данных.

Решение 2: Использование вычисляемых полей

Этот метод позволяет не просто скрыть, а фактически заменить дублирующиеся значения на другие, например, на 0 или NULL. Это может быть полезно, если итоговый отчет будет выгружаться для дальнейшей обработки. Метод немного сложнее, так как требует написания выражений.

Посмотрим на пример реализации. Вместо того чтобы выводить поля "СуммаБезНДС", "Количество" и "Цена" напрямую, мы создадим для них вычисляемые поля.

  1. В настройках СКД перейдите на вкладку "Вычисляемые поля".
  2. Создайте новое поле, например, СуммаБезНДС_Вывод.
  3. В поле "Выражение" напишите конструкцию с использованием функции ВычислитьВыражение и оператора ВЫБОР.
    
    ВЫБОР
        КОГДА ВычислитьВыражение("НомерПоПорядкуВГруппировке()", "ДетальныеЗаписи") = 1
        ТОГДА СуммаБезНДС
        ИНАЧЕ 0
    КОНЕЦ
    

    Разберем выражение:

    • ВычислитьВыражение("НомерПоПорядкуВГруппировке()", "ДетальныеЗаписи") — эта функция вычисляет значение выражения (в данном случае, порядковый номер строки) в контексте указанной группировки ("ДетальныеЗаписи").
    • КОГДА ... = 1 — мы проверяем, является ли текущая строка первой в своей группе.
    • ТОГДА СуммаБезНДС — если строка первая, мы выводим ее реальное значение.
    • ИНАЧЕ 0 — в противном случае (для всех дублей) выводим 0. Можно также использовать NULL.
  4. Аналогичные вычисляемые поля создайте для "Количества" и "Цены".
  5. После этого на вкладке "Выбранные поля" замените исходные поля на новые вычисляемые (СуммаБезНДС_Вывод и т.д.).

Этот способ дает больше контроля над данными, но требует более тщательной настройки.

Решение 3: Оконные функции в запросе (для платформы 8.3.21 и выше)

Если вы работаете на современной версии платформы, можно решить задачу еще на уровне запроса с помощью оконных функций. Это наиболее производительный и "правильный" с точки зрения архитектуры данных способ.

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

Рассмотрим, как изменить запрос для второго набора данных (состав партий):


ВЫБРАТЬ
    СоставПартий.НоменклатураСостав,
    СоставПартий.Количество,
    // ... другие поля из второго набора
    СоставПартий.СсылкаНаРеализацию,
    НОМЕРСТРОКИ() В РАМКАХ (РАЗДЕЛ СоставПартий.СсылкаНаРеализацию) КАК НомерСтрокиВГруппе
ИЗ
    РегистрСведений.СоставПартий КАК СоставПартий
...

Что здесь происходит:

После того как вы добавили это поле в запрос, его можно использовать в СКД точно так же, как и стандартные функции:

Этот подход переносит логику на уровень базы данных, что зачастую эффективнее, особенно на больших объемах данных.

Решение 4: Программная постобработка результата

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

Общий алгоритм действий:

  1. Сформировать отчет СКД программно со всеми дублями.
  2. Результат получить не для вывода пользователю, а в виде объекта ТабличныйДокумент.
  3. Организовать цикл для обхода ячеек этого табличного документа.
  4. В цикле отслеживать изменение значения в ключевой колонке (например, по номенклатуре из документа реализации). Для этого нужно хранить значение из предыдущей строки в переменной.
  5. Если значение в текущей строке совпадает с предыдущим, то программно очистить значения в нужных ячейках (Область.Текст = "").
  6. После обработки вывести измененный ТабличныйДокумент пользователю.

Этот способ имеет недостатки: он сложнее в реализации и поддержке, а также может медленно работать на больших отчетах. Однако он дает полный контроль над финальным видом документа.

← На главную