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

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

1. Базовые понятия: что такое отбор в СКД и где он хранится

Отбор в системе компоновки данных — это набор условий, которые фильтруют данные перед их выводом в отчёт. В отличие от обычных запросов, где условия пишутся напрямую в тексте, в СКД отборы хранятся в объекте настроек компоновки (НастройкиКомпоновкиДанных) и могут динамически изменяться.

Физически отборы представлены в двух местах:

  • 📁 Схема компоновки данных — здесь определяются доступные поля для отбора (в разделе Настройки → Отбор конструктора СКД).
  • 🔧 Настройки пользователя — здесь хранятся текущие значения отборов, которые можно менять программно.

Важно понимать, что 1С:Предприятие 8.3 работает с отборами через коллекцию ЭлементыОтбора, где каждый элемент имеет свойства:

  • 🔹 ЛевоеЗначение — поле, по которому идёт отбор (например, "ДатаДокумента").
  • 🔹 ВидСравнения — тип условия (Равно, Больше, ВСписке и т.д.).
  • 🔹 ПравоеЗначение — значение для сравнения (может быть простым типом, массивом или объектом).
  • 🔹 Использование — флаг, включающий/отключающий отбор (Истина/Ложь).
⚠️ Внимание: Если вы работаете с управляемыми формами, изменения отборов через НастройкиКомпоновкиДанных не всегда сразу отображаются в интерфейсе. Для принудительного обновления используйте метод Обновить() у элемента формы.

2. Способ 1: Простое задание значения через свойство Значение

Самый очевидный способ — напрямую присвоить значение отбору по его имени. Этот метод подходит, когда имя отбора заранее известно и не меняется.

Пример кода для установки отбора по дате:

Процедура УстановитьОтборПоДате(НастройкиКомпоновки, ДатаНачала, ДатаОкончания)

НастройкиКомпоновки.Отбор.ДатаДокумента.ВидСравнения = ВидСравненияКомпоновкиДанных.Между;

НастройкиКомпоновки.Отбор.ДатаДокумента.Значение = Новый Массив(ДатаНачала, ДатаОкончания);

КонецПроцедуры

Здесь:

  • 📅 ДатаДокумента — имя поля отбора (должно совпадать с именем в схеме СКД).
  • 🔄 ВидСравненияКомпоновкиДанных.Между — тип условия (альтернативы: Равно, Больше, ВСписке и др.).
  • 📊 Новый Массив() — используется для условий типа Между или ВСписке.

Этот метод удобен своей простотой, но имеет ограничения:

  • ❌ Не работает, если имя отбора содержит специальные символы или пробелы (в таком случае используйте ЭлементыОтбора).
  • ❌ Не позволяет динамически добавлять новые отборы — только модифицировать существующие.
📊 Какой способ задания отборов вы используете чаще?
Прямое присваивание значений
Работа с коллекцией ЭлементыОтбора
Изменение схемы компоновки
Другой

3. Способ 2: Работа с коллекцией ЭлементыОтбора

Более гибкий подход — использование коллекции ЭлементыОтбора, которая доступна через свойство Отбор настроек компоновки. Этот метод позволяет:

  • 🔍 Добавлять новые отборы динамически.
  • 🔄 Менять условия для отборов с нестандартными именами.
  • 🗑️ Удалять ненужные отборы.

Пример добавления отбора по контрагенту:

Процедура ДобавитьОтборПоКонтрагенту(НастройкиКомпоновки, СписокКонтрагентов)

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

НовыйОтбор.ЛевоеЗначение = Новый ПолеКомпоновкиДанных("Контрагент");

НовыйОтбор.ВидСравнения = ВидСравненияКомпоновкиДанных.ВСписке;

НовыйОтбор.ПравоеЗначение = СписокКонтрагентов;

НовыйОтбор.Использование = Истина;

КонецПроцедуры

Ключевые моменты:

  • 🆔 Новый ПолеКомпоновкиДанных() — создаёт объект поля для отбора. Имя поля ("Контрагент") должно совпадать с именем в схеме СКД.
  • 📋 ВидСравненияКомпоновкиДанных.ВСписке — используется для проверки вхождения в массив значений.
  • 🔘 Использование = Истина — активирует отбор (по умолчанию может быть Ложь).
⚠️ Внимание: При работе с перечислениями или ссылками (например, справочники) правое значение должно быть корректного типа. Если передать строку вместо ссылки, отбор не сработает!

Имя поля отбора существует в схеме СКД|Тип правого значения соответствует типу поля (дата, ссылка, число)|Вид сравнения поддерживается для данного типа поля|Отбор включён (свойство Использование = Истина)-->

4. Способ 3: Динамическое изменение схемы компоновки

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

Пример добавления нового поля отбора по сумме документа:

