При разработке сложных отчетов в Системе компоновки данных (СКД), особенно когда требуется совместить динамические периоды (месяцы) и аналитические показатели, такие как ABC-классификация, программисты часто сталкиваются с двумя проблемами: появлением лишних пустых колонок и некорректным расчетом категорий. В этой статье мы подробно разберем, как очистить структуру отчета от пустых данных и как программно обработать результаты для вывода ABC-статусов.
Лишний пустой столбец в начале таблицы отчета чаще всего свидетельствует о наличии записей со значением NULL или пустой ссылкой в полях, которые используются в группировках колонок. Рассмотрим подробнее, почему это происходит и как это исправить.
Проанализируем ситуацию: когда мы выполняем ЛЕВОЕ СОЕДИНЕНИЕ в запросе (как это показано в Сообщении 3), система берет все записи из левой таблицы (например, втНоменклатура) и пытается найти соответствия в правой (ПродажиОбороты). Если продаж за конкретный месяц не было, поля правой таблицы примут значение NULL. Если это поле (например, ВариантИсполнения) выбрано в качестве группировки колонок, СКД создаст отдельный столбец для значения «Пусто».
Способы решения:
ГДЕ или в параметрах виртуальных таблиц следует отсекать пустые значения. Однако более гибким методом является использование функции ЕСТЬNULL.ЕСТЬNULL(ВариантИсполнения, ЗНАЧЕНИЕ(Справочник.ВариантыИсполнения.ПустаяСсылка)). Это позволит системе сгруппировать «пустые» записи с явно заданными пустыми ссылками, избегая дублирования столбцов.Рассмотрим структуру запроса, используемую для получения данных. Она состоит из нескольких временных таблиц, что является хорошей практикой для оптимизации.
Первым шагом мы подготавливаем полный список номенклатуры и ее вариантов:
ВЫБРАТЬ
Номенклатура.Ссылка КАК Номенклатура,
ВариантыИсполнения.Ссылка КАК ВариантИсполнения
ПОМЕСТИТЬ втНоменклатура
ИЗ Справочник.Номенклатура КАК Номенклатура
ЛЕВОЕ СОЕДИНЕНИЕ Справочник.ВариантыИсполнения КАК ВариантыИсполнения
ПО Номенклатура.Ссылка = ВариантыИсполнения.Владелец
Затем мы получаем данные о продажах, используя параметры &НачПериода_1 и &КонПериода_1. Обратите внимание, что в запросе из примера используется группировка по периодам (месяц и год). Это критически важно для отчета «по месяцам».
Проблема в исходном коде заключалась в том, что при добавлении таблицы в структуру отчета расчет ABC мог «отвалиться», так как логика классификации часто привязана к итогам. Если мы хотим видеть ABC-статус в динамике по месяцам, нам нужно решить: считается ли категория один раз за весь период или индивидуально для каждого месяца.
Иногда возможностей простого запроса СКД недостаточно, и требуется программное вмешательство в процесс компоновки. Рассмотрим, как правильно перехватить данные отчета через процедуру ПриКомпоновкеРезультата в модуле объекта.
Для того чтобы рассчитать категории и записать их, например, в дополнительные реквизиты номенклатуры, мы должны выполнить компоновку во временную ТаблицуЗначений. Посмотрим на алгоритм:
Процедура ПриКомпоновкеРезультата(ДокументРезультат, ДанныеРасшифровки, СтандартнаяОбработка)
СтандартнаяОбработка = Ложь;
// 1. Инициализируем схему и настройки
КомпоновщикМакета = Новый КомпоновщикМакетаКомпоновкиДанных;
МакетКомпоновкиДанных = КомпоновщикМакета.Выполнить(СхемаКомпоновкиДанных, КомпоновщикНастроек.Настройки, ДанныеРасшифровки);
// 2. Создаем процессор компоновки
ПроцессорКомпоновкиДанных = Новый ПроцессорКомпоновкиДанных;
ПроцессорКомпоновкиДанных.Инициализировать(МакетКомпоновкиДанных);
// 3. Выводим результат в таблицу значений для обработки
ТаблицаРезультат = Новый ТаблицаЗначений;
ПроцессорВывода = Новый ПроцессорВыводаРезультатаКомпоновкиДанныхВТаблицуЗначений;
ПроцессорВывода.УстановитьОбъект(ТаблицаРезультат);
ПроцессорВывода.Вывести(ПроцессорКомпоновкиДанных);
// 4. Анализируем полученные данные
Для Каждого _Строка Из ТаблицаРезультат Цикл
// Проверяем заполнение ключевых полей, например АБЦ_Маржа или АБЦ_Кол
Если Не ЗначениеЗаполнено(_Строка.АБЦ_Маржа) Тогда
Продолжить;
КонецЕсли;
// Логика присвоения символьных категорий
Если _Строка.АБЦ_Маржа = 1 Тогда
Статус = "A";
ИначеЕсли _Строка.АБЦ_Маржа = 2 Тогда
Статус = "B";
Иначе
Статус = "C";
КонецЕсли;
// Здесь можно вызвать процедуру записи результата в справочник
КонецЦикла;
// 5. Не забудьте в конце вывести финальный результат в ДокументРезультат
// чтобы пользователь увидел отчет на экране
КонецПроцедуры
Проанализируем типичную ошибку из Сообщения 4: в коде дважды вызывался ПроцессорВывода в ТабличныйДокумент, но при этом переменная ТаблицаРезультат оставалась пустой. Чтобы программный цикл заработал, необходимо использовать ПроцессорВыводаРезультатаКомпоновкиДанныхВТаблицуЗначений. Если выводить данные только в документ, то программно «прочитать» их из ячеек таблицы будет гораздо сложнее и медленнее.
Также обратите внимание на работу с группами номенклатуры. При расчете ABC-анализа иерархия может искажать проценты. Рекомендуется использовать условие Если _Строка.Номенклатура.ЭтоГруппа Тогда Продолжить; КонецЕсли;, чтобы расчет производился только по конечным элементам (товарам).
Выясним, как упростить задачу в актуальных версиях платформы 1С 8.3. В СКД на закладке «Вычисляемые поля» или непосредственно в ресурсах можно использовать встроенную функцию ABCКлассификация.
Синтаксис выглядит так: ABCКлассификация(СуммаОборот, 3, 80, 15). Где:
СуммаОборот — показатель, по которому строим рейтинг;3 — количество групп (A, B и C);80 — процент для группы A;15 — процент для группы B (оставшиеся 5% уйдут в группу C).Использование этой функции позволяет избежать написания сложного кода в модуле объекта и корректно пересчитывать категории при изменении пользователем настроек отбора или группировки.
Резюме: Чтобы ваш ABC-отчет по месяцам был чистым и информативным, всегда проверяйте левые соединения на NULL, используйте ЕСТЬNULL для полей группировок и старайтесь использовать штатные функции классификации СКД, обращаясь к программному коду в модуле объекта только для специфических задач (например, для записи результатов анализа обратно в базу данных).