Разработка сложных отчетов в среде 1С:Предприятие часто требует не просто статического вывода данных, а гибкой фильтрации на лету. Механизм системы компоновки данных (СКД) предоставляет мощный инструментарий для решения этих задач, позволяя программисту динамически управлять структурой выборки.
Понимание того, как корректно добавить отбор в отчет программно, является критическим навыком для любого разработчика платформы. Это позволяет создавать универсальные формы анализа, где пользователь может изменять критерии поиска без перекомпиляции конфигурации.
В данной статье мы детально разберем архитектуру объектов СКД, методы формирования условий фильтрации и нюансы, которые часто упускают из виду начинающие специалисты, что приводит к некорректной работе отчетов или падению производительности.
Архитектура отборов в системе компоновки данных
Прежде чем писать код, необходимо четко представлять, где именно в объектной модели хранятся настройки фильтрации. В терминах платформы 1С отбор — это коллекция элементов, принадлежащая объекту НастройкиКомпоновкиДанных. Каждый элемент этой коллекции описывает одно условие сравнения.
Работа с отборами происходит на уровне структуры настроек, которую можно получить из макета компоновки данных или из текущих настроек отчета. Важно различать макет, который хранит статический шаблон, и настройки, которые формируются в момент исполнения.
Основной объект, с которым вы будете взаимодействовать — это ЭлементОтбора. Он содержит поля для указания левого операнда (поле данных), вида сравнения (равно, больше, содержит) и правого операнда (значение). Неправильная инициализация этих полей — самая частая причина ошибок.
Всегда создавайте копию настроек перед их изменением, если не хотите повлиять на глобальные настройки сеанса или другие отчеты, использующие тот же макет.
Система позволяет добавлять отборы как на поля исходных таблиц запроса, так и на поля, полученные в результате вычислений или присоединения виртуальных таблиц. Однако тип данных левого и правого операнда должен быть совместим, иначе платформа выдаст исключение при выполнении.
Программное создание простого отбора
Самый распространенный сценарий — фильтрация по конкретному значению реквизита, например, по контрагенту или периоду. Для этого используется метод Добавить коллекции отборов. Синтаксис требует строгого соблюдения порядка аргументов.
Рассмотрим базовый пример добавления отбора по полю "Организация". Вам потребуется создать новый элемент отбора, задать вид сравнения и указать значение. Обратите внимание на использование перечисления ВидСравнения, которое гарантирует типобезопасность кода.
Настройки = Новый НастройкиКомпоновкиДанных;
ЭлементОтбора = Настройки.Отбор.Добавить();
ЭлементОтбора.ЛевоеЗначение = Новый ПолеКомпоновкиДанных("Организация");
ЭлементОтбора.ВидСравнения = ВидСравненияКомпоновкиДанных.Равно;
ЭлементОтбора.ПравоеЗначение = СсылкаНаОрганизацию;
В данном фрагменте кода мы явно указываем, что поле ЛевоеЗначение представляет собой поле компоновки данных. Это важно, так как СКД работает со своей абстракцией полей, а не напрямую с именами колонок базы данных.
Если необходимо добавить несколько условий, вы просто вызываете метод Добавить повторно. Система автоматически объединит их логическим оператором "И", если не задана группировка. Для более сложной логики потребуется использование групп отборов.
☑️ Алгоритм создания отбора
Работа с группами отборов и логикой "ИЛИ"
Стандартное поведение СКД подразумевает конъюнкцию (логическое "И") между элементами отбора. Однако бизнес-требования часто диктуют необходимость использования дизъюнкции ("ИЛИ"). Например, нужно выбрать документы, где статус "Проведен" ИЛИ сумма больше миллиона.
Для реализации такой логики используется механизм Групп отборов. Вы создаете элемент типа "Группа", указываете для неё логический оператор, а затем добавляете вложенные отборы уже в коллекцию этой группы.
| Свойство | Тип значения | Описание назначения |
|---|---|---|
| Использование | Булево | Активен ли данный отбор в текущий момент |
| ВидСравнения | Перечисление | Определяет оператор сравнения (Равно, НеРавно, Больше) |
| ЛевоеЗначение | ПолеКомпоновкиДанных | Поле из набора данных, к которому применяется условие |
| ПравоеЗначение | Произвольный | Значение для сравнения или второе поле |
| Группировка | ГруппаЭлементовОтбора | Ссылка на родительскую группу для вложенных условий |
При создании группы важно правильно установить свойство Группировка у вложенных элементов. Если вы забудете связать элемент с группой, он останется в корневом уровне и будет работать как отдельное условие "И".
Внимание ⚠️: Глубокая вложенность групп отборов может существенно замедлить генерацию запроса системой компоновки данных. Старайтесь не превышать 3-4 уровня вложенности без острой необходимости.
Оптимизация сложных групп
Если у вас много условий "ИЛИ" для одного поля, иногда эффективнее сформировать массив значений и использовать вид сравнения "В Списке", вместо создания десятка отдельных условий в группе.
Динамические отборы на основе параметров формы
В реальных конфигурациях значения для отборов редко жестко заданы в коде. Чаще всего они поступают из параметров формы отчета или внешних обработчиков. Механизм Параметров СКД позволяет связать отбор с переменной, значение которой пользователь вводит перед запуском.
Чтобы реализовать это программно, вы должны сначала убедиться, что в макете компоновки данных объявлен соответствующий параметр. Затем в коде вы присваиваете значение этому параметру, а в отборе ссылаетесь на него через конструкцию Параметр("ИмяПараметра").
Параметры = Новый Структура;
Параметры.Вставить("ПериодНачала", ДатаНачала);
Параметры.Вставить("ПериодОкончания", ДатаОкончания);
Отчет.Настройки.Параметры.ЗагрузитьИзСтруктуры(Параметры);
Элемент = Отчет.Настройки.Отбор.Добавить();
Элемент.ЛевоеЗначение = Новый ПолеКомпоновкиДанных("Период");
Элемент.ВидСравнения = ВидСравненияКомпоновкиДанных.ВИнтервале;
// Значение берется автоматически из параметров, если имена совпадают
Такой подход делает отчет максимально гибким. Пользователь может менять параметры в интерфейсе, а программный код автоматически подхватит новые значения при формировании.
Однако, если параметр не передан или имеет значение Неопределено, отбор может сработать непредсказуемо. Всегда проверяйте наличие значений перед добавлением условия в коллекцию.
Типовые ошибки и методы отладки
Даже опытные разработчики сталкиваются с ситуацией, когда код выполняется без ошибок, но отчет выдает пустую выборку или, наоборот, все данные. Чаще всего проблема кроется в несовпадении типов данных или неверном имени поля.
Одной из распространенных ошибок является попытка добавить отбор по полю, которое не входит в текущий НаборДанных. Система компоновки данных строго следит за областью видимости полей. Если поле находится в другой таблице или не выбрано в настройки, отбор игнорируется.
Также стоит обращать внимание на представление полей. Иногда в коде используется синоним, а в макете — имя поля из запроса. Используйте метод ПолучитьВсеПоляНаборовДанных для программной проверки доступных имен перед формированием условия.
⚠️ Внимание: При работе с составными типами данных (например, СправочникСсылка.Номенклатура или СправочникСсылка.Услуги) убедитесь, что тип значения в отборе точно совпадает с ожидаемым типом поля. Приведение типов в СКД работает не всегда явно.
Для отладки сложных отчетов включите режим отладки СКД в конфигураторе или используйте метод ПолучитьМакет с последующим выводом структуры настроек в файл. Это позволит увидеть, как именно система интерпретировала ваши программные установки.
Если отчет пустой, первым делом проверьте, что имена полей в ЛевомЗначении точно совпадают с именами полей в МакетеКомпоновкиДанных, учитывая регистр.
Оптимизация производительности при больших объемах
Когда отчет строится по миллионам записей, способ добавления отборов напрямую влияет на время формирования. Добавление сотен отдельных условий "ИЛИ" в цикле — это путь к зависанию клиента.
Вместо цикла по элементам используйте оператор В Списке. Вы можете собрать все необходимые значения в массив или таблицу значений и передать её как правый операнд отбора. Это позволит базе данных сгенерировать один эффективный SQL-запрос с конструкцией IN (...).
Кроме того, избегайте добавления отборов по полям, не имеющим индексов в базе данных, если это возможно. Хотя СКД старается оптимизировать запрос, наличие индекса на полях фильтрации всегда дает выигрыш в скорости.
⚠️ Внимание: Интерфейс и методы работы с СКД могут незначительно меняться в новых релизах платформы 1С. Если вы используете очень старую версию платформы (ниже 8.3.10), некоторые методы работы с группами отборов могут отличаться. Сверяйте синтаксис с синтаксис-помощником вашей версии.
Еще один прием — использование Виртуальных таблиц с отборами на уровне запроса, если логика позволяет. Это переносит фильтрацию на уровень СУБД до того, как данные попадут в механизм компоновки, что значительно быстрее.
Часто задаваемые вопросы
Как удалить все существующие отборы перед добавлением новых?
Для очистки коллекции отборов используйте метод Очистить() у объекта Настройки.Отбор. Это удалит все ранее установленные условия, включая вложенные группы, и позволит сформировать фильтрацию с нуля.
Можно ли добавить отбор по полю, которого нет в настройках отчета?
Нет, отбор можно применить только к тем полям, которые существуют в наборах данных макета компоновки. Если нужного поля нет, его необходимо сначала добавить в запрос макета или в структуру наборов данных программно.
Почему отбор не работает, хотя код не выдает ошибок?
Проверьте свойство Использование у элемента отбора. По умолчанию оно может быть установлено в Ложь, если отбор был скопирован из неактивных настроек. Также убедитесь, что тип данных левого и правого операнда совместим.
Как программно считать значение отбора, установленного пользователем?
Вы можете Iterate (перебрать) коллекцию Отчет.Настройки.Отбор. Для каждого элемента проверяйте свойство ЛевоеЗначение, чтобы найти нужное поле, и считывайте ПравоеЗначение.