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

Программист 1С v8.3 (Управляемые формы) Управленческий учет Промышленность, строительство и АПК
← На главную

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

Разбор исходной ситуации

Проанализируем задачу: имеется запрос, объединяющий данные из двух источников. Первый источник — это реализация продукции (себестоимость берется из регистра сведений), второй — реализация товаров (себестоимость берется как цена закупки из регистра накопления). Для корректного разделения потоков данных во второй части объединения нам нужно наложить фильтр: Номенклатура В ИЕРАРХИИ(&Товары). Основная сложность заключается в том, чтобы передать в &Товары конкретную ссылку на папку справочника "Номенклатура".

Способ 1: Использование выражений в параметрах СКД

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

Рассмотрим примеры выражений:

  1. Поиск по коду (рекомендуется): Справочники.Номенклатура.НайтиПоКоду("00000001"). Это более надежно, чем поиск по наименованию, так как коды меняются реже.
  2. Поиск по наименованию: Справочники.Номенклатура.НайтиПоНаименованию("Товары"). Используйте осторожно: если пользователь переименует папку, отчет перестанет работать.

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

Способ 2: Установка параметра через программный код

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

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


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

Способ 3: Использование предопределенных элементов

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

Значение(Справочник.Номенклатура.Товары)

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

Оптимизация запроса: параметры виртуальных таблиц

Проанализируем ситуацию с производительностью. В тексте запроса автора условие В ИЕРАРХИИ стоит в секции ГДЕ. Для виртуальных таблиц (таких как Обороты) это неэффективно, так как система сначала выберет ВСЕ обороты, а потом будет их фильтровать.

Рассмотрим, как правильно передать условие в параметры виртуальной таблицы:


ВЫБРАТЬ
    ВыручкаОбороты.АналитикаУчетаНоменклатуры.Номенклатура,
    ВыручкаОбороты.СуммаВыручкиОборот
ИЗ
    РегистрНакопления.ВыручкаИСебестоимостьПродаж.Обороты(
        &НачалоПериода, 
        &КонецПериода, 
        Авто, 
        Номенклатура В ИЕРАРХИИ (&Товары)
    ) КАК ВыручкаОбороты

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

Работа с NULL при объединении и соединениях

Посмотрим на пример расчета прибыли из исходного сообщения: СуммаВыручки - Себестоимость * Количество. Если мы используем ЛЕВОЕ СОЕДИНЕНИЕ с регистром сведений, и для какой-то номенклатуры себестоимость не задана, в поле придет значение NULL. В 1С любая арифметическая операция с NULL дает NULL, что приведет к потере данных в отчете.

Для решения этой проблемы всегда используйте функцию ЕСТЬNULL:


ВЫБРАТЬ
    ДанныеРеализаций.Номенклатура,
    ЕСТЬNULL(ДанныеПоСебестоимости.Себестоимость, 0) КАК СебестоимостьЕд,
    ДанныеРеализаций.СуммаВыручки - ЕСТЬNULL(ДанныеПоСебестоимости.Себестоимость, 0) * ДанныеРеализаций.Количество КАК Прибыль
ИЗ
    ПолучениеДанныхРеализаций КАК ДанныеРеализаций
ЛЕВОЕ СОЕДИНЕНИЕ 
    ДанныеПоСебестоимостям КАК ДанныеПоСебестоимости
ПО 
    ДанныеРеализаций.Номенклатура = ДанныеПоСебестоимости.Номенклатура

Альтернативный подход: Связи наборов данных

Вместо сложного запроса с ОБЪЕДИНИТЬ ВСЕ и СОЕДИНЕНИЕ, в СКД можно использовать механизм связей. Создадим два набора данных: НаборПродажи и НаборСебестоимость. На вкладке "Связи наборов данных" укажем условие связи по номенклатуре.

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

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

← На главную