Процедура ДобавитьПолеОтбораПоСумме(СхемаКомпоновки)

// Добавляем поле в набор данных

ПолеСумма = СхемаКомпоновки.НаборыДанных.Элементы[0].Поля.Добавить();

ПолеСумма.Имя = "СуммаДокумента";

ПолеСумма.ПутьКДанным = "СуммаДокумента";

// Добавляем отбор по этому полю

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

НовыйОтбор.ЛевоеЗначение = Новый ПолеКомпоновкиДанных("СуммаДокумента");

НовыйОтбор.ВидСравнения = ВидСравненияКомпоновкиДанных.Больше;

НовыйОтбор.ПравоеЗначение = 10000;

КонецПроцедуры

Особенности метода:

  • 🛠️ Требует прав на изменение схемы компоновки (может быть ограничено в типовой конфигурации).
  • 🔄 Изменения схемы применяются ко всем пользователям отчёта, если не использовать персональные настройки.
  • ⚡ После изменения схемы нужно обновить настройки компоновки (НастройкиКомпоновки.Загрузить(СхемаКомпоновки)).
Способ Когда использовать Ограничения
Прямое присваивание Простые отборы с известными именами Не работает с нестандартными именами полей
Коллекция ЭлементыОтбора Динамические отборы, сложные условия Требует знания структуры СКД
Изменение схемы Добавление новых полей отбора Может затрагивать всех пользователей

5. Работа с датами и перечислениями: типичные ошибки

Отборы по датам и перечислениям часто становятся источником ошибок из-за неверного формата данных или неправильного вида сравнения. Рассмотрим ключевые моменты.

Отбор по датам

При установке отбора по дате убедитесь, что:

  • 📅 Правое значение — это объект типа Дата, а не строка.
  • 🕒 Для условий Между массив дат должен содержать ровно два элемента.
  • 🌍 Учитывается временная зона (если даты приходят из внешних систем).

Пример корректного отбора по текущему месяцу:

НастройкиКомпоновки.Отбор.Дата.ВидСравнения = ВидСравненияКомпоновкиДанных.Между;

НастройкиКомпоновки.Отбор.Дата.Значение = Новый Массив(

НачалоМесяца(ТекущаяДата()),

КонецМесяца(ТекущаяДата())

);

Отбор по перечислениям

Для полей типа Перечисление правое значение должно быть:

  • 🔢 Объектом ЗначениеПеречисления (не строкой!).
  • 📋 Для условия ВСписке — массивом таких объектов.

Ошибка, которая приводит к пустому результату:

// НЕПРАВИЛЬНО: передаём строку вместо значения перечисления

НастройкиКомпоновки.Отбор.Статус.Значение = "Завершён";

Правильный вариант:

// ПРАВИЛЬНО: используем значение перечисления

НастройкиКомпоновки.Отбор.Статус.Значение = Перечисления.СтатусыДокументов.Завершён;

💡

Чтобы избежать ошибок с типами данных, используйте функцию ТипЗнч() для проверки правого значения перед установкой отбора. Например: Если ТипЗнч(Значение) <> Тип("Дата") Тогда ...

6. Отборы в управляемых и обычных формах: ключевые различия

Логика работы с отборами в управляемых и обычных формах имеет нюансы, которые важно учитывать.

Управляемые формы

В управляемых формах отчёты СКД обычно размещаются в элементе ПолеHTMLДокумента или ПолеТабличногоДокумента. После изменения отборов необходимо:

  1. 🔄 Обновить настройки компоновки: Отчёт.Настройки = НастройкиКомпоновки;
  2. 🖥️ Вызвать метод Обновить() у элемента формы: ЭлементыФормы.Отчёт.Обновить();

Пример для управляемой формы:

Процедура ПриИзмененииПараметров(Элемент)

НастройкиКомпоновки = Отчёт.Настройки;

НастройкиКомпоновки.Отбор.Дата.Значение = ТекущаяДата();

Отчёт.Настройки = НастройкиКомпоновки;

ЭлементыФормы.Отчёт.Обновить();

КонецПроцедуры

Обычные формы

В обычных формах отчёт СКД часто представлен элементом ПолеТабличногоДокумента. Здесь достаточно обновить настройки:

Процедура УстановитьОтбор()

НастройкиКомпоновки = Отчёт.Настройки;

НастройкиКомпоновки.Отбор.Контрагент.Значение = Справочники.Контрагенты.НайтиПоНаименованию("ООО Ромашка");

Отчёт.Настройки = НастройкиКомпоновки;

Отчёт.СкомпоноватьРезультат();

КонецПроцедуры

⚠️ Внимание: В тонком клиенте или веб-клиенте некоторые методы (например, СкомпоноватьРезультат()) могут работать иначе, чем в толстом клиенте. Всегда тестируйте отчёты в целевой среде!
Что делать, если отбор не применяется?

