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

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

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

Метод 1: Группировка и соединение на уровне запроса

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

Разберем этот процесс по шагам:

  1. Создадим временную таблицу, в которой сгруппируем данные по сотруднику и выберем для него "основное" подразделение (например, через функцию МАКСИМУМ или МИНИМУМ).
  2. В этой же таблице можно рассчитать уникальный номер или просто оставить флаг "Первичность".
  3. Соединим основную таблицу данных с этой временной таблицей по полям Сотрудник и Подразделение.

Посмотрим на пример логики запроса:


ВЫБРАТЬ
    Сотрудник,
    МАКСИМУМ(Подразделение) КАК ОсновноеПодразделение
ПОМЕСТИТЬ ВТ_УникальныеСотрудники
ИЗ
    РегистрСведений.СоставПодразделений
СГРУППИРОВАТЬ ПО
    Сотрудник;

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
    ОсновнаяТаблица.Подразделение,
    ОсновнаяТаблица.Сотрудник,
    ВЫБОР
        КОГДА ВТ_УникальныеСотрудники.Сотрудник ЕСТЬ НЕ NULL 
        ТОГДА 1 
        ИНАЧЕ 0 
    КОНЕЦ КАК ЭтоПервоеВхождение
ИЗ
    РегистрСведений.СоставПодразделений КАК ОсновнаяТаблица
ЛЕВОЕ СОЕДИНЕНИЕ ВТ_УникальныеСотрудники КАК ВТ_УникальныеСотрудники
    ПО ОсновнаяТаблица.Сотрудник = ВТ_УникальныеСотрудники.Сотрудник
    И ОсновнаяТаблица.Подразделение = ВТ_УникальныеСотрудники.ОсновноеПодразделение

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

Метод 2: Использование функции СКД ВычислитьВыражение

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

Если нам нужно присвоить Иванову номер 1 в первом подразделении и номер 2 во втором, мы можем создать Вычисляемое поле и в колонке "Выражение" указать следующую конструкцию:

ВычислитьВыражение("Количество(Сотрудник)", , "Общий", "Первая", "Текущая")

Рассмотрим, как это работает: СКД перебирает строки и для каждой текущей строки подсчитывает количество упоминаний сотрудника от самой первой строки отчета до текущей. В результате для первого появления Иванова мы получим 1, для второго — 2 и так далее.

Метод 3: Агрегатные функции в ресурсах (Количество Различные)

Посмотрим на самый простой способ получения итоговых данных. Если ваша задача — просто вывести в подвале отчета корректное число "Уникальных сотрудников", воспользуйтесь вкладкой Ресурсы в схеме компоновки.

В поле "Выражение" для ресурса Сотрудник напишите:

Количество(Различные Сотрудник)

Важный момент: при такой настройке в группировке по конкретному подразделению вы увидите количество людей в этом подразделении, а в группировке "Общий итог" 1С автоматически исключит дубли и покажет реальное количество физических лиц, работающих в компании.

Метод 4: Условное оформление для скрытия повторов

Иногда требуется не просто посчитать, а визуально скрыть повторяющиеся значения, чтобы отчет выглядел чище (как в примере автора: "Иванов — пусто"). Для этого воспользуемся Условным оформлением.

  1. Создадим вычисляемое поле (например, ПорядковыйНомерВхождения), используя метод с ВычислитьВыражение, описанный выше.
  2. Перейдем на закладку "Условное оформление".
  3. Добавим новое оформление: установим формат "Текст" равным пустой строке (или цвет текста в цвет фона).
  4. В условии укажем: ПорядковыйНомерВхождения > 1.
  5. В области использования выберем только те поля, которые нужно скрыть при повторе.

Метод 5: Программная обработка в ПриКомпоновкеРезультата

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

Разберем алгоритм программного вывода:


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

Используя этот метод, мы получаем полный контроль над каждой ячейкой до того, как она будет отрисована в табличном документе. Мы можем создать структуру Соответствие, записывать туда идентификаторы сотрудников и, если встречаем сотрудника повторно, программно очищать значение ресурса "Количество" в объекте ЭлементРезультата.

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

← На главную