Как объединить склады в отчете СКД и убрать дублирование строк

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

При разработке отчетов в системе компоновки данных (СКД) программисты часто сталкиваются с проблемой визуального дублирования строк. Типичный пример: в отчете выводятся данные по остаткам товаров в разрезе складов и качества. Если для одного склада существует несколько категорий качества (например, «Новый», «Брак», «Уцененный»), СКД по умолчанию выводит имя склада в каждой строке. Это перегружает отчет и делает его трудночитаемым.

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

Вариант 1. Настройка структуры группировок в СКД (без программирования)

Самый быстрый и правильный способ избавиться от дублирования названий складов — настроить подчиненные группировки на вкладке «Настройки» в схеме компоновки данных. Выясним, как сделать это пошагово:

  1. Перейдем на вкладку «Настройки» в нашей схеме компоновки данных.
  2. Обратим внимание на структуру группировок. Если у нас создана одна группировка, в которую добавлены сразу два поля — Склад и Качество, то система будет выводить их в одной строке, дублируя склад для каждого нового значения качества.
  3. Удалим совместную группировку и создадим правильную иерархию «Родитель — Потомок». Для этого добавим группировку верхнего уровня по полю Склад.
  4. Нажмем правой кнопкой мыши по созданной группировке Склад и выберем пункт «Добавить». Добавим подчиненную группировку по полю Качество.

Теперь настроим визуальное отображение. Выделим корневой элемент настроек («Отчет») или конкретную группировку и перейдем на вкладку «Другие настройки» в нижней части экрана. Найдем параметр «Расположение полей группировок»:

Чтобы отчет не перегружался лишними промежуточными суммами по складу (если они не требуются), в тех же «Других настройках» для группировки Склад установим параметр «Расположение итогов» в значение «Нет».

Вариант 2. Использование структуры «Таблица» (Кросс-таблица)

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

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

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

Вариант 3. Борьба с дублированием данных при соединении разнородных таблиц

Иногда дублирование строк и искажение итогов происходит из-за неверной логики запроса. Например, когда мы пытаемся объединить в одном запросе остатки (которые хранятся в разрезе складов и качества) и плановые показатели (которые задаются только для склада в целом, без учета качества).

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

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

Благодаря этому СКД выполнит соединение на уровне компоновки. План по складу рассчитается ровно один раз на уровне группировки по складу и не будет размножаться на подчиненные строки качества.

Также важно правильно настроить расчет ресурсов на вкладке «Ресурсы». Для поля КоличествоПлан в колонке «Рассчитывать по...» укажем конкретно группировку Склад и Общий итог. Для подчиненной группировки Качество расчет этого ресурса выполнять не нужно — оставим поле пустым, чтобы не вводить пользователей в заблуждение пустым дублированием плановых цифр на детальных строках качества.

Вариант 4. Программное объединение ячеек в Табличном Документе

Если пользователю требуется исключительно плоская таблица, но при этом одинаковые ячейки склада по вертикали должны быть физически объединены (как при использовании кнопки «Объединить» в Excel), стандартными настройками СКД этого не добиться. Здесь нам поможет программный вывод отчета с последующей постобработкой результирующего табличного документа.

Для реализации этого метода откроем модуль объекта отчета и переопределим процедуру ПриКомпоновкеРезультата:


Процедура ПриКомпоновкеРезультата(ДокументРезультат, ДанныеРасшифровки, СтандартнаяОбработка)
    
    СтандартнаяОбработка = Ложь;
    
    // Инициализируем схему и настройки
    СхемаКомпоновкиДанных = ПолучитьМакет("ОсновнаяСхемаКомпоновкиДанных");
    Настройки = КомпоновщикНастроек.ПолучитьНастройки();
    
    // Компонуем результат
    КомпоновщикМакета = Новый КомпоновщикМакетаКомпоновкиДанных;
    МакетКомпоновки = КомпоновщикМакета.Выполнить(СхемаКомпоновкиДанных, Настройки, ДанныеРасшифровки);
    
    ПроцессорКомпоновки = Новый ПроцессорКомпоновкиДанных;
    ПроцессорКомпоновки.Инициализировать(МакетКомпоновки, , ДанныеРасшифровки, Истина);
    
    ПроцессорВывода = Новый ПроцессорВыводаРезультатаКомпоновкиДанныхВТабличныйДокумент;
    ПроцессорВывода.УстановитьДокумент(ДокументРезультат);
    ПроцессорВывода.Вывести(ПроцессорКомпоновки);
    
    // Запускаем алгоритм объединения смежных ячеек склада
    ОбъединитьОдинаковыеОбласти(ДокументРезультат, 2); // 2 — это номер колонки со складом
    
КонецПроцедуры

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


Процедура ОбъединитьОдинаковыеОбласти(ТабличныйДокумент, НомерКолонки)
    
    ВсегоСтрок = ТабличныйДокумент.ВысотаТаблицы;
    Если ВсегоСтрок < 3 Тогда
        Возврат;
    КонецЕсли;
    
    КонецОбъединения = ВсегоСтрок;
    
    Для НомерСтроки = -(ВсегоСтрок - 1) По -2 Цикл
        ТекущаяСтрока = -НомерСтроки;
        
        ЗначениеТекущее = ТабличныйДокумент.Область(ТекущаяСтрока, НомерКолонки).Текст;
        ЗначениеПредыдущее = ТабличныйДокумент.Область(ТекущаяСтрока - 1, НомерКолонки).Текст;
        
        Если ЗначениеТекущее = ЗначениеПредыдущее И НЕ ПустаяСтрока(ЗначениеТекущее) Тогда
            Продолжить;
        Иначе
            Если КонецОбъединения > ТекущаяСтрока Тогда
                ОбластьДляОбъединения = ТабличныйДокумент.Область(ТекущаяСтрока, НомерКолонки, КонецОбъединения, НомерКолонки);
                ОбластьДляОбъединения.Объединить();
                ОбластьДляОбъединения.ВертикальноеПоложение = ВертикальноеПоложение.Центр;
            КонецЕсли;
            КонецОбъединения = ТекущаяСтрока - 1;
        КонецЕсли;
    КонецЦикла;
    
    // Обработка самой первой группы ячеек в начале таблицы
    Если КонецОбъединения > 1 Тогда
        ОбластьДляОбъединения = ТабличныйДокумент.Область(1, НомерКолонки, КонецОбъединения, НомерКолонки);
        ОбластьДляОбъединения.Объединить();
        ОбластьДляОбъединения.ВертикальноеПоложение = ВертикальноеПоложение.Центр;
    КонецЕсли;
    
КонецПроцедуры

Рассмотрим, как работает данный алгоритм. Мы обходим строки таблицы снизу вверх. Это позволяет корректно определять границы блоков без использования сложных промежуточных коллекций. Если значение в текущей ячейке совпадает со значением в ячейке выше, мы продолжаем цикл. Как только обнаруживается изменение значения, мы выделяем область от текущей строки до сохраненного индекса КонецОбъединения с помощью метода Область() и вызываем метод Объединить(). Также мы устанавливаем вертикальное положение текста по центру для красивого визуального отображения.

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

← На главную