Если после программной установки отбора данные в отчёте не фильтруются, проверьте:

1. Тип правого значения — например, для поля типа "СправочникСсылка.Контрагенты" правое значение должно быть ссылкой, а не строкой.

2. Вид сравнения — условие "Равно" не сработает, если поле содержит NULL.

3. Флаг "Использование" — отбор может быть отключён (свойство = Ложь).

4. Обновление отчёта — в управляемых формах требуется явный вызов Обновить().

5. Права доступа — пользователь может не иметь прав на чтение данных, попадающих под отбор.

7. Продвинутые техники: динамические отборы и работа с виртуальными таблицами

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

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

Пример: фильтрация документов по произвольному набору реквизитов, выбранных пользователем в таблице значений.

Процедура ПрименитьДинамическиеОтборы(НастройкиКомпоновки, ТаблицаОтборов)

Для Каждого СтрокаОтбора Из ТаблицаОтборов Цикл

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

НовыйОтбор.ЛевоеЗначение = Новый ПолеКомпоновкиДанных(СтрокаОтбора.Поле);

НовыйОтбор.ВидСравнения = СтрокаОтбора.ВидСравнения;

НовыйОтбор.ПравоеЗначение = СтрокаОтбора.Значение;

КонецЦикла;

КонецПроцедуры

Отборы по виртуальным таблицам

Если отчёт использует виртуальные таблицы (например, Документ.РеализацияТоваровУслуг.Обороты), имена полей для отбора должны соответствовать структуре виртуальной таблицы. Пример:

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

НастройкиКомпоновки.Отбор.Период.ВидСравнения = ВидСравненияКомпоновкиДанных.ВИерархии;

НастройкиКомпоновки.Отбор.Период.ПравоеЗначение = ТекущийДокумент.Дата;

Для виртуальных таблиц с иерархией (например, по периодам) используйте ВидСравненияКомпоновкиДанных.ВИерархии.

💡

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

8. Типичные ошибки и как их избежать

Даже опытные разработчики сталкиваются с проблемами при программной установке отборов. Вот наиболее распространённые ошибки и способы их решения:

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

Ещё одна частая проблема — отборы не сохраняются между сеансами. Это происходит, если настройки компоновки не сохранены в пользовательские настройки. Решение:

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

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

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

Для отладки отборов используйте Сообщить() или ЗаписатьВФайл(), чтобы вывести текущие настройки:

ЗаписатьВФайл(НастройкиКомпоновки.Отбор, "C:\temp\отборы.txt", "UTF-8");

FAQ: Ответы на частые вопросы

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

Чтобы очистить все отборы, пройдите по коллекции ЭлементыОтбора и удалите элементы:

Пока НастройкиКомпоновки.Отбор.ЭлементыОтбора.Количество() > 0 Цикл

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

КонецЦикла;

Или создайте новый пустой отбор:

НастройкиКомпоновки.Отбор = Новый ОтборКомпоновкиДанных();
Можно ли установить отбор по полю, которого нет в схеме СКД?

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

Исключение — виртуальные таблицы с динамическими полями (например, обороты по регистрам), где поля определяются системой.

Как сделать отбор по нескольким значениям (аналог SQL IN)?

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

НастройкиКомпоновки.Отбор.Контрагент.ВидСравнения = ВидСравненияКомпоновкиДанных.ВСписке;

НастройкиКомпоновки.Отбор.Контрагент.Значение = Новый Массив(

Справочники.Контрагенты.НайтиПоНаименованию("ООО Альфа"),

Справочники.Контрагенты.НайтиПоНаименованию("ООО Бета")

);

Почему отбор по дате не работает с временной частью?

В 1С:Предприятие даты без времени сравниваются как ДатаНачалаДня. Чтобы учесть время, используйте:

НастройкиКомпоновки.Отбор.Дата.ВидСравнения = ВидСравненияКомпоновкиДанных.БольшеИлиРавно;

НастройкиКомпоновки.Отбор.Дата.Значение = НачалоДня(ТекущаяДата());

Для точного сравнения с временем используйте тип ДатаВремя.

Как передать отборы из формы в отчёт СКД?

Создайте на форме реквизиты для хранения параметров отбора, а затем переносите их в настройки компоновки:

Процедура СформироватьОтчёт(Команда)

НастройкиКомпоновки = Отчёт.Настройки;

Если ЗначениеЗаполнено(ПараметрыОтчёта.ДатаНачала) Тогда

НастройкиКомпоновки.Отбор.Дата.Значение = ПараметрыОтчёта.ДатаНачала;

КонецЕсли;

Отчёт.Настройки = НастройкиКомпоновки;

Отчёт.СкомпоноватьРезультат();

КонецПроцедуры