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

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

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

В чем заключается проблема сравнения

Проанализируем структуру объекта ЭлементОтбораКомпоновкиДанных. Свойство ЛевоеЗначение содержит не обычную строку с именем поля, а специализированный платформенный объект с типом ПолеКомпоновкиДанных. Из-за этого прямое сравнение со строковым литералом всегда возвращает Ложь, так как типы данных не совпадают.

Способ 1. Сравнение через создание нового объекта ПолеКомпоновкиДанных

Самый надежный и платформенный способ — создать для проверки такой же объект компоновки с нужным путем к данным. Для этого используем конструктор Новый ПолеКомпоновкиДанных("ИмяПоля"). Платформа 1С корректно сравнивает два объекта этого типа между собой по их значению.

Посмотрим на пример правильной проверки:


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

Способ 2. Преобразование левого значения к строке

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


Если Строка(ТекОтбор.ЛевоеЗначение) = "СчетКт" Тогда
    // Условие выполнено
КонецЕсли;

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

Важные нюансы при обходе коллекции отборов

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

  1. Наличие групп элементов отбора. Коллекция КомпоновщикНастроек.Настройки.Отбор.Элементы может содержать не только конечные элементы (ЭлементОтбораКомпоновкиДанных), но и группы условий (ГруппаЭлементовОтбораКомпоновкиДанных с логикой «И», «ИЛИ», «НЕ»). У группы отсутствуют свойства ЛевоеЗначение, ВидСравнения и ПравоеЗначение. Попытка обратиться к ним напрямую в цикле без проверки типа вызовет критическую ошибку «Поле объекта не обнаружено». Кроме того, если отбор вложен внутрь группы, линейный цикл его пропустит. Для полного контроля требуется выполнять рекурсивный обход.
  2. Пользовательские настройки отчета. В управляемом интерфейсе отборы, вынесенные в шапку отчета для быстрого доступа, хранятся в коллекции КомпоновщикНастроек.ПользовательскиеНастройки. Если проверять только коллекцию КомпоновщикНастроек.Настройки.Отбор, можно не увидеть изменения, внесенные пользователем на форме. Чтобы получить актуальное объединенное состояние настроек перед формированием, следует вызывать метод КомпоновщикНастроек.ПолучитьНастройки().
  3. Ограничение прав доступа через отборы. Попытка скрыть конфиденциальные проводки (например, по счетам учета заработной платы) с помощью программного добавления отбора по условию РольДоступна() не обеспечивает надежной защиты. Пользователь с базовыми правами на изменение варианта отчета может отключить или изменить этот фильтр в настройках. Для гарантированной безопасности необходимо использовать механизм RLS (ограничение доступа на уровне записей) либо жестко ограничивать выборку данных в параметрах виртуальных таблиц запроса СКД.

Итоговый пример надежного алгоритма

Объединим рассмотренные правила в единую процедуру, которая корректно перебирает элементы, проверяет их тип и безопасно сравнивает поля отбора:


ОтборДтУжеЕсть = Ложь;
ОтборКтУжеЕсть = Ложь;

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

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

    Если Не Элемент.Использование Тогда
        Продолжить;
    КонецЕсли;

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

Если Не ОтборДтУжеЕсть Тогда
    ТиповыеОтчеты.ДобавитьОтбор(КомпоновщикНастроек, "СчетДт", НужныйСчет, ВидСравненияКомпоновкиДанных.НеРавно);
КонецЕсли;

Если Не ОтборКтУжеЕсть Тогда
    ТиповыеОтчеты.ДобавитьОтбор(КомпоновщикНастроек, "СчетКт", НужныйСчет, ВидСравненияКомпоновкиДанных.НеРавно);
КонецЕсли;

Такой подход обеспечивает корректное сопоставление полей компоновки и защищает код от падений при наличии сложных пользовательских группировок в фильтрах отчета.

← На главную