СКД в 1С

1С СКД: отбор программно — элементы, группы и виды сравнения

Коротко

Чтобы установить отбор 1С СКД программно, добавьте элемент в коллекцию Настройки.Отбор.Элементы методом Добавить() с типом ЭлементОтбораКомпоновкиДанных и заполните три свойства: ЛевоеЗначениеНовый ПолеКомпоновкиДанных("ИмяПоля"), ВидСравнения — значение ВидСравненияКомпоновкиДанных, ПравоеЗначение — искомое значение.

Для условий вида «ИЛИ» и «НЕ» в ту же коллекцию добавляется ГруппаЭлементовОтбораКомпоновкиДанных со свойством ТипГруппы. Отбор действует на данные после выборки набора, параметр — внутри запроса, поэтому по скорости почти всегда выигрывает параметр.

Как программно установить отбор в СКД: ЭлементОтбораКомпоновкиДанных

Точка входа — объект НастройкиКомпоновкиДанных: это либо КомпоновщикНастроек.Настройки в отчёте, либо СхемаКомпоновкиДанных.НастройкиПоУмолчанию при программной компоновке. Свойство Отбор возвращает ОтборКомпоновкиДанных, а его Элементы — коллекцию, в которую и добавляется условие:

Настройки = КомпоновщикНастроек.Настройки;

ЭлементОтбора = Настройки.Отбор.Элементы.Добавить(
    Тип("ЭлементОтбораКомпоновкиДанных"));

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

ЛевоеЗначение — это не строка, а объект ПолеКомпоновкиДанных. Путь к данным пишется так же, как имя поля в схеме компоновки: "Номенклатура.ВидНоменклатуры" для реквизита через точку, "Склад" для поля верхнего уровня.

Коллекция элементов отбора: добавить, найти, удалить, очистить

Настройки.Отбор.Элементы — это КоллекцияЭлементовОтбораКомпоновкиДанных. Она поддерживает полный набор операций, поэтому отборы 1С СКД можно не только добавлять, но и пересобирать перед каждым запуском отчёта:

Элементы = Настройки.Отбор.Элементы;

// Полная пересборка отбора отчёта СКД
Элементы.Очистить();

Новый1 = Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
Новый1.ЛевоеЗначение  = Новый ПолеКомпоновкиДанных("Организация");
Новый1.ВидСравнения   = ВидСравненияКомпоновкиДанных.Равно;
Новый1.ПравоеЗначение = ТекущаяОрганизация;

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

Обход коллекции обязан учитывать, что в ней лежат объекты двух типов — элементы и группы. Проверка ТипЗнч() перед обращением к ЛевоеЗначение избавляет от ошибки на группе, у которой такого свойства нет.

В Консоли кода этот фрагмент удобно отлаживать целиком: агент собирает настройки, выполняет компоновку и сразу показывает, сколько строк осталось после отбора — видно, отработало условие или молча отсеяло всё.

Виды сравнения отбора СКД: полный список ВидСравненияКомпоновкиДанных

Свойство ВидСравнения принимает значения системного перечисления ВидСравненияКомпоновкиДанных. Доступны:

  • Равенство и порядок: Равно, НеРавно, Больше, БольшеИлиРавно, Меньше, МеньшеИлиРавно.
  • Списки: ВСписке, НеВСписке, ВСпискеПоИерархии, НеВСпискеПоИерархии.
  • Иерархия: ВИерархии, НеВИерархии.
  • Строки: Содержит, НеСодержит, НачинаетсяС, НеНачинаетсяС, Подобно, НеПодобно.
  • Заполненность: Заполнено, НеЗаполнено.

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

СписокСкладов = Новый СписокЗначений;
СписокСкладов.Добавить(СкладОсновной);
СписокСкладов.Добавить(СкладРозница);

Отбор = Настройки.Отбор.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
Отбор.ЛевоеЗначение  = Новый ПолеКомпоновкиДанных("Склад");
Отбор.ВидСравнения   = ВидСравненияКомпоновкиДанных.ВСписке;
Отбор.ПравоеЗначение = СписокСкладов;

