Как реализовать отбор по сегментам номенклатуры в отчетах на СКД для 1С:УТ 11, КА 2 и ERP

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

При разработке собственных отчетов в конфигурациях «Управление торговлей 11», «Комплексная автоматизация 2» или «ERP Управление предприятием» разработчики часто сталкиваются с необходимостью добавить функционал отбора по сегментам номенклатуры. В типовых отчетах этот механизм реализован очень удобно для пользователя, но его перенос во внешний отчет требует понимания работы внутренних механизмов системы. В этой статье мы подробно разберем, как интегрировать этот функционал в ваш отчет на СКД.

Понимание архитектуры сегментов

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

  1. Справочник СегментыНоменклатуры — содержит настройки и правила формирования сегмента.
  2. Регистр сведений НоменклатураСегмента — хранит информацию о принадлежности конкретного товара к сегменту.

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

Шаг 1. Подготовка запроса в СКД

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


ВЫБРАТЬ
    Сегменты.Номенклатура КАК Номенклатура,
    Сегменты.Характеристика КАК Характеристика
ПОМЕСТИТЬ ВТ_ОтборПоСегментам
ИЗ
    РегистрСведений.НоменклатураСегмента КАК Сегменты
ГДЕ
    Сегменты.Сегмент = &СегментНоменклатуры
;

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

Разберем, что мы сделали. Мы создали временную таблицу ВТ_ОтборПоСегментам. Это критически важно, так как многие типовые процедуры ищут таблицу именно с таким или похожим названием для программной модификации текста запроса. Подобные методики часто применяются в отчетах про движения товаров с резервами нарастающим итогом. Также мы ввели параметр &ИспользоватьОтборПоСегментамНоменклатуры, который позволяет системе гибко управлять применением фильтра.

Шаг 2. Настройка параметров в СКД

Перейдем на закладку «Параметры» в СКД и убедимся, что:

  1. Параметр СегментНоменклатуры имеет тип СправочникСсылка.СегментыНоменклатуры.
  2. Добавлен логический параметр ИспользоватьОтборПоСегментамНоменклатуры (Тип: Булево).
  3. Для параметра сегмента включено ограничение доступности, если вы планируете управлять им только программно, либо выведено в пользовательские настройки для удобства.

Шаг 3. Программная инициализация отбора

Чтобы отчет заработал как типовой, необходимо в модуле объекта отчета переопределить процедуру ПриКомпоновкеРезультата. Выясним причину, по которой простого запроса бывает недостаточно: системе нужно обновить состав динамических сегментов перед выполнением отчета. Рассмотрим пример кода:


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

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

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

Шаг 4. Решение проблемы «Один товар — много сегментов»

Рассмотрим ситуацию, когда вам нужно не просто отфильтровать данные, но и вывести информацию о сегменте в колонку или использовать её для оформления (например, раскрасить строки). Поскольку один товар может входить в несколько сегментов, обычное соединение (LEFT JOIN) приведет к дублированию строк с остатками и движениями, что недопустимо в финансовых отчетах.

Проанализируем два способа решения этой задачи:

Способ А: Использование механизма характеристик

В СКД на закладке «Настройки» есть вкладка «Характеристики». Мы можем настроить получение сегментов как дополнительных реквизитов номенклатуры. Для этого:

  1. Указываем тип объекта: СправочникСсылка.Номенклатура.
  2. Запрос для получения видов характеристик: выбираем все используемые сегменты.
  3. Запрос для получения значений: обращаемся к регистру НоменклатураСегмента.

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

Способ Б: Вычисляемые поля и агрегация

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

Массив(Различные Сегмент.Наименование) — в ресурсах, с последующим преобразованием в строку. При необходимости реализовать различные варианты объединения значений пригодится руководство по выводу строк в одной ячейке СКД.

Шаг 5. Условное оформление

Если стоит задача раскрашивать номенклатуру в зависимости от сегмента, выполним следующие шаги:

  1. В настройках СКД на уровне отчета перейдем на вкладку «Условное оформление».
  2. Добавим новое правило. Установим цвет оформления (например, Цвет фона).
  3. В условии укажем: Номенклатура В (ВЫБРАТЬ Номенклатура ИЗ РегистрСведений.НоменклатураСегмента ГДЕ Сегмент = &НужныйСегмент).

Помните: Правила условного оформления применяются сверху вниз. Если товар входит в несколько сегментов, сработает то правило, которое находится выше в списке. Используйте это для настройки приоритетов раскраски.

Рекомендации по производительности

При работе с большими базами данных использование условия ГДЕ Номенклатура В (ВТ_ОтборПоСегментам) в виртуальных таблицах (например, ОстаткиИОбороты) является наиболее эффективным. Это позволяет СУБД отсечь ненужные записи на самом раннем этапе выполнения запроса, значительно ускоряя формирование отчета и снижая нагрузку на сервер.

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

← На главную