Виды Заполнено и НеЗаполнено — единственные, для которых ПравоеЗначение заполнять не нужно. Для ВИерархии правое значение — ссылка на группу-родителя, а не список.

Группы элементов отбора: условия И, ИЛИ, НЕ

Все условия верхнего уровня объединяются логическим «И». Чтобы получить «ИЛИ» или отрицание, добавьте в коллекцию ГруппаЭлементовОтбораКомпоновкиДанных и заполните её собственную коллекцию Элементы:

Группа = Настройки.Отбор.Элементы.Добавить(
    Тип("ГруппаЭлементовОтбораКомпоновкиДанных"));
Группа.ТипГруппы     = ТипГруппыЭлементовОтбораКомпоновкиДанных.ГруппаИли;
Группа.Использование = Истина;
Группа.Представление = "Просроченные или крупные заказы";

Условие1 = Группа.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
Условие1.ЛевоеЗначение  = Новый ПолеКомпоновкиДанных("ДатаОплаты");
Условие1.ВидСравнения   = ВидСравненияКомпоновкиДанных.Меньше;
Условие1.ПравоеЗначение = ТекущаяДата();

Условие2 = Группа.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
Условие2.ЛевоеЗначение  = Новый ПолеКомпоновкиДанных("СуммаДокумента");
Условие2.ВидСравнения   = ВидСравненияКомпоновкиДанных.Больше;
Условие2.ПравоеЗначение = 100000;
ГруппаЭлементовОтбораКомпоновкиДанных
ТипГруппыГруппаИ, ГруппаИли, ГруппаНе
Элементывложенные условия и группы
Использованиевыключает всю группу целиком
ПрименениеТипПримененияОтбораКомпоновкиДанных
РежимОтображениявидимость в настройках
Представлениезаголовок группы условий
→ вложенность групп не ограничена

ТипГруппыЭлементовОтбораКомпоновкиДанных.ГруппаНе инвертирует результат вложенных условий. Группы вкладываются друг в друга, поэтому выражение вида «(А ИЛИ Б) И НЕ В» собирается из трёх групп без обходных приёмов.

Отбор по группировке: своё условие на уровень структуры

Кроме общего отбора отчёта, СКД поддерживает отбор на отдельной группировке. У объекта ГруппировкаКомпоновкиДанных есть собственное свойство Отбор с такой же коллекцией Элементы:

Группировка = Настройки.Структура[0];

ОтборГруппировки = Группировка.Отбор.Элементы.Добавить(
    Тип("ЭлементОтбораКомпоновкиДанных"));
ОтборГруппировки.ЛевоеЗначение  = Новый ПолеКомпоновкиДанных("КоличествоОстаток");
ОтборГруппировки.ВидСравнения   = ВидСравненияКомпоновкиДанных.Больше;
ОтборГруппировки.ПравоеЗначение = 0;

Такой отбор применяется к уже посчитанным итогам этой группировки — это штатный способ убрать нулевые остатки или показать только группы с оборотом. Общий отбор отчёта такую задачу не решает: он работает до расчёта итогов.

Проверить и снять отбор конкретного элемента структуры удобно методами самого объекта настроек:

Если Настройки.НаличиеОтбораУЭлемента(Группировка) Тогда
    Настройки.ОчиститьОтборЭлемента(Группировка);
КонецЕсли;

// Идентификатор нужен для адресации настройки из формы отчёта
Идентификатор = Настройки.ПолучитьИдентификаторПоОбъекту(Группировка);
ТотЖеОбъект   = Настройки.ПолучитьОбъектПоИдентификатору(Идентификатор);
НастройкиКомпоновкиДанных
НаличиеОтбораУЭлемента(Элемент)есть ли отбор у элемента структуры
ОчиститьОтборЭлемента(Элемент)снять отбор элемента
НастройкиЭлемента(Элемент)настройки элемента структуры
ПолучитьИдентификаторПоОбъекту(Объект)идентификатор настройки
ПолучитьОбъектПоИдентификатору(Идентификатор)обратное преобразование
ОтборОтборКомпоновкиДанных всего отчёта
Структурагруппировки отчёта
Новый НастройкиКомпоновкиДанных()

Применение отбора: элементы, иерархия, только иерархия

Свойство Применение элемента и группы отбора принимает значения ТипПримененияОтбораКомпоновкиДанных: Элементы, Иерархия, ТолькоИерархия. Оно определяет, к каким записям результата компоновки применяется условие — к обычным строкам, к строкам иерархии или только к иерархическим итогам:

Отбор = Настройки.Отбор.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
Отбор.ЛевоеЗначение  = Новый ПолеКомпоновкиДанных("Номенклатура");
Отбор.ВидСравнения   = ВидСравненияКомпоновкиДанных.ВИерархии;
Отбор.ПравоеЗначение = ГруппаНоменклатуры;
Отбор.Применение     = ТипПримененияОтбораКомпоновкиДанных.Элементы;

У элементов из коллекции пользовательских настроек свойства Применение и ЛевоеЗначение недоступны — они существуют только у основных настроек. Это частая причина ошибки «поле не найдено» при попытке донастроить отбор из формы отчёта.

Отбор или параметр СКД: чем отличаются и что быстрее

Оба механизма ограничивают данные, но работают на разных этапах:

  • Параметр подставляется в текст запроса набора данных и ограничивает выборку в СУБД. Задаётся через Настройки.ПараметрыДанных.
  • Отбор применяется компоновщиком к уже полученным данным набора (кроме случаев, когда платформа сама может протолкнуть условие в запрос).
// Параметр данных — ограничение на уровне запроса
Настройки.ПараметрыДанных.УстановитьЗначениеПараметра("НачалоПериода", НачалоДня(ДатаС));
Настройки.ПараметрыДанных.УстановитьЗначениеПараметра("КонецПериода", КонецДня(ДатаПо));

// Чтение и выключение параметра
ЗначениеПараметра = Настройки.ПараметрыДанных.НайтиЗначениеПараметра(
    Новый ПараметрКомпоновкиДанных("НачалоПериода"));
Если ЗначениеПараметра <> Неопределено Тогда
    ЗначениеПараметра.Использование = Истина;
КонецЕсли;

Практическое правило: период, организация и прочие условия, которые всегда есть, — параметры; произвольные пользовательские условия — отбор. Отбор по полю виртуальной таблицы почти всегда нужно дублировать параметром, иначе платформа сначала прочитает все записи и отсечёт лишние в памяти.

Отдельная тема — параметры выбора в СКД: они не фильтруют данные, а ограничивают список значений, который видит пользователь при заполнении отбора. Задаются в схеме компоновки на доступном поле отбора, программно в момент установки условия значение всё равно кладётся в ПравоеЗначение.

Отбор в пользовательских настройках отчёта

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

Отбор = Настройки.Отбор.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
Отбор.ЛевоеЗначение  = Новый ПолеКомпоновкиДанных("Склад");
Отбор.ВидСравнения   = ВидСравненияКомпоновкиДанных.Равно;
Отбор.ПравоеЗначение = СкладОсновной;
Отбор.РежимОтображения = РежимОтображенияЭлементаНастройкиКомпоновкиДанных.БыстрыйДоступ;
Отбор.ИдентификаторПользовательскойНастройки = "ОтборПоСкладу";
Отбор.ПредставлениеПользовательскойНастройки = "Склад";

Обратная задача — изменить уже существующий пользовательский отбор перед формированием отчёта. Элемент ищется в коллекции пользовательских настроек по идентификатору:

ПользовательскиеНастройки = КомпоновщикНастроек.ПользовательскиеНастройки;

Для Каждого ЭлементПН Из ПользовательскиеНастройки.Элементы Цикл
    Если ТипЗнч(ЭлементПН) = Тип("ЭлементОтбораКомпоновкиДанных")
        И ЭлементПН.ИдентификаторПользовательскойНастройки = "ОтборПоСкладу" Тогда
        ЭлементПН.ПравоеЗначение = НужныйСклад;
        ЭлементПН.Использование  = Истина;
    КонецЕсли;
КонецЦикла;

Чтобы от пользовательской настройки перейти к основной, используйте ПользовательскиеНастройки.ПолучитьОсновныеНастройкиПоИдентификаторуПользовательскойНастройки() — там доступны все свойства элемента отбора, включая ЛевоеЗначение.

Проверить, какие идентификаторы пользовательских настроек реально есть в конкретном отчёте, быстрее прогоном кода, чем чтением схемы в конфигураторе: попросите агента Консоли вывести все элементы ПользовательскиеНастройки.Элементы с типами и идентификаторами.

Полный пример: отчёт 1С СКД с отбором программно

Формирование отчёта СКД без формы — схема, настройки по умолчанию, отбор, компоновка в таблицу значений:

Схема = ПолучитьМакет("ОсновнаяСхемаКомпоновкиДанных");

Компоновщик = Новый КомпоновщикНастроекКомпоновкиДанных;
Компоновщик.Инициализировать(
    Новый ИсточникДоступныхНастроекКомпоновкиДанных(Схема));
Компоновщик.ЗагрузитьНастройки(Схема.НастройкиПоУмолчанию);

Настройки = Компоновщик.Настройки;
Настройки.Отбор.Элементы.Очистить();

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

КомпоновщикМакета = Новый КомпоновщикМакетаКомпоновкиДанных;
Макет = КомпоновщикМакета.Выполнить(Схема, Настройки);

Процессор = Новый ПроцессорКомпоновкиДанных;
Процессор.Инициализировать(Макет);

Вывод = Новый ПроцессорВыводаРезультатаКомпоновкиДанныхВКоллекциюЗначений;
Результат = Новый ТаблицаЗначений;
Вывод.УстановитьОбъект(Результат);
Вывод.Вывести(Процессор);

Сообщить("Строк после отбора: " + Результат.Количество());

Порядок важен: отбор задаётся до вызова КомпоновщикМакетаКомпоновкиДанных.Выполнить(). Изменение настроек после получения макета ни на что не влияет — макет уже скомпонован.

Частые ошибки при программной установке отбора СКД

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

Частые вопросы про отбор в СКД

Как программно добавить отбор по нескольким значениям в СКД?

Используйте один элемент отбора с ВидСравненияКомпоновкиДанных.ВСписке и СписокЗначений (или массивом) в ПравоеЗначение. Это короче и быстрее, чем группа ГруппаИли из отдельных равенств.

Чем отбор СКД отличается от параметра?

Параметр подставляется в запрос набора данных и ограничивает выборку в СУБД, отбор применяется компоновщиком к полученным данным. Постоянные условия (период, организация) лучше делать параметрами, произвольные пользовательские — отбором.

Почему программный отбор в отчёте СКД не применяется?

Три типовые причины: ЛевоеЗначение задано строкой вместо ПолеКомпоновкиДанных; поле отсутствует в Настройки.ДоступныеПоляОтбора; отбор добавлен уже после вызова Выполнить() компоновщика макета.

Тарифы

ИИ Консоль запросов 1С

Лайт

Бесплатно

Для ознакомления с возможностями

  • Все функции бесплатно на 2 дня +2 дня за подписку на Telegram или Max
  • Полный набор инструментов без урезаний
  • Без ввода карты
Начать бесплатно

Старт

Популярный выбор
990 руб. в месяц
≈ 5 млн токенов

Для индивидуального использования

Выбрать тариф

Продвинутый

3900 руб. в месяц
≈ 19,5 млн токенов

Для интенсивного использования или команд

Выбрать